1 // Written in the D programming language.
2 /++
3  + Authors: KanzakiKino
4  + Copyright: KanzakiKino 2018
5  + License: LGPL-3.0
6 ++/
7 module w4d.widget.image;
8 import w4d.style.color,
9        w4d.style.scalar,
10        w4d.task.window,
11        w4d.widget.base;
12 import g4d.element.shape.rect,
13        g4d.gl.texture,
14        g4d.shader.base,
15        g4d.util.bitmap;
16 import gl3n.linalg;
17 import std.algorithm,
18        std.math;
19 
20 /// A widget of image.
21 class ImageWidget : Widget
22 {
23     protected RectElement _imageElm;
24     protected Tex2D       _texture;
25     protected vec2        _imageSize;
26     protected vec2        _uv;
27 
28     ///
29     override @property vec2 wantedSize ()
30     {
31         return _imageSize;
32     }
33 
34     ///
35     this ()
36     {
37         super();
38 
39         _imageElm  = new RectElement;
40         _texture   = null;
41         _imageSize = vec2(0,0);
42         _uv        = vec2(0,0);
43     }
44 
45     /// Sets new image.
46     void setImage (B) ( B bmp, bool compress = true )
47         if ( isBitmap!B )
48     {
49         if ( !bmp ) {
50             _texture   = null;
51             _imageSize = vec2(0,0);
52             _uv        = vec2(0,0);
53             return;
54         }
55 
56         _texture = new Tex2D( bmp, compress );
57 
58         _uv.x      = bmp.width*1f / _texture.size.x;
59         _uv.y      = bmp.rows *1f / _texture.size.y;
60         _imageSize = vec2(bmp.width,bmp.rows);
61         requestLayout();
62     }
63 
64     protected void resizeElement ()
65     {
66         if ( _texture ) {
67             auto sz = style.box.clientSize;
68             _imageElm.resize( sz, _uv );
69         }
70     }
71     ///
72     override vec2 layout ( vec2 pos, vec2 size )
73     {
74         if ( style.box.size.width.isNone && style.box.size.height.isNone ) {
75             const w = _imageSize.x, h = _imageSize.y;
76             const ratio = w/h;
77             const maxsz = size;
78 
79             size.x = ratio * size.y;
80             if ( size.x > maxsz.x ) {
81                 size.x = maxsz.x;
82                 size.y = (1f/ratio) * size.x;
83             }
84         }
85 
86         scope(success) resizeElement();
87         return super.layout( pos, size );
88     }
89     ///
90     override void draw ( Window w, in ColorSet parent )
91     {
92         super.draw( w, parent );
93 
94         if ( _texture ) {
95             auto  shader = w.shaders.rgba3;
96             const saver  = ShaderStateSaver( shader );
97             const late   = style.clientLeftTop + style.box.clientSize/2;
98 
99             shader.use();
100             shader.matrix.late = vec3( late, 0 );
101             shader.matrix.rota = vec3( PI, 0, 0 );
102             shader.uploadTexture( _texture );
103             _imageElm.draw( shader );
104         }
105     }
106 
107     ///
108     override @property bool trackable () { return false; }
109     ///
110     override @property bool focusable () { return false; }
111 }