1 module evael.graphics.gui.controls.PictureBox;
2 
3 import evael.graphics.gui.controls.Control;
4 import evael.graphics.gui.controls.Panel;
5 import evael.graphics.gui.controls.TextBlock;
6 
7 import evael.graphics.Texture;
8 
9 import evael.utils.Math;
10 import evael.utils.Size;
11 import evael.utils.Color;
12 import evael.utils.Rectangle;
13 
14 class PictureBox : Control
15 {
16 	enum ScaleType
17 	{
18 		Center,
19 		Fit
20 	}
21 
22 	/// Scale type
23 	private ScaleType m_scaleType;
24 
25 	public this(in float x, in float y, in int width, in int height)
26 	{
27 		this(vec2(x, y,), Size!int(width, height));
28 	}
29 
30 	public this()(in auto ref vec2 position, in auto ref Size!int size)
31 	{
32 		super(position, size);
33 
34 		this.m_name = "pictureBox";
35 		
36 		this.m_scaleType = ScaleType.Fit;
37 	}
38 
39 	/**
40 	 * Renders the picturebox
41 	 */
42 	public override void draw(in float deltaTime)
43 	{
44 		if(!this.m_isVisible)
45 		{
46 			return;
47 		}
48 
49 		super.draw(deltaTime);
50 		
51 		if(this.m_texture is null)
52 		{
53 			return;
54 		}
55 
56 		immutable x = this.m_realPosition.x;
57 		immutable y = this.m_realPosition.y;
58 		immutable w = this.m_size.width;
59 		immutable h = this.m_size.height;
60 
61 		auto vg = this.m_nvg;
62 
63 		// https://github.com/memononen/nanovg/issues/348
64 		// Aspect ratios of pixel in x and y dimensions. 
65 		// This allows us to scale the sprite to fill the whole rectangle.
66 		immutable ax = cast(float)w / this.m_textureCoords.size.width;
67 		immutable ay = cast(float)h / this.m_textureCoords.size.height;
68 		
69 		// si w = 48
70 		// ax = 1
71 		// si w = 28
72 		// ax = 0.58
73 		NVGpaint imgPaint = nvgImagePattern(vg, x - this.m_textureCoords.left * ax, y - this.m_textureCoords.bottom * ay,
74 			this.m_texture.size.width * ax , this.m_texture.size.height * ay,  0, this.m_texture.nvgId, this.m_opacity / 255.0f);
75 			
76 		nvgBeginPath(vg);
77 		nvgRoundedRect(vg, x, y, w, h, 3);
78 		nvgFillPaint(vg, imgPaint);
79 		nvgFill(vg);
80 	}
81 
82 	/**
83 	 * Event called on mouse button click
84 	 * Params:
85 	 *		mouseButton : mouse button	 
86 	 *		mousePosition : mouse position
87 	 */
88 	public override void onMouseClick(in MouseButton mouseButton, in ref vec2 mousePosition)
89 	{
90 		super.onMouseClick(mouseButton, mousePosition);
91 		this.switchState!(State.Clicked);
92 	}
93 
94 	/**
95 	 * Event called on mouse button release
96 	 * Params:
97 	 *		mouseButton : mouse button
98 	 */
99 	public override void onMouseUp(in MouseButton mouseButton)
100 	{
101 		super.onMouseUp(mouseButton);
102 		this.switchState!(State.Hovered);
103 	}
104 
105 	/**
106 	 * Event called when mouse enters in control's rect
107 	 * Params:
108 	 * 		 mousePosition : mouse position
109 	 */
110 	public override void onMouseMove(in ref vec2 mousePosition)
111 	{
112 		if(this.hasFocus)
113 		{
114 			return;
115 		}
116 
117 		super.onMouseMove(mousePosition);
118 
119 		if(this.isClicked)
120 		{
121 			this.switchState!(State.Clicked);
122 		}
123 		else
124 		{
125 			this.switchState!(State.Hovered);
126 		}
127 	}
128 
129 	/**
130 	 * Event called when mouse leaves in control's rect
131 	 */
132 	public override void onMouseLeave()
133 	{
134 		super.onMouseLeave();
135 		this.switchState!(State.Normal);
136 	}
137 
138 	@property
139 	{
140 		public void scaleType(in ScaleType value) nothrow @nogc
141 		{
142 			this.m_scaleType = value;
143 		}
144 	}
145 }