1 /**
2 Film-strip on/off switch.
3 
4 Copyright: Ethan Reker 2017.
5 Copyright: Guillaume Piolat 2018.
6 License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7 */
8 
9 module dplug.flatwidgets.flatswitch;
10 
11 import std.math;
12 import dplug.core.math;
13 import dplug.gui.element;
14 import dplug.client.params;
15 
16 class UIImageSwitch : UIElement, IParameterListener
17 {
18 public:
19 nothrow:
20 @nogc:
21 
22     enum Orientation
23     {
24         vertical,
25         horizontal
26     }
27 
28     @ScriptProperty
29     {
30         Orientation orientation = Orientation.vertical;
31     }
32 
33     this(UIContext context, BoolParameter param, OwnedImage!RGBA onImage, OwnedImage!RGBA offImage)
34     {
35         super(context, flagRaw);
36         _param = param;
37         _param.addListener(this);
38 
39         _onImage = onImage;
40         _offImage = offImage;
41         assert(_onImage.h == _offImage.h);
42         assert(_onImage.w == _offImage.w);
43         _width = _onImage.w;
44         _height = _onImage.h;
45 
46         _onImageScaled = mallocNew!(OwnedImage!RGBA)();
47         _offImageScaled = mallocNew!(OwnedImage!RGBA)();
48 
49     }
50 
51     ~this()
52     {
53         _param.removeListener(this);
54         _onImageScaled.destroyFree();
55         _offImageScaled.destroyFree();
56     }
57 
58     bool getState()
59     {
60       return unsafeObjectCast!BoolParameter(_param).valueAtomic();
61     }
62 
63     override void reflow()
64     {
65         _onImageScaled.size(position.width, position.height);
66         _offImageScaled.size(position.width, position.height);
67         context.globalImageResizer.resizeImage_sRGBWithAlpha(_onImage.toRef, _onImageScaled.toRef);
68         context.globalImageResizer.resizeImage_sRGBWithAlpha(_offImage.toRef, _offImageScaled.toRef);
69     }
70 
71     override void onDrawRaw(ImageRef!RGBA rawMap, box2i[] dirtyRects)
72     {
73           auto _currentImage = getState() ? _onImageScaled : _offImageScaled;
74           foreach(dirtyRect; dirtyRects)
75           {
76               auto croppedRawIn = _currentImage.toRef.cropImageRef(dirtyRect);
77               auto croppedRawOut = rawMap.cropImageRef(dirtyRect);
78 
79               int w = dirtyRect.width;
80               int h = dirtyRect.height;
81 
82               for(int j = 0; j < h; ++j)
83               {
84                   RGBA[] input = croppedRawIn.scanline(j);
85                   RGBA[] output = croppedRawOut.scanline(j);
86 
87                   for(int i = 0; i < w; ++i)
88                   {
89                       ubyte alpha = input[i].a;
90 
91                       RGBA color = blendColor(input[i], output[i], alpha);
92                       output[i] = color;
93                   }
94               }
95           }
96     }
97 
98     override Click onMouseClick(int x, int y, int button, bool isDoubleClick, MouseState mstate)
99     {
100         if (mstate.altPressed) // reset on ALT + click
101         {
102             _param.beginParamEdit();
103             _param.setFromGUI(_param.defaultValue());
104             _param.endParamEdit();
105         }
106         else
107         {
108             // Any click => invert
109             // Note: double-click doesn't reset to default, would be annoying
110             _param.beginParamEdit();
111             _param.setFromGUI(!_param.value());
112             _param.endParamEdit();
113         }
114         return Click.startDrag; 
115     }
116 
117     override void onMouseEnter()
118     {
119         _param.beginParamHover();
120         setDirtyWhole();
121     }
122 
123     override void onMouseMove(int x, int y, int dx, int dy, MouseState mstate)
124     {        
125     }
126 
127     override void onMouseExit()
128     {
129         _param.endParamHover();
130         setDirtyWhole();
131     }
132 
133     override void onBeginDrag()
134     {
135     }
136 
137     override void onStopDrag()
138     {
139     }
140     
141     override void onMouseDrag(int x, int y, int dx, int dy, MouseState mstate)
142     {        
143     }
144 
145     override void onParameterChanged(Parameter sender) nothrow @nogc
146     {
147         setDirtyWhole();
148     }
149 
150     override void onBeginParameterEdit(Parameter sender)
151     {
152     }
153 
154     override void onEndParameterEdit(Parameter sender)
155     {
156     }
157 
158     override void onBeginParameterHover(Parameter sender)
159     {
160     }
161 
162     override void onEndParameterHover(Parameter sender)
163     {
164     }
165 
166 protected:
167 
168     BoolParameter _param;
169     bool _state;
170     OwnedImage!RGBA _onImage;
171     OwnedImage!RGBA _offImage;
172     OwnedImage!RGBA _onImageScaled;
173     OwnedImage!RGBA _offImageScaled;
174     int _width;
175     int _height;
176 }