2019-08-23 11:56:54 -07:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using Beefy.gfx;
|
|
|
|
|
using Beefy.events;
|
|
|
|
|
using Beefy.sys;
|
|
|
|
|
using Beefy.geom;
|
|
|
|
|
|
|
|
|
|
namespace Beefy.widgets
|
|
|
|
|
{
|
|
|
|
|
public delegate void MouseLeftWindowHandler(BFWindow window);
|
|
|
|
|
public delegate void WindowLostFocusHandler(BFWindow window, BFWindow newFocus);
|
|
|
|
|
public delegate bool WindowCloseQueryHandler(BFWindow window);
|
|
|
|
|
public delegate void WindowClosedHandler(BFWindow window);
|
|
|
|
|
public delegate void WindowMovedHandler(BFWindow window);
|
|
|
|
|
public delegate void MouseWheelHandler(MouseEvent mouseEvent);
|
|
|
|
|
public delegate void KeyDownHandler(KeyDownEvent keyboardEvent);
|
|
|
|
|
//public delegate void CloseTemporaryHandler(WidgetWindow window);
|
|
|
|
|
|
|
|
|
|
public class WidgetWindow : BFWindow
|
|
|
|
|
{
|
|
|
|
|
public Event<MouseLeftWindowHandler> mOnMouseLeftWindow ~ _.Dispose();
|
|
|
|
|
public Event<WindowLostFocusHandler> mOnWindowLostFocus ~ _.Dispose();
|
|
|
|
|
public Event<MouseEventHandler> mOnMouseDown ~ _.Dispose();
|
|
|
|
|
public Event<WindowCloseQueryHandler> mOnWindowCloseQuery ~ _.Dispose();
|
|
|
|
|
public Event<WindowClosedHandler> mOnWindowClosed ~ _.Dispose();
|
|
|
|
|
public Event<WindowMovedHandler> mOnWindowMoved ~ _.Dispose();
|
|
|
|
|
public Event<MouseWheelHandler> mOnMouseWheel ~ _.Dispose();
|
|
|
|
|
public Event<MenuItemSelectedHandler> mOnMenuItemSelected ~ _.Dispose();
|
|
|
|
|
public Event<KeyDownHandler> mOnWindowKeyDown ~ _.Dispose();
|
|
|
|
|
public Event<Func<int32, int32, HitTestResult>> mOnHitTest ~ _.Dispose();
|
|
|
|
|
|
|
|
|
|
public static Event<MouseLeftWindowHandler> sOnMouseLeftWindow ~ _.Dispose();
|
|
|
|
|
public static Event<WindowLostFocusHandler> sOnWindowLostFocus ~ _.Dispose();
|
|
|
|
|
public static Event<MouseEventHandler> sOnMouseDown ~ _.Dispose();
|
|
|
|
|
public static Event<WindowClosedHandler> sOnWindowClosed ~ _.Dispose();
|
|
|
|
|
public static Event<WindowMovedHandler> sOnWindowMoved ~ _.Dispose();
|
|
|
|
|
public static Event<MouseWheelHandler> sOnMouseWheel ~ _.Dispose();
|
|
|
|
|
public static Event<MenuItemSelectedHandler> sOnMenuItemSelected ~ _.Dispose();
|
|
|
|
|
public static Event<KeyDownHandler> sOnKeyDown ~ _.Dispose();
|
|
|
|
|
//public Event<CloseTemporaryHandler> sOnCloseTemporaries ~ _.Dispose();
|
|
|
|
|
|
|
|
|
|
public bool mIsMainWindow;
|
|
|
|
|
|
|
|
|
|
public MouseFlag mMouseFlags;
|
|
|
|
|
public Widget mRootWidget;
|
|
|
|
|
public Widget mCaptureWidget;
|
|
|
|
|
public Widget mOverWidget;
|
|
|
|
|
public Widget mFocusWidget;
|
|
|
|
|
public int32 mClientMouseX;
|
|
|
|
|
public int32 mClientMouseY;
|
|
|
|
|
public float mMouseX;
|
|
|
|
|
public float mMouseY;
|
|
|
|
|
public bool mIsMouseMoving;
|
|
|
|
|
public bool mHasMouseInside;
|
|
|
|
|
public bool mHasProxyMouseInside;
|
|
|
|
|
public bool mIsKeyDownHandled;
|
|
|
|
|
|
|
|
|
|
public int32 mContentClientWidth;
|
|
|
|
|
public int32 mContentClientHeight;
|
|
|
|
|
|
|
|
|
|
public static WidgetWindow sMouseInsideWindow;
|
|
|
|
|
public static int32 sLastClosedTick = -1;
|
|
|
|
|
|
|
|
|
|
public Matrix mScaleMatrix = Matrix.IdentityMatrix;
|
|
|
|
|
public Matrix mInvScaleMatrix = Matrix.IdentityMatrix;
|
|
|
|
|
|
|
|
|
|
public bool[] mIsKeyDown = new bool[(int32)KeyCode.COUNT] ~ delete _;
|
|
|
|
|
|
|
|
|
|
public this(BFWindow parent, String title, int x, int y, int width, int height, BFWindow.Flags windowFlags, Widget rootWidget) :
|
|
|
|
|
//TODO: Do BFWindow init outside constructor.. see where it be hanging
|
|
|
|
|
base(parent, title, x, y, width, height, windowFlags)
|
|
|
|
|
{
|
|
|
|
|
if (mWindowFlags.HasFlag(Flags.ClientSized))
|
|
|
|
|
{
|
|
|
|
|
mContentClientWidth = (int32)width;
|
|
|
|
|
mContentClientHeight = (int32)height;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!mWindowFlags.HasFlag(BFWindowBase.Flags.NoActivate))
|
|
|
|
|
GotFocus();
|
|
|
|
|
|
|
|
|
|
SetRootWidget(rootWidget);
|
|
|
|
|
|
|
|
|
|
//Debug.WriteLine("WidgetWindow.this {0} {1} {2}", this, mTitle, mRootWidget);
|
|
|
|
|
|
|
|
|
|
//Debug.WriteLine("WidgetWindow this");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ~this()
|
|
|
|
|
{
|
|
|
|
|
if (sMouseInsideWindow == this)
|
|
|
|
|
sMouseInsideWindow = null;
|
|
|
|
|
delete mRootWidget;
|
|
|
|
|
|
|
|
|
|
//Debug.WriteLine("WidgetWindow ~this");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetRootWidget(Widget rootWidget)
|
|
|
|
|
{
|
|
|
|
|
if (mRootWidget != null)
|
|
|
|
|
mRootWidget.[Friend]RemovedFromWindow();
|
|
|
|
|
|
|
|
|
|
mRootWidget = rootWidget;
|
|
|
|
|
if (mRootWidget != null)
|
|
|
|
|
{
|
|
|
|
|
mRootWidget.mWidgetWindow = this;
|
|
|
|
|
mRootWidget.InitChildren();
|
|
|
|
|
mRootWidget.AddedToParent();
|
2019-12-21 05:48:44 -08:00
|
|
|
|
RehupSize();
|
2019-08-23 11:56:54 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public KeyFlags GetKeyFlags()
|
|
|
|
|
{
|
|
|
|
|
KeyFlags keyFlags = default;
|
|
|
|
|
if (IsKeyDown(KeyCode.Shift))
|
|
|
|
|
keyFlags |= KeyFlags.Shift;
|
|
|
|
|
if (IsKeyDown(KeyCode.Control))
|
|
|
|
|
keyFlags |= KeyFlags.Ctrl;
|
|
|
|
|
if (IsKeyDown(KeyCode.Menu))
|
|
|
|
|
keyFlags |= KeyFlags.Alt;
|
|
|
|
|
return keyFlags;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool IsKeyDown(KeyCode keyCode)
|
|
|
|
|
{
|
|
|
|
|
return mIsKeyDown[(int32)keyCode];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Draw(Graphics g)
|
|
|
|
|
{
|
|
|
|
|
if (mRootWidget == null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
base.Draw(g);
|
|
|
|
|
mRootWidget.DrawAll(g);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Update()
|
|
|
|
|
{
|
|
|
|
|
if (mOverWidget != null)
|
|
|
|
|
Debug.Assert(mHasMouseInside);
|
|
|
|
|
|
|
|
|
|
if (mRootWidget == null)
|
|
|
|
|
return;
|
|
|
|
|
base.Update();
|
|
|
|
|
RehupMouse(false);
|
|
|
|
|
mRootWidget.UpdateAll();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override int32 CloseQuery()
|
|
|
|
|
{
|
|
|
|
|
bool hadFalse = false;
|
|
|
|
|
for (var handler in mOnWindowCloseQuery)
|
|
|
|
|
{
|
|
|
|
|
if (!handler(this))
|
|
|
|
|
{
|
|
|
|
|
hadFalse = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (hadFalse)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
return base.CloseQuery();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void Closed()
|
|
|
|
|
{
|
|
|
|
|
sLastClosedTick = BFApp.sApp.mUpdateCnt;
|
|
|
|
|
|
|
|
|
|
if (!mHasClosed)
|
|
|
|
|
{
|
|
|
|
|
//Debug.WriteLine("WidgetWindow.Closed {0} {1} {2}", this, mTitle, mRootWidget);
|
|
|
|
|
|
|
|
|
|
if (mRootWidget != null)
|
|
|
|
|
{
|
|
|
|
|
mRootWidget.[Friend]RemovedFromWindow();
|
|
|
|
|
mRootWidget.RemovedFromParent(null, this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Debug.WriteLine("Window closing: {0}", this);
|
|
|
|
|
mOnWindowClosed(this);
|
|
|
|
|
sOnWindowClosed(this);
|
|
|
|
|
base.Closed();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void PreDraw(Graphics g)
|
|
|
|
|
{
|
|
|
|
|
base.PreDraw(g);
|
|
|
|
|
|
2019-12-21 05:48:44 -08:00
|
|
|
|
g.mMatrix.Set(mScaleMatrix);
|
|
|
|
|
g.mMatrixStack[g.mMatrixStackIdx] = g.mMatrix;
|
2019-08-23 11:56:54 -07:00
|
|
|
|
}
|
|
|
|
|
|
2019-12-21 05:48:44 -08:00
|
|
|
|
public override void RehupSize()
|
|
|
|
|
{
|
|
|
|
|
base.RehupSize();
|
|
|
|
|
|
|
|
|
|
if (mWindowFlags.HasFlag(Flags.ScaleContent))
|
|
|
|
|
{
|
|
|
|
|
float scaleX = mClientWidth / (float)mContentClientWidth;
|
|
|
|
|
float scaleY = mClientHeight / (float)mContentClientHeight;
|
|
|
|
|
|
|
|
|
|
if (scaleX > scaleY)
|
|
|
|
|
{
|
|
|
|
|
float scale = scaleY;
|
|
|
|
|
mScaleMatrix.a = scale;
|
|
|
|
|
mScaleMatrix.b = 0;
|
|
|
|
|
mScaleMatrix.c = 0;
|
|
|
|
|
mScaleMatrix.d = scale;
|
|
|
|
|
mScaleMatrix.tx = (int32)(mClientWidth - (scale * mContentClientWidth)) / 2;
|
|
|
|
|
mScaleMatrix.ty = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
float scale = scaleX;
|
|
|
|
|
mScaleMatrix.a = scale;
|
|
|
|
|
mScaleMatrix.b = 0;
|
|
|
|
|
mScaleMatrix.c = 0;
|
|
|
|
|
mScaleMatrix.d = scale;
|
|
|
|
|
mScaleMatrix.tx = 0;
|
|
|
|
|
mScaleMatrix.ty = (int32)(mClientHeight - (scale * mContentClientHeight)) / 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mInvScaleMatrix.Set(mScaleMatrix);
|
|
|
|
|
mInvScaleMatrix.Invert();
|
|
|
|
|
mRootWidget.Resize(0, 0, mContentClientWidth, mContentClientHeight);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
mInvScaleMatrix = Matrix.IdentityMatrix;
|
|
|
|
|
mScaleMatrix = Matrix.IdentityMatrix;
|
|
|
|
|
mContentClientWidth = mClientWidth;
|
|
|
|
|
mContentClientHeight = mClientHeight;
|
|
|
|
|
mRootWidget.Resize(0, 0, mClientWidth, mClientHeight);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-23 11:56:54 -07:00
|
|
|
|
public override void Moved()
|
|
|
|
|
{
|
|
|
|
|
base.Moved();
|
|
|
|
|
|
|
|
|
|
mOnWindowMoved(this);
|
|
|
|
|
sOnWindowMoved(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetFocus(Widget widget)
|
|
|
|
|
{
|
|
|
|
|
/*if (widget != null)
|
|
|
|
|
Debug.WriteLine("SetFocus: {0} {1}", widget.GetType(), widget.mWidgetWindow.mTitle);*/
|
|
|
|
|
|
|
|
|
|
if (mFocusWidget == widget)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
Widget oldFocusWidget = mFocusWidget;
|
|
|
|
|
mFocusWidget = null;
|
|
|
|
|
if (oldFocusWidget != null)
|
|
|
|
|
{
|
|
|
|
|
Debug.Assert(oldFocusWidget.mWidgetWindow == this);
|
|
|
|
|
if (oldFocusWidget.mHasFocus)
|
|
|
|
|
oldFocusWidget.LostFocus();
|
|
|
|
|
else
|
|
|
|
|
Debug.Assert(!mHasFocus);
|
|
|
|
|
}
|
|
|
|
|
if (mFocusWidget != null)
|
|
|
|
|
return; // Already got a new focus after LostFocus callbacks
|
|
|
|
|
mFocusWidget = widget;
|
|
|
|
|
if ((mFocusWidget != null) && (mHasFocus))
|
|
|
|
|
mFocusWidget.GotFocus();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void GotFocus()
|
|
|
|
|
{
|
|
|
|
|
if (mHasFocus)
|
|
|
|
|
return;
|
|
|
|
|
mIsDirty = true;
|
|
|
|
|
|
|
|
|
|
//Debug.WriteLine("GotFocus {0}", mIsMainWindow);
|
|
|
|
|
|
|
|
|
|
for (var window in sWindowDictionary.Values)
|
|
|
|
|
{
|
|
|
|
|
// Don't let more than one window think it has the focus
|
|
|
|
|
var widgetWindow = window as WidgetWindow;
|
|
|
|
|
if ((widgetWindow != null) && (widgetWindow != this) && (widgetWindow.mHasFocus))
|
|
|
|
|
{
|
|
|
|
|
widgetWindow.LostFocus(this);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Debug.WriteLine("GotFocus {0} {1}", mTitle, mIsMainWindow);
|
|
|
|
|
base.GotFocus();
|
|
|
|
|
|
|
|
|
|
if (mFocusWidget != null)
|
|
|
|
|
{
|
|
|
|
|
//Debug.Assert(!mFocusWidget.mHasFocus);
|
|
|
|
|
if (!mFocusWidget.mHasFocus)
|
|
|
|
|
mFocusWidget.GotFocus();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void LostFocus(BFWindow newFocus)
|
|
|
|
|
{
|
|
|
|
|
//Debug.WriteLine("LostFocus {0}", mIsMainWindow);
|
|
|
|
|
|
|
|
|
|
if (!mHasFocus)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mIsDirty = true;
|
|
|
|
|
for (int32 i = 0; i < (int32)mIsKeyDown.Count; i++)
|
|
|
|
|
if (mIsKeyDown[i])
|
|
|
|
|
KeyUp(i);
|
|
|
|
|
|
|
|
|
|
// We could have a mousedown in one window while another window has focus still<6C><6C><EFBFBD>
|
|
|
|
|
// So this check isn't valid.
|
|
|
|
|
/*for (int btnIdx = 0; btnIdx < 3; btnIdx++)
|
|
|
|
|
{
|
|
|
|
|
if (((int)mMouseFlags & (1 << btnIdx)) != 0)
|
|
|
|
|
{
|
|
|
|
|
MouseUp(mClientMouseX, mClientMouseY, btnIdx);
|
|
|
|
|
}
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
base.LostFocus(newFocus);
|
|
|
|
|
|
|
|
|
|
if (mCaptureWidget != null)
|
|
|
|
|
mCaptureWidget = null;
|
|
|
|
|
if (mFocusWidget != null)
|
|
|
|
|
{
|
|
|
|
|
Debug.Assert(mFocusWidget.mWidgetWindow == this);
|
|
|
|
|
var prevFocus = mFocusWidget;
|
|
|
|
|
prevFocus.LostFocus();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mOnWindowLostFocus(this, newFocus);
|
|
|
|
|
sOnWindowLostFocus(this, newFocus);
|
|
|
|
|
|
|
|
|
|
//Debug.Assert(!mHasFocus);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void KeyChar(char32 c)
|
|
|
|
|
{
|
|
|
|
|
var fakeFocusWindow = GetFakeFocusWindow();
|
|
|
|
|
if (fakeFocusWindow != null)
|
|
|
|
|
{
|
|
|
|
|
fakeFocusWindow.KeyChar(c);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mIsDirty = true;
|
|
|
|
|
|
|
|
|
|
if ((mHasFocus) && (mFocusWidget != null) && (!mIsKeyDownHandled))
|
|
|
|
|
{
|
|
|
|
|
let keyEvent = scope KeyCharEvent();
|
|
|
|
|
keyEvent.mChar = c;
|
|
|
|
|
keyEvent.mSender = mFocusWidget;
|
|
|
|
|
mFocusWidget.KeyChar(keyEvent);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BFWindow GetFakeFocusWindow()
|
|
|
|
|
{
|
|
|
|
|
/*for (int windowIdx = BFApp.sApp.mWindows.Count - 1; windowIdx >= 0; windowIdx--)
|
|
|
|
|
{
|
|
|
|
|
var checkWindow = BFApp.sApp.mWindows[windowIdx];
|
|
|
|
|
if (checkWindow == this)
|
|
|
|
|
return null;
|
|
|
|
|
if ((checkWindow.mWindowFlags.HasFlag(.FakeFocus)) && (checkWindow.mHasFocus))
|
|
|
|
|
return checkWindow;
|
|
|
|
|
}*/
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override bool KeyDown(int32 keyCode, int32 isRepeat)
|
|
|
|
|
{
|
|
|
|
|
var fakeFocusWindow = GetFakeFocusWindow();
|
|
|
|
|
if (fakeFocusWindow != null)
|
|
|
|
|
return fakeFocusWindow.KeyDown(keyCode, isRepeat);
|
|
|
|
|
|
|
|
|
|
mIsDirty = true;
|
|
|
|
|
|
|
|
|
|
mIsKeyDownHandled = false;
|
|
|
|
|
if (keyCode < mIsKeyDown.Count)
|
|
|
|
|
mIsKeyDown[keyCode] = true;
|
|
|
|
|
|
|
|
|
|
KeyDownEvent e = scope KeyDownEvent();
|
|
|
|
|
e.mSender = this;
|
|
|
|
|
e.mKeyFlags = GetKeyFlags();
|
|
|
|
|
e.mKeyCode = (KeyCode)keyCode;
|
|
|
|
|
e.mIsRepeat = isRepeat != 0;
|
|
|
|
|
|
|
|
|
|
if ((sOnKeyDown.HasListeners) || (mOnWindowKeyDown.HasListeners))
|
|
|
|
|
{
|
|
|
|
|
if (sOnKeyDown.HasListeners)
|
|
|
|
|
sOnKeyDown(e);
|
|
|
|
|
if (mOnWindowKeyDown.HasListeners)
|
|
|
|
|
mOnWindowKeyDown(e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((mFocusWidget != null) && (!e.mHandled))
|
|
|
|
|
{
|
|
|
|
|
e.mSender = mFocusWidget;
|
|
|
|
|
mFocusWidget.KeyDown(e);
|
|
|
|
|
}
|
|
|
|
|
if (e.mHandled)
|
|
|
|
|
mIsKeyDownHandled = true;
|
|
|
|
|
|
|
|
|
|
return e.mHandled;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void KeyUp(int32 keyCode)
|
|
|
|
|
{
|
|
|
|
|
mIsDirty = true;
|
|
|
|
|
|
|
|
|
|
if (keyCode < mIsKeyDown.Count)
|
|
|
|
|
mIsKeyDown[keyCode] = false;
|
|
|
|
|
|
|
|
|
|
if (mFocusWidget != null)
|
|
|
|
|
mFocusWidget.KeyUp((KeyCode)keyCode);
|
|
|
|
|
|
|
|
|
|
var fakeFocusWindow = GetFakeFocusWindow();
|
|
|
|
|
if (fakeFocusWindow != null)
|
|
|
|
|
fakeFocusWindow.KeyUp(keyCode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override HitTestResult HitTest(int32 x, int32 y)
|
|
|
|
|
{
|
|
|
|
|
if (mOnHitTest.HasListeners)
|
|
|
|
|
{
|
|
|
|
|
var result = mOnHitTest(x, y);
|
|
|
|
|
if (result != HitTestResult.NotHandled)
|
2019-09-02 17:39:47 -07:00
|
|
|
|
{
|
2019-09-10 11:25:53 -07:00
|
|
|
|
if ((result == .Transparent) || (result == .Caption))
|
2019-09-02 17:39:47 -07:00
|
|
|
|
{
|
|
|
|
|
if (mHasMouseInside)
|
|
|
|
|
MouseLeave();
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-23 11:56:54 -07:00
|
|
|
|
return result;
|
2019-09-02 17:39:47 -07:00
|
|
|
|
}
|
2019-08-23 11:56:54 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mWindowFlags.HasFlag(Flags.Resizable))
|
|
|
|
|
{
|
|
|
|
|
if ((x - mX > mWindowWidth - 24) && (y - mY > mWindowHeight - 24))
|
|
|
|
|
return HitTestResult.BottomRight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return HitTestResult.NotHandled;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void RehupMouse(bool force)
|
|
|
|
|
{
|
|
|
|
|
if (!mHasMouseInside)
|
|
|
|
|
return;
|
|
|
|
|
|
2019-09-02 17:39:47 -07:00
|
|
|
|
Widget aWidget = mRootWidget.FindWidgetByCoords(mMouseX, mMouseY);
|
2019-08-23 11:56:54 -07:00
|
|
|
|
if (mCaptureWidget != null)
|
|
|
|
|
{
|
|
|
|
|
bool didSomething = false;
|
|
|
|
|
|
|
|
|
|
if (mCaptureWidget == aWidget)
|
|
|
|
|
{
|
|
|
|
|
if (!mCaptureWidget.mMouseOver)
|
|
|
|
|
{
|
|
|
|
|
mCaptureWidget.MouseEnter();
|
|
|
|
|
didSomething = true;
|
|
|
|
|
}
|
|
|
|
|
mOverWidget = aWidget;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (mCaptureWidget.mMouseOver)
|
|
|
|
|
{
|
|
|
|
|
mCaptureWidget.MouseLeave();
|
|
|
|
|
didSomething = true;
|
|
|
|
|
}
|
|
|
|
|
mOverWidget = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((didSomething) || (force))
|
|
|
|
|
{
|
|
|
|
|
float childX;
|
|
|
|
|
float childY;
|
|
|
|
|
mCaptureWidget.RootToSelfTranslate(mMouseX, mMouseY, out childX, out childY);
|
|
|
|
|
mCaptureWidget.MouseMove(childX, childY);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (mOverWidget != aWidget)
|
|
|
|
|
{
|
|
|
|
|
if (mOverWidget != null)
|
|
|
|
|
{
|
|
|
|
|
mOverWidget.MouseLeave();
|
|
|
|
|
if (!IsMouseCaptured())
|
|
|
|
|
{
|
|
|
|
|
// Clear out mousedowns if we don't have capture anymore
|
|
|
|
|
for (int32 btn < 4)
|
|
|
|
|
{
|
|
|
|
|
let checkFlag = (MouseFlag)(1 << btn);
|
|
|
|
|
if (mMouseFlags.HasFlag(checkFlag))
|
|
|
|
|
{
|
|
|
|
|
mMouseFlags &= ~checkFlag;
|
|
|
|
|
float childX;
|
|
|
|
|
float childY;
|
|
|
|
|
mOverWidget.RootToSelfTranslate(mMouseX, mMouseY, out childX, out childY);
|
|
|
|
|
mOverWidget.MouseUp(childX, childY, btn);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mOverWidget = aWidget;
|
|
|
|
|
if (aWidget != null)
|
|
|
|
|
{
|
|
|
|
|
aWidget.MouseEnter();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Debug.WriteLine("Set OverWidget {0} in {1}", mOverWidget, this);
|
|
|
|
|
}
|
|
|
|
|
else if (!force)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (aWidget != null)
|
|
|
|
|
{
|
|
|
|
|
float childX;
|
|
|
|
|
float childY;
|
|
|
|
|
aWidget.RootToSelfTranslate(mMouseX, mMouseY, out childX, out childY);
|
|
|
|
|
aWidget.MouseMove(childX, childY);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CheckOtherMouseCaptures()
|
|
|
|
|
{
|
|
|
|
|
if (mCaptureWidget == null)
|
|
|
|
|
{
|
|
|
|
|
/*foreach (WidgetWindow window in sWindowDictionary.Values)
|
|
|
|
|
{
|
|
|
|
|
if (window.mCaptureWidget != null)
|
|
|
|
|
{
|
|
|
|
|
//int a = 0;
|
|
|
|
|
}
|
|
|
|
|
}*/
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SetMouseInside()
|
|
|
|
|
{
|
|
|
|
|
if (sMouseInsideWindow == this)
|
|
|
|
|
{
|
|
|
|
|
//Debug.WriteLine("Mouse already inside");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Debug.WriteLine("SetMouseInside 1 {0} prev={1}", this, sMouseInsideWindow);
|
|
|
|
|
var prevMouseInsideWindow = sMouseInsideWindow;
|
|
|
|
|
sMouseInsideWindow = null;
|
|
|
|
|
if (prevMouseInsideWindow != null)
|
|
|
|
|
prevMouseInsideWindow.MouseLeave();
|
|
|
|
|
if (sMouseInsideWindow != null)
|
|
|
|
|
{
|
|
|
|
|
//Debug.WriteLine("SetMouseInside {0} aborted", this);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
sMouseInsideWindow = this;
|
|
|
|
|
mHasMouseInside = true;
|
|
|
|
|
|
|
|
|
|
//Debug.WriteLine("SetMouseInside 2 {0}", this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void MouseMove(int32 inX, int32 inY)
|
|
|
|
|
{
|
|
|
|
|
//Debug.WriteLine("MouseMove {0} {1},{2}", this, inX, inY);
|
|
|
|
|
|
|
|
|
|
mClientMouseX = inX;
|
|
|
|
|
mClientMouseY = inY;
|
|
|
|
|
|
|
|
|
|
float x;
|
|
|
|
|
float y;
|
|
|
|
|
TranslateMouseCoords(inX, inY, out x, out y);
|
|
|
|
|
|
|
|
|
|
SetMouseInside();
|
|
|
|
|
CheckOtherMouseCaptures();
|
|
|
|
|
|
|
|
|
|
if ((mMouseX == x) && (mMouseY == y))
|
|
|
|
|
{
|
|
|
|
|
RehupMouse(false);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mIsMouseMoving = true;
|
|
|
|
|
mMouseX = x;
|
|
|
|
|
mMouseY = y;
|
|
|
|
|
RehupMouse(true);
|
|
|
|
|
mIsMouseMoving = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void MouseProxyMove(int32 x, int32 y)
|
|
|
|
|
{
|
|
|
|
|
// This is just from dragging from another so we don't acknowledge the moves directly
|
|
|
|
|
//SetMouseInside();
|
|
|
|
|
mHasProxyMouseInside = true;
|
|
|
|
|
mMouseX = x;
|
|
|
|
|
mMouseY = y;
|
|
|
|
|
|
|
|
|
|
CheckOtherMouseCaptures();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TranslateMouseCoords(int32 x, int32 y, out float outX, out float outY)
|
|
|
|
|
{
|
|
|
|
|
var pt = mInvScaleMatrix.Multiply(Point(x, y));
|
|
|
|
|
outX = pt.x;
|
|
|
|
|
outY = pt.y;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void MouseDown(int32 inX, int32 inY, int32 btn, int32 btnCount)
|
|
|
|
|
{
|
|
|
|
|
mMouseFlags |= (MouseFlag)(1 << btn);
|
|
|
|
|
if ((!mHasFocus) && (mParent == null))
|
|
|
|
|
{
|
|
|
|
|
//INVESTIGATE: This shouldn't be required normally
|
|
|
|
|
// Fixes some focus issues while debugging?
|
|
|
|
|
GotFocus();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float x;
|
|
|
|
|
float y;
|
|
|
|
|
TranslateMouseCoords(inX, inY, out x, out y);
|
|
|
|
|
|
|
|
|
|
MouseMove(inX, inY);
|
|
|
|
|
|
|
|
|
|
if ((mOnMouseDown.HasListeners) || (sOnMouseDown.HasListeners))
|
|
|
|
|
{
|
|
|
|
|
MouseEvent anEvent = scope MouseEvent();
|
|
|
|
|
anEvent.mSender = this;
|
|
|
|
|
anEvent.mX = x;
|
|
|
|
|
anEvent.mY = y;
|
|
|
|
|
mOnMouseDown(anEvent);
|
|
|
|
|
sOnMouseDown(anEvent);
|
|
|
|
|
if (anEvent.mHandled)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Widget aWidget = mCaptureWidget ?? mOverWidget;
|
|
|
|
|
if (aWidget != null)
|
|
|
|
|
{
|
|
|
|
|
Debug.Assert(aWidget.mWidgetWindow == this);
|
|
|
|
|
float childX;
|
|
|
|
|
float childY;
|
|
|
|
|
aWidget.RootToSelfTranslate(mMouseX, mMouseY, out childX, out childY);
|
|
|
|
|
aWidget.MouseDown(childX, childY, btn, btnCount);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void MouseUp(int32 inX, int32 inY, int32 btn)
|
|
|
|
|
{
|
|
|
|
|
//Debug.WriteLine("MouseUp {0} {1} {2}", mIsMainWindow, this, mMouseFlags);
|
|
|
|
|
|
|
|
|
|
if (((int32)mMouseFlags & (1 << btn)) == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
MouseMove(inX, inY);
|
|
|
|
|
mMouseFlags &= (MouseFlag)(~(1 << btn));
|
|
|
|
|
Widget aWidget = mCaptureWidget ?? mOverWidget;
|
|
|
|
|
if (aWidget != null)
|
|
|
|
|
{
|
|
|
|
|
float childX;
|
|
|
|
|
float childY;
|
|
|
|
|
aWidget.RootToSelfTranslate(mMouseX, mMouseY, out childX, out childY);
|
|
|
|
|
aWidget.MouseUp(childX, childY, btn);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void MouseWheel(int32 inX, int32 inY, int32 delta)
|
|
|
|
|
{
|
|
|
|
|
float x;
|
|
|
|
|
float y;
|
|
|
|
|
TranslateMouseCoords(inX, inY, out x, out y);
|
|
|
|
|
|
|
|
|
|
MouseMove(inX, inY);
|
|
|
|
|
|
|
|
|
|
if (sOnMouseWheel.HasListeners)
|
|
|
|
|
{
|
|
|
|
|
MouseEvent anEvent = scope MouseEvent();
|
|
|
|
|
anEvent.mX = x;
|
|
|
|
|
anEvent.mY = y;
|
|
|
|
|
anEvent.mWheelDelta = delta;
|
|
|
|
|
anEvent.mSender = this;
|
|
|
|
|
sOnMouseWheel(anEvent);
|
|
|
|
|
|
|
|
|
|
if (anEvent.mHandled)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mOnMouseWheel.HasListeners)
|
|
|
|
|
{
|
|
|
|
|
MouseEvent anEvent = scope MouseEvent();
|
|
|
|
|
anEvent.mX = x;
|
|
|
|
|
anEvent.mY = y;
|
|
|
|
|
anEvent.mWheelDelta = delta;
|
|
|
|
|
anEvent.mSender = this;
|
|
|
|
|
mOnMouseWheel(anEvent);
|
|
|
|
|
|
|
|
|
|
if (anEvent.mHandled)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Widget aWidget = mOverWidget;
|
|
|
|
|
if (aWidget != null)
|
|
|
|
|
{
|
|
|
|
|
float childX;
|
|
|
|
|
float childY;
|
|
|
|
|
aWidget.RootToSelfTranslate(mMouseX, mMouseY, out childX, out childY);
|
|
|
|
|
aWidget.MouseWheel(childX, childY, delta);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void MouseLeave()
|
|
|
|
|
{
|
|
|
|
|
if (sMouseInsideWindow == this)
|
|
|
|
|
{
|
|
|
|
|
sMouseInsideWindow = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mHasProxyMouseInside = false;
|
|
|
|
|
mHasMouseInside = false;
|
|
|
|
|
if (mOverWidget != null)
|
|
|
|
|
{
|
|
|
|
|
mOverWidget.MouseLeave();
|
|
|
|
|
mOverWidget = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mOnMouseLeftWindow(this);
|
|
|
|
|
sOnMouseLeftWindow(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void MenuItemSelected(SysMenu sysMenu)
|
|
|
|
|
{
|
|
|
|
|
mOnMenuItemSelected(sysMenu);
|
|
|
|
|
sOnMenuItemSelected(sysMenu);
|
|
|
|
|
base.MenuItemSelected(sysMenu);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void TransferMouse(WidgetWindow newMouseWindow)
|
|
|
|
|
{
|
|
|
|
|
if (mWindowFlags.HasFlag(.FakeFocus))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (mMouseFlags == default)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
newMouseWindow.mMouseFlags = mMouseFlags;
|
|
|
|
|
newMouseWindow.CaptureMouse();
|
|
|
|
|
mMouseFlags = default;
|
|
|
|
|
}
|
2019-12-21 05:48:44 -08:00
|
|
|
|
|
|
|
|
|
public void SetContentSize(int width, int height)
|
|
|
|
|
{
|
|
|
|
|
mContentClientWidth = (.)width;
|
|
|
|
|
mContentClientHeight = (.)height;
|
|
|
|
|
RehupSize();
|
|
|
|
|
}
|
2019-08-23 11:56:54 -07:00
|
|
|
|
}
|
|
|
|
|
}
|