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 }