support standard mouse cursors

This commit is contained in:
Vadim Lopatin 2014-05-14 10:45:36 +04:00
parent 455e0ebd52
commit e16d1cacbc
4 changed files with 121 additions and 15 deletions

View File

@ -282,7 +282,7 @@ class Window {
return res;
}
protected bool dispatchMouseEvent(Widget root, MouseEvent event) {
protected bool dispatchMouseEvent(Widget root, MouseEvent event, ref bool cursorIsSet) {
// only route mouse events to visible widgets
if (root.visibility != Visibility.Visible)
return false;
@ -291,9 +291,16 @@ class Window {
// offer event to children first
for (int i = 0; i < root.childCount; i++) {
Widget child = root.child(i);
if (dispatchMouseEvent(child, event))
if (dispatchMouseEvent(child, event, cursorIsSet))
return true;
}
if (event.action == MouseAction.Move && !cursorIsSet) {
uint cursorType = root.getCursorType(event.x, event.y);
if (cursorType != CursorType.Parent) {
setCursorType(cursorType);
cursorIsSet = true;
}
}
// if not processed by children, offer event to root
if (sendAndCheckOverride(root, event)) {
debug(mouse) Log.d("MouseEvent is processed");
@ -445,6 +452,7 @@ class Window {
if (event.action == MouseAction.Move || event.action == MouseAction.Leave) {
processed = checkRemoveTracking(event);
}
bool cursorIsSet = false;
if (!res) {
bool insideOneOfPopups = false;
for (int i = cast(int)_popups.length - 1; i >= 0; i--) {
@ -458,11 +466,11 @@ class Window {
if (p.onMouseEventOutside(event)) // stop loop when true is returned, but allow other main widget to handle event
break;
} else {
if (dispatchMouseEvent(p, event))
if (dispatchMouseEvent(p, event, cursorIsSet))
return true;
}
}
res = dispatchMouseEvent(_mainWidget, event);
res = dispatchMouseEvent(_mainWidget, event, cursorIsSet);
}
return res || processed || _mainWidget.needDraw;
}
@ -485,6 +493,10 @@ class Window {
for (int i = 0; i < root.childCount; i++)
checkUpdateNeeded(root.child(i), needDraw, needLayout, animationActive);
}
/// sets cursor type for window
protected void setCursorType(uint cursorType) {
// override to support different mouse cursors
}
/// checks content widgets for necessary redraw and/or layout
bool checkUpdateNeeded(ref bool needDraw, ref bool needLayout, ref bool animationActive) {
needDraw = needLayout = animationActive = false;

View File

@ -144,6 +144,69 @@ version(USE_SDL) {
invalidate();
}
protected uint _lastCursorType = CursorType.None;
protected SDL_Cursor * [uint] _cursorMap;
/// sets cursor type for window
override protected void setCursorType(uint cursorType) {
// override to support different mouse cursors
if (_lastCursorType != cursorType) {
_lastCursorType = cursorType;
if (cursorType in _cursorMap) {
Log.d("changing cursor to ", cursorType);
SDL_SetCursor(_cursorMap[cursorType]);
return;
}
SDL_Cursor * cursor;
switch (cursorType) {
case CursorType.Arrow:
cursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
break;
case CursorType.IBeam:
cursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
break;
case CursorType.Wait:
cursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAIT);
break;
case CursorType.WaitArrow:
cursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAITARROW);
break;
case CursorType.Crosshair:
cursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_CROSSHAIR);
break;
case CursorType.No:
cursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO);
break;
case CursorType.Hand:
cursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);
break;
case CursorType.SizeNWSE:
cursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE);
break;
case CursorType.SizeNESW:
cursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW);
break;
case CursorType.SizeWE:
cursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
break;
case CursorType.SizeNS:
cursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);
break;
case CursorType.SizeAll:
cursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);
break;
default:
// TODO: support custom cursors
cursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
break;
}
if (cursor) {
Log.d("changing cursor to ", cursorType);
_cursorMap[cursorType] = cursor;
SDL_SetCursor(cursor);
}
}
}
SDL_Texture * _texture;
int _txw;
int _txh;
@ -191,12 +254,12 @@ version(USE_SDL) {
float r = ((_backgroundColor >> 16) & 255) / 255.0f;
float g = ((_backgroundColor >> 8) & 255) / 255.0f;
float b = ((_backgroundColor >> 0) & 255) / 255.0f;
glClearColor(r, g, b, a);
glClear(GL_COLOR_BUFFER_BIT);
GLDrawBuf buf = new GLDrawBuf(_dx, _dy, false);
buf.beforeDrawing();
glClearColor(r, g, b, a);
glClear(GL_COLOR_BUFFER_BIT);
GLDrawBuf buf = new GLDrawBuf(_dx, _dy, false);
buf.beforeDrawing();
onDraw(buf);
buf.afterDrawing();
buf.afterDrawing();
SDL_GL_SwapWindow(_win);
destroy(buf);
}
@ -872,7 +935,7 @@ version(USE_SDL) {
Log.e("Cannot load opengl library", e);
}
}
SDL_DisplayMode displayMode;
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_EVENTS) != 0) {
Log.e("Cannot init SDL2");
@ -880,13 +943,13 @@ version(USE_SDL) {
}
scope(exit)SDL_Quit();
int request = SDL_GetDesktopDisplayMode(0,&displayMode);
version(USE_OPENGL) {
// we want OpenGL 3.3
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION,3);
// we want OpenGL 3.3
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION,3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION,2);
// Set OpenGL attributes
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
// Set OpenGL attributes
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
}

View File

@ -936,6 +936,7 @@ class EditWidgetBase : WidgetGroup, EditableContentListener, MenuItemActionHandl
return super.isActionEnabled(action);
}
}
/// shows popup at (x,y)
override void showPopupMenu(int x, int y) {
/// if preparation signal handler assigned, call it; don't show popup if false is returned from handler
@ -960,6 +961,12 @@ class EditWidgetBase : WidgetGroup, EditableContentListener, MenuItemActionHandl
// TODO
}
/// returns mouse cursor type for widget
override uint getCursorType(int x, int y) {
return CursorType.IBeam;
}
/// when true, Tab / Shift+Tab presses are processed internally in widget (e.g. insert tab character) instead of focus change navigation.
@property bool wantTabs() {
return _wantTabs;

View File

@ -85,6 +85,25 @@ enum FocusMovement {
Right,
}
/// standard mouse cursor types
enum CursorType {
None,
/// use parent's cursor
Parent,
Arrow,
IBeam,
Wait,
Crosshair,
WaitArrow,
SizeNWSE,
SizeNESW,
SizeWE,
SizeNS,
SizeAll,
No,
Hand
}
class Widget {
/// widget id
protected string _id;
@ -121,6 +140,11 @@ class Widget {
/// set new trackHover flag value (when true, widget will change Hover state while mouse is moving)
@property Widget trackHover(bool v) { _trackHover = v; return this; }
/// returns mouse cursor type for widget
uint getCursorType(int x, int y) {
return CursorType.Arrow;
}
debug(resalloc) {
private static int _instanceCount = 0;
private static bool _appShuttingDown = false;