mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +02:00
772 lines
23 KiB
Beef
772 lines
23 KiB
Beef
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();
|
||
Moved(); // Rehup size
|
||
}
|
||
}
|
||
|
||
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);
|
||
|
||
g.mMatrix.Set(mScaleMatrix);
|
||
}
|
||
|
||
public override void Moved()
|
||
{
|
||
base.Moved();
|
||
|
||
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);
|
||
}
|
||
|
||
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)
|
||
{
|
||
if ((result == .Transparent) || (result == .Caption))
|
||
{
|
||
if (mHasMouseInside)
|
||
MouseLeave();
|
||
}
|
||
|
||
return result;
|
||
}
|
||
}
|
||
|
||
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;
|
||
|
||
Widget aWidget = mRootWidget.FindWidgetByCoords(mMouseX, mMouseY);
|
||
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 (mTitle == "Tooltip")
|
||
{
|
||
NOP!();
|
||
}
|
||
|
||
Debug.WriteLine("MouseLeave {0}", this);*/
|
||
|
||
// This line breaks the ability to drag a tab outside the window. Why did we have it?
|
||
/*if (sMouseInsideWindow == this)
|
||
return;*/
|
||
|
||
//Debug.WriteLine("MouseLeave {0}", this);
|
||
|
||
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;
|
||
}
|
||
}
|
||
}
|