From 83b4e9839030f9b4d8906a24d703cd24746df292 Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Mon, 12 Jan 2015 13:44:46 +0300 Subject: [PATCH 01/20] fix OpenGL support in additional windows under pure win32 - issue #27 --- dlanguilib.visualdproj | 4 +- examples/example1/example1.visualdproj | 4 +- src/dlangui/graphics/gldrawbuf.d | 32 +- src/dlangui/graphics/glsupport.d | 695 +++++++++++++------------ src/dlangui/platforms/sdl/sdlapp.d | 4 +- src/dlangui/platforms/windows/winapp.d | 19 +- 6 files changed, 393 insertions(+), 365 deletions(-) diff --git a/dlanguilib.visualdproj b/dlanguilib.visualdproj index a3290833..a28e84c3 100644 --- a/dlanguilib.visualdproj +++ b/dlanguilib.visualdproj @@ -66,7 +66,7 @@ 0 DebugFocus 0 - USE_OPENGL Unicode + USE_OPENGL USE_SDL Unicode 0 0 1 @@ -89,7 +89,6 @@ $(OutDir)\$(ProjectName).lib 1 - 2 @@ -184,7 +183,6 @@ $(OutDir)\$(ProjectName).lib 1 - 1 diff --git a/examples/example1/example1.visualdproj b/examples/example1/example1.visualdproj index a7d67fa0..c1aca680 100644 --- a/examples/example1/example1.visualdproj +++ b/examples/example1/example1.visualdproj @@ -66,7 +66,7 @@ 0 0 - USE_OPENGL Unicode + USE_OPENGL USE_SDL Unicode 0 3 0 @@ -89,7 +89,6 @@ $(OutDir)\$(ProjectName).exe 1 - 2 -profile @@ -184,7 +183,6 @@ $(OutDir)\$(ProjectName).exe 1 - 1 diff --git a/src/dlangui/graphics/gldrawbuf.d b/src/dlangui/graphics/gldrawbuf.d index 434f4232..ef414f5e 100644 --- a/src/dlangui/graphics/gldrawbuf.d +++ b/src/dlangui/graphics/gldrawbuf.d @@ -62,9 +62,9 @@ class GLDrawBuf : DrawBuf { /// reserved for hardware-accelerated drawing - ends drawing batch override void afterDrawing() { - setOrthoProjection(_dx, _dy); + glSupport.setOrthoProjection(_dx, _dy); _scene.draw(); - flushGL(); + glSupport.flushGL(); destroy(_scene); _scene = null; } @@ -244,7 +244,7 @@ private class GLImageCache { _drawbuf = null; } if (_textureId != 0) { - deleteTexture(_textureId); + glSupport.deleteTexture(_textureId); _textureId = 0; } } @@ -254,14 +254,14 @@ private class GLImageCache { return; // no draw buffer!!! if (_textureId == 0) { //CRLog::debug("updateTexture - new texture"); - _textureId = genTexture(); + _textureId = glSupport.genTexture(); if (!_textureId) return; } //CRLog::debug("updateTexture - setting image %dx%d", _drawbuf.width, _drawbuf.height); uint * pixels = _drawbuf.scanLine(0); - if (!setTextureImage(_textureId, _drawbuf.width, _drawbuf.height, cast(ubyte*)pixels)) { - deleteTexture(_textureId); + if (!glSupport.setTextureImage(_textureId, _drawbuf.width, _drawbuf.height, cast(ubyte*)pixels)) { + glSupport.deleteTexture(_textureId); _textureId = 0; return; } @@ -339,7 +339,7 @@ private class GLImageCache { if (_needUpdateTexture) updateTexture(); if (_textureId != 0) { - if (!isTexture(_textureId)) { + if (!glSupport.isTexture(_textureId)) { Log.e("Invalid texture ", _textureId); return; } @@ -371,12 +371,12 @@ private class GLImageCache { dstrc.bottom -= clip.bottom; } if (!dstrc.empty) - drawColorAndTextureRect(_textureId, _tdx, _tdy, srcrc, dstrc, color, srcrc.width() != dstrc.width() || srcrc.height() != dstrc.height()); + glSupport.drawColorAndTextureRect(_textureId, _tdx, _tdy, srcrc, dstrc, color, srcrc.width() != dstrc.width() || srcrc.height() != dstrc.height()); //drawColorAndTextureRect(vertices, texcoords, color, _textureId); if (rotationAngle) { // unset rotation - setRotation(rx, ry, 0); + glSupport.setRotation(rx, ry, 0); // glMatrixMode(GL_PROJECTION); // glPopMatrix(); // checkError("pop matrix"); @@ -576,7 +576,7 @@ private class GLGlyphCache { _drawbuf = null; } if (_textureId != 0) { - deleteTexture(_textureId); + glSupport.deleteTexture(_textureId); _textureId = 0; } } @@ -589,7 +589,7 @@ private class GLGlyphCache { return; // no draw buffer!!! if (_textureId == 0) { //CRLog::debug("updateTexture - new texture"); - _textureId = genTexture(); + _textureId = glSupport.genTexture(); if (!_textureId) return; } @@ -600,8 +600,8 @@ private class GLGlyphCache { _rgbaBuffer.length = len; for (int i = 0; i < len; i++) _rgbaBuffer[i] = ((cast(uint)pixels[i]) << 24) | 0x00FFFFFF; - if (!setTextureImage(_textureId, _drawbuf.width, _drawbuf.height, cast(ubyte*)_rgbaBuffer.ptr)) { - deleteTexture(_textureId); + if (!glSupport.setTextureImage(_textureId, _drawbuf.width, _drawbuf.height, cast(ubyte*)_rgbaBuffer.ptr)) { + glSupport.deleteTexture(_textureId); _textureId = 0; return; } @@ -667,7 +667,7 @@ private class GLGlyphCache { if (_needUpdateTexture) updateTexture(); if (_textureId != 0) { - if (!isTexture(_textureId)) { + if (!glSupport.isTexture(_textureId)) { Log.e("Invalid texture ", _textureId); return; } @@ -693,7 +693,7 @@ private class GLGlyphCache { } if (!dstrc.empty) { //Log.d("drawing glyph with color ", color); - drawColorAndTextureRect(_textureId, _tdx, _tdy, srcrc, dstrc, color, false); + glSupport.drawColorAndTextureRect(_textureId, _tdx, _tdy, srcrc, dstrc, color, false); } } @@ -818,7 +818,7 @@ class SolidRectSceneItem : SceneItem { _color = color; } override void draw() { - drawSolidFillRect(_rc, _color, _color, _color, _color); + glSupport.drawSolidFillRect(_rc, _color, _color, _color, _color); } } diff --git a/src/dlangui/graphics/glsupport.d b/src/dlangui/graphics/glsupport.d index fa5cb762..bfef4498 100644 --- a/src/dlangui/graphics/glsupport.d +++ b/src/dlangui/graphics/glsupport.d @@ -53,7 +53,8 @@ static this() { 0x0505: "GL_OUT_OF_MEMORY" ]; } -/* Convenient wrapper around glGetError() +/** + * Convenient wrapper around glGetError() * TODO use one of the DEBUG extensions instead */ bool checkError(string context="", string file=__FILE__, int line=__LINE__) @@ -67,295 +68,6 @@ bool checkError(string context="", string file=__FILE__, int line=__LINE__) return false; } -immutable float Z_2D = -2.0f; -void drawSolidFillRect(Rect rc, uint color1, uint color2, uint color3, uint color4) { - float[6 * 4] colors; - LVGLFillColor(color1, colors.ptr + 4*0, 1); - LVGLFillColor(color4, colors.ptr + 4*1, 1); - LVGLFillColor(color3, colors.ptr + 4*2, 1); - LVGLFillColor(color1, colors.ptr + 4*3, 1); - LVGLFillColor(color3, colors.ptr + 4*4, 1); - LVGLFillColor(color2, colors.ptr + 4*5, 1); - float x0 = cast(float)(rc.left); - float y0 = cast(float)(bufferDy-rc.top); - float x1 = cast(float)(rc.right); - float y1 = cast(float)(bufferDy-rc.bottom); - - // don't flip for framebuffer - if (currentFramebufferId) { - y0 = cast(float)(rc.top); - y1 = cast(float)(rc.bottom); - } - - float[3 * 6] vertices = [ - x0,y0,Z_2D, - x0,y1,Z_2D, - x1,y1,Z_2D, - x0,y0,Z_2D, - x1,y1,Z_2D, - x1,y0,Z_2D]; - if (_solidFillProgram !is null) { - //Log.d("solid fill: vertices ", vertices, " colors ", colors); - _solidFillProgram.execute(vertices, colors); - } else - Log.e("No program"); -} - -void drawColorAndTextureRect(uint textureId, int tdx, int tdy, Rect srcrc, Rect dstrc, uint color, bool linear) { - //Log.v("drawColorAndTextureRect tx=", textureId, " src=", srcrc, " dst=", dstrc); - drawColorAndTextureRect(textureId, tdx, tdy, srcrc.left, srcrc.top, srcrc.width(), srcrc.height(), dstrc.left, dstrc.top, dstrc.width(), dstrc.height(), color, linear); -} - -void drawColorAndTextureRect(uint textureId, int tdx, int tdy, int srcx, int srcy, int srcdx, int srcdy, int xx, int yy, int dx, int dy, uint color, bool linear) { - float[6*4] colors; - LVGLFillColor(color, colors.ptr, 6); - float dstx0 = cast(float)xx; - float dsty0 = cast(float)(bufferDy - (yy)); - float dstx1 = cast(float)(xx + dx); - float dsty1 = cast(float)(bufferDy - (yy + dy)); - - // don't flip for framebuffer - if (currentFramebufferId) { - dsty0 = cast(float)((yy)); - dsty1 = cast(float)((yy + dy)); - } - - float srcx0 = srcx / cast(float)tdx; - float srcy0 = srcy / cast(float)tdy; - float srcx1 = (srcx + srcdx) / cast(float)tdx; - float srcy1 = (srcy + srcdy) / cast(float)tdy; - float[3 * 6] vertices = [dstx0,dsty0,Z_2D, - dstx0,dsty1,Z_2D, - dstx1,dsty1,Z_2D, - dstx0,dsty0,Z_2D, - dstx1,dsty1,Z_2D, - dstx1,dsty0,Z_2D]; - float[2 * 6] texcoords = [srcx0,srcy0, srcx0,srcy1, srcx1,srcy1, srcx0,srcy0, srcx1,srcy1, srcx1,srcy0]; - _textureProgram.execute(vertices, texcoords, colors, textureId, linear); - //drawColorAndTextureRect(vertices, texcoords, colors, textureId, linear); -} - -/// generate new texture ID -uint genTexture() { - GLuint textureId = 0; - glGenTextures(1, &textureId); - return textureId; -} - -/// delete OpenGL texture -void deleteTexture(ref uint textureId) { - if (!textureId) - return; - if (glIsTexture(textureId) != GL_TRUE) { - Log.e("Invalid texture ", textureId); - return; - } - GLuint id = textureId; - glDeleteTextures(1, &id); - checkError("glDeleteTextures"); - textureId = 0; -} - -/// call glFlush -void flushGL() { - glFlush(); - checkError("glFlush"); -} - -bool setTextureImage(uint textureId, int dx, int dy, ubyte * pixels) { - //checkError("before setTextureImage"); - glActiveTexture(GL_TEXTURE0); - checkError("updateTexture - glActiveTexture"); - glBindTexture(GL_TEXTURE_2D, 0); - checkError("updateTexture - glBindTexture(0)"); - glBindTexture(GL_TEXTURE_2D, textureId); - checkError("updateTexture - glBindTexture"); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - checkError("updateTexture - glPixelStorei"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - checkError("updateTexture - glTexParameteri"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - checkError("updateTexture - glTexParameteri"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - checkError("updateTexture - glTexParameteri"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - checkError("updateTexture - glTexParameteri"); - - if (!glIsTexture(textureId)) - Log.e("second test - invalid texture passed to CRGLSupportImpl::setTextureImage"); - - // ORIGINAL: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dx, dy, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dx, dy, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - checkError("updateTexture - glTexImage2D"); - if (glGetError() != GL_NO_ERROR) { - Log.e("Cannot set image for texture"); - return false; - } - checkError("after setTextureImage"); - return true; -} - -bool setTextureImageAlpha(uint textureId, int dx, int dy, ubyte * pixels) { - checkError("before setTextureImageAlpha"); - glActiveTexture(GL_TEXTURE0); - checkError("updateTexture - glActiveTexture"); - glBindTexture(GL_TEXTURE_2D, 0); - checkError("updateTexture - glBindTexture(0)"); - glBindTexture(GL_TEXTURE_2D, textureId); - checkError("setTextureImageAlpha - glBindTexture"); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - checkError("setTextureImageAlpha - glPixelStorei"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - checkError("setTextureImageAlpha - glTexParameteri"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - checkError("setTextureImageAlpha - glTexParameteri"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - checkError("setTextureImageAlpha - glTexParameteri"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - checkError("setTextureImageAlpha - glTexParameteri"); - - if (!glIsTexture(textureId)) - Log.e("second test: invalid texture passed to CRGLSupportImpl::setTextureImageAlpha"); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, dx, dy, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels); - checkError("setTextureImageAlpha - glTexImage2D"); - if (glGetError() != GL_NO_ERROR) { - Log.e("Cannot set image for texture"); - return false; - } - glBindTexture(GL_TEXTURE_2D, 0); - checkError("updateTexture - glBindTexture(0)"); - checkError("after setTextureImageAlpha"); - return true; -} - -private uint currentFramebufferId; - -/// returns texture ID for buffer, 0 if failed -bool createFramebuffer(ref uint textureId, ref uint framebufferId, int dx, int dy) { - checkError("before createFramebuffer"); - bool res = true; - textureId = framebufferId = 0; - textureId = genTexture(); - if (!textureId) - return false; - GLuint fid = 0; - glGenFramebuffers(1, &fid); - if (checkError("createFramebuffer glGenFramebuffersOES")) return false; - framebufferId = fid; - glBindFramebuffer(GL_FRAMEBUFFER, framebufferId); - if (checkError("createFramebuffer glBindFramebuffer")) return false; - - glBindTexture(GL_TEXTURE_2D, textureId); - checkError("glBindTexture(GL_TEXTURE_2D, _textureId)"); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, dx, dy, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, null); - checkError("glTexImage2D"); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - checkError("texParameter"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - checkError("texParameter"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - checkError("texParameter"); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - checkError("texParameter"); - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0); - checkError("glFramebufferTexture2D"); - // Always check that our framebuffer is ok - if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - Log.e("glFramebufferTexture2D failed"); - res = false; - } - checkError("glCheckFramebufferStatus"); - //glClearColor(0.5f, 0, 0, 1); - glClearColor(0.5f, 0.5f, 0.5f, 1.0f); - checkError("glClearColor"); - glClear(GL_COLOR_BUFFER_BIT); - checkError("glClear"); - checkError("after createFramebuffer"); - //CRLog::trace("CRGLSupportImpl::createFramebuffer %d,%d texture=%d, buffer=%d", dx, dy, textureId, framebufferId); - currentFramebufferId = framebufferId; - - glBindTexture(GL_TEXTURE_2D, 0); - checkError("createFramebuffer - glBindTexture(0)"); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - checkError("createFramebuffer - glBindFramebuffer(0)"); - - return res; -} - -void deleteFramebuffer(ref uint framebufferId) { - //CRLog::debug("GLDrawBuf::deleteFramebuffer"); - if (framebufferId != 0) { - glBindFramebuffer(GL_FRAMEBUFFER, 0); - checkError("deleteFramebuffer - glBindFramebuffer"); - GLuint fid = framebufferId; - glDeleteFramebuffers(1, &fid); - checkError("deleteFramebuffer - glDeleteFramebuffer"); - } - //CRLog::trace("CRGLSupportImpl::deleteFramebuffer(%d)", framebufferId); - framebufferId = 0; - checkError("after deleteFramebuffer"); - currentFramebufferId = 0; -} - -bool bindFramebuffer(uint framebufferId) { - //CRLog::trace("CRGLSupportImpl::bindFramebuffer(%d)", framebufferId); - glBindFramebuffer(GL_FRAMEBUFFER, framebufferId); - currentFramebufferId = framebufferId; - return !checkError("glBindFramebuffer"); -} - -/// projection matrix -//private mat4 m; -/// current gl buffer width -private int bufferDx; -/// current gl buffer height -private int bufferDy; - -//private float[16] matrix; -private float[16] qtmatrix; - -void QMatrix4x4_ortho(float left, float right, float bottom, float top, float nearPlane, float farPlane) -{ - // Bail out if the projection volume is zero-sized. - if (left == right || bottom == top || nearPlane == farPlane) - return; - - // Construct the projection. - float width = right - left; - float invheight = top - bottom; - float clip = farPlane - nearPlane; - float[4][4] m; - m[0][0] = 2.0f / width; - m[1][0] = 0.0f; - m[2][0] = 0.0f; - m[3][0] = -(left + right) / width; - m[0][1] = 0.0f; - m[1][1] = 2.0f / invheight; - m[2][1] = 0.0f; - m[3][1] = -(top + bottom) / invheight; - m[0][2] = 0.0f; - m[1][2] = 0.0f; - m[2][2] = -2.0f / clip; - m[3][2] = -(nearPlane + farPlane) / clip; - m[0][3] = 0.0f; - m[1][3] = 0.0f; - m[2][3] = 0.0f; - m[3][3] = 1.0f; - for (int y = 0; y < 4; y++) - for (int x = 0; x < 4; x++) - qtmatrix[y * 4 + x] = m[y][x]; -} - -void setOrthoProjection(int dx, int dy) { - bufferDx = dx; - bufferDy = dy; - QMatrix4x4_ortho(0, dx, 0, dy, 0.5f, 50.0f); - glViewport(0, 0, dx, dy); - checkError("glViewport"); -} class GLProgram { @property abstract string vertexSource(); @@ -503,7 +215,7 @@ class SolidFillProgram : GLProgram { bind(); //glUniformMatrix4fv(matrixLocation, 1, false, m.value_ptr); //glUniformMatrix4fv(matrixLocation, 1, false, matrix.ptr); - glUniformMatrix4fv(matrixLocation, 1, false, qtmatrix.ptr); + glUniformMatrix4fv(matrixLocation, 1, false, glSupport.qtmatrix.ptr); checkError("glUniformMatrix4fv"); } @@ -704,57 +416,366 @@ class TextureProgram : SolidFillProgram { } } -__gshared TextureProgram _textureProgram; -__gshared SolidFillProgram _solidFillProgram; +__gshared GLSupport _glSupport; +@property GLSupport glSupport() { + if (!_glSupport) { + Log.f("GLSupport is not initialized"); + assert(false, "GLSupport is not initialized"); + } + if (!_glSupport.valid) { + Log.e("GLSupport programs are not initialized"); + } + return _glSupport; +} -bool initShaders() { - if (_textureProgram is null) { - _textureProgram = new TextureProgram(); - if (!_textureProgram.compile()) +class GLSupport { + + TextureProgram _textureProgram; + SolidFillProgram _solidFillProgram; + + @property bool valid() { + return _textureProgram && _solidFillProgram; + } + + bool initShaders() { + if (_textureProgram is null) { + _textureProgram = new TextureProgram(); + if (!_textureProgram.compile()) + return false; + } + if (_solidFillProgram is null) { + _solidFillProgram = new SolidFillProgram(); + if (!_solidFillProgram.compile()) + return false; + } + Log.d("Shaders compiled successfully"); + return true; + } + + bool uninitShaders() { + Log.d("Uniniting shaders"); + if (_textureProgram !is null) { + destroy(_textureProgram); + _textureProgram = null; + } + if (_solidFillProgram !is null) { + destroy(_solidFillProgram); + _solidFillProgram = null; + } + return true; + } + + bool isTexture(uint textureId) { + return glIsTexture(textureId) == GL_TRUE; + } + + void setRotation(int x, int y, int rotationAngle) { + /* + this->rotationAngle = rotationAngle; + rotationX = x; + rotationY = y; + if (!currentFramebufferId) { + rotationY = bufferDy - rotationY; + } + + QMatrix4x4 matrix2; + matrix2.ortho(0, bufferDx, 0, bufferDy, 0.5f, 5.0f); + if (rotationAngle) { + matrix2.translate(rotationX, rotationY, 0); + matrix2.rotate(rotationAngle, 0, 0, 1); + matrix2.translate(-rotationX, -rotationY, 0); + } + matrix2.copyDataTo(m); + */ + } + static immutable float Z_2D = -2.0f; + void drawSolidFillRect(Rect rc, uint color1, uint color2, uint color3, uint color4) { + float[6 * 4] colors; + LVGLFillColor(color1, colors.ptr + 4*0, 1); + LVGLFillColor(color4, colors.ptr + 4*1, 1); + LVGLFillColor(color3, colors.ptr + 4*2, 1); + LVGLFillColor(color1, colors.ptr + 4*3, 1); + LVGLFillColor(color3, colors.ptr + 4*4, 1); + LVGLFillColor(color2, colors.ptr + 4*5, 1); + float x0 = cast(float)(rc.left); + float y0 = cast(float)(bufferDy-rc.top); + float x1 = cast(float)(rc.right); + float y1 = cast(float)(bufferDy-rc.bottom); + + // don't flip for framebuffer + if (currentFramebufferId) { + y0 = cast(float)(rc.top); + y1 = cast(float)(rc.bottom); + } + + float[3 * 6] vertices = [ + x0,y0,Z_2D, + x0,y1,Z_2D, + x1,y1,Z_2D, + x0,y0,Z_2D, + x1,y1,Z_2D, + x1,y0,Z_2D]; + if (_solidFillProgram !is null) { + //Log.d("solid fill: vertices ", vertices, " colors ", colors); + _solidFillProgram.execute(vertices, colors); + } else + Log.e("No program"); + } + + void drawColorAndTextureRect(uint textureId, int tdx, int tdy, Rect srcrc, Rect dstrc, uint color, bool linear) { + //Log.v("drawColorAndTextureRect tx=", textureId, " src=", srcrc, " dst=", dstrc); + drawColorAndTextureRect(textureId, tdx, tdy, srcrc.left, srcrc.top, srcrc.width(), srcrc.height(), dstrc.left, dstrc.top, dstrc.width(), dstrc.height(), color, linear); + } + + void drawColorAndTextureRect(uint textureId, int tdx, int tdy, int srcx, int srcy, int srcdx, int srcdy, int xx, int yy, int dx, int dy, uint color, bool linear) { + float[6*4] colors; + LVGLFillColor(color, colors.ptr, 6); + float dstx0 = cast(float)xx; + float dsty0 = cast(float)(bufferDy - (yy)); + float dstx1 = cast(float)(xx + dx); + float dsty1 = cast(float)(bufferDy - (yy + dy)); + + // don't flip for framebuffer + if (currentFramebufferId) { + dsty0 = cast(float)((yy)); + dsty1 = cast(float)((yy + dy)); + } + + float srcx0 = srcx / cast(float)tdx; + float srcy0 = srcy / cast(float)tdy; + float srcx1 = (srcx + srcdx) / cast(float)tdx; + float srcy1 = (srcy + srcdy) / cast(float)tdy; + float[3 * 6] vertices = [dstx0,dsty0,Z_2D, + dstx0,dsty1,Z_2D, + dstx1,dsty1,Z_2D, + dstx0,dsty0,Z_2D, + dstx1,dsty1,Z_2D, + dstx1,dsty0,Z_2D]; + float[2 * 6] texcoords = [srcx0,srcy0, srcx0,srcy1, srcx1,srcy1, srcx0,srcy0, srcx1,srcy1, srcx1,srcy0]; + _textureProgram.execute(vertices, texcoords, colors, textureId, linear); + //drawColorAndTextureRect(vertices, texcoords, colors, textureId, linear); + } + + /// generate new texture ID + uint genTexture() { + GLuint textureId = 0; + glGenTextures(1, &textureId); + return textureId; + } + + /// delete OpenGL texture + void deleteTexture(ref uint textureId) { + if (!textureId) + return; + if (glIsTexture(textureId) != GL_TRUE) { + Log.e("Invalid texture ", textureId); + return; + } + GLuint id = textureId; + glDeleteTextures(1, &id); + checkError("glDeleteTextures"); + textureId = 0; + } + + /// call glFlush + void flushGL() { + glFlush(); + checkError("glFlush"); + } + + bool setTextureImage(uint textureId, int dx, int dy, ubyte * pixels) { + //checkError("before setTextureImage"); + glActiveTexture(GL_TEXTURE0); + checkError("updateTexture - glActiveTexture"); + glBindTexture(GL_TEXTURE_2D, 0); + checkError("updateTexture - glBindTexture(0)"); + glBindTexture(GL_TEXTURE_2D, textureId); + checkError("updateTexture - glBindTexture"); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + checkError("updateTexture - glPixelStorei"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + checkError("updateTexture - glTexParameteri"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + checkError("updateTexture - glTexParameteri"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + checkError("updateTexture - glTexParameteri"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + checkError("updateTexture - glTexParameteri"); + + if (!glIsTexture(textureId)) + Log.e("second test - invalid texture passed to CRGLSupportImpl::setTextureImage"); + + // ORIGINAL: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dx, dy, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dx, dy, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + checkError("updateTexture - glTexImage2D"); + if (glGetError() != GL_NO_ERROR) { + Log.e("Cannot set image for texture"); return false; + } + checkError("after setTextureImage"); + return true; } - if (_solidFillProgram is null) { - _solidFillProgram = new SolidFillProgram(); - if (!_solidFillProgram.compile()) + + bool setTextureImageAlpha(uint textureId, int dx, int dy, ubyte * pixels) { + checkError("before setTextureImageAlpha"); + glActiveTexture(GL_TEXTURE0); + checkError("updateTexture - glActiveTexture"); + glBindTexture(GL_TEXTURE_2D, 0); + checkError("updateTexture - glBindTexture(0)"); + glBindTexture(GL_TEXTURE_2D, textureId); + checkError("setTextureImageAlpha - glBindTexture"); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + checkError("setTextureImageAlpha - glPixelStorei"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + checkError("setTextureImageAlpha - glTexParameteri"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + checkError("setTextureImageAlpha - glTexParameteri"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + checkError("setTextureImageAlpha - glTexParameteri"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + checkError("setTextureImageAlpha - glTexParameteri"); + + if (!glIsTexture(textureId)) + Log.e("second test: invalid texture passed to CRGLSupportImpl::setTextureImageAlpha"); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, dx, dy, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels); + checkError("setTextureImageAlpha - glTexImage2D"); + if (glGetError() != GL_NO_ERROR) { + Log.e("Cannot set image for texture"); return false; - } - Log.d("Shaders compiled successfully"); - return true; -} - -bool uninitShaders() { - Log.d("Uniniting shaders"); - if (_textureProgram !is null) { - destroy(_textureProgram); - _textureProgram = null; - } - if (_solidFillProgram !is null) { - destroy(_solidFillProgram); - _solidFillProgram = null; - } - return true; -} - -bool isTexture(uint textureId) { - return glIsTexture(textureId) == GL_TRUE; -} - -void setRotation(int x, int y, int rotationAngle) { - /* - this->rotationAngle = rotationAngle; - rotationX = x; - rotationY = y; - if (!currentFramebufferId) { - rotationY = bufferDy - rotationY; + } + glBindTexture(GL_TEXTURE_2D, 0); + checkError("updateTexture - glBindTexture(0)"); + checkError("after setTextureImageAlpha"); + return true; } - QMatrix4x4 matrix2; - matrix2.ortho(0, bufferDx, 0, bufferDy, 0.5f, 5.0f); - if (rotationAngle) { - matrix2.translate(rotationX, rotationY, 0); - matrix2.rotate(rotationAngle, 0, 0, 1); - matrix2.translate(-rotationX, -rotationY, 0); + private uint currentFramebufferId; + + /// returns texture ID for buffer, 0 if failed + bool createFramebuffer(ref uint textureId, ref uint framebufferId, int dx, int dy) { + checkError("before createFramebuffer"); + bool res = true; + textureId = framebufferId = 0; + textureId = genTexture(); + if (!textureId) + return false; + GLuint fid = 0; + glGenFramebuffers(1, &fid); + if (checkError("createFramebuffer glGenFramebuffersOES")) return false; + framebufferId = fid; + glBindFramebuffer(GL_FRAMEBUFFER, framebufferId); + if (checkError("createFramebuffer glBindFramebuffer")) return false; + + glBindTexture(GL_TEXTURE_2D, textureId); + checkError("glBindTexture(GL_TEXTURE_2D, _textureId)"); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, dx, dy, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, null); + checkError("glTexImage2D"); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + checkError("texParameter"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + checkError("texParameter"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + checkError("texParameter"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + checkError("texParameter"); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0); + checkError("glFramebufferTexture2D"); + // Always check that our framebuffer is ok + if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + Log.e("glFramebufferTexture2D failed"); + res = false; + } + checkError("glCheckFramebufferStatus"); + //glClearColor(0.5f, 0, 0, 1); + glClearColor(0.5f, 0.5f, 0.5f, 1.0f); + checkError("glClearColor"); + glClear(GL_COLOR_BUFFER_BIT); + checkError("glClear"); + checkError("after createFramebuffer"); + //CRLog::trace("CRGLSupportImpl::createFramebuffer %d,%d texture=%d, buffer=%d", dx, dy, textureId, framebufferId); + currentFramebufferId = framebufferId; + + glBindTexture(GL_TEXTURE_2D, 0); + checkError("createFramebuffer - glBindTexture(0)"); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + checkError("createFramebuffer - glBindFramebuffer(0)"); + + return res; } - matrix2.copyDataTo(m); - */ + + void deleteFramebuffer(ref uint framebufferId) { + //CRLog::debug("GLDrawBuf::deleteFramebuffer"); + if (framebufferId != 0) { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + checkError("deleteFramebuffer - glBindFramebuffer"); + GLuint fid = framebufferId; + glDeleteFramebuffers(1, &fid); + checkError("deleteFramebuffer - glDeleteFramebuffer"); + } + //CRLog::trace("CRGLSupportImpl::deleteFramebuffer(%d)", framebufferId); + framebufferId = 0; + checkError("after deleteFramebuffer"); + currentFramebufferId = 0; + } + + bool bindFramebuffer(uint framebufferId) { + //CRLog::trace("CRGLSupportImpl::bindFramebuffer(%d)", framebufferId); + glBindFramebuffer(GL_FRAMEBUFFER, framebufferId); + currentFramebufferId = framebufferId; + return !checkError("glBindFramebuffer"); + } + + /// projection matrix + //private mat4 m; + /// current gl buffer width + private int bufferDx; + /// current gl buffer height + private int bufferDy; + //private float[16] matrix; + private float[16] qtmatrix; + + void QMatrix4x4_ortho(float left, float right, float bottom, float top, float nearPlane, float farPlane) + { + // Bail out if the projection volume is zero-sized. + if (left == right || bottom == top || nearPlane == farPlane) + return; + + // Construct the projection. + float width = right - left; + float invheight = top - bottom; + float clip = farPlane - nearPlane; + float[4][4] m; + m[0][0] = 2.0f / width; + m[1][0] = 0.0f; + m[2][0] = 0.0f; + m[3][0] = -(left + right) / width; + m[0][1] = 0.0f; + m[1][1] = 2.0f / invheight; + m[2][1] = 0.0f; + m[3][1] = -(top + bottom) / invheight; + m[0][2] = 0.0f; + m[1][2] = 0.0f; + m[2][2] = -2.0f / clip; + m[3][2] = -(nearPlane + farPlane) / clip; + m[0][3] = 0.0f; + m[1][3] = 0.0f; + m[2][3] = 0.0f; + m[3][3] = 1.0f; + for (int y = 0; y < 4; y++) + for (int x = 0; x < 4; x++) + qtmatrix[y * 4 + x] = m[y][x]; + } + + void setOrthoProjection(int dx, int dy) { + bufferDx = dx; + bufferDy = dy; + QMatrix4x4_ortho(0, dx, 0, dy, 0.5f, 50.0f); + glViewport(0, 0, dx, dy); + checkError("glViewport"); + } + } + diff --git a/src/dlangui/platforms/sdl/sdlapp.d b/src/dlangui/platforms/sdl/sdlapp.d index e7c69825..58732ddc 100644 --- a/src/dlangui/platforms/sdl/sdlapp.d +++ b/src/dlangui/platforms/sdl/sdlapp.d @@ -97,6 +97,8 @@ class SDLWindow : Window { version(USE_OPENGL) { if (_enableOpengl) windowFlags |= SDL_WINDOW_OPENGL; + if (!_glSupport) + _glSupport = new GLSupport(); } _win = SDL_CreateWindow(toUTF8(_caption).toStringz, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 700, 500, @@ -127,7 +129,7 @@ class SDLWindow : Window { } else if (!_gl3Reloaded) { DerelictGL3.reload(); _gl3Reloaded = true; - if (!initShaders()) + if (!glSupport.valid && !glSupport.initShaders()) _enableOpengl = false; } } diff --git a/src/dlangui/platforms/windows/winapp.d b/src/dlangui/platforms/windows/winapp.d index 023a0423..60c65ad3 100644 --- a/src/dlangui/platforms/windows/winapp.d +++ b/src/dlangui/platforms/windows/winapp.d @@ -154,10 +154,12 @@ version (USE_OPENGL) { class Win32Window : Window { Win32Platform _platform; + HWND _hwnd; version (USE_OPENGL) { HGLRC _hGLRC; // opengl context HPALETTE _hPalette; + GLSupport _gl; } dstring _caption; Win32ColorDrawBuf _drawbuf; @@ -167,6 +169,7 @@ class Win32Window : Window { Win32Window w32parent = cast(Win32Window)parent; HWND parenthwnd = w32parent ? w32parent._hwnd : null; _platform = platform; + _gl = new GLSupport(); _caption = windowCaption; _flags = flags; uint ws = WS_CLIPCHILDREN | WS_CLIPSIBLINGS; @@ -199,7 +202,9 @@ class Win32Window : Window { _hPalette = setupPalette(hDC); _hGLRC = wglCreateContext(hDC); if (_hGLRC) { + wglMakeCurrent(hDC, _hGLRC); + _glSupport = _gl; if (!DERELICT_GL3_RELOADED) { // run this code only once @@ -208,7 +213,7 @@ class Win32Window : Window { import derelict.opengl3.gl3; DerelictGL3.reload(); // successful - if (initShaders()) { + if (glSupport.initShaders()) { setOpenglEnabled(); useOpengl = true; } else { @@ -218,7 +223,7 @@ class Win32Window : Window { Log.e("Derelict exception", e); } } else { - if (initShaders()) { + if (glSupport.initShaders()) { setOpenglEnabled(); useOpengl = true; } else { @@ -252,6 +257,7 @@ class Win32Window : Window { //scope(exit) EndPaint(_hwnd, &ps); HDC hdc = GetDC(_hwnd); wglMakeCurrent(hdc, _hGLRC); + _glSupport = _gl; glDisable(GL_DEPTH_TEST); glViewport(0, 0, _dx, _dy); float a = 1.0f; @@ -288,7 +294,10 @@ class Win32Window : Window { version (USE_OPENGL) { import derelict.opengl3.wgl; if (_hGLRC) { - uninitShaders(); + glSupport.uninitShaders(); + delete _glSupport; + _glSupport = null; + _gl = null; wglMakeCurrent (null, null) ; wglDeleteContext(_hGLRC); _hGLRC = null; @@ -470,7 +479,7 @@ class Win32Window : Window { } void onPaint() { - Log.d("onPaint()"); + debug(DebugRedraw) Log.d("onPaint()"); long paintStart = currentTimeMillis; version (USE_OPENGL) { if (useOpengl && _hGLRC) { @@ -482,7 +491,7 @@ class Win32Window : Window { paintUsingGDI(); } long paintEnd = currentTimeMillis; - Log.d("WM_PAINT handling took ", paintEnd - paintStart, " ms"); + debug(DebugRedraw) Log.d("WM_PAINT handling took ", paintEnd - paintStart, " ms"); } protected ButtonDetails _lbutton; From d709a26434c2255f571b68afa76a47db23bf2e23 Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Mon, 12 Jan 2015 14:18:32 +0300 Subject: [PATCH 02/20] fix win32 window icon - issue #28 --- src/dlangui/platforms/windows/win32drawbuf.d | 3 ++- src/dlangui/platforms/windows/winapp.d | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/dlangui/platforms/windows/win32drawbuf.d b/src/dlangui/platforms/windows/win32drawbuf.d index e9d6d42f..d97eac64 100644 --- a/src/dlangui/platforms/windows/win32drawbuf.d +++ b/src/dlangui/platforms/windows/win32drawbuf.d @@ -42,6 +42,7 @@ class Win32ColorDrawBuf : ColorDrawBufBase { /// create resized copy of ColorDrawBuf this(ColorDrawBuf v, int dx, int dy) { this(dx, dy); + resetClipping(); fill(0xFFFFFFFF); if (_dx == dx && _dy == dy) drawImage(0, 0, v); @@ -87,7 +88,7 @@ class Win32ColorDrawBuf : ColorDrawBufBase { //return CreateBitmap(_dx, _dy, 1, 1, buf.ptr); } /// destroy object, but leave bitmap as is - HBITMAP destoryLeavingBitmap() { + HBITMAP destroyLeavingBitmap() { HBITMAP res = _drawbmp; _drawbmp = null; destroy(this); diff --git a/src/dlangui/platforms/windows/winapp.d b/src/dlangui/platforms/windows/winapp.d index 60c65ad3..123fae09 100644 --- a/src/dlangui/platforms/windows/winapp.d +++ b/src/dlangui/platforms/windows/winapp.d @@ -449,7 +449,7 @@ class Win32Window : Window { resizedicon.invertAlpha(); ICONINFO ii; HBITMAP mask = resizedicon.createTransparencyBitmap(); - HBITMAP color = resizedicon.destoryLeavingBitmap(); + HBITMAP color = resizedicon.destroyLeavingBitmap(); ii.fIcon = TRUE; ii.xHotspot = 0; ii.yHotspot = 0; @@ -457,8 +457,8 @@ class Win32Window : Window { ii.hbmColor = color; _icon = CreateIconIndirect(&ii); if (_icon) { - SendMessage(_hwnd, WM_SETICON, ICON_SMALL, cast(int)_icon); - SendMessage(_hwnd, WM_SETICON, ICON_BIG, cast(int)_icon); + SendMessageW(_hwnd, WM_SETICON, ICON_SMALL, cast(LPARAM)_icon); + SendMessageW(_hwnd, WM_SETICON, ICON_BIG, cast(LPARAM)_icon); } else { Log.e("failed to create icon"); } From 24a033f1d9d355ad1a220b9fe61a76b4425529e1 Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Mon, 12 Jan 2015 14:18:58 +0300 Subject: [PATCH 03/20] don't shrink non-fill-parent items in linear layout --- src/dlangui/widgets/layouts.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dlangui/widgets/layouts.d b/src/dlangui/widgets/layouts.d index 2f8e5a02..2546b518 100644 --- a/src/dlangui/widgets/layouts.d +++ b/src/dlangui/widgets/layouts.d @@ -194,7 +194,7 @@ class LayoutItems { // need resize of some children needResize = true; // resize all if need to shrink or only resizable are too small to correct delta - needForceResize = delta < 0 || resizableWeight == 0; // || resizableSize * 2 / 3 < delta; // do we need resize non-FILL_PARENT items? + needForceResize = /*delta < 0 || */ resizableWeight == 0; // || resizableSize * 2 / 3 < delta; // do we need resize non-FILL_PARENT items? // calculate scale factor: weight / delta * 10000 if (needForceResize && nonresizableSize + resizableSize > 0) scaleFactor = 10000 * delta / (nonresizableSize + resizableSize); From bdba7bd15ba9543ba5627e4f747382d4ebbfab98 Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Mon, 12 Jan 2015 17:14:57 +0300 Subject: [PATCH 04/20] fix win32 build w/o opengl --- src/dlangui/platforms/windows/winapp.d | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/dlangui/platforms/windows/winapp.d b/src/dlangui/platforms/windows/winapp.d index 123fae09..232ed755 100644 --- a/src/dlangui/platforms/windows/winapp.d +++ b/src/dlangui/platforms/windows/winapp.d @@ -169,7 +169,9 @@ class Win32Window : Window { Win32Window w32parent = cast(Win32Window)parent; HWND parenthwnd = w32parent ? w32parent._hwnd : null; _platform = platform; - _gl = new GLSupport(); + version (USE_OPENGL) { + _gl = new GLSupport(); + } _caption = windowCaption; _flags = flags; uint ws = WS_CLIPCHILDREN | WS_CLIPSIBLINGS; @@ -295,7 +297,7 @@ class Win32Window : Window { import derelict.opengl3.wgl; if (_hGLRC) { glSupport.uninitShaders(); - delete _glSupport; + destroy(_glSupport); _glSupport = null; _gl = null; wglMakeCurrent (null, null) ; @@ -960,12 +962,17 @@ LRESULT WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { if (window !is null) { WINDOWPOS * pos = cast(WINDOWPOS*)lParam; + Log.d("WM_WINDOWPOSCHANGED: ", *pos); GetClientRect(hwnd, &rect); - int dx = rect.right - rect.left; - int dy = rect.bottom - rect.top; //window.onResize(pos.cx, pos.cy); - window.onResize(dx, dy); - InvalidateRect(hwnd, null, FALSE); + //if (!(pos.flags & 0x8000)) { //SWP_NOACTIVATE)) { + //if (pos.x > -30000) { + int dx = rect.right - rect.left; + int dy = rect.bottom - rect.top; + window.onResize(dx, dy); + InvalidateRect(hwnd, null, FALSE); + //} + //} } } return 0; From cc838718ef0b91ab8271a8f393ed35351aa58fbf Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Mon, 12 Jan 2015 17:43:33 +0300 Subject: [PATCH 05/20] fix LinearLayout --- dlanguilib.visualdproj | 2 +- examples/example1/example1.visualdproj | 2 +- src/dlangui/dialogs/dialog.d | 7 ++++-- src/dlangui/dialogs/filedlg.d | 33 ++++++++++++++++++------- src/dlangui/platforms/common/platform.d | 2 ++ src/dlangui/widgets/layouts.d | 9 +++++-- src/dlangui/widgets/widget.d | 9 +++++-- 7 files changed, 47 insertions(+), 17 deletions(-) diff --git a/dlanguilib.visualdproj b/dlanguilib.visualdproj index a28e84c3..fbb01e43 100644 --- a/dlanguilib.visualdproj +++ b/dlanguilib.visualdproj @@ -66,7 +66,7 @@ 0 DebugFocus 0 - USE_OPENGL USE_SDL Unicode + USE_OPENGL Unicode 0 0 1 diff --git a/examples/example1/example1.visualdproj b/examples/example1/example1.visualdproj index c1aca680..8170912c 100644 --- a/examples/example1/example1.visualdproj +++ b/examples/example1/example1.visualdproj @@ -66,7 +66,7 @@ 0 0 - USE_OPENGL USE_SDL Unicode + USE_OPENGL Unicode 0 3 0 diff --git a/src/dlangui/dialogs/dialog.d b/src/dlangui/dialogs/dialog.d index 56b86d68..1955abf1 100644 --- a/src/dlangui/dialogs/dialog.d +++ b/src/dlangui/dialogs/dialog.d @@ -52,7 +52,7 @@ class Dialog : VerticalLayout { Signal!DialogResultHandler onDialogResult; this(UIString caption, Window parentWindow = null, uint flags = DialogFlag.Modal) { - super("dlg"); + super("dialog-main-widget"); _caption = caption; _parentWindow = parentWindow; _flags = flags; @@ -155,8 +155,11 @@ class Dialog : VerticalLayout { uint wflags = 0; if (_flags & DialogFlag.Modal) wflags |= WindowFlag.Modal; - if (_flags & DialogFlag.Resizable) + if (_flags & DialogFlag.Resizable) { wflags |= WindowFlag.Resizable; + layoutWidth = FILL_PARENT; + layoutHeight = FILL_PARENT; + } _window = Platform.instance.createWindow(_caption, _parentWindow, wflags); if (_window && _icon) _window.windowIcon = drawableCache.getImage(_icon); diff --git a/src/dlangui/dialogs/filedlg.d b/src/dlangui/dialogs/filedlg.d index 67dde005..81e2f252 100644 --- a/src/dlangui/dialogs/filedlg.d +++ b/src/dlangui/dialogs/filedlg.d @@ -133,13 +133,6 @@ class FileDialog : Dialog, CustomGridCellAdapter { return null; } - /// Set widget rectangle to specified value and layout widget contents. (Step 2 of two phase layout). - override void layout(Rect rc) { - super.layout(rc); - _fileList.autoFitColumnWidths(); - _fileList.fillColumnWidth(1); - } - protected bool upLevel() { return openDirectory(parentDir(_path), _path); } @@ -310,11 +303,11 @@ class FileDialog : Dialog, CustomGridCellAdapter { layoutWidth(FILL_PARENT); layoutWidth(FILL_PARENT); minWidth = 600; - minHeight = 400; + //minHeight = 400; LinearLayout content = new HorizontalLayout("dlgcontent"); - content.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT).minWidth(400).minHeight(300); + content.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT); //.minWidth(400).minHeight(300); leftPanel = new VerticalLayout("places"); leftPanel.addChild(createRootsList()); @@ -387,6 +380,28 @@ class FileDialog : Dialog, CustomGridCellAdapter { } + /// Set widget rectangle to specified value and layout widget contents. (Step 2 of two phase layout). + override void layout(Rect rc) { + super.layout(rc); + _fileList.autoFitColumnWidths(); + _fileList.fillColumnWidth(1); + } + + + ///// Measure widget according to desired width and height constraints. (Step 1 of two phase layout). + //override void measure(int parentWidth, int parentHeight) { + // super.measure(parentWidth, parentHeight); + // for(int i = 0; i < childCount; i++) { + // Widget w = child(i); + // Log.d("id=", w.id, " measuredHeight=", w.measuredHeight ); + // for (int j = 0; j < w.childCount; j++) { + // Widget w2 = w.child(j); + // Log.d(" id=", w2.id, " measuredHeight=", w.measuredHeight ); + // } + // } + // Log.d("this id=", id, " measuredHeight=", measuredHeight); + //} + override void onShow() { _fileList.setFocus(); } diff --git a/src/dlangui/platforms/common/platform.d b/src/dlangui/platforms/common/platform.d index 303e1486..6de8ec04 100644 --- a/src/dlangui/platforms/common/platform.d +++ b/src/dlangui/platforms/common/platform.d @@ -107,11 +107,13 @@ class Window { Log.d("onResize ", _dx, "x", _dy); long measureStart = currentTimeMillis; measure(); + //Log.d("measured size: ", _mainWidget.measuredWidth, "x", _mainWidget.measuredHeight); long measureEnd = currentTimeMillis; Log.d("measure took ", measureEnd - measureStart, " ms"); layout(); long layoutEnd = currentTimeMillis; Log.d("layout took ", layoutEnd - measureEnd, " ms"); + //Log.d("layout position: ", _mainWidget.pos); } } diff --git a/src/dlangui/widgets/layouts.d b/src/dlangui/widgets/layouts.d index 2546b518..54a3fec3 100644 --- a/src/dlangui/widgets/layouts.d +++ b/src/dlangui/widgets/layouts.d @@ -174,15 +174,20 @@ class LayoutItems { contentSecondarySize = maxItem; else contentSecondarySize = rc.width; - if (_layoutHeight == FILL_PARENT || totalSize > rc.height) + if (_layoutHeight == FILL_PARENT && totalSize < rc.height && resizableSize > 0) { delta = rc.height - totalSize; // total space to add to fit + } else if (totalSize > rc.height) { + delta = rc.height - totalSize; // total space to reduce to fit + } } else { if (_layoutHeight == WRAP_CONTENT && maxItem < rc.height) contentSecondarySize = maxItem; else contentSecondarySize = rc.height; - if (_layoutWidth == FILL_PARENT || totalSize > rc.width) + if (_layoutWidth == FILL_PARENT && totalSize < rc.width && resizableSize > 0) delta = rc.width - totalSize; // total space to add to fit + else if (totalSize > rc.width) + delta = rc.width - totalSize; // total space to reduce to fit } // calculate resize options and scale bool needForceResize = false; diff --git a/src/dlangui/widgets/widget.d b/src/dlangui/widgets/widget.d index 3ecd6571..bed6141a 100644 --- a/src/dlangui/widgets/widget.d +++ b/src/dlangui/widgets/widget.d @@ -1061,14 +1061,19 @@ class Widget { int maxw = maxWidth; int minh = minHeight; int maxh = maxHeight; - if (dx < minw) + if (minw != SIZE_UNSPECIFIED && dx < minw) dx = minw; - if (dy < minh) + if (minh != SIZE_UNSPECIFIED && dy < minh) dy = minh; if (maxw != SIZE_UNSPECIFIED && dx > maxw) dx = maxw; if (maxh != SIZE_UNSPECIFIED && dy > maxh) dy = maxh; + // apply FILL_PARENT + //if (parentWidth != SIZE_UNSPECIFIED && layoutWidth == FILL_PARENT) + // dx = parentWidth; + //if (parentHeight != SIZE_UNSPECIFIED && layoutHeight == FILL_PARENT) + // dy = parentHeight; // apply max parent size constraint if (parentWidth != SIZE_UNSPECIFIED && dx > parentWidth) dx = parentWidth; From 55f9a43a2fa006d2319e2da70830624fc2fb838d Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Tue, 13 Jan 2015 15:19:26 +0300 Subject: [PATCH 06/20] fix tree view and scroll widget --- src/dlangui/widgets/scroll.d | 12 ++++++++++-- src/dlangui/widgets/tree.d | 29 ++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/dlangui/widgets/scroll.d b/src/dlangui/widgets/scroll.d index 53c08f67..0d4e8a3a 100644 --- a/src/dlangui/widgets/scroll.d +++ b/src/dlangui/widgets/scroll.d @@ -217,11 +217,19 @@ class ScrollWidgetBase : WidgetGroup, OnScrollHandler { pwidth -= m.left + m.right + p.left + p.right; if (parentHeight != SIZE_UNSPECIFIED) pheight -= m.top + m.bottom + p.top + p.bottom; - if (_hscrollbar) + if (_hscrollbar) { _hscrollbar.measure(pwidth, pheight); - if (_vscrollbar) + } + if (_vscrollbar) { _vscrollbar.measure(pwidth, pheight); + } Point sz = fullContentSize(); + if (_hscrollbar) { + sz.y += _hscrollbar.measuredHeight; + } + if (_vscrollbar) { + sz.x += _vscrollbar.measuredWidth; + } measuredContent(parentWidth, parentHeight, sz.x, sz.y); } diff --git a/src/dlangui/widgets/tree.d b/src/dlangui/widgets/tree.d index e2140dea..435c83e5 100644 --- a/src/dlangui/widgets/tree.d +++ b/src/dlangui/widgets/tree.d @@ -122,6 +122,10 @@ class TreeItem { p = p._parent; return cast(TreeItems)p; } + + void clear() { + _children.clear(); + } @property TreeItem parent() { return _parent; } @property protected TreeItem parent(TreeItem p) { _parent = p; return this; } @@ -197,6 +201,29 @@ class TreeItem { return _parent.topParent; } + + protected int _intParam; + protected Object _objectParam; + + @property int intParam() { + return _intParam; + } + + @property TreeItem intParam(int value) { + _intParam = value; + return this; + } + + @property Object objectParam() { + return _objectParam; + } + + @property TreeItem objectParam(Object value) { + _objectParam = value; + return this; + } + + /// returns true if item has at least one child @property bool hasChildren() { return childCount > 0; } @@ -643,7 +670,7 @@ class TreeWidgetBase : ScrollWidget, OnTreeContentChangeListener, OnTreeStateCh super.layout(rc); } - /// Measure widget according to desired width and height constraints. (Step 1 of two phase layout). + /// Measure widget according to desired width and height constraints. (Step 1 of two phase layout). override void measure(int parentWidth, int parentHeight) { if (visibility == Visibility.Gone) { return; From acf5fb353152bc997861c0fdb2570891101713d8 Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Tue, 13 Jan 2015 16:25:45 +0300 Subject: [PATCH 07/20] update checkbox resources; support fixed layoutWidth, layoutHeight --- res/btn_check.xml | 51 +++++----------------- res/btn_check_holo_light.xml | 65 ++++++++++++++++++++++++++++ res/mdpi/btn_check_off.png | Bin 0 -> 360 bytes res/mdpi/btn_check_off_disabled.png | Bin 0 -> 241 bytes res/mdpi/btn_check_off_focused.png | Bin 0 -> 353 bytes res/mdpi/btn_check_off_pressed.png | Bin 0 -> 376 bytes res/mdpi/btn_check_on.png | Bin 0 -> 514 bytes res/mdpi/btn_check_on_disabled.png | Bin 0 -> 376 bytes res/mdpi/btn_check_on_focused.png | Bin 0 -> 516 bytes res/mdpi/btn_check_on_pressed.png | Bin 0 -> 528 bytes src/dlangui/widgets/styles.d | 6 ++- src/dlangui/widgets/widget.d | 7 +++ 12 files changed, 89 insertions(+), 40 deletions(-) create mode 100644 res/btn_check_holo_light.xml create mode 100644 res/mdpi/btn_check_off.png create mode 100644 res/mdpi/btn_check_off_disabled.png create mode 100644 res/mdpi/btn_check_off_focused.png create mode 100644 res/mdpi/btn_check_off_pressed.png create mode 100644 res/mdpi/btn_check_on.png create mode 100644 res/mdpi/btn_check_on_disabled.png create mode 100644 res/mdpi/btn_check_on_focused.png create mode 100644 res/mdpi/btn_check_on_pressed.png diff --git a/res/btn_check.xml b/res/btn_check.xml index c8c2bee0..c38e9325 100644 --- a/res/btn_check.xml +++ b/res/btn_check.xml @@ -1,65 +1,38 @@ - - - - - + android:drawable="@drawable/btn_check_on_pressed" /> + android:drawable="@drawable/btn_check_off_pressed" /> + android:drawable="@drawable/btn_check_on_focused" /> + android:drawable="@drawable/btn_check_off_focused" /> + android:drawable="@drawable/btn_check_off" /> + android:drawable="@drawable/btn_check_on" /> - - + + - - - - - + + diff --git a/res/btn_check_holo_light.xml b/res/btn_check_holo_light.xml new file mode 100644 index 00000000..c8c2bee0 --- /dev/null +++ b/res/btn_check_holo_light.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/mdpi/btn_check_off.png b/res/mdpi/btn_check_off.png new file mode 100644 index 0000000000000000000000000000000000000000..ae0bd562fdc849232298c5df31be961e681d04fb GIT binary patch literal 360 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP~BQK8$)1Hob9YCS4o-U3d7N?g^_Vr^ns^E@0;WE?V6&x zQ;Nmur=Qqk_TMzoZgE*=HsP%V>kP?vZFg2^8nryxAvv>9M!|9|o1(h&7AcQKQElQQ3<&u4CRp3SN7>Sc)X4O?BF zwbq4grsW++{&&g^vtO^C{M)g8-*e5tb8nAre$4#PT<*7l=gbgb05EvE`njxgN@xNA DJ*bhx literal 0 HcmV?d00001 diff --git a/res/mdpi/btn_check_off_disabled.png b/res/mdpi/btn_check_off_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..7f9630a74cca1bbe5c0c18fe482bba0c1c4dea19 GIT binary patch literal 241 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP~BQGz5%%6NKZJVX%d|kDnVpd>RK2!wZL{P%MTVrbbiO;yM`R3M`-IFq;Hks(S!YLdhvB~{ fwL5u>Po?gWV-VWv=)SrG=n@7`S3j3^P6(pS*z}wuaEcj z4h`keWUq*+y)vEaxcF`gQC-nEoC2Wc$dFBd|CC! z=ih$6=Q(H76)Eyd-=)>WLB(uVLv*+eA7_JB3v*yvKvc`h1HO8H8{D37?K~JNz}5Zu z$^nynKU+Sj!j}OODZAKvY#1|gtwpq0Sf|hMW>GQHkTtv7_u6O14g=1BSzBH{pLHUk s?z+hp^|0#lhd-+0f{aR}r#60Nc1%}TI;;0=9nj|tp00i_>zopr0PHw}p#T5? literal 0 HcmV?d00001 diff --git a/res/mdpi/btn_check_off_pressed.png b/res/mdpi/btn_check_off_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..1dc226ad3ce4219e160a0f7c1de964849131b7c8 GIT binary patch literal 376 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP~BQK9NpV6{&ISdSpte!58Ar_~XPPPp?Y#`FI|GV&zEt9I<`QJS! zty(3)%x(qi)MyZZ;h5+V}CwYA-R6Bk;Jok5FlWRVLn~;2^-?Lg zu5f;CPU;2#&x*y%t7wgg;QKz-TAr`1HFi+r^_%xi;_ghEPhSmRev~QB43kO4nnyTK zuBWFSiwJ$a-K?x{aA+!w{X8I>j)xo6P)bO|I(fVEog-7BFP9)c*oC#W@!kKz_I8(K zq7&C?BObfO=BquFQaqh}fLHOF3!P8WsU+S%c(?nTu2h^4AAeCktdPsb7f`~9Reh(o)DMeK4@DX%GVUEf?naCpqXdPj!(9enI5!ir8 z_8~^|S07*qoM6N<$ Ef&wq&kN^Mx literal 0 HcmV?d00001 diff --git a/res/mdpi/btn_check_on_disabled.png b/res/mdpi/btn_check_on_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..683aaeb781cf23cee719ea4be8e489a9aeca7ef8 GIT binary patch literal 376 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP~BQGzb>GETffd(+Ldb&7~+WNzt)ZOpX__TaBJJ^ zT?x;!8-3??95`ce%z>kETkgR#9glxpIjDE?jDS-@q*zHTyQXSeV#775zQ+f?|E*P< z&ey?F8k;;ztzusLvP=h;=~wM#42-7)C8SMB?W~-ac-ySze!JnbxP)Sbr7i+2)(Txp z2A?0w-`Vz|YVQOU&K^SrrIy4BiBE5}_cTuln!Y5sQRno(tv+8$q$T+ua~I$Az7^m$ R5g1?$44$rjF6*2UngIV$mIVL+ literal 0 HcmV?d00001 diff --git a/res/mdpi/btn_check_on_focused.png b/res/mdpi/btn_check_on_focused.png new file mode 100644 index 0000000000000000000000000000000000000000..84b5e2c40e33ab8be29ce5f905a9977a9b119cab GIT binary patch literal 516 zcmV+f0{i`mP)W4-n1D%TX zunY+nxY_+TqmnS$M=3P0<$Bm5H~1C+-+CSdY4#con&c0^HgIMAP|da8Yn1K5SM}oacilI9R&XX3(mzs z(4|8WoSk$K+MyBzmqLGlNEIVOu@cM`W2`Z`*Tn{7+6$6*I>R~7d0#k3Se8XOQUKBE z_s)F><8u?D003B=ee=&o0n}G%7)p@(lP8mNn4DQCcJNp88~Y`IKEH=d;ukyn$Gnb3 z(5tIUBivSZqh6?`5Da%bU~=gr$<#T!{Q;hY+S~yJ>r&9=HTk@?M>2KJLw^J90Uu{s zyQojz9c(srf-N2ly^@f(mX-DINGTZ`3G>ssDp^zn2zpI?B1hs!f*yYzn_mt%IZ5-# zSI+jnam z{XWIpSj%9fgG<}SQz_j6hv__Kjm}UsfRdmIc=0^Qg$=rtm=)4Jf>4Th(q?odjM5}} zg=8Sw$w4}Y?SP?#J7D~=34o&nFJn(}fWu6lY~H!K3;qwdeV+G`DEAvBW$GH6+j4); SSR(@f0000= WRAP_CONTENT; +} + /// Align option bit constants enum Align : ubyte { /// alignment is not specified diff --git a/src/dlangui/widgets/widget.d b/src/dlangui/widgets/widget.d index bed6141a..71ed5051 100644 --- a/src/dlangui/widgets/widget.d +++ b/src/dlangui/widgets/widget.d @@ -1056,6 +1056,13 @@ class Widget { // summarize margins, padding, and content size int dx = m.left + m.right + p.left + p.right + contentWidth; int dy = m.top + m.bottom + p.top + p.bottom + contentHeight; + // check for fixed size set in layoutWidth, layoutHeight + int lh = layoutHeight; + int lw = layoutWidth; + if (!isSpecialSize(lh)) + dy = lh; + if (!isSpecialSize(lw)) + dx = lw; // apply min/max width and height constraints int minw = minWidth; int maxw = maxWidth; From 77a44a9e06b7a5ddeeb40a61e10c517972fde700 Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Tue, 13 Jan 2015 16:50:45 +0300 Subject: [PATCH 08/20] better resources for radio buttons and checkboxes --- res/btn_check.xml | 7 ++++ res/btn_radio.xml | 55 +++++++------------------- res/btn_radio_holo_light.xml | 59 ++++++++++++++++++++++++++++ res/mdpi/btn_check_off_pressed.png | Bin 376 -> 593 bytes res/mdpi/btn_radio_off.png | Bin 0 -> 584 bytes res/mdpi/btn_radio_off_disabled.png | Bin 0 -> 583 bytes res/mdpi/btn_radio_off_focused.png | Bin 0 -> 601 bytes res/mdpi/btn_radio_off_pressed.png | Bin 0 -> 584 bytes res/mdpi/btn_radio_on.png | Bin 0 -> 632 bytes res/mdpi/btn_radio_on_disabled.png | Bin 0 -> 625 bytes res/mdpi/btn_radio_on_focused.png | Bin 0 -> 644 bytes res/mdpi/btn_radio_on_pressed.png | Bin 0 -> 632 bytes 12 files changed, 81 insertions(+), 40 deletions(-) create mode 100644 res/btn_radio_holo_light.xml create mode 100644 res/mdpi/btn_radio_off.png create mode 100644 res/mdpi/btn_radio_off_disabled.png create mode 100644 res/mdpi/btn_radio_off_focused.png create mode 100644 res/mdpi/btn_radio_off_pressed.png create mode 100644 res/mdpi/btn_radio_on.png create mode 100644 res/mdpi/btn_radio_on_disabled.png create mode 100644 res/mdpi/btn_radio_on_focused.png create mode 100644 res/mdpi/btn_radio_on_pressed.png diff --git a/res/btn_check.xml b/res/btn_check.xml index c38e9325..172c177c 100644 --- a/res/btn_check.xml +++ b/res/btn_check.xml @@ -17,6 +17,13 @@ android:state_enabled="true" android:drawable="@drawable/btn_check_off_focused" /> + + + diff --git a/res/btn_radio.xml b/res/btn_radio.xml index e2f1f84c..4b0b6e01 100644 --- a/res/btn_radio.xml +++ b/res/btn_radio.xml @@ -1,59 +1,34 @@ - - - - - + android:drawable="@drawable/btn_radio_on_pressed" /> + android:drawable="@drawable/btn_radio_off_pressed" /> + android:drawable="@drawable/btn_radio_on_focused" /> + android:drawable="@drawable/btn_radio_off_focused" /> + + + + android:drawable="@drawable/btn_radio_off" /> + android:drawable="@drawable/btn_radio_on" /> - - - - - - - - + + diff --git a/res/btn_radio_holo_light.xml b/res/btn_radio_holo_light.xml new file mode 100644 index 00000000..e2f1f84c --- /dev/null +++ b/res/btn_radio_holo_light.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/mdpi/btn_check_off_pressed.png b/res/mdpi/btn_check_off_pressed.png index 1dc226ad3ce4219e160a0f7c1de964849131b7c8..2e64acc26da59d30bef6fb106a91fa3811d632b1 100644 GIT binary patch delta 520 zcmV+j0{8v+0?`DJRDTU9ClEP(r2qf{-bqA3R5;7cl1)z&VHAa*cix#PGfW30(*cV> zseG7FVWE;JiE*PY+!_9d@s|+(hheQ{XF>=GF=PM}KD1K_q*QE$5u`2C*M+f>P~GZT z-sC>_+>-VR=)nhDUrT9|LgH@8WL8hK(O{%q+N8?G}tZtLBWa}O67hq+#%+zQ4|tb}Bs+oT>V zhW#XAC8BKx0EQv342=#`!!k4+Q$q@YQs7yVMpGd*an-?4k4t#;jXu{TYA9?|!%1k^ zx`u5C6bj$b*{_^(qdR#OFrD=Xw)dGxTU6^YQLTwYAb)_yg`yEFTt^aY?=zkCt^#If za-vWyvGhLVLADbi;q%!A)$^Eh6djIaajih1SYmc2C;nKZxqQIzP#?LG>x}hw0kCs; z!usw3g<^@9PbM!Fscn^CEp4cGpT4kF`U=2^=W;Kbx^(&f(GNJ3qT+wKi(UW#002ov KPDHLkU;%=(MEI8g delta 301 zcmV+|0n+}_1o#4wRDTRR4l<_BYybcO1xZ9fR5;6}lRZ+yFcgHp_anu2JTMGUr{xgL za0D(uO9LGTpx^*>(2&EV-~@04N*ebNOd*@Zkl19rGb%KCyKnbNlB%j00|z+0d8&6M zKHp!;j{v~q-Sxl8SGNyc2QB6=vY8>^2Ci^%QvZ#xjBx27|@h$L1MqX^MFw z22BoB7#0vsg)R_$W!(hII3S=3(Nb44$PA_q)(9Nu0`$zl4JM84%;6v^g{L?*aFi?X z)$gDsmjMcgi9t&%gY-wR#z7gNFeMs90g>dO3 diff --git a/res/mdpi/btn_radio_off.png b/res/mdpi/btn_radio_off.png new file mode 100644 index 0000000000000000000000000000000000000000..1137dbfd489d8e7e9316c98647f4e58bec64f116 GIT binary patch literal 584 zcmV-O0=NB%P)VH9u9{DK>$FpSfpC5;+&j_ zL?W@5FMeNPyubv8GPY$=DwP13PN%q@$9O!ZadCmBY2tuDO3A0ItN2Z=M!kMU zukUfc{02b&ILq5wmCnr#{lS2bmzTRqb_AVnH(sq)oS(nvOY19|rlIRPLI|QCAz>Ku z?#!XpYGD`#_0vnl~1h!={a9v(kUa{GHXA_3I zPEiygr9{&-2Cj>3S%(CU;|SmP>2^ERY#Sj24-bz#uGdJpMO9VW?KZye<2a6Z(nz11 zO)8ZNR<%mGTn1n=nc#XJzVGv)(fGTO_N?6N#lz8v$z%dR$uzMn3&(N(ZRP*+jlTfh W5XFbU)gnOv0000BlBu&6N+;w4ut z4X+Db6_Hr#CX1fsXy(kBnKL3u65fIn-U$75KqakT^A`O0JGVQD2|zq$21xZYPFh3DNsrgh9SQ1b9Hr1|ND@~ z!5DyIK1aP?=dsr#3`45bDu0z66nwhB-!B#mZmKoDeC=VHCYJ30u-~j$uh&$s-_z-I za2$t^cX#5&65}YscU_{v6PD%R*f|W{AZwXOS)`OdV>+GUyDo7QrLT}A2~tXa{Q5~Q z>tJSdvX)NXHaN3SIhO_0Rw1S2cyFmIWOM_|G_Xz$tc-?X7ziQQ?M|?4i`{OA5F)Lh zP$)2;&nXsi?6;dkv99arx(;l~+BQj&kk9AS1fJ&+#W5G}Dy&w|tTvlNr|ou&QVP>F ziQ*W~^U?%C5Qy<;M8E$H-}M1lES~wjT%wd9lgZHSb{UUG1VNDYfu?CRn@z$nWVv4B zU0zZymjReeCJcr{#-kC|W zK~y-)#gorY6Hye#e|Khz{Rb^2q|?$mZLN^B8iq1?+C|nxJoEoF|o<^br}$LzMcbh~{X z-CrXf2?`&<*!6h&q9$*Za;)7cQSVCn-zOk_8rCy{`i{vv)8fg)jdLaEdTM4z8ir0~ zxx}U^IU6f1CN!238lJ20vL&gklrRjPn%R-QAvX4VEH7QB(Ua&Ag@vd>P=)9e6ygfG z8HMH-Il=7r{9CXF4p}`x?;9jT3IP>D0SE^sIUiFPjs;mgfi-Y0--4#XHEr@JsKHD? z5KzFApoavm=by{ePXr6}LbP{_jW%KyK`rnOo(aKxzJ96j1rqw$J npr|LfTTD|e|HI1vVH9u9{DK>$FpSfpC5;+&j_ zL?W@5FMeNPyubv8GPY$=DwP13PN%q@$9O!ZadCmBY2tuDO3A0ItN2Z=M!kMU zukUfc{02b&ILq5wmCnr#{lS2bmzTRqb_AVnH(sq)oS(nvOY19|rlIRPLI|QCAz>Ku z?#!XpYGD`#_0vnl~1h!={a9v(kUa{GHXA_3I zPEiygr9{&-2Cj>3S%(CU;|SmP>2^ERY#Sj24-bz#uGdJpMO9VW?KZye<2a6Z(nz11 zO)8ZNR<%mGTn1n=nc#XJzVGv)(fGTO_N?6N#lz8v$z%dR$uzMn3&(N(ZRP*+jlTfh W5XFbU)gnOv0000G6@`MPaV*xyookozI!zAD zPvf1R#wRp+aQgcOE|B_M_(<4ry4H#p>4%(-+Qh{_GhFg#uo$mv}s`Y&)Wql1L=NhjNA4 z2T!?j`4Ts7&Tx9_BI`EXnw>-H4I+^UQp!OJrfH(8DsL9vF+8*n_aT+Jg?WmNRm7s$qxt$79`6B8PM*NBEPOuSpnwnpDJ4gb#JD;=h1&s3FYnQMb)OLz z%v`@lPz@lZLkZP7mV97YW4J00000 LNkvXXu0mjf{*nr0 literal 0 HcmV?d00001 diff --git a/res/mdpi/btn_radio_on_focused.png b/res/mdpi/btn_radio_on_focused.png new file mode 100644 index 0000000000000000000000000000000000000000..228b8a3891d32452fde93085184963e460cc58e1 GIT binary patch literal 644 zcmV-~0( zK~y-)#gk1;k^vaUe=j03!HFLPI1n|G4IwHeTW+@MR%>l-ZQkqR+WJ_z)@q$xmku_` zP93tXQ-=<&wN;zN$+X;rVgiXECO8sa0tyXzJG42CJ`NuGAD_eX{J$PS6h*cJ8QX;X z*FkZ;gvTG1-p$1cFQ)-$)78@4Y?<@NyV0nWLfL}idWpfu9?5QNp?jZ=@!2dhz90a5cDHlbTEoP&pZERczq^q<^IHebNwk4i@zt-=-)r$S3O zt<88sSze9~bM^8$9=ZoPcJ~(F6xBStKg47-kJH-BRA{L@g-BAwq_1b{t(TfA8I3&- zZYu@G7VA)+9bzpf;+vkqq^~EE6#txpOn^ip!L{cFN{y9#U4z`JgaW9og!NL13Yk#O zz^v77)8RP5r4;}y`g*!7O&sd@ eN0tA}H~s*9b>BNHwOGXf0000>j58 literal 0 HcmV?d00001 diff --git a/res/mdpi/btn_radio_on_pressed.png b/res/mdpi/btn_radio_on_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..06fec87ed0a5db0dc3d940a81bb3dffd7eb922a9 GIT binary patch literal 632 zcmV-;0*C#HP)G6@`MPaV*xyookozI!zAD zPvf1R#wRp+aQg Date: Tue, 13 Jan 2015 18:41:06 +0300 Subject: [PATCH 09/20] refactoring --- src/dlangui/core/collections.d | 79 ++++++++++++++++++++++++++++++++++ src/dlangui/widgets/widget.d | 75 +------------------------------- 2 files changed, 80 insertions(+), 74 deletions(-) diff --git a/src/dlangui/core/collections.d b/src/dlangui/core/collections.d index 879c1f26..50c6d574 100644 --- a/src/dlangui/core/collections.d +++ b/src/dlangui/core/collections.d @@ -221,3 +221,82 @@ struct Collection(T, bool ownItems = false) { } } + +/** object list holder, owning its objects - on destroy of holder, all own objects will be destroyed */ +struct ObjectList(T) { + protected T[] _list; + protected int _count; + /** returns count of items */ + @property int count() const { return _count; } + /** get item by index */ + T get(int index) { + assert(index >= 0 && index < _count, "child index out of range"); + return _list[index]; + } + /// get item by index + T opIndex(int index) { + return get(index); + } + /** add item to list */ + T add(T item) { + if (_list.length <= _count) // resize + _list.length = _list.length < 4 ? 4 : _list.length * 2; + _list[_count++] = item; + return item; + } + /** add item to list */ + T insert(T item, int index = -1) { + if (index > _count || index < 0) + index = _count; + if (_list.length <= _count) // resize + _list.length = _list.length < 4 ? 4 : _list.length * 2; + for (int i = _count; i > index; i--) + _list[i] = _list[i - 1]; + _list[index] = item; + _count++; + return item; + } + /** find child index for item, return -1 if not found */ + int indexOf(T item) { + for (int i = 0; i < _count; i++) + if (_list[i] == item) + return i; + return -1; + } + /** find child index for item by id, return -1 if not found */ + static if (__traits(hasMember, T, "compareId")) { + int indexOf(string id) { + for (int i = 0; i < _count; i++) + if (_list[i].compareId(id)) + return i; + return -1; + } + } + /** remove item from list, return removed item */ + T remove(int index) { + assert(index >= 0 && index < _count, "child index out of range"); + T item = _list[index]; + for (int i = index; i < _count - 1; i++) + _list[i] = _list[i + 1]; + _count--; + return item; + } + /** Replace item with another value, destroy old value. */ + void replace(T item, int index) { + T old = _list[index]; + _list[index] = item; + destroy(old); + } + /** remove and destroy all items */ + void clear() { + for (int i = 0; i < _count; i++) { + destroy(_list[i]); + _list[i] = null; + } + _count = 0; + } + ~this() { + clear(); + } +} + diff --git a/src/dlangui/widgets/widget.d b/src/dlangui/widgets/widget.d index 71ed5051..fb05fc4e 100644 --- a/src/dlangui/widgets/widget.d +++ b/src/dlangui/widgets/widget.d @@ -38,6 +38,7 @@ module dlangui.widgets.widget; public import dlangui.core.types; public import dlangui.core.events; public import dlangui.core.i18n; +public import dlangui.core.collections; public import dlangui.widgets.styles; public import dlangui.graphics.drawbuf; @@ -1263,80 +1264,6 @@ class Widget { } -/** object list holder, owning its objects - on destroy of holder, all own objects will be destroyed */ -struct ObjectList(T) { - protected T[] _list; - protected int _count; - /** returns count of items */ - @property int count() const { return _count; } - /** get item by index */ - T get(int index) { - assert(index >= 0 && index < _count, "child index out of range"); - return _list[index]; - } - /** add item to list */ - T add(T item) { - if (_list.length <= _count) // resize - _list.length = _list.length < 4 ? 4 : _list.length * 2; - _list[_count++] = item; - return item; - } - /** add item to list */ - T insert(T item, int index = -1) { - if (index > _count || index < 0) - index = _count; - if (_list.length <= _count) // resize - _list.length = _list.length < 4 ? 4 : _list.length * 2; - for (int i = _count; i > index; i--) - _list[i] = _list[i - 1]; - _list[index] = item; - _count++; - return item; - } - /** find child index for item, return -1 if not found */ - int indexOf(T item) { - for (int i = 0; i < _count; i++) - if (_list[i] == item) - return i; - return -1; - } - /** find child index for item by id, return -1 if not found */ - static if (__traits(hasMember, T, "compareId")) { - int indexOf(string id) { - for (int i = 0; i < _count; i++) - if (_list[i].compareId(id)) - return i; - return -1; - } - } - /** remove item from list, return removed item */ - T remove(int index) { - assert(index >= 0 && index < _count, "child index out of range"); - T item = _list[index]; - for (int i = index; i < _count - 1; i++) - _list[i] = _list[i + 1]; - _count--; - return item; - } - /** Replace item with another value, destroy old value. */ - void replace(T item, int index) { - T old = _list[index]; - _list[index] = item; - destroy(old); - } - /** remove and destroy all items */ - void clear() { - for (int i = 0; i < _count; i++) { - destroy(_list[i]); - _list[i] = null; - } - _count = 0; - } - ~this() { - clear(); - } -} - /** Widget list holder. */ alias WidgetList = ObjectList!Widget; From 05165a5b18b063179432359b5eb4dbae462b238b Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Wed, 14 Jan 2015 09:56:11 +0300 Subject: [PATCH 10/20] new button style for default theme --- res/btn_background.xml | 18 ++++++++++++++++++ res/btn_background_transparent.xml | 17 +++++++++++++++++ res/mdpi/btn_default.9.png | Bin 0 -> 532 bytes res/mdpi/btn_disabled.9.png | Bin 0 -> 354 bytes res/mdpi/btn_hover.9.png | Bin 0 -> 461 bytes res/mdpi/btn_normal.9.png | Bin 0 -> 412 bytes res/mdpi/btn_pressed.9.png | Bin 0 -> 537 bytes res/theme_default.xml | 6 +++--- src/dlangui/graphics/resources.d | 1 + src/dlangui/widgets/styles.d | 8 ++++---- 10 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 res/btn_background.xml create mode 100644 res/btn_background_transparent.xml create mode 100644 res/mdpi/btn_default.9.png create mode 100644 res/mdpi/btn_disabled.9.png create mode 100644 res/mdpi/btn_hover.9.png create mode 100644 res/mdpi/btn_normal.9.png create mode 100644 res/mdpi/btn_pressed.9.png diff --git a/res/btn_background.xml b/res/btn_background.xml new file mode 100644 index 00000000..066aed5b --- /dev/null +++ b/res/btn_background.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + diff --git a/res/btn_background_transparent.xml b/res/btn_background_transparent.xml new file mode 100644 index 00000000..f96baa91 --- /dev/null +++ b/res/btn_background_transparent.xml @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/res/mdpi/btn_default.9.png b/res/mdpi/btn_default.9.png new file mode 100644 index 0000000000000000000000000000000000000000..9cbe49ae4c9eddbe1ed81da56db61a1590f5ea9c GIT binary patch literal 532 zcmV+v0_**WP)5fB_Nt)0~CM+ z7EqXu2C$S+FqUQVg6w-JLclf;BXJ+M8;$0EI&;qa1b`SL=ar_Za8!&j%#Oo3;7RYJ z4&MwI#1l_{vb4_bcE;^%R{}r+@c88iJ$m*S8Mclu5$478J%{E1klkir@GRh+stWRaP_C#{Knn9!O<`$O;aVa zlai2pfW`I6;-s7eDHH>QN>U(%{-D4N3r>KsM8O>U9|1pl{jNYInydl^lgX6fXbcq} zU}!Lz)PIhh?fzcLocm@Nev@aTK9?dZ!2{Eh6q$sXoPdB3p(sUW#u8*_u~s9-c=n?0ZDs8D z`na<&7D(Ud~D?X1-U4Zq~D!bbmopvkC{VM*~x8*xM WmE~9wCSisE0000cdx@v7EBk#$J~mx5Nx7G@K%w`ZE{-7{$KPJt=yk+F;Mm9iIW1?` z6+CmaSuFVQ30G|@_rXI>f`I}`4{IiTJ)jc3Be`%+#n-CXeR;Ef8eXko5^zeGy=v8z zo)&>8?{%UdJY9R$&@ITz^0(o!fT+_?U6uDAIQw?4+}X4_SC7k7&1bFoYWw~!`~26Y z;ip?=7;2Wg1fMTlmm+gq=YX|)@cEtfHMe3|R;+roSNWJnUQ$oR`+(3@tAY;CGiDSv z0HOb^9UT|GGhe&)ruACXuQ~@84#gb1s6de|ce_4c7M`QMxgk*^bGN8#;2XQY?a#w~ sH5bkb)e;cwF^tg{-^Bc8^|n6@E3U^{-IbNx2=qFGr>mdKI;Vst023;YrvLx| literal 0 HcmV?d00001 diff --git a/res/mdpi/btn_hover.9.png b/res/mdpi/btn_hover.9.png new file mode 100644 index 0000000000000000000000000000000000000000..8f50cd26fa46c85b16377fe0a1902ae9e9dc38d9 GIT binary patch literal 461 zcmV;;0W$uHP)lQSPOeH|IrUw|&r$Rfdo= zX3un2O-$6zdAz)A<>nJpH9F-E)vS^&0l9#LC!@uF`m;>f;Q515Mc z0G0qa1YjLN9M(WK)gaasjTq>L$_XHwTAnpxmOnLc)TXkjO$4z5lLDCbjF-uH*! zXtX-W`@FjJFPd$64-?kIrj^2hKgE5utX2SVeOrD3xS;BRJcdx@v7EBk#$J~n-o8xwzBXJBB|^mK6y@i_i=+Qu#>LlIa1BMR$$ z&)n#^@zYzW?2y^Iz4tdX?cKWeXwB5t-n>OeErdSiZq$g1NKNDZ7{US_C#+oAlgr zJ%&Mh#avhf7joSF9Wr0E>(YNlmzL8{KlQz^d{ARoY$3yCm}?@ny|i`GSAoDl-@1p{ zQCTkQ3!65@1uxwy_FQJJU;Ec8+0=V)%L>me+mhJ`*in*<*m8TCa!)C7>*2{u6{1-oD!M< DKqspk literal 0 HcmV?d00001 diff --git a/res/mdpi/btn_pressed.9.png b/res/mdpi/btn_pressed.9.png new file mode 100644 index 0000000000000000000000000000000000000000..6084c61d211d7af635a6a921a3f78dd5d6320664 GIT binary patch literal 537 zcmV+!0_OdRP)B_Yt3Xb z;lVmA4)^!y_qN!~bA%8p8OIo@tR;wy zlhZNg_YY3rzY-aM*&6V8e~(8GA5e~lNGbmd;GAdr`3pw}@a~gaBvML6Hgbl$cPU3h zx@t7M&!B%BHgc3wF>dDnPse5Y`EZ2?32Jk*ryDg0H$F{4z;Qzv=2xQ6dQ-qQ@pOUzErr;=)gAt;J3+V>&+L;&R4p ze$Cui=9OFRF_!tY;o@?}bbQ86FGFiB#B!=QI{py9pBqBQ>q1Jwy?(*T%cr8ADpHLs bZKKN{suKzl1+W6000000NkvXXu0mjfahK$F literal 0 HcmV?d00001 diff --git a/res/theme_default.xml b/res/theme_default.xml index 8aed3d80..292bc014 100644 --- a/res/theme_default.xml +++ b/res/theme_default.xml @@ -1,12 +1,12 @@ * From c532ca84e6c16d99a8e9654fe55dc16a4162b1da Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Wed, 14 Jan 2015 10:16:27 +0300 Subject: [PATCH 11/20] support custom colors in styles --- res/theme_default.xml | 4 +++ src/dlangui/widgets/styles.d | 61 ++++++++++++++++++++++++++++++++++-- 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/res/theme_default.xml b/res/theme_default.xml index 292bc014..e07a4843 100644 --- a/res/theme_default.xml +++ b/res/theme_default.xml @@ -34,6 +34,10 @@ backgroundImageId="btn_background" align="Center" /> + + + + diff --git a/src/dlangui/widgets/styles.d b/src/dlangui/widgets/styles.d index 2d6eab2c..b3a47650 100644 --- a/src/dlangui/widgets/styles.d +++ b/src/dlangui/widgets/styles.d @@ -154,6 +154,7 @@ class Style { protected Style[] _children; protected DrawableAttribute[string] _customDrawables; + protected uint[string] _customColors; protected FontRef _font; protected DrawableRef _backgroundDrawable; @@ -230,6 +231,19 @@ class Style { return this; } + /// get custom color attribute + uint customColor(string id) { + if (id in _customColors) + return _customColors[id]; + return parentStyle.customColor(id); + } + + /// sets custom color attribute for style + Style setCustomColor(string id, uint color) { + _customColors[id] = color; + return this; + } + //=================================================== // font properties @@ -681,18 +695,25 @@ class Theme : Style { } private DrawableRef _emptyDrawable; - @property override ref DrawableRef customDrawable(string id) const { + override ref DrawableRef customDrawable(string id) const { if (id in _customDrawables) return _customDrawables[id].drawable; return (cast(Theme)this)._emptyDrawable; } - @property override string customDrawableId(string id) const { + override string customDrawableId(string id) const { if (id in _customDrawables) return _customDrawables[id].drawableId; return null; } + /// get custom color attribute - transparent by default + override uint customColor(string id) { + if (id in _customColors) + return _customColors[id]; + return 0xFFFFFFFF; + } + /// create new named style or get existing override Style createSubstyle(string id) { if (id !is null && id in _byId) @@ -862,6 +883,35 @@ Rect decodeRect(string s) { return Rect(0,0,0,0); } +/// decodes hex digit (0..9, a..f, A..F), returns uint.max if invalid +uint decodeHexDigit(char ch) { + if (ch >= '0' && ch <= '9') + return ch - '0'; + else if (ch >= 'a' && ch <= 'f') + return ch - 'a' + 10; + else if (ch >= 'A' && ch <= 'F') + return ch - 'A' + 10; + return uint.max; +} + +/// supported formats: #RGB #ARGB #RRGGBB #AARRGGBB +uint decodeColor(string s, uint defValue) { + if (s.length != 4 && s.length != 5 && s.length != 7 && s.length != 9) + return defValue; + if (s[0] != '#') + return defValue; + uint value = 0; + for (int i = 1; i < s.length; i++) { + uint digit = decodeHexDigit(s[i]); + if (digit == uint.max) + return defValue; + value = (value << 4) | digit; + if (s.length < 7) // double the same digit for short forms + value = (value << 4) | digit; + } + return value; +} + /// parses string like "Left|VCenter" to bit set of Align flags ubyte decodeAlignment(string s) { ubyte res = 0; @@ -1002,6 +1052,13 @@ bool loadStyleAttributes(Style style, Element elem, bool allowStates) { string drawablevalue = attrValue(item, "value"); if (drawableid) style.setCustomDrawable(drawableid, drawablevalue); + } else if (item.tag.name.equal("color")) { + // + string colorid = attrValue(item, "id"); + string colorvalue = attrValue(item, "value"); + uint color = decodeColor(colorvalue, 0xFFFFFFFF); + if (colorid) + style.setCustomColor(colorid, color); } } return true; From c815bdbffecaffcfb53dbfa01b033f00f546b9ae Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Wed, 14 Jan 2015 11:32:56 +0300 Subject: [PATCH 12/20] focus rectangle support added --- res/theme_default.xml | 1 + src/dlangui/graphics/drawbuf.d | 26 ++++++++++++ src/dlangui/widgets/styles.d | 72 ++++++++++++++++++++++++++++++++-- src/dlangui/widgets/widget.d | 26 +++++++++++- 4 files changed, 119 insertions(+), 6 deletions(-) diff --git a/res/theme_default.xml b/res/theme_default.xml index e07a4843..fd35489b 100644 --- a/res/theme_default.xml +++ b/res/theme_default.xml @@ -4,6 +4,7 @@ backgroundImageId="btn_background" align="Center" margins="5,5,5,5" + focusRectColors="#000" /> + +