/src/fwt/java/WidgetPeer.java
Java | 597 lines | 445 code | 77 blank | 75 comment | 87 complexity | f5e2d61fcc1968e48149f28df50a9083 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
- //
- // Copyright (c) 2008, Brian Frank and Andy Frank
- // Licensed under the Academic Free License version 3.0
- //
- // History:
- // 12 Jun 08 Brian Frank Creation
- //
- package fan.fwt;
- import java.lang.reflect.Field;
- import java.util.HashMap;
- import fan.sys.*;
- import fan.gfx.*;
- import fan.sys.List;
- import org.eclipse.swt.*;
- import org.eclipse.swt.graphics.Color;
- import org.eclipse.swt.graphics.Point;
- import org.eclipse.swt.graphics.Rectangle;
- import org.eclipse.swt.widgets.*;
- import org.eclipse.swt.widgets.Display;
- import org.eclipse.swt.widgets.Event;
- import org.eclipse.swt.widgets.Widget;
- import org.eclipse.swt.widgets.MenuItem;
- import org.eclipse.swt.custom.ScrolledComposite;
- import org.eclipse.swt.events.*;
- /**
- * Native methods for Widget
- */
- public class WidgetPeer
- implements KeyListener, FocusListener, Listener, DisposeListener
- {
- //////////////////////////////////////////////////////////////////////////
- // Constructor
- //////////////////////////////////////////////////////////////////////////
- public static WidgetPeer make(fan.fwt.Widget self)
- throws Exception
- {
- WidgetPeer peer = new WidgetPeer();
- peer.self = self;
- return peer;
- }
- //////////////////////////////////////////////////////////////////////////
- // Accessors
- //////////////////////////////////////////////////////////////////////////
- public fan.fwt.Widget parent()
- {
- return self.parent();
- }
- public Widget control()
- {
- return control;
- }
- public Widget parentControl()
- {
- fan.fwt.Widget p = self.parent();
- return p == null ? null : p.peer.control;
- }
- //////////////////////////////////////////////////////////////////////////
- // Fields
- //////////////////////////////////////////////////////////////////////////
- // Bool enabled := true
- public boolean enabled(fan.fwt.Widget self) { return enabled.get(); }
- public void enabled(fan.fwt.Widget self, boolean v)
- {
- if (enabled.get() == v) return;
- enabled.set(v);
- // propagate enabled down tree
- List kids = self.kids;
- for (int i=0; i<kids.sz(); ++i)
- {
- fan.fwt.Widget kid = (fan.fwt.Widget)kids.get(i);
- kid.enabled(v);
- }
- }
- public final Prop.BoolProp enabled = new Prop.BoolProp(this, true)
- {
- public boolean get(Widget w)
- {
- // pain in the ass due to SWT's class hierarchy
- if (control instanceof Control) return ((Control)control).getEnabled();
- if (control instanceof MenuItem) return ((MenuItem)control).getEnabled();
- if (control instanceof ToolItem) return ((ToolItem)control).getEnabled();
- return true;
- }
- public void set(Widget w, boolean v)
- {
- // pain in the ass due to SWT's class hierarchy
- if (control instanceof Control) ((Control)control).setEnabled(v);
- if (control instanceof MenuItem) ((MenuItem)control).setEnabled(v);
- if (control instanceof ToolItem) ((ToolItem)control).setEnabled(v);
- }
- };
- // Bool visible := true
- public boolean visible(fan.fwt.Widget self) { return visible.get(); }
- public void visible(fan.fwt.Widget self, boolean v) { visible.set(v); }
- public final Prop.BoolProp visible = new Prop.BoolProp(this, true)
- {
- public boolean get(Widget w)
- {
- return (w instanceof Control) ? ((Control)w).getVisible() : true;
- }
- public void set(Widget w, boolean v)
- {
- // shell always controls its own visibility via open/close
- if (w instanceof Control && !(w instanceof Shell))
- ((Control)w).setVisible(v);
- }
- };
- public Cursor cursor(fan.fwt.Widget self) { return cursor.get(); }
- public void cursor(fan.fwt.Widget self, Cursor v) { cursor.set(v); }
- public final Prop.CursorProp cursor = new Prop.CursorProp(this);
- // Size size
- public fan.gfx.Point pos(fan.fwt.Widget self) { return pos.get(); }
- public void pos(fan.fwt.Widget self, fan.gfx.Point v) { pos.set(v); onPosChange(); }
- public final Prop.PosProp pos = new Prop.PosProp(this);
- // Size size
- public Size size(fan.fwt.Widget self) { return size.get(); }
- public void size(fan.fwt.Widget self, Size v) { size.set(v); onSizeChange(); }
- public final Prop.SizeProp size = new Prop.SizeProp(this);
- void onPosChange() {}
- void onSizeChange() {}
- //////////////////////////////////////////////////////////////////////////
- // Layout
- //////////////////////////////////////////////////////////////////////////
- public Size prefSize(fan.fwt.Widget self, Hints hints)
- {
- if (!(control instanceof Control)) return Size.defVal;
- int w = (hints.w == null) ? SWT.DEFAULT : hints.w.intValue();
- int h = (hints.h == null) ? SWT.DEFAULT : hints.h.intValue();
- Point s = ((Control)control).computeSize(w, h, true);
- return size(s);
- }
- public fan.gfx.Point posOnWindow(fan.fwt.Widget self)
- {
- if (!(control instanceof Control)) return null;
- fan.fwt.Window window = self.window();
- if (window == null || !(window.peer.control instanceof Control)) return null;
- Control widgetControl = (Control)control;
- Control windowControl = (Control)window.peer.control;
- Point pt = Fwt.get().display.map(widgetControl, windowControl, 0, 0);
- return point(pt);
- }
- public fan.gfx.Point posOnDisplay(fan.fwt.Widget self)
- {
- if (!(control instanceof Control)) return null;
- Point pt = Fwt.get().display.map((Control)control, null, 0, 0);
- return point(pt);
- }
- public fan.fwt.Widget relayout(fan.fwt.Widget self)
- {
- if (control instanceof Composite) ((Composite)control).layout(true);
- //if (control instanceof Control) ((Control)control).redraw();
- return self;
- }
- public fan.fwt.Widget pack(fan.fwt.Widget self)
- {
- if (control instanceof Control)
- ((Control)control).pack();
- return self;
- }
- public void repaint(fan.fwt.Widget self, Rect r)
- {
- if (control instanceof Control)
- {
- Control c = (Control)control;
- if (r == null)
- c.redraw();
- else
- c.redraw((int)r.x, (int)r.y, (int)r.w, (int)r.h, true);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- // Focus Eventing
- //////////////////////////////////////////////////////////////////////////
- public boolean hasFocus(fan.fwt.Widget self)
- {
- if (control instanceof Control)
- return ((Control)control).isFocusControl();
- else
- return false;
- }
- public void focus(fan.fwt.Widget self)
- {
- if (control instanceof Control)
- ((Control)control).setFocus();
- }
- public void checkFocusListeners(fan.fwt.Widget self)
- {
- // if we don't have any onFocus listeners, then I
- // shouldn't be actively registered as a focus listener
- if (!(control instanceof Control)) return;
- boolean now = self.onFocus().isEmpty() && self.onBlur().isEmpty();
- if (now != activeFocusListener) return;
- if (activeFocusListener)
- {
- ((Control)control).removeFocusListener(this);
- activeFocusListener = false;
- }
- else
- {
- ((Control)control).addFocusListener(this);
- activeFocusListener = true;
- }
- }
- public void focusGained(FocusEvent se)
- {
- self.onFocus().fire(event(EventId.focus));
- }
- public void focusLost(FocusEvent se)
- {
- self.onBlur().fire(event(EventId.blur));
- }
- //////////////////////////////////////////////////////////////////////////
- // Key Eventing
- //////////////////////////////////////////////////////////////////////////
- public void checkKeyListeners(fan.fwt.Widget self)
- {
- // if we don't have any onKey listeners, then I
- // shouldn't be actively registered as a key listener
- if (!(control instanceof Control)) return;
- boolean now = self.onKeyDown().isEmpty() && self.onKeyUp().isEmpty();
- if (now != activeKeyListener) return;
- if (activeKeyListener)
- {
- ((Control)control).removeKeyListener(this);
- activeKeyListener = false;
- }
- else
- {
- ((Control)control).addKeyListener(this);
- activeKeyListener = true;
- }
- }
- public void keyPressed(KeyEvent se)
- {
- fireKeyEvent(self.onKeyDown(), EventId.keyDown, se);
- }
- public void keyReleased(KeyEvent se)
- {
- fireKeyEvent(self.onKeyUp(), EventId.keyUp, se);
- }
- void fireKeyEvent(EventListeners listeners, EventId id, KeyEvent se)
- {
- fan.fwt.Event fe = event(id);
- fe.keyChar = Long.valueOf(se.character);
- fe.key = toKey(se.keyCode, se.stateMask);
- listeners.fire(fe);
- if (fe.consumed) se.doit = false;
- }
- static Key toKey(int keyCode, int stateMask)
- {
- Key key = Key.fromMask(keyCode);
- if ((stateMask & SWT.SHIFT) != 0) key = key.plus(Key.shift);
- if ((stateMask & SWT.ALT) != 0) key = key.plus(Key.alt);
- if ((stateMask & SWT.CTRL) != 0) key = key.plus(Key.ctrl);
- if ((stateMask & SWT.COMMAND) != 0) key = key.plus(Key.command);
- return key;
- }
- //////////////////////////////////////////////////////////////////////////
- // Mouse Eventing
- //////////////////////////////////////////////////////////////////////////
- public void handleEvent(Event se)
- {
- switch(se.type)
- {
- case SWT.MouseDown: fireMouseEvent(self.onMouseDown(), EventId.mouseDown, se); break;
- case SWT.MouseUp: fireMouseEvent(self.onMouseUp(), EventId.mouseUp, se); break;
- case SWT.MouseMove: fireMouseEvent(self.onMouseMove(), EventId.mouseMove, se); break;
- case SWT.MouseEnter: fireMouseEvent(self.onMouseEnter(), EventId.mouseEnter, se); break;
- case SWT.MouseExit: fireMouseEvent(self.onMouseExit(), EventId.mouseExit, se); break;
- case SWT.MouseHover: fireMouseEvent(self.onMouseHover(), EventId.mouseHover, se); break;
- case SWT.MouseVerticalWheel:
- fireMouseEvent(self.onMouseWheel(), EventId.mouseWheel, se, 0, point(0, -se.count));
- break;
- case SWT.MouseHorizontalWheel:
- fireMouseEvent(self.onMouseWheel(), EventId.mouseWheel, se, 0, point(-se.count, 0));
- break;
- default: System.out.println("WARNING: WidgetPeer.handleEvent: " + se);
- }
- }
- private void fireMouseEvent(EventListeners listeners, EventId id, Event se)
- {
- fireMouseEvent(listeners, id, se, se.count, null);
- }
- private void fireMouseEvent(EventListeners listeners, EventId id, Event se, int count, fan.gfx.Point delta)
- {
- // save modifiers on mouse events for future selection, action,
- // and popup events which might occur; this allows us to check
- // for Ctrl down to handle newTab style of eventing
- int mask = se.stateMask & SWT.MODIFIER_MASK;
- Key key = toKey(0, mask);
- modifiers = mask == 0 ? null : key;
- // fire event
- fan.fwt.Event fe = event(id);
- fe.pos = point(se.x, se.y);
- fe.count = Long.valueOf(count);
- fe.button = Long.valueOf(se.button);
- fe.delta = delta;
- fe.key = key;
- listeners.fire(fe);
- if (fe.consumed) se.doit = false;
- }
- //////////////////////////////////////////////////////////////////////////
- // Attachment
- //////////////////////////////////////////////////////////////////////////
- public final boolean attached(fan.fwt.Widget self)
- {
- return control != null;
- }
- public final void attach(fan.fwt.Widget self) { attach(self, null); }
- public final void attach(fan.fwt.Widget self, Widget parentControl)
- {
- // short circuit if I'm already attached
- if (control != null) return;
- // if parent wasn't explictly specified use my fwt parent
- fan.fwt.Widget parentWidget = null;
- if (parentControl == null)
- {
- // short circuit if my parent isn't attached
- parentWidget = self.parent();
- if (parentWidget == null || parentWidget.peer.control == null) return;
- parentControl = parentWidget.peer.control;
- }
- // create control and initialize
- // TODO: need to rework this cluster f**k
- if (parentControl instanceof TabItem)
- {
- TabItem item = (TabItem)parentControl;
- attachTo(create(item.getParent()));
- item.setControl((Control)this.control);
- }
- else
- {
- attachTo(create(parentControl));
- if (parentControl instanceof ScrolledComposite)
- ((ScrolledComposite)parentControl).setContent((Control)control);
- }
- // callback on parent
- if (parentWidget != null) parentWidget.peer.childAdded(self);
- }
- void childAdded(fan.fwt.Widget child) {}
- void attachTo(Widget control)
- {
- // sync with native control
- this.control = control;
- // reset focus/key eventing
- this.activeKeyListener = false;
- this.activeFocusListener = false;
- checkFocusListeners(self);
- checkKeyListeners(self);
- if (control instanceof Control)
- {
- Control c = (Control)control;
- c.addListener(SWT.MouseDown, this);
- c.addListener(SWT.MouseUp, this);
- c.addListener(SWT.MouseMove, this);
- c.addListener(SWT.MouseEnter, this);
- c.addListener(SWT.MouseExit, this);
- c.addListener(SWT.MouseHover, this);
- c.addListener(SWT.MouseVerticalWheel, this);
- c.addListener(SWT.MouseHorizontalWheel, this);
- }
- control.addDisposeListener(this);
- syncPropsToControl();
- // stick myself in data field
- control.setData(self);
- // recursively attach my children
- List kids = self.kids;
- for (int i=0; i<kids.sz(); ++i)
- {
- fan.fwt.Widget kid = (fan.fwt.Widget)kids.get(i);
- kid.peer.attach(kid);
- }
- }
- public Widget create(Widget parent)
- {
- throw new IllegalStateException(getClass().getName());
- }
- public void detach(fan.fwt.Widget self)
- {
- // dipose the control which automatically disposes all the
- // children; we do cleanup in the widgetDisposed callback.
- if (control != null) control.dispose();
- control = null;
- }
- public void widgetDisposed(DisposeEvent e)
- {
- syncPropsFromControl();
- control = null;
- }
- //////////////////////////////////////////////////////////////////////////
- // Widget/Control synchronization
- //////////////////////////////////////////////////////////////////////////
- public void syncPropsToControl() { syncProps(true); }
- public void syncPropsFromControl(){ syncProps(false); }
- private void syncProps(boolean to)
- {
- try
- {
- Field[] fields = getClass().getFields();
- for (int i=0; i<fields.length; ++i)
- {
- Field f = fields[i];
- try
- {
- if (Prop.class.isAssignableFrom(f.getType()))
- {
- Prop prop = (Prop)f.get(this);
- if (to)
- prop.syncToControl();
- else
- prop.syncFromControl();
- }
- }
- catch (Exception e)
- {
- System.out.println("ERROR: setting " + f);
- e.printStackTrace();
- }
- }
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- }
- //////////////////////////////////////////////////////////////////////////
- // Utils
- //////////////////////////////////////////////////////////////////////////
- static fan.fwt.Widget toFanWidget(Widget w)
- {
- if (w != null)
- {
- Object data = w.getData();
- if (data instanceof fan.fwt.Widget)
- return (fan.fwt.Widget)data;
- }
- return null;
- }
- static fan.gfx.Point point(int x, int y)
- {
- return fan.gfx.Point.make(x, y);
- }
- static fan.gfx.Point point(Point pt)
- {
- return fan.gfx.Point.make(pt.x, pt.y);
- }
- static fan.gfx.Point point(Rectangle r)
- {
- return fan.gfx.Point.make(r.x, r.y);
- }
- static Point point(fan.gfx.Point pt)
- {
- return new Point((int)pt.x, (int)pt.y);
- }
- static fan.gfx.Size size(int w, int h)
- {
- return fan.gfx.Size.make(w, h);
- }
- static fan.gfx.Size size(Point pt)
- {
- return fan.gfx.Size.make(pt.x, pt.y);
- }
- static fan.gfx.Size size(Rectangle r)
- {
- return fan.gfx.Size.make(r.width, r.height);
- }
- static fan.gfx.Rect rect(Rectangle r)
- {
- return fan.gfx.Rect.make(r.x, r.y, r.width, r.height);
- }
- static Rectangle rect(fan.gfx.Rect r)
- {
- return new Rectangle((int)r.x, (int)r.y, (int)r.w, (int)r.h);
- }
- static int style(Halign halign)
- {
- if (halign == Halign.left) return SWT.LEFT;
- if (halign == Halign.center) return SWT.CENTER;
- if (halign == Halign.right) return SWT.RIGHT;
- throw new IllegalStateException(halign.toString());
- }
- static int orientation(Orientation orientation)
- {
- if (orientation == Orientation.horizontal) return SWT.HORIZONTAL;
- if (orientation == Orientation.vertical) return SWT.VERTICAL;
- throw new IllegalStateException(orientation.toString());
- }
- static Orientation orientation(int style)
- {
- if ((style & SWT.HORIZONTAL) != 0) return Orientation.horizontal;
- if ((style & SWT.VERTICAL) != 0) return Orientation.vertical;
- throw new IllegalStateException(Integer.toHexString(style));
- }
- static int accelerator(Key key)
- {
- if (key == null) return 0;
- return (int)key.mask;
- }
- //////////////////////////////////////////////////////////////////////////
- // Event Utils
- //////////////////////////////////////////////////////////////////////////
- fan.fwt.Event event(EventId id) { return event(id, null); }
- fan.fwt.Event event(EventId id, Object data)
- {
- fan.fwt.Event f = fan.fwt.Event.make();
- f.id(id);
- f.widget(self);
- f.data(data);
- f.key(modifiers);
- return f;
- }
- //////////////////////////////////////////////////////////////////////////
- // Fields
- //////////////////////////////////////////////////////////////////////////
- public fan.fwt.Widget self;
- Widget control;
- Key modifiers;
- boolean activeKeyListener = false;
- boolean activeFocusListener = false;
- }