PageRenderTime 49ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/fwt/java/WidgetPeer.java

https://bitbucket.org/bedlaczech/fan-1.0
Java | 597 lines | 445 code | 77 blank | 75 comment | 87 complexity | f5e2d61fcc1968e48149f28df50a9083 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.lang.reflect.Field;
  10. import java.util.HashMap;
  11. import fan.sys.*;
  12. import fan.gfx.*;
  13. import fan.sys.List;
  14. import org.eclipse.swt.*;
  15. import org.eclipse.swt.graphics.Color;
  16. import org.eclipse.swt.graphics.Point;
  17. import org.eclipse.swt.graphics.Rectangle;
  18. import org.eclipse.swt.widgets.*;
  19. import org.eclipse.swt.widgets.Display;
  20. import org.eclipse.swt.widgets.Event;
  21. import org.eclipse.swt.widgets.Widget;
  22. import org.eclipse.swt.widgets.MenuItem;
  23. import org.eclipse.swt.custom.ScrolledComposite;
  24. import org.eclipse.swt.events.*;
  25. /**
  26. * Native methods for Widget
  27. */
  28. public class WidgetPeer
  29. implements KeyListener, FocusListener, Listener, DisposeListener
  30. {
  31. //////////////////////////////////////////////////////////////////////////
  32. // Constructor
  33. //////////////////////////////////////////////////////////////////////////
  34. public static WidgetPeer make(fan.fwt.Widget self)
  35. throws Exception
  36. {
  37. WidgetPeer peer = new WidgetPeer();
  38. peer.self = self;
  39. return peer;
  40. }
  41. //////////////////////////////////////////////////////////////////////////
  42. // Accessors
  43. //////////////////////////////////////////////////////////////////////////
  44. public fan.fwt.Widget parent()
  45. {
  46. return self.parent();
  47. }
  48. public Widget control()
  49. {
  50. return control;
  51. }
  52. public Widget parentControl()
  53. {
  54. fan.fwt.Widget p = self.parent();
  55. return p == null ? null : p.peer.control;
  56. }
  57. //////////////////////////////////////////////////////////////////////////
  58. // Fields
  59. //////////////////////////////////////////////////////////////////////////
  60. // Bool enabled := true
  61. public boolean enabled(fan.fwt.Widget self) { return enabled.get(); }
  62. public void enabled(fan.fwt.Widget self, boolean v)
  63. {
  64. if (enabled.get() == v) return;
  65. enabled.set(v);
  66. // propagate enabled down tree
  67. List kids = self.kids;
  68. for (int i=0; i<kids.sz(); ++i)
  69. {
  70. fan.fwt.Widget kid = (fan.fwt.Widget)kids.get(i);
  71. kid.enabled(v);
  72. }
  73. }
  74. public final Prop.BoolProp enabled = new Prop.BoolProp(this, true)
  75. {
  76. public boolean get(Widget w)
  77. {
  78. // pain in the ass due to SWT's class hierarchy
  79. if (control instanceof Control) return ((Control)control).getEnabled();
  80. if (control instanceof MenuItem) return ((MenuItem)control).getEnabled();
  81. if (control instanceof ToolItem) return ((ToolItem)control).getEnabled();
  82. return true;
  83. }
  84. public void set(Widget w, boolean v)
  85. {
  86. // pain in the ass due to SWT's class hierarchy
  87. if (control instanceof Control) ((Control)control).setEnabled(v);
  88. if (control instanceof MenuItem) ((MenuItem)control).setEnabled(v);
  89. if (control instanceof ToolItem) ((ToolItem)control).setEnabled(v);
  90. }
  91. };
  92. // Bool visible := true
  93. public boolean visible(fan.fwt.Widget self) { return visible.get(); }
  94. public void visible(fan.fwt.Widget self, boolean v) { visible.set(v); }
  95. public final Prop.BoolProp visible = new Prop.BoolProp(this, true)
  96. {
  97. public boolean get(Widget w)
  98. {
  99. return (w instanceof Control) ? ((Control)w).getVisible() : true;
  100. }
  101. public void set(Widget w, boolean v)
  102. {
  103. // shell always controls its own visibility via open/close
  104. if (w instanceof Control && !(w instanceof Shell))
  105. ((Control)w).setVisible(v);
  106. }
  107. };
  108. public Cursor cursor(fan.fwt.Widget self) { return cursor.get(); }
  109. public void cursor(fan.fwt.Widget self, Cursor v) { cursor.set(v); }
  110. public final Prop.CursorProp cursor = new Prop.CursorProp(this);
  111. // Size size
  112. public fan.gfx.Point pos(fan.fwt.Widget self) { return pos.get(); }
  113. public void pos(fan.fwt.Widget self, fan.gfx.Point v) { pos.set(v); onPosChange(); }
  114. public final Prop.PosProp pos = new Prop.PosProp(this);
  115. // Size size
  116. public Size size(fan.fwt.Widget self) { return size.get(); }
  117. public void size(fan.fwt.Widget self, Size v) { size.set(v); onSizeChange(); }
  118. public final Prop.SizeProp size = new Prop.SizeProp(this);
  119. void onPosChange() {}
  120. void onSizeChange() {}
  121. //////////////////////////////////////////////////////////////////////////
  122. // Layout
  123. //////////////////////////////////////////////////////////////////////////
  124. public Size prefSize(fan.fwt.Widget self, Hints hints)
  125. {
  126. if (!(control instanceof Control)) return Size.defVal;
  127. int w = (hints.w == null) ? SWT.DEFAULT : hints.w.intValue();
  128. int h = (hints.h == null) ? SWT.DEFAULT : hints.h.intValue();
  129. Point s = ((Control)control).computeSize(w, h, true);
  130. return size(s);
  131. }
  132. public fan.gfx.Point posOnWindow(fan.fwt.Widget self)
  133. {
  134. if (!(control instanceof Control)) return null;
  135. fan.fwt.Window window = self.window();
  136. if (window == null || !(window.peer.control instanceof Control)) return null;
  137. Control widgetControl = (Control)control;
  138. Control windowControl = (Control)window.peer.control;
  139. Point pt = Fwt.get().display.map(widgetControl, windowControl, 0, 0);
  140. return point(pt);
  141. }
  142. public fan.gfx.Point posOnDisplay(fan.fwt.Widget self)
  143. {
  144. if (!(control instanceof Control)) return null;
  145. Point pt = Fwt.get().display.map((Control)control, null, 0, 0);
  146. return point(pt);
  147. }
  148. public fan.fwt.Widget relayout(fan.fwt.Widget self)
  149. {
  150. if (control instanceof Composite) ((Composite)control).layout(true);
  151. //if (control instanceof Control) ((Control)control).redraw();
  152. return self;
  153. }
  154. public fan.fwt.Widget pack(fan.fwt.Widget self)
  155. {
  156. if (control instanceof Control)
  157. ((Control)control).pack();
  158. return self;
  159. }
  160. public void repaint(fan.fwt.Widget self, Rect r)
  161. {
  162. if (control instanceof Control)
  163. {
  164. Control c = (Control)control;
  165. if (r == null)
  166. c.redraw();
  167. else
  168. c.redraw((int)r.x, (int)r.y, (int)r.w, (int)r.h, true);
  169. }
  170. }
  171. //////////////////////////////////////////////////////////////////////////
  172. // Focus Eventing
  173. //////////////////////////////////////////////////////////////////////////
  174. public boolean hasFocus(fan.fwt.Widget self)
  175. {
  176. if (control instanceof Control)
  177. return ((Control)control).isFocusControl();
  178. else
  179. return false;
  180. }
  181. public void focus(fan.fwt.Widget self)
  182. {
  183. if (control instanceof Control)
  184. ((Control)control).setFocus();
  185. }
  186. public void checkFocusListeners(fan.fwt.Widget self)
  187. {
  188. // if we don't have any onFocus listeners, then I
  189. // shouldn't be actively registered as a focus listener
  190. if (!(control instanceof Control)) return;
  191. boolean now = self.onFocus().isEmpty() && self.onBlur().isEmpty();
  192. if (now != activeFocusListener) return;
  193. if (activeFocusListener)
  194. {
  195. ((Control)control).removeFocusListener(this);
  196. activeFocusListener = false;
  197. }
  198. else
  199. {
  200. ((Control)control).addFocusListener(this);
  201. activeFocusListener = true;
  202. }
  203. }
  204. public void focusGained(FocusEvent se)
  205. {
  206. self.onFocus().fire(event(EventId.focus));
  207. }
  208. public void focusLost(FocusEvent se)
  209. {
  210. self.onBlur().fire(event(EventId.blur));
  211. }
  212. //////////////////////////////////////////////////////////////////////////
  213. // Key Eventing
  214. //////////////////////////////////////////////////////////////////////////
  215. public void checkKeyListeners(fan.fwt.Widget self)
  216. {
  217. // if we don't have any onKey listeners, then I
  218. // shouldn't be actively registered as a key listener
  219. if (!(control instanceof Control)) return;
  220. boolean now = self.onKeyDown().isEmpty() && self.onKeyUp().isEmpty();
  221. if (now != activeKeyListener) return;
  222. if (activeKeyListener)
  223. {
  224. ((Control)control).removeKeyListener(this);
  225. activeKeyListener = false;
  226. }
  227. else
  228. {
  229. ((Control)control).addKeyListener(this);
  230. activeKeyListener = true;
  231. }
  232. }
  233. public void keyPressed(KeyEvent se)
  234. {
  235. fireKeyEvent(self.onKeyDown(), EventId.keyDown, se);
  236. }
  237. public void keyReleased(KeyEvent se)
  238. {
  239. fireKeyEvent(self.onKeyUp(), EventId.keyUp, se);
  240. }
  241. void fireKeyEvent(EventListeners listeners, EventId id, KeyEvent se)
  242. {
  243. fan.fwt.Event fe = event(id);
  244. fe.keyChar = Long.valueOf(se.character);
  245. fe.key = toKey(se.keyCode, se.stateMask);
  246. listeners.fire(fe);
  247. if (fe.consumed) se.doit = false;
  248. }
  249. static Key toKey(int keyCode, int stateMask)
  250. {
  251. Key key = Key.fromMask(keyCode);
  252. if ((stateMask & SWT.SHIFT) != 0) key = key.plus(Key.shift);
  253. if ((stateMask & SWT.ALT) != 0) key = key.plus(Key.alt);
  254. if ((stateMask & SWT.CTRL) != 0) key = key.plus(Key.ctrl);
  255. if ((stateMask & SWT.COMMAND) != 0) key = key.plus(Key.command);
  256. return key;
  257. }
  258. //////////////////////////////////////////////////////////////////////////
  259. // Mouse Eventing
  260. //////////////////////////////////////////////////////////////////////////
  261. public void handleEvent(Event se)
  262. {
  263. switch(se.type)
  264. {
  265. case SWT.MouseDown: fireMouseEvent(self.onMouseDown(), EventId.mouseDown, se); break;
  266. case SWT.MouseUp: fireMouseEvent(self.onMouseUp(), EventId.mouseUp, se); break;
  267. case SWT.MouseMove: fireMouseEvent(self.onMouseMove(), EventId.mouseMove, se); break;
  268. case SWT.MouseEnter: fireMouseEvent(self.onMouseEnter(), EventId.mouseEnter, se); break;
  269. case SWT.MouseExit: fireMouseEvent(self.onMouseExit(), EventId.mouseExit, se); break;
  270. case SWT.MouseHover: fireMouseEvent(self.onMouseHover(), EventId.mouseHover, se); break;
  271. case SWT.MouseVerticalWheel:
  272. fireMouseEvent(self.onMouseWheel(), EventId.mouseWheel, se, 0, point(0, -se.count));
  273. break;
  274. case SWT.MouseHorizontalWheel:
  275. fireMouseEvent(self.onMouseWheel(), EventId.mouseWheel, se, 0, point(-se.count, 0));
  276. break;
  277. default: System.out.println("WARNING: WidgetPeer.handleEvent: " + se);
  278. }
  279. }
  280. private void fireMouseEvent(EventListeners listeners, EventId id, Event se)
  281. {
  282. fireMouseEvent(listeners, id, se, se.count, null);
  283. }
  284. private void fireMouseEvent(EventListeners listeners, EventId id, Event se, int count, fan.gfx.Point delta)
  285. {
  286. // save modifiers on mouse events for future selection, action,
  287. // and popup events which might occur; this allows us to check
  288. // for Ctrl down to handle newTab style of eventing
  289. int mask = se.stateMask & SWT.MODIFIER_MASK;
  290. Key key = toKey(0, mask);
  291. modifiers = mask == 0 ? null : key;
  292. // fire event
  293. fan.fwt.Event fe = event(id);
  294. fe.pos = point(se.x, se.y);
  295. fe.count = Long.valueOf(count);
  296. fe.button = Long.valueOf(se.button);
  297. fe.delta = delta;
  298. fe.key = key;
  299. listeners.fire(fe);
  300. if (fe.consumed) se.doit = false;
  301. }
  302. //////////////////////////////////////////////////////////////////////////
  303. // Attachment
  304. //////////////////////////////////////////////////////////////////////////
  305. public final boolean attached(fan.fwt.Widget self)
  306. {
  307. return control != null;
  308. }
  309. public final void attach(fan.fwt.Widget self) { attach(self, null); }
  310. public final void attach(fan.fwt.Widget self, Widget parentControl)
  311. {
  312. // short circuit if I'm already attached
  313. if (control != null) return;
  314. // if parent wasn't explictly specified use my fwt parent
  315. fan.fwt.Widget parentWidget = null;
  316. if (parentControl == null)
  317. {
  318. // short circuit if my parent isn't attached
  319. parentWidget = self.parent();
  320. if (parentWidget == null || parentWidget.peer.control == null) return;
  321. parentControl = parentWidget.peer.control;
  322. }
  323. // create control and initialize
  324. // TODO: need to rework this cluster f**k
  325. if (parentControl instanceof TabItem)
  326. {
  327. TabItem item = (TabItem)parentControl;
  328. attachTo(create(item.getParent()));
  329. item.setControl((Control)this.control);
  330. }
  331. else
  332. {
  333. attachTo(create(parentControl));
  334. if (parentControl instanceof ScrolledComposite)
  335. ((ScrolledComposite)parentControl).setContent((Control)control);
  336. }
  337. // callback on parent
  338. if (parentWidget != null) parentWidget.peer.childAdded(self);
  339. }
  340. void childAdded(fan.fwt.Widget child) {}
  341. void attachTo(Widget control)
  342. {
  343. // sync with native control
  344. this.control = control;
  345. // reset focus/key eventing
  346. this.activeKeyListener = false;
  347. this.activeFocusListener = false;
  348. checkFocusListeners(self);
  349. checkKeyListeners(self);
  350. if (control instanceof Control)
  351. {
  352. Control c = (Control)control;
  353. c.addListener(SWT.MouseDown, this);
  354. c.addListener(SWT.MouseUp, this);
  355. c.addListener(SWT.MouseMove, this);
  356. c.addListener(SWT.MouseEnter, this);
  357. c.addListener(SWT.MouseExit, this);
  358. c.addListener(SWT.MouseHover, this);
  359. c.addListener(SWT.MouseVerticalWheel, this);
  360. c.addListener(SWT.MouseHorizontalWheel, this);
  361. }
  362. control.addDisposeListener(this);
  363. syncPropsToControl();
  364. // stick myself in data field
  365. control.setData(self);
  366. // recursively attach my children
  367. List kids = self.kids;
  368. for (int i=0; i<kids.sz(); ++i)
  369. {
  370. fan.fwt.Widget kid = (fan.fwt.Widget)kids.get(i);
  371. kid.peer.attach(kid);
  372. }
  373. }
  374. public Widget create(Widget parent)
  375. {
  376. throw new IllegalStateException(getClass().getName());
  377. }
  378. public void detach(fan.fwt.Widget self)
  379. {
  380. // dipose the control which automatically disposes all the
  381. // children; we do cleanup in the widgetDisposed callback.
  382. if (control != null) control.dispose();
  383. control = null;
  384. }
  385. public void widgetDisposed(DisposeEvent e)
  386. {
  387. syncPropsFromControl();
  388. control = null;
  389. }
  390. //////////////////////////////////////////////////////////////////////////
  391. // Widget/Control synchronization
  392. //////////////////////////////////////////////////////////////////////////
  393. public void syncPropsToControl() { syncProps(true); }
  394. public void syncPropsFromControl(){ syncProps(false); }
  395. private void syncProps(boolean to)
  396. {
  397. try
  398. {
  399. Field[] fields = getClass().getFields();
  400. for (int i=0; i<fields.length; ++i)
  401. {
  402. Field f = fields[i];
  403. try
  404. {
  405. if (Prop.class.isAssignableFrom(f.getType()))
  406. {
  407. Prop prop = (Prop)f.get(this);
  408. if (to)
  409. prop.syncToControl();
  410. else
  411. prop.syncFromControl();
  412. }
  413. }
  414. catch (Exception e)
  415. {
  416. System.out.println("ERROR: setting " + f);
  417. e.printStackTrace();
  418. }
  419. }
  420. }
  421. catch (Exception e)
  422. {
  423. e.printStackTrace();
  424. }
  425. }
  426. //////////////////////////////////////////////////////////////////////////
  427. // Utils
  428. //////////////////////////////////////////////////////////////////////////
  429. static fan.fwt.Widget toFanWidget(Widget w)
  430. {
  431. if (w != null)
  432. {
  433. Object data = w.getData();
  434. if (data instanceof fan.fwt.Widget)
  435. return (fan.fwt.Widget)data;
  436. }
  437. return null;
  438. }
  439. static fan.gfx.Point point(int x, int y)
  440. {
  441. return fan.gfx.Point.make(x, y);
  442. }
  443. static fan.gfx.Point point(Point pt)
  444. {
  445. return fan.gfx.Point.make(pt.x, pt.y);
  446. }
  447. static fan.gfx.Point point(Rectangle r)
  448. {
  449. return fan.gfx.Point.make(r.x, r.y);
  450. }
  451. static Point point(fan.gfx.Point pt)
  452. {
  453. return new Point((int)pt.x, (int)pt.y);
  454. }
  455. static fan.gfx.Size size(int w, int h)
  456. {
  457. return fan.gfx.Size.make(w, h);
  458. }
  459. static fan.gfx.Size size(Point pt)
  460. {
  461. return fan.gfx.Size.make(pt.x, pt.y);
  462. }
  463. static fan.gfx.Size size(Rectangle r)
  464. {
  465. return fan.gfx.Size.make(r.width, r.height);
  466. }
  467. static fan.gfx.Rect rect(Rectangle r)
  468. {
  469. return fan.gfx.Rect.make(r.x, r.y, r.width, r.height);
  470. }
  471. static Rectangle rect(fan.gfx.Rect r)
  472. {
  473. return new Rectangle((int)r.x, (int)r.y, (int)r.w, (int)r.h);
  474. }
  475. static int style(Halign halign)
  476. {
  477. if (halign == Halign.left) return SWT.LEFT;
  478. if (halign == Halign.center) return SWT.CENTER;
  479. if (halign == Halign.right) return SWT.RIGHT;
  480. throw new IllegalStateException(halign.toString());
  481. }
  482. static int orientation(Orientation orientation)
  483. {
  484. if (orientation == Orientation.horizontal) return SWT.HORIZONTAL;
  485. if (orientation == Orientation.vertical) return SWT.VERTICAL;
  486. throw new IllegalStateException(orientation.toString());
  487. }
  488. static Orientation orientation(int style)
  489. {
  490. if ((style & SWT.HORIZONTAL) != 0) return Orientation.horizontal;
  491. if ((style & SWT.VERTICAL) != 0) return Orientation.vertical;
  492. throw new IllegalStateException(Integer.toHexString(style));
  493. }
  494. static int accelerator(Key key)
  495. {
  496. if (key == null) return 0;
  497. return (int)key.mask;
  498. }
  499. //////////////////////////////////////////////////////////////////////////
  500. // Event Utils
  501. //////////////////////////////////////////////////////////////////////////
  502. fan.fwt.Event event(EventId id) { return event(id, null); }
  503. fan.fwt.Event event(EventId id, Object data)
  504. {
  505. fan.fwt.Event f = fan.fwt.Event.make();
  506. f.id(id);
  507. f.widget(self);
  508. f.data(data);
  509. f.key(modifiers);
  510. return f;
  511. }
  512. //////////////////////////////////////////////////////////////////////////
  513. // Fields
  514. //////////////////////////////////////////////////////////////////////////
  515. public fan.fwt.Widget self;
  516. Widget control;
  517. Key modifiers;
  518. boolean activeKeyListener = false;
  519. boolean activeFocusListener = false;
  520. }