diff --git a/dlangui-msvc.visualdproj b/dlangui-msvc.visualdproj index 6fc6c1e8..b8eed368 100644 --- a/dlangui-msvc.visualdproj +++ b/dlangui-msvc.visualdproj @@ -8,7 +8,7 @@ 0 0 0 - 0 + 1 0 0 0 @@ -317,7 +317,7 @@ 0 0 0 - 0 + 1 0 0 0 @@ -1276,6 +1276,7 @@ + diff --git a/examples/dragon/dragon-monod-linux.dproj b/examples/dragon/dragon-monod-linux.dproj new file mode 100644 index 00000000..c88ff90a --- /dev/null +++ b/examples/dragon/dragon-monod-linux.dproj @@ -0,0 +1,218 @@ + + + + Debug + x64 + {1E722D80-CF8D-4D98-BEAE-7BC9E6752AC4} + DMD2 + true + true + true + + + {A38BEF21-AAFE-4115-A978-63B7C8C2FBD1} + + + + + ../../src + ../../3rdparty + ../../deps/DerelictSDL2/source + ../../deps/DerelictFT/source + ../../deps/DerelictGL3/source + ../../deps/DerelictUtil/source + + + + + true + bin\Debug + + + USE_SDL + USE_OPENGL + USE_FREETYPE + + + obj/Debug + true + false + dragon-monod-linux + Executable + true + 0 + + + true + bin\Unittest + + + USE_SDL + USE_OPENGL + USE_FREETYPE + + + obj/Unittest + true + true + dragon-monod-linux + Executable + true + 0 + + + bin\Release + + + USE_SDL + USE_OPENGL + USE_FREETYPE + + + obj/Release + true + false + dragon-monod-linux + Executable + true + 0 + + + bin\DebugMinimal + + + USE_SDL + USE_FREETYPE + EmbedStandardResources + + + obj/DebugMinimal + true + false + dragon-monod-linux + Executable + true + 0 + + + bin\ReleaseMinimal + + + USE_SDL + USE_FREETYPE + EmbedStandardResources + + + obj/ReleaseMinimal + true + false + dragon-monod-linux + Executable + true + 0 + + + bin\UnittestMinimal + + + USE_SDL + USE_FREETYPE + EmbedStandardResources + + + obj/UnittestMinimal + true + false + dragon-monod-linux + Executable + true + 0 + + + true + bin\DebugX11 + + + USE_X11 + USE_OPENGL + USE_FREETYPE + + + obj/DebugX11 + true + false + dragon-monod-linux + Executable + true + 0 + + + -L-lX11 + + + + + bin\ReleaseX11 + + + USE_X11 + USE_OPENGL + USE_FREETYPE + + + obj/ReleaseX11 + true + -lX11 + false + dragon-monod-linux + Executable + true + 0 + + + bin\UnittestX11 + + + USE_X11 + USE_OPENGL + USE_FREETYPE + + + obj/UnittestX11 + true + -lX11 + false + dragon-monod-linux + Executable + true + 0 + + + bin\DebugConsole + + + USE_CONSOLE + + + obj/DebugConsole + false + false + dragon-monod-linux + Executable + true + 0 + + + bin\DebugConsole + obj/DebugConsole + false + false + dragon-monod-linux + Executable + true + 0 + + + + + \ No newline at end of file diff --git a/examples/dragon/dragon-monod-osx.dproj b/examples/dragon/dragon-monod-osx.dproj new file mode 100644 index 00000000..692fb0fa --- /dev/null +++ b/examples/dragon/dragon-monod-osx.dproj @@ -0,0 +1,95 @@ + + + + Debug + x64 + {1B4E43FF-5E6A-4F4E-9A6C-F182EC258112} + DMD2 + true + true + true + + + ../../src + ../../3rdparty + ../../deps/DerelictGL3/source + ../../deps/DerelictSDL2/source + ../../deps/DerelictFT/source + ../../deps/DerelictUtil/source + + + + + true + bin\Debug + + + USE_SDL + USE_OPENGL + USE_FREETYPE + EmbedStandardResources + + + obj/Debug + true + -Jviews -Jviews/res -Jviews/res/i18n -Jviews/res/mdpi -Jviews/res/hdpi + false + dragon-monod-osx + Executable + true + 0 + + + bin\Release + + + USE_SDL + USE_OPENGL + USE_FREETYPE + EmbedStandardResources + + + obj/Release + true + -Jviews -Jviews/res -Jviews/res/i18n -Jviews/res/mdpi -Jviews/res/hdpi + false + dragon-monod-osx + Executable + true + 0 + + + true + bin\Unittest + + + USE_SDL + USE_OPENGL + USE_FREETYPE + EmbedStandardResources + + + obj/Unittest + true + -Jviews -Jviews/res -Jviews/res/i18n -Jviews/res/mdpi -Jviews/res/hdpi + true + dragon-monod-osx + Executable + true + 0 + + + bin\DebugX11 + obj/DebugX11 + false + -Jviews -Jviews/res -Jviews/res/i18n -Jviews/res/mdpi -Jviews/res/hdpi + false + dragon-monod-osx + Executable + true + 0 + + + + + \ No newline at end of file diff --git a/examples/dragon/dragon-monod-windows.dproj b/examples/dragon/dragon-monod-windows.dproj new file mode 100644 index 00000000..64cbcde2 --- /dev/null +++ b/examples/dragon/dragon-monod-windows.dproj @@ -0,0 +1,92 @@ + + + + Debug + x64 + {1EB161E7-0DB3-459F-86C5-32A84A3F4334} + DMD2 + true + true + true + + + {45FB40CD-E99A-4C12-AC52-C13364412E09} + + + + + ../../src + ../../3rdparty + ../../deps/DerelictSDL2/source + ../../deps/DerelictFT/source + ../../deps/DerelictGL3/source + ../../deps/DerelictUtil/source + + + + + true + bin\Debug + Executable + dragon-monod-windows + false + true + obj\Debug + + + USE_FREETYPE + USE_OPENGL + EmbedStandardResources + Unicode + windows + + + 0 + false + + + bin\Release + Executable + dragon-monod-windows + false + true + obj\Release + + + USE_FREETYPE + USE_OPENGL + EmbedStandardResources + Unicode + windows + + + 0 + false + + + true + bin\Unittest + true + Executable + dragon-monod-windows + true + true + obj\Unittest + + + USE_FREETYPE + USE_OPENGL + EmbedStandardResources + Unicode + windows + + + 0 + + + + + + + + \ No newline at end of file diff --git a/examples/dragon/dragon-msvc.visualdproj b/examples/dragon/dragon-msvc.visualdproj new file mode 100644 index 00000000..82aa8d2f --- /dev/null +++ b/examples/dragon/dragon-msvc.visualdproj @@ -0,0 +1,830 @@ + + {1F5147FF-DB71-4CEC-BF2F-803143E42BCD} + + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + $(CC) -c + 1 + 0 + $(DMDInstallDir)windows\bin\dmd.exe + $(SolutionDir)/src $(SolutionDir)/3rdparty $(SolutionDir)/deps/DerelictGL3/source $(SolutionDir)/deps/DerelictUtil/source $(SolutionDir)/deps/DerelictFT/source $(SolutionDir)/deps/DerelictSDL2/source + views + $(ConfigurationName) + $(OutDir) + + + 0 + + + + + 0 + + + 1 + $(IntDir)\$(TargetName).json + 0 + + 0 + EmbedStandardResources USE_FREETYPE NO_OPENGL + 0 + 0 + 0 + + + + 0 + + 1 + $(VisualDInstallDir)cv2pdb\cv2pdb.exe + 0 + 0 + 0 + + + + ole32.lib kernel32.lib user32.lib comctl32.lib comdlg32.lib + + + + $(OutDir)\$(ProjectName).exe + 1 + 2 + 0 + + + + *.obj;*.cmd;*.build;*.json;*.dep + + + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 2.043 + 0 + 0 + 0 + 0 + 0 + $(CC) -c + 1 + 0 + $(DMDInstallDir)windows\bin\dmd.exe + $(SolutionDir)/src $(SolutionDir)/3rdparty $(SolutionDir)/deps/DerelictGL3/source $(SolutionDir)/deps/DerelictUtil/source $(SolutionDir)/deps/DerelictFT/source $(SolutionDir)/deps/DerelictSDL2/source + views views/res views/res/i18n views/res/mdpi views/res/hdpi + $(ConfigurationName) + $(OutDir) + + + 0 + + + + + 0 + + + 1 + $(IntDir)\$(TargetName).json + 0 + + 0 + EmbedStandardResources USE_OPENGL USE_FREETYPE + 0 + 0 + 0 + + + + 0 + + 0 + $(VisualDInstallDir)cv2pdb\cv2pdb.exe + 0 + 0 + 0 + + + + ole32.lib kernel32.lib user32.lib comctl32.lib comdlg32.lib + + + + $(OutDir)\$(ProjectName).exe + 1 + 1 + 0 + + + + *.obj;*.cmd;*.build;*.json;*.dep + + + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + $(CC) -c + 1 + 0 + $(DMDInstallDir)windows\bin\dmd.exe + $(SolutionDir)/src $(SolutionDir)/3rdparty $(SolutionDir)/deps/DerelictGL3/source $(SolutionDir)/deps/DerelictUtil/source $(SolutionDir)/deps/DerelictFT/source $(SolutionDir)/deps/DerelictSDL2/source + views + $(ConfigurationName) + $(OutDir) + + + 0 + + + + + 0 + + + 1 + $(IntDir)\$(TargetName).json + 0 + + 0 + EmbedStandardResources USE_FREETYPE NO_OPENGL + 0 + 0 + 0 + + + + 0 + + 1 + $(VisualDInstallDir)cv2pdb\cv2pdb.exe + 0 + 0 + 0 + + + + ole32.lib kernel32.lib user32.lib comctl32.lib comdlg32.lib + + + + $(OutDir)\$(ProjectName).exe + 1 + 2 + 0 + + + + *.obj;*.cmd;*.build;*.json;*.dep + + + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2.043 + 0 + 0 + 0 + 0 + 0 + $(CC) -c + 1 + 0 + $(DMDInstallDir)windows\bin\dmd.exe + $(SolutionDir)/src $(SolutionDir)/3rdparty $(SolutionDir)/deps/DerelictGL3/source $(SolutionDir)/deps/DerelictUtil/source $(SolutionDir)/deps/DerelictFT/source $(SolutionDir)/deps/DerelictSDL2/source + views views/res views/res/i18n views/res/mdpi views/res/hdpi + $(ConfigurationName) + $(OutDir) + + + 0 + + + + + 0 + + + 1 + $(IntDir)\$(TargetName).json + 0 + + 0 + EmbedStandardResources + 0 + 0 + 0 + + + + 0 + + 0 + $(VisualDInstallDir)cv2pdb\cv2pdb.exe + 0 + 0 + 0 + + + + ole32.lib kernel32.lib user32.lib comctl32.lib comdlg32.lib + + + + $(OutDir)\$(ProjectName).exe + 1 + 1 + 0 + + + + *.obj;*.cmd;*.build;*.json;*.dep + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + $(CC) -c + 1 + 0 + $(DMDInstallDir)windows\bin\dmd.exe + $(SolutionDir)/src $(SolutionDir)/3rdparty $(SolutionDir)/deps/DerelictGL3/source $(SolutionDir)/deps/DerelictUtil/source $(SolutionDir)/deps/DerelictFT/source $(SolutionDir)/deps/DerelictSDL2/source + views views/res views/res/i18n views/res/mdpi views/res/hdpi + $(ConfigurationName) + $(OutDir) + + + 0 + + + + + 0 + + + 1 + $(IntDir)\$(TargetName).json + 0 + + 0 + USE_CONSOLE EmbedStandardResources ForceLogs + 0 + 0 + 0 + + + + 0 + + 1 + $(VisualDInstallDir)cv2pdb\cv2pdb.exe + 0 + 0 + 0 + + + + ole32.lib kernel32.lib user32.lib comctl32.lib comdlg32.lib + + + + $(OutDir)\$(ProjectName).exe + 1 + 2 + 0 + + + + *.obj;*.cmd;*.build;*.json;*.dep + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + $(CC) -c + 1 + 0 + $(DMDInstallDir)windows\bin\dmd.exe + $(SolutionDir)/src $(SolutionDir)/3rdparty $(SolutionDir)/deps/DerelictGL3/source $(SolutionDir)/deps/DerelictUtil/source $(SolutionDir)/deps/DerelictFT/source $(SolutionDir)/deps/DerelictSDL2/source + views views/res views/res/i18n views/res/mdpi views/res/hdpi + $(ConfigurationName) + $(OutDir) + + + 0 + + + + + 0 + + + 1 + $(IntDir)\$(TargetName).json + 0 + + 0 + USE_CONSOLE + 0 + 0 + 0 + + + + 0 + + 1 + $(VisualDInstallDir)cv2pdb\cv2pdb.exe + 0 + 0 + 0 + + + + ole32.lib kernel32.lib user32.lib comctl32.lib comdlg32.lib + + + + $(OutDir)\$(ProjectName).exe + 1 + 2 + 0 + + + + *.obj;*.cmd;*.build;*.json;*.dep + + + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2.043 + 0 + 0 + 0 + 0 + 0 + $(CC) -c + 1 + 0 + $(DMDInstallDir)windows\bin\dmd.exe + $(SolutionDir)/src $(SolutionDir)/3rdparty $(SolutionDir)/deps/DerelictGL3/source $(SolutionDir)/deps/DerelictUtil/source $(SolutionDir)/deps/DerelictFT/source $(SolutionDir)/deps/DerelictSDL2/source + views views/res views/res/i18n views/res/mdpi views/res/hdpi + $(ConfigurationName) + $(OutDir) + + + 0 + + + + + 0 + + + 1 + $(IntDir)\$(TargetName).json + 0 + + 0 + EmbedStandardResources + 0 + 0 + 0 + + + + 0 + + 1 + $(VisualDInstallDir)cv2pdb\cv2pdb.exe + 0 + 0 + 0 + + + + ole32.lib kernel32.lib user32.lib comctl32.lib comdlg32.lib + + + + $(OutDir)\$(ProjectName).exe + 1 + 2 + 0 + + + + *.obj;*.cmd;*.build;*.json;*.dep + + + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2.043 + 0 + 0 + 0 + 0 + 0 + $(CC) -c + 1 + 0 + $(DMDInstallDir)windows\bin\dmd.exe + $(SolutionDir)/src $(SolutionDir)/3rdparty $(SolutionDir)/deps/DerelictGL3/source $(SolutionDir)/deps/DerelictUtil/source $(SolutionDir)/deps/DerelictFT/source $(SolutionDir)/deps/DerelictSDL2/source + views views/res views/res/i18n views/res/mdpi views/res/hdpi + $(ConfigurationName) + $(OutDir) + + + 0 + + + + + 0 + + + 1 + $(IntDir)\$(TargetName).json + 0 + + 0 + EmbedStandardResources + 0 + 0 + 0 + + + + 0 + + 1 + $(VisualDInstallDir)cv2pdb\cv2pdb.exe + 0 + 0 + 0 + + + + ole32.lib kernel32.lib user32.lib comctl32.lib comdlg32.lib + + + + $(OutDir)\$(ProjectName).exe + 1 + 2 + 0 + + + + *.obj;*.cmd;*.build;*.json;*.dep + + + + + diff --git a/examples/dragon/dub.json b/examples/dragon/dub.json new file mode 100644 index 00000000..fd7833c5 --- /dev/null +++ b/examples/dragon/dub.json @@ -0,0 +1,34 @@ +{ + "name": "dragon", + "description": "dlangui library example Dragon Curve", + "homepage": "https://github.com/buggins/dlangui", + "license": "Boost", + "authors": ["Vadim Lopatin"], + + "targetPath": "bin", + "targetName": "dragon", + "targetType": "executable", + + "sourceFiles-windows": ["$PACKAGE_DIR/src/win_app.def"], + + "versions": ["EmbedStandardResources"], + + "dependencies": { + "dlangui": {"path": "../../"} + }, + + "configurations" : [ + { + "name" : "default", + "subConfigurations" : { + "dlangui" : "minimal" + } + }, + { + "name" : "console", + "subConfigurations" : { + "dlangui" : "console" + } + } + ] +} diff --git a/examples/dragon/src/dragon.d b/examples/dragon/src/dragon.d new file mode 100644 index 00000000..d06373ae --- /dev/null +++ b/examples/dragon/src/dragon.d @@ -0,0 +1,357 @@ +module app; + +import dlangui; + +mixin APP_ENTRY_POINT; + +import dlangui.widgets.scroll; + +class DragonView : ScrollWidget { + + int _scaleX; + int _scaleY; + int _middleX; + int _middleY; + int _dx; + int _dy; + int _x0; + int _y0; + int _length = 1000; + int _dir0 = 0; // either 0 or 1 + int _straightLen = 10; + int _roundLen = 4; + uint _bgcolor = 0x101010; + uint _grid1color = 0x303030; + uint _grid2color = 0x202020; + uint _grid3color = 0x181818; + uint _curve1color = 0x4050FF; + uint _curve2color = 0xFF4040; + uint _curve3color = 0x30FF20; + uint _curve4color = 0xC000D0; + Point[8] _directionVectors = [ + Point(4, 0), + Point(3, -3), + Point(0, -4), + Point(-3, -3), + Point(-4, 0), + Point(-3, 3), + Point(0, 4), + Point(3, 3), + ]; + + ColorDrawBuf _drawBuf; + + this(string ID) { + super(ID); + fillParent(); + //_fullScrollableArea.right = 2048; + //_fullScrollableArea.bottom = 2048; + setVectors(); + resize(2048, 2048); + } + + void resize(int dx, int dy) { + _dx = dx; + _dy = dy; + _fullScrollableArea.right = dx; + _fullScrollableArea.bottom = dy; + _visibleScrollableArea.left = dx / 2 - 300; + _visibleScrollableArea.top = dy / 2 - 300; + _visibleScrollableArea.right = _visibleScrollableArea.left + 400; + _visibleScrollableArea.bottom = _visibleScrollableArea.top + 400; + + if (!_drawBuf) { + _drawBuf = new ColorDrawBuf(_fullScrollableArea.width, _fullScrollableArea.height); + } else { + _drawBuf.resize(dx, dy); + } + _middleX = _fullScrollableArea.width / 2; + _middleY = _fullScrollableArea.height / 2; + drawCurve(); + } + + void setVectors() { + setVectors(_straightLen, _roundLen); + } + void setVectors(int straightLen, int roundLen) { + if (!straightLen && !roundLen) + straightLen = 1; + setVectors([ + Point(straightLen, 0), + Point(roundLen, -roundLen), + Point(0, -straightLen), + Point(-roundLen, -roundLen), + Point(-straightLen, 0), + Point(-roundLen, roundLen), + Point(0, straightLen), + Point(roundLen, roundLen), + ]); + } + + void setVectors(Point[8] vectors) { + import std.math : abs; + _directionVectors = vectors; + int maxx1, maxx2, maxy1, maxy2; + for(int i = 0; i < 8; i += 2) { + if (maxx1 == 0 || maxx1 < abs(_directionVectors[i].x)) + maxx1 = abs(_directionVectors[i].x); + if (maxy1 == 0 || maxy1 < abs(_directionVectors[i].y)) + maxy1 = abs(_directionVectors[i].y); + if (maxx2 == 0 || maxx1 < abs(_directionVectors[i + 1].x)) + maxx2 = abs(_directionVectors[i + 1].x); + if (maxy2 == 0 || maxy1 < abs(_directionVectors[i + 1].y)) + maxy2 = abs(_directionVectors[i + 1].y); + } + if (_dir0 == 0) { + _scaleX = maxx1 + maxx2 * 2; + _scaleY = maxy1 + maxy2 * 2; + } else { + _scaleX = maxx1 + maxx2; + _scaleY = maxy1 + maxy2; + } + _x0 = vectors[1].x; + _y0 = vectors[1].y; + } + + @property int straightLen() { + return _straightLen; + } + @property DragonView straightLen(int n) { + if (_straightLen != n) { + _straightLen = n; + setVectors(); + drawCurve(); + } + return this; + } + @property int roundLen() { + return _roundLen; + } + @property DragonView roundLen(int n) { + if (_roundLen != n) { + _roundLen = n; + setVectors(); + drawCurve(); + } + return this; + } + @property int length() { + return _length; + } + @property DragonView length(int n) { + if (_length != n) { + _length = n; + drawCurve(); + } + return this; + } + @property int rotation() { + return _dir0; + } + @property DragonView rotation(int angle) { + if (_dir0 != (angle & 7)) { + _dir0 = angle & 7; + drawCurve(); + } + return this; + } + + void drawLine(Point pt1, Point pt2, uint color) { + pt1.x += _middleX; + pt2.x += _middleX; + pt1.y += _middleY; + pt2.y += _middleY; + _drawBuf.drawLine(pt1, pt2, color); + } + + void drawBackground() { + _drawBuf.fill(_bgcolor); + int i = 0; + for (int x = 0; x < _middleX; x += _scaleX) { + uint color = _scaleX > 2 ? _grid3color : COLOR_TRANSPARENT; + if (i == 0) + color = _grid1color; + else if ((i & 15) == 0) + color = _grid2color; + if (color != COLOR_TRANSPARENT) { + drawLine(Point(x, -_middleY), Point(x, _middleY), color); + drawLine(Point(-x, -_middleY), Point(-x, _middleY), color); + if (x == 0) { + drawLine(Point(x - 1, -_middleY), Point(x - 1, _middleY), color); + drawLine(Point(x + 1, -_middleY), Point(x + 1, _middleY), color); + } + } + i++; + } + i = 0; + for (int y = 0; y < _middleY; y += _scaleY) { + uint color = _scaleY > 2 ? _grid3color : COLOR_TRANSPARENT; + if (i == 0) + color = _grid1color; + else if ((i & 15) == 0) + color = _grid2color; + if (color != COLOR_TRANSPARENT) { + drawLine(Point(-_middleX, y), Point(_middleX, y), color); + drawLine(Point(-_middleX, -y), Point(_middleX, -y), color); + if (y == 0) { + drawLine(Point(-_middleX, y - 1), Point(_middleX, y - 1), color); + drawLine(Point(-_middleX, y + 1), Point(_middleX, y + 1), color); + } + } + i++; + } + } + + int getDirectionDelta(int n) { + if (n == 0) + return -1; + for (int i = 0; i < 30; i++) { + if (n & (1 << i)) { + return (n & (2 << i)) ? 1 : -1; + } + } + return 0; + } + + void drawSegment(ref Point currentPoint, ref int currentDir, int n, uint color, int mirror) { + int delta = getDirectionDelta(n) * mirror; + Point nextPoint = currentPoint + _directionVectors[currentDir]; + drawLine(currentPoint, nextPoint, color); + currentPoint = nextPoint; + currentDir = (currentDir + delta) & 7; + nextPoint = currentPoint + _directionVectors[currentDir]; + drawLine(currentPoint, nextPoint, color); + currentPoint = nextPoint; + currentDir = (currentDir + delta) & 7; + } + + void drawCurve() { + drawBackground(); + // segment 1 + int dir; + Point p0; + //Point p0 = Point(_directionVectors[_dir0].y, _directionVectors[_dir0 + 1].y ); + if (_dir0 == 0) + p0 = Point(0, _directionVectors[_dir0 + 1].y); + else + p0 = Point(-_directionVectors[0].x / 2, _directionVectors[_dir0 + 1].y / 2); + //Point p0 = Point(-_directionVectors[0].x * 0, -_directionVectors[0].y / 2); + Point pt; + ///* + dir = 0 + _dir0; + //Point pt = Point(_directionVectors[dir + 1].x - _scaleX, _directionVectors[dir].y); + pt = p0 - (_directionVectors[dir] + _directionVectors[dir + 1]); + for(int i = 0; i < _length; i++) + drawSegment(pt, dir, i, _curve1color, 1); + // segment 2 + ///* + dir = 4 + _dir0; + //pt = Point(-_directionVectors[dir + 1].x - _directionVectors[dir].x - _scaleX, _directionVectors[dir].y); + pt = p0 + _directionVectors[dir + 1];//_directionVectors[dir].y + for(int i = -1; i > -_length; i--) + drawSegment(pt, dir, i, _curve2color, -1); + //*/ + ///* + // segment 3 + dir = 4 + _dir0; + pt = p0 - (_directionVectors[dir - 1] + _directionVectors[dir]); + for(int i = 0; i < _length; i++) + drawSegment(pt, dir, i, _curve3color, 1); + // segment 4 + dir = 0 + _dir0; + pt = p0 + _directionVectors[(dir - 1) & 7]; + for(int i = -1; i > -_length; i--) + drawSegment(pt, dir, i, _curve4color, -1); + //*/ + invalidate(); + } + + /// calculate full content size in pixels + override Point fullContentSize() { + Point sz = Point(_fullScrollableArea.width, _fullScrollableArea.height); + return sz; + } + + override protected void drawClient(DrawBuf buf) { + Point sz = fullContentSize(); + Point p = scrollPos; + //_contentWidget.layout(Rect(_clientRect.left - p.x, _clientRect.top - p.y, _clientRect.left + sz.x - p.x, _clientRect.top + sz.y - p.y)); + //_contentWidget.onDraw(buf); + /// draw source buffer rectangle contents to destination buffer + buf.drawFragment(_clientRect.left, _clientRect.top, _drawBuf, + Rect(_visibleScrollableArea.left, _visibleScrollableArea.top, + _visibleScrollableArea.left + _clientRect.width, _visibleScrollableArea.top + _clientRect.height)); + //Rect rc = _clientRect; + //rc.shrink(5, 5); + //buf.fillRect(rc, 0xFF8080); + } + + +} + +/// entry point for dlangui based application +extern (C) int UIAppMain(string[] args) { + + // create window + Log.d("Creating window"); + Window window = Platform.instance.createWindow("DlangUI example - Dragon Curve", null); + Log.d("Window created"); + + DragonView dragon = new DragonView("DRAGON_VIEW"); + + auto onScrollEvent = delegate(AbstractSlider source, ScrollEvent event) { + if (event.action == ScrollAction.SliderMoved) { + switch(source.id) { + case "straight": + dragon.straightLen = event.position; + break; + case "round": + dragon.roundLen = event.position; + break; + case "size": + dragon.length = event.position; + break; + default: + break; + } + } + return true; + }; + + auto content = new VerticalLayout().fillParent; + auto controls1 = new HorizontalLayout().fillHorizontal.padding(3.pointsToPixels).backgroundColor(0xD8D8D8); + + controls1.addChild(new TextWidget(null," Straight"d)); + auto sliderStraight = new SliderWidget("straight"); + sliderStraight.setRange(0, 20).position(dragon.straightLen).layoutWeight(1).fillHorizontal; + sliderStraight.scrollEvent = onScrollEvent; + controls1.addChild(sliderStraight); + + controls1.addChild(new TextWidget(null," Rounding"d)); + auto sliderRound = new SliderWidget("round"); + sliderRound.setRange(0, 20).position(dragon.roundLen).layoutWeight(1).fillHorizontal; + sliderRound.scrollEvent = onScrollEvent; + controls1.addChild(sliderRound); + + auto cbRotate = new CheckBox(null, " Rotate 45`"d); + controls1.addChild(cbRotate).checked(dragon.rotation ? true : false); + cbRotate.checkChange = delegate(Widget w, bool check) { + dragon.rotation(check ? 1 : 0); return true; + }; + + controls1.addChild(new TextWidget(null," Size"d)); + auto sliderSize = new SliderWidget("size"); + sliderSize.setRange(2, 10000).position(dragon.length).layoutWeight(10).fillHorizontal; + sliderSize.scrollEvent = onScrollEvent; + controls1.addChild(sliderSize); + + content.addChildren([controls1, dragon]); + + window.mainWidget = content; + + // show window + window.show(); + + // run message loop + return Platform.instance.enterMessageLoop(); +} diff --git a/examples/dragon/src/win_app.def b/examples/dragon/src/win_app.def new file mode 100644 index 00000000..40b796c7 --- /dev/null +++ b/examples/dragon/src/win_app.def @@ -0,0 +1,2 @@ +EXETYPE NT +SUBSYSTEM WINDOWS diff --git a/src/dlangui/core/types.d b/src/dlangui/core/types.d index 260f38cb..21187060 100644 --- a/src/dlangui/core/types.d +++ b/src/dlangui/core/types.d @@ -50,12 +50,18 @@ struct Point { int x; int y; - Point opBinary(string op)(Point v) if (op == "+") { + Point opBinary(string op)(Point v) const if (op == "+") { return Point(x + v.x, y + v.y); } - Point opBinary(string op)(Point v) if (op == "-") { + Point opBinary(string op)(int n) const if (op == "*") { + return Point(x * n, y * n); + } + Point opBinary(string op)(Point v) const if (op == "-") { return Point(x - v.x, y - v.y); } + Point opUnary(string op)() const if (op == "-") { + return Point(-x, -y); + } int opCmp(ref const Point b) const { if (x == b.x) return y - b.y; return x - b.x; diff --git a/src/dlangui/graphics/resources.d b/src/dlangui/graphics/resources.d index b595aab1..d0b59601 100644 --- a/src/dlangui/graphics/resources.d +++ b/src/dlangui/graphics/resources.d @@ -125,11 +125,13 @@ struct EmbeddedResourceList { void addResources(EmbeddedResource[] resources) { list ~= resources; } + void dumpEmbeddedResources() { foreach(r; list) { Log.d("EmbeddedResource: ", r.name); } } + /// find by exact file name EmbeddedResource * find(string name) { // search backwards to allow overriding standard resources (which are added first) @@ -147,6 +149,7 @@ struct EmbeddedResourceList { return &list[i]; return null; } + /// find by name w/o extension EmbeddedResource * findAutoExtension(string name) { string xmlname = name ~ ".xml"; @@ -211,18 +214,6 @@ EmbeddedResource[] embedResources(string[] resourceNames)() { return embedResources!(resourceNames[0 .. $/2])() ~ embedResources!(resourceNames[$/2 .. $])(); } -/// split string into lines, autodetect line endings -string[] splitLines(string s) { - auto lines_crlf = split(s, "\r\n"); - auto lines_cr = split(s, "\r"); - auto lines_lf = split(s, "\n"); - if (lines_crlf.length >= lines_cr.length && lines_crlf.length >= lines_lf.length) - return lines_crlf; - if (lines_cr.length > lines_lf.length) - return lines_cr; - return lines_lf; -} - /// embed all resources from list EmbeddedResource[] embedResourcesFromList(string resourceList)() { static if (BACKEND_CONSOLE) { @@ -850,6 +841,7 @@ class ImageDrawable : Drawable { debug _instanceCount--; debug(resalloc) Log.d("Destroyed ImageDrawable, count=", _instanceCount); } + @property override int width() { if (_image.isNull) return 0; @@ -857,6 +849,7 @@ class ImageDrawable : Drawable { return _image.width - 2; return _image.width; } + @property override int height() { if (_image.isNull) return 0; @@ -864,11 +857,13 @@ class ImageDrawable : Drawable { return _image.height - 2; return _image.height; } + @property override Rect padding() { if (!_image.isNull && _image.hasNinePatch) return _image.ninePatch.padding; return Rect(0,0,0,0); } + private static void correctFrameBounds(ref int n1, ref int n2, ref int n3, ref int n4) { if (n1 > n2) { //assert(n2 - n1 == n4 - n3); @@ -877,6 +872,7 @@ class ImageDrawable : Drawable { n3 = n4 = n3 + middledist; } } + override void drawTo(DrawBuf buf, Rect rc, uint state = 0, int tilex0 = 0, int tiley0 = 0) { if (_image.isNull) return; @@ -1266,9 +1262,11 @@ class ImageCache { bool _error; // flag to avoid loading of file if it has been failed once bool _used; + this(string filename) { _filename = filename; } + /// get normal image @property ref DrawBufRef get() { if (!_drawbuf.isNull || _error) { @@ -1301,6 +1299,7 @@ class ImageCache { } return _transformMap[transform]; } + /// remove from memory, will cause reload on next access void compact() { if (!_drawbuf.isNull) @@ -1389,13 +1388,12 @@ class DrawableCache { string _id; string _filename; bool _tiled; - bool _error; - bool _used; DrawableRef _drawable; DrawableRef[ColorTransform] _transformed; - debug private static __gshared int _instanceCount; - debug @property static int instanceCount() { return _instanceCount; } + bool _error; // flag to avoid loading of file if it has been failed once + bool _used; + this(string id, string filename, bool tiled) { _id = id; _filename = filename; @@ -1404,6 +1402,9 @@ class DrawableCache { debug ++_instanceCount; debug(resalloc) Log.d("Created DrawableCacheItem, count=", _instanceCount); } + debug private static __gshared int _instanceCount; + debug @property static int instanceCount() { return _instanceCount; } + ~this() { _drawable.clear(); foreach(ref t; _transformed) @@ -1431,126 +1432,26 @@ class DrawableCache { } /// returns drawable (loads from file if necessary) - @property ref DrawableRef drawable() { + @property ref DrawableRef drawable(in ColorTransform transform = ColorTransform()) { _used = true; - if (!_drawable.isNull || _error) - return _drawable; - if (_filename !is null) { - // reload from file - if (_filename.endsWith(".xml")) { - // XML drawables support - StateDrawable d = new StateDrawable(); - if (!d.load(_filename)) { - destroy(d); - _error = true; - } else { - _drawable = d; - } - } else if (_filename.endsWith(".tim")) { - static if (BACKEND_CONSOLE) { - try { - // .tim (text image) drawables support - string s = cast(string)loadResourceBytes(_filename); - if (s.length) { - TextDrawable d = new TextDrawable(s); - if (d.width && d.height) { - _drawable = d; - } - } - } catch (Exception e) { - // cannot find drawable file - } - } - if (!_drawable) - _error = true; - } else if (_filename.startsWith("#")) { - // color reference #AARRGGBB, e.g. #5599AA, or a gradient, or BorderDrawable description - _drawable = createColorDrawable(_filename); - } else if (_filename.startsWith("{")) { - // json in {} with text drawable description - static if (BACKEND_CONSOLE) { - _drawable = createTextDrawable(_filename); - } - } else { - static if (BACKEND_GUI) { - // PNG/JPEG drawables support - DrawBufRef image = imageCache.get(_filename); - if (!image.isNull) { - bool ninePatch = _filename.endsWith(".9.png"); - _drawable = new ImageDrawable(image, _tiled, ninePatch); - } else - _error = true; - } else { - _error = true; - } - } - } - return _drawable; - } - /// returns drawable (loads from file if necessary) - @property ref DrawableRef drawable(ref ColorTransform transform) { - if (transform.empty) - return drawable(); - if (transform in _transformed) + if (!transform.empty && transform in _transformed) return _transformed[transform]; - _used = true; if (!_drawable.isNull || _error) return _drawable; - if (_filename !is null) { - // reload from file - if (_filename.endsWith(".xml") || _filename.endsWith(".XML")) { - // XML drawables support - StateDrawable d = new StateDrawable(); - if (!d.load(_filename)) { - Log.e("failed to load .xml drawable from ", _filename); - destroy(d); - _error = true; - } else { - Log.d("loaded .xml drawable from ", _filename); - _drawable = d; - } - } else if (_filename.endsWith(".tim") || _filename.endsWith(".TIM")) { - static if (BACKEND_CONSOLE) { - try { - // .tim (text image) drawables support - string s = cast(string)loadResourceBytes(_filename); - if (s.length) { - TextDrawable d = new TextDrawable(s); - if (d.width && d.height) { - _drawable = d; - } - } - } catch (Exception e) { - // cannot find drawable file - } - } - if (!_drawable) - _error = true; - } else if (_filename.startsWith("{")) { - // json in {} with text drawable description - static if (BACKEND_CONSOLE) { - _drawable = createTextDrawable(_filename); - } - } else { - static if (BACKEND_GUI) { - // PNG/JPEG drawables support - DrawBufRef image = imageCache.get(_filename, transform); - if (!image.isNull) { - bool ninePatch = _filename.endsWith(".9.png") || _filename.endsWith(".9.PNG"); - _transformed[transform] = new ImageDrawable(image, _tiled, ninePatch); - return _transformed[transform]; - } else { - Log.e("failed to load image from ", _filename); - _error = true; - } - } else { - _error = true; - } - } + + // not in cache - create it + Drawable dr = makeDrawableFromId(_filename, _tiled, transform); + _error = dr is null; + if (transform.empty) { + _drawable = dr; + return _drawable; + } else { + _transformed[transform] = dr; + return _transformed[transform]; } - return _drawable; } } + void clear() { Log.d("DrawableCache.clear()"); _idToFileMap.destroy(); @@ -1568,35 +1469,19 @@ class DrawableCache { foreach (item; _idToDrawableMap) item.cleanup(); } + string[] _resourcePaths; string[string] _idToFileMap; DrawableCacheItem[string] _idToDrawableMap; DrawableRef _nullDrawable; - ref DrawableRef get(string id) { - while (id.length && (id[0] == ' ' || id[0] == '\t' || id[0] == '\r' || id[0] == '\n')) - id = id[1 .. $]; - if (id.equal("@null")) - return _nullDrawable; - if (id in _idToDrawableMap) - return _idToDrawableMap[id].drawable; - string resourceId = id; - bool tiled = false; - if (id.endsWith(".tiled")) { - resourceId = id[0..$-6]; // remove .tiled - tiled = true; - } - string filename = findResource(resourceId); - DrawableCacheItem item = new DrawableCacheItem(id, filename, tiled); - _idToDrawableMap[id] = item; - return item.drawable; - } - ref DrawableRef get(string id, ref ColorTransform transform) { - if (transform.empty) - return get(id); + + ref DrawableRef get(string id, in ColorTransform transform = ColorTransform()) { + id = id.strip; if (id.equal("@null")) return _nullDrawable; if (id in _idToDrawableMap) return _idToDrawableMap[id].drawable(transform); + // not found - create it string resourceId = id; bool tiled = false; if (id.endsWith(".tiled")) { @@ -1604,10 +1489,11 @@ class DrawableCache { tiled = true; } string filename = findResource(resourceId); - DrawableCacheItem item = new DrawableCacheItem(id, filename, tiled); + auto item = new DrawableCacheItem(id, filename, tiled); _idToDrawableMap[id] = item; return item.drawable(transform); } + @property string[] resourcePaths() { return _resourcePaths; } @@ -1629,6 +1515,7 @@ class DrawableCache { _resourcePaths = existingPaths; clear(); } + /// concatenates path with resource id and extension, returns pathname if there is such file, null if file does not exist private string checkFileName(string path, string id, string extension) { char[] fn = path.dup; @@ -1638,10 +1525,11 @@ class DrawableCache { return fn.dup; return null; } + /// get resource file full pathname by resource id, null if not found string findResource(string id) { if (id.startsWith("#") || id.startsWith("{")) - return id; // it's not a file name, just a color #AARRGGBB + return id; // it's not a file name if (id in _idToFileMap) return _idToFileMap[id]; EmbeddedResource * embedded = embeddedResourceList.findAutoExtension(id); @@ -1697,12 +1585,63 @@ class DrawableCache { } -// load text resource +/// This function takes an id and creates a drawable +/// id may be a name of file, #directive, color or json +private Drawable makeDrawableFromId(in string id, in bool tiled, ColorTransform transform = ColorTransform()) { + if (id !is null) { + if (id.endsWith(".xml") || id.endsWith(".XML")) { + // XML drawables support + auto d = new StateDrawable; + if (!d.load(id)) { + Log.e("failed to load .xml drawable from ", id); + destroy(d); + return null; + } else { + Log.d("loaded .xml drawable from ", id); + return d; + } + } else if (id.endsWith(".tim") || id.endsWith(".TIM")) { + static if (BACKEND_CONSOLE) { + try { + // .tim (text image) drawables support + string s = cast(string)loadResourceBytes(id); + if (s.length) { + auto d = new TextDrawable(s); + if (d.width && d.height) { + return d; + } + } + } catch (Exception e) { + // cannot find drawable file + } + } + } else if (id.startsWith("#")) { + // color reference #AARRGGBB, e.g. #5599AA, a gradient, border description, etc. + return createColorDrawable(id); + } else if (id.startsWith("{")) { + // json in {} with text drawable description + static if (BACKEND_CONSOLE) { + return createTextDrawable(id); + } + } else { + static if (BACKEND_GUI) { + // PNG/JPEG drawables support + DrawBufRef image = transform.empty ? imageCache.get(id) : imageCache.get(id, transform); + if (!image.isNull) { + bool ninePatch = id.endsWith(".9.png") || id.endsWith(".9.PNG"); + return new ImageDrawable(image, tiled, ninePatch); + } else + Log.e("Failed to load image from ", id); + } + } + } + return null; +} + + +/// load text resource string loadTextResource(string resourceId) { - import dlangui.graphics.resources; - import std.string : endsWith; - string filename; - filename = drawableCache.findResource(resourceId); + string filename = drawableCache.findResource(resourceId); if (!filename) { Log.e("Object resource file not found for resourceId ", resourceId); assert(false); diff --git a/src/dlangui/platforms/common/startup.d b/src/dlangui/platforms/common/startup.d index ba145a56..70190234 100644 --- a/src/dlangui/platforms/common/startup.d +++ b/src/dlangui/platforms/common/startup.d @@ -416,41 +416,7 @@ extern (C) void initResourceManagers() { Log.d("initResourceManagers() -- finished"); } -/// register standard widgets to use in DML -void registerStandardWidgets() { - Log.d("Registering standard widgets for DML"); - import dlangui.widgets.metadata; - import dlangui.widgets.widget; - import dlangui.widgets.layouts; - import dlangui.widgets.controls; - import dlangui.widgets.scrollbar; - import dlangui.widgets.lists; - import dlangui.widgets.combobox; - import dlangui.widgets.editors; - import dlangui.widgets.grid; - import dlangui.widgets.groupbox; - import dlangui.widgets.progressbar; - import dlangui.dialogs.filedlg; - import dlangui.widgets.menu; - import dlangui.widgets.tree; - import dlangui.widgets.tabs; - mixin(registerWidgets!(FileNameEditLine, DirEditLine, //dlangui.dialogs.filedlg - ComboBox, ComboEdit, //dlangui.widgets.combobox - Widget, TextWidget, MultilineTextWidget, Button, ImageWidget, ImageButton, ImageCheckButton, ImageTextButton, - SwitchButton, RadioButton, CheckBox, HSpacer, VSpacer, CanvasWidget, // dlangui.widgets.controls - ScrollBar, SliderWidget, // dlangui.widgets.scrollbar - EditLine, EditBox, LogWidget,//dlangui.widgets.editors - GroupBox, // dlangui.widgets.groupbox - ProgressBarWidget, // dlangui.widgets.progressbar - StringGridWidget, //dlangui.widgets.grid - VerticalLayout, HorizontalLayout, TableLayout, FrameLayout, // dlangui.widgets.layouts - ListWidget, StringListWidget,//dlangui.widgets.lists - MainMenu, //dlangui.widgets.menu - TreeWidget, // dlangui.widgets.tree - TabWidget, // dlangui.widgets.tabs - )("void registerWidgets")); - registerWidgets(); -} + /// call this from shared static this() extern (C) void initSharedResourceManagers() { @@ -466,6 +432,9 @@ shared static this() { //initSharedResourceManagers(); } +/// register standard widgets to use in DML +extern(C) void registerStandardWidgets(); + /// call this when all resources are supposed to be freed to report counts of non-freed resources by type extern (C) void releaseResourcesOnAppExit() { diff --git a/src/dlangui/widgets/dmlwidgets.d b/src/dlangui/widgets/dmlwidgets.d new file mode 100644 index 00000000..edff07ac --- /dev/null +++ b/src/dlangui/widgets/dmlwidgets.d @@ -0,0 +1,117 @@ +module dlangui.widgets.dmlwidgets; + +/// register standard widgets to use in DML +extern(C) void registerStandardWidgets() { + import dlangui.core.config; + import dlangui.core.logger; + + Log.d("Registering standard widgets for DML"); + + import dlangui.widgets.metadata; + import dlangui.widgets.widget; + + mixin(registerWidgetMetadataClass!Widget); + + import dlangui.widgets.layouts; + mixin(registerWidgetMetadataClass!VerticalLayout); + mixin(registerWidgetMetadataClass!HorizontalLayout); + mixin(registerWidgetMetadataClass!TableLayout); + mixin(registerWidgetMetadataClass!FrameLayout); // dlangui.widgets.layouts + + import dlangui.widgets.controls; + + mixin(registerWidgetMetadataClass!TextWidget); + mixin(registerWidgetMetadataClass!MultilineTextWidget); + mixin(registerWidgetMetadataClass!Button); + mixin(registerWidgetMetadataClass!ImageWidget); + mixin(registerWidgetMetadataClass!ImageButton); + mixin(registerWidgetMetadataClass!ImageCheckButton); + mixin(registerWidgetMetadataClass!ImageTextButton); + mixin(registerWidgetMetadataClass!SwitchButton); + mixin(registerWidgetMetadataClass!RadioButton); + mixin(registerWidgetMetadataClass!CheckBox); + mixin(registerWidgetMetadataClass!HSpacer); + mixin(registerWidgetMetadataClass!VSpacer); + mixin(registerWidgetMetadataClass!CanvasWidget); // dlangui.widgets.controls + + import dlangui.widgets.scrollbar; + + mixin(registerWidgetMetadataClass!ScrollBar); + mixin(registerWidgetMetadataClass!SliderWidget); // dlangui.widgets.scrollbar + + import dlangui.widgets.lists; + + mixin(registerWidgetMetadataClass!ListWidget); + mixin(registerWidgetMetadataClass!StringListWidget);//dlangui.widgets.lists + + + import dlangui.widgets.editors; + + mixin(registerWidgetMetadataClass!EditLine); + mixin(registerWidgetMetadataClass!EditBox); + mixin(registerWidgetMetadataClass!LogWidget);//dlangui.widgets.editors + + import dlangui.widgets.combobox; + mixin(registerWidgetMetadataClass!ComboBox); + mixin(registerWidgetMetadataClass!ComboEdit); //dlangui.widgets.combobox + + import dlangui.widgets.grid; + + mixin(registerWidgetMetadataClass!StringGridWidget); //dlangui.widgets.grid + + import dlangui.widgets.groupbox; + + mixin(registerWidgetMetadataClass!GroupBox); // dlangui.widgets.groupbox + + import dlangui.widgets.progressbar; + + mixin(registerWidgetMetadataClass!ProgressBarWidget); // dlangui.widgets.progressbar + + import dlangui.widgets.menu; + + mixin(registerWidgetMetadataClass!MainMenu); //dlangui.widgets.menu + + import dlangui.widgets.tree; + + mixin(registerWidgetMetadataClass!TreeWidget); // dlangui.widgets.tree + + import dlangui.widgets.tabs; + + mixin(registerWidgetMetadataClass!TabWidget); // dlangui.widgets.tabs + + import dlangui.dialogs.filedlg; + + mixin(registerWidgetMetadataClass!FileNameEditLine); + mixin(registerWidgetMetadataClass!DirEditLine); + + /* + mixin (registerWidgets!("void registerWidgets1", + FileNameEditLine, DirEditLine, //dlangui.dialogs.filedlg + ComboBox, ComboEdit, //dlangui.widgets.combobox + // )()); + //mixin(registerWidgets!("void registerWidgets2", + Widget, TextWidget, MultilineTextWidget, Button, ImageWidget, ImageButton, ImageCheckButton, ImageTextButton, + )); + mixin(registerWidgets!("void registerWidgets3", + SwitchButton, RadioButton, CheckBox, HSpacer, VSpacer, CanvasWidget, // dlangui.widgets.controls + ScrollBar, SliderWidget, // dlangui.widgets.scrollbar + EditLine, EditBox, LogWidget,//dlangui.widgets.editors + )); + mixin(registerWidgets!("void registerWidgets4", + GroupBox, // dlangui.widgets.groupbox + ProgressBarWidget, // dlangui.widgets.progressbar + StringGridWidget, //dlangui.widgets.grid + VerticalLayout, HorizontalLayout, TableLayout, FrameLayout, // dlangui.widgets.layouts + MainMenu, //dlangui.widgets.menu + TreeWidget, // dlangui.widgets.tree + TabWidget, // dlangui.widgets.tabs + )); + + + registerWidgets1(); + //registerWidgets2(); + registerWidgets3(); + registerWidgets4(); + */ +} + diff --git a/src/dlangui/widgets/lists.d b/src/dlangui/widgets/lists.d index e46ae548..e102a76f 100644 --- a/src/dlangui/widgets/lists.d +++ b/src/dlangui/widgets/lists.d @@ -1402,7 +1402,8 @@ class ListWidget : WidgetGroup, OnScrollHandler, OnAdapterChangeHandler { class StringListWidget : ListWidget { import std.conv : to; - import std.datetime : dto = to, StopWatch; + import std.datetime.stopwatch : StopWatch; + import core.time : dur; private dstring _searchString; private StopWatch _stopWatch; @@ -1479,9 +1480,10 @@ class StringListWidget : ListWidget { if (event.action == KeyAction.Text) { if ( !_stopWatch.running) { _stopWatch.start; } - auto timePassed = _stopWatch.peek.dto!("seconds", float)(); // dtop is std.datetime.to + auto timePassed = _stopWatch.peek; //.to!("seconds", float)(); // dtop is std.datetime.to - if (timePassed > 0.5) _searchString = ""d; + if (timePassed > dur!"msecs"(500)) + _searchString = ""d; _searchString ~= to!dchar(event.text.toUTF8); _stopWatch.reset; diff --git a/src/dlangui/widgets/metadata.d b/src/dlangui/widgets/metadata.d index 86c630e8..793bd49e 100644 --- a/src/dlangui/widgets/metadata.d +++ b/src/dlangui/widgets/metadata.d @@ -83,53 +83,136 @@ template isMarkupType(T) is(T==StringListValue[]); } -string generatePropertiesMetadata(alias T)() { - version (GENERATE_PROPERTY_METADATA) { - import std.algorithm.searching; +private bool hasPropertyAnnotation(alias ti)() { + bool res = false; + foreach ( attr; __traits(getFunctionAttributes, ti)) { + static if (attr == "@property") { + res = true; + } + } + return res; +} +/* +string markupPropertyGetterType(alias overload)() { + static if (__traits(getProtection, overload) == "public") { import std.traits; - import std.meta; - char[] str; - str ~= "["; - foreach(m; __traits(allMembers, T)) { - static if (__traits(compiles, (typeof(__traits(getMember, T, m))))){ - // skip non-public members, only functions that takes 0 or 1 arguments, add only types that parseable in markup - static if (__traits(getProtection, __traits(getMember, T, m)) == "public") { - static if (isFunction!(__traits(getMember, T, m))) { - immutable int fnArity = arity!(__traits(getMember, T, m)); - static if (fnArity == 0 || fnArity == 1) { - // TODO: filter out templates, signals and such - // iterates class members and process @property functions (note: foreach {if}) - foreach ( attr; __traits(getFunctionAttributes, __traits(getMember, T, m))) if (attr == "@property") { - alias ret = ReturnType!(__traits(getMember, T, m)); - alias params = Parameters!(__traits(getMember, T, m)); - string typestring; - static if (fnArity == 0 && !__traits(isTemplate,ret) && isMarkupType!ret) - typestring = ret.stringof; - else static if (fnArity == 1 && !__traits(isTemplate,params[0]) && isMarkupType!(params[0])) - typestring = params[0].stringof; - if (typestring is null) - continue; - str ~= "WidgetPropertyMetadata( typeid(" ~ typestring ~ "), " ~ m.stringof ~ " ), "; - } + static if (is(typeof(overload) == function) && hasPropertyAnnotation!overload) { + alias ret = ReturnType!overload; + //alias params = Parameters!overload; + alias params = ParameterTypeTuple!overload; + static if (params.length == 0 && isMarkupType!ret && !isTemplate!ret) { + return ret.stringof; + } else { + return null; + } + } else { + return null; + } + } +} + +string markupPropertySetterType(alias overload)() { + static if (__traits(getProtection, overload) == "public") { + import std.traits; + static if (is(typeof(overload) == function) && hasPropertyAnnotation!overload) { + //alias params = Parameters!overload; + alias params = ParameterTypeTuple!overload; + static if (params.length == 1 && isMarkupType!(params[0]) && !isTemplate!(params[0])) { + return params[0].stringof; + } else { + return null; + } + } else { + return null; + } + } +} +*/ + +private template isPublicPropertyFunction(alias overload) { + static if (__traits(getProtection, overload) == "public") { + static if (hasPropertyAnnotation!overload) { + enum isPublicPropertyFunction = true; + } else { + enum isPublicPropertyFunction = false; + } + } else { + enum isPublicPropertyFunction = false; + } + //pragma(msg, is(typeof(overload) == function).stringof); + //enum isPublicPropertyFunction = (__traits(getProtection, overload) == "public") && is(typeof(overload) == function);// && hasPropertyAnnotation!overload; +} + +private template markupPropertyType(alias overload) { + import std.traits : ReturnType, ParameterTypeTuple; + alias ret = ReturnType!overload; + alias params = ParameterTypeTuple!overload; + static if (params.length == 0 && isMarkupType!ret /* && !isTemplate!ret*/) { + enum string markupPropertyType = ret.stringof; + } else static if (params.length == 1 && isMarkupType!(params[0]) /* && !isTemplate!(params[0])*/) { + enum string markupPropertyType = params[0].stringof; + } else { + enum string markupPropertyType = null; + } +} + +private string[] generatePropertyTypeList(alias T)() { + import std.meta; + string[] properties; + properties ~= "["; + foreach(m; __traits(allMembers, T)) { + static if (__traits(compiles, (typeof(__traits(getMember, T, m))))){ + //static if (is (typeof(__traits(getMember, T, m)) == function)) { + static if (__traits(isVirtualFunction, __traits(getMember, T, m))) {// + import std.traits : MemberFunctionsTuple; + alias overloads = typeof(__traits(getVirtualFunctions, T, m)); + static if (overloads.length == 2) { + static if (isPublicPropertyFunction!(__traits(getVirtualFunctions, T, m)[0]) && isPublicPropertyFunction!(__traits(getVirtualFunctions, T, m)[1])) { + //pragma(msg, m ~ " isPublicPropertyFunction0=" ~ isPublicPropertyFunction!(__traits(getVirtualFunctions, T, m)[0]).stringof); + //pragma(msg, m ~ " isPublicPropertyFunction1=" ~ isPublicPropertyFunction!(__traits(getVirtualFunctions, T, m)[1]).stringof); + immutable getterType = markupPropertyType!(__traits(getVirtualFunctions, T, m)[0]); + immutable setterType = markupPropertyType!(__traits(getVirtualFunctions, T, m)[1]); + static if (getterType && setterType && getterType == setterType) { + //pragma(msg, "markup property found: " ~ getterType ~ " " ~ m.stringof); + properties ~= "WidgetPropertyMetadata( typeid(" ~ getterType ~ "), " ~ m.stringof ~ " ), "; } } } } } - str ~= "]"; - return cast(string)str; + } + properties ~= "]"; + return properties; +} + +string joinStrings(string[] lines) { + if (lines.length == 0) + return ""; + if (lines.length == 1) + return lines[0]; + else + return joinStrings(lines[0 .. $/2]) ~ joinStrings(lines[$/2 .. $]); +} + +private string generatePropertiesMetadata(alias T)() if (is(T : Widget)) { + version (GENERATE_PROPERTY_METADATA) { + //import std.algorithm.searching; + //import std.traits : MemberFunctionsTuple; + //import std.meta; + auto properties = generatePropertyTypeList!T; + return joinStrings(properties); } else { return "[]"; } } -string generateMetadataClass(alias t)() { +string generateMetadataClass(alias t)() if (is(t : Widget)) { //pragma(msg, moduleName!t); import std.traits; //pragma(msg, getSignalList!t); //pragma(msg, generatePropertiesMetadata!t); immutable string metadataClassName = t.stringof ~ "Metadata"; - return "class " ~ metadataClassName ~ " : WidgetMetadataDef { \n" ~ + return "static class " ~ metadataClassName ~ " : WidgetMetadataDef { \n" ~ " override Widget create() {\n" ~ " return new " ~ moduleName!t ~ "." ~ t.stringof ~ "();\n" ~ " }\n" ~ @@ -142,33 +225,73 @@ string generateMetadataClass(alias t)() { " override string fullName() {\n" ~ " return \"" ~ moduleName!t ~ "." ~ t.stringof ~ "\";\n" ~ " }\n" ~ - " override WidgetPropertyMetadata[] properties() {" ~ + " override WidgetPropertyMetadata[] properties() {\n" ~ " return " ~ generatePropertiesMetadata!t ~ ";\n" ~ " }\n" ~ "}\n"; } -string generateRegisterMetadataClass(alias t)() { +string generateRegisterMetadataClass(alias t)() if (is(t : Widget)) { immutable string metadataClassName = t.stringof ~ "Metadata"; - return "registerWidgetMetadata(\"" ~ t.stringof ~ "\", new " ~ metadataClassName ~ "());\n"; + //pragma(msg, metadataClassName); + return "registerWidgetMetadata(\"" ~ t.stringof ~ "\", new " ~ t.stringof ~ "Metadata" ~ "());\n"; } -string registerWidgets(T...)(string registerFunctionName = "__gshared static this") { - string classDefs; - string registerDefs; +template registerWidgetMetadataClass(alias t) if (is(t : Widget)) { + //pragma(msg, t.stringof); + //pragma(msg, generateMetadataClass!t); + immutable string classDef = generateMetadataClass!t; + immutable string registerDef = "registerWidgetMetadata(\"" ~ t.stringof ~ "\", new " ~ t.stringof ~ "Metadata" ~ "());\n"; + enum registerWidgetMetadataClass = classDef ~ registerDef; + //mixin(classDef); + + //pragma(msg, "registerWidgetMetadata(\"" ~ t.stringof ~ "\", new " ~ t.stringof ~ "Metadata" ~ "());\n"); + //mixin("registerWidgetMetadata(\"" ~ t.stringof ~ "\", new " ~ t.stringof ~ "Metadata" ~ "());\n"); +} + +string registerWidgetsFunction(string registerFunctionName = "__gshared static this", T...)() { + pragma(msg, registerFunctionName); + pragma(msg, T); + string[] registerDefs; foreach(t; T) { - //pragma(msg, t.stringof); + pragma(msg, t.stringof); //pragma(msg, moduleName!t); // - immutable string classdef = generateMetadataClass!t; - //pragma(msg, classdef); - immutable string registerdef = generateRegisterMetadataClass!t; - //pragma(msg, registerdef); - classDefs ~= classdef; - registerDefs ~= registerdef; + static if (is(t : Widget)) { + //pragma(msg, classdef); + immutable string registerdef = generateRegisterMetadataClass!t; + pragma(msg, registerdef); + registerDefs ~= registerdef; + } else { + pragma(msg, "Skipping non-widget class: " ~ t.stringof); + } //registerWidgetMetadata(T.stringof, new Metadata()); } - return classDefs ~ "\n" ~ registerFunctionName ~ "() {\n" ~ registerDefs ~ "}"; + return registerFunctionName ~ "() {\n" ~ joinStrings(registerDefs) ~ "}\n"; +} + +string registerWidgets(string registerFunctionName = "__gshared static this", T...)() { + pragma(msg, registerFunctionName); + pragma(msg, T); + string[] classDefs; + string[] registerDefs; + foreach(t; T) { + pragma(msg, t.stringof); + //pragma(msg, moduleName!t); + // + static if (is(t : Widget)) { + immutable string classdef = generateMetadataClass!t; + //pragma(msg, classdef); + immutable string registerdef = generateRegisterMetadataClass!t; + pragma(msg, registerdef); + classDefs ~= classdef; + registerDefs ~= registerdef; + } else { + pragma(msg, "Skipping non-widget class: " ~ t.stringof); + } + //registerWidgetMetadata(T.stringof, new Metadata()); + } + return joinStrings(classDefs) ~ "\n" ~ registerFunctionName ~ "() {\n" ~ joinStrings(registerDefs) ~ "}\n"; } /// returns true if passed name is identifier of registered widget class diff --git a/src/dlangui/widgets/widget.d b/src/dlangui/widgets/widget.d index e769f82a..3ac0e600 100644 --- a/src/dlangui/widgets/widget.d +++ b/src/dlangui/widgets/widget.d @@ -637,6 +637,13 @@ public: /// sets layout weight (while resizing to fill parent, widget will be resized proportionally to this value) @property Widget layoutWeight(int value) { ownStyle.layoutWeight = value; return this; } + /// sets layoutWidth=FILL_PARENT and layoutHeight=FILL_PARENT + Widget fillParent() { return layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT); } + /// sets layoutWidth=FILL_PARENT + Widget fillHorizontal() { return layoutWidth(FILL_PARENT); } + /// sets layoutHeight=FILL_PARENT + Widget fillVertical() { return layoutHeight(FILL_PARENT); } + /// returns widget visibility (Visible, Invisible, Gone) @property Visibility visibility() { return _visibility; } /// sets widget visibility (Visible, Invisible, Gone) diff --git a/views/DLANGUI_VERSION b/views/DLANGUI_VERSION index 705171d0..ce001651 100644 --- a/views/DLANGUI_VERSION +++ b/views/DLANGUI_VERSION @@ -1 +1 @@ -v0.9.166 \ No newline at end of file +v0.9.167 \ No newline at end of file