FRColorEditor.pas 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. //
  2. // This unit is part of the GLScene Engine, http://glscene.org
  3. //
  4. unit FRColorEditor;
  5. (* RGB+Alpha color editor. *)
  6. interface
  7. {$I GLScene.inc}
  8. uses
  9. WinApi.Windows,
  10. System.Classes,
  11. System.SysUtils,
  12. System.Types,
  13. VCL.Forms,
  14. VCL.StdCtrls,
  15. VCL.ComCtrls,
  16. VCL.ExtCtrls,
  17. VCL.Dialogs,
  18. VCL.Controls,
  19. VCL.Graphics,
  20. GLVectorGeometry,
  21. GLColor,
  22. GLTexture,
  23. GLCrossPlatform,
  24. GLVectorTypes;
  25. type
  26. TRColorEditor = class(TFrame)
  27. Label1: TLabel;
  28. Label2: TLabel;
  29. Label3: TLabel;
  30. Label4: TLabel;
  31. PAPreview: TPanel;
  32. ColorDialog: TColorDialog;
  33. Panel1: TPanel;
  34. ColorEditorPaintBox: TPaintBox;
  35. RedEdit: TEdit;
  36. GreenEdit: TEdit;
  37. BlueEdit: TEdit;
  38. AlphaEdit: TEdit;
  39. procedure TBEChange(Sender: TObject);
  40. procedure PAPreviewDblClick(Sender: TObject);
  41. procedure ColorEditorPaintBoxPaint(Sender: TObject);
  42. procedure FrameResize(Sender: TObject);
  43. procedure ColorEditorPaintBoxMouseDown(Sender: TObject;
  44. Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  45. procedure ColorEditorPaintBoxMouseMove(Sender: TObject;
  46. Shift: TShiftState; X, Y: Integer);
  47. procedure ColorEditorPaintBoxMouseUp(Sender: TObject;
  48. Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  49. procedure RedEditChange(Sender: TObject);
  50. procedure GreenEditChange(Sender: TObject);
  51. procedure BlueEditChange(Sender: TObject);
  52. procedure AlphaEditChange(Sender: TObject);
  53. private
  54. FOnChange : TNotifyEvent;
  55. updating : Boolean;
  56. WorkBitmap : tBitmap;
  57. RedValue : Integer;
  58. GreenValue : integer;
  59. BlueValue : integer;
  60. AlphaVAlue : integer;
  61. DraggingValue : (None,Red,Green,Blue,Alpha);
  62. procedure SetColor(const val : THomogeneousFltVector);
  63. function GetColor : THomogeneousFltVector;
  64. procedure DrawContents;
  65. procedure DragColorSliderToPosition(XPos : integer);
  66. procedure ContentsChanged;
  67. public
  68. constructor Create(AOwner: TComponent); override;
  69. destructor Destroy; override;
  70. property Color : THomogeneousFltVector read GetColor write SetColor;
  71. published
  72. property OnChange : TNotifyEvent read FOnChange write FOnChange;
  73. end;
  74. //--------------------------------------------------------------------
  75. implementation
  76. //--------------------------------------------------------------------
  77. {$R *.dfm}
  78. const
  79. MaxColorValue = 255;
  80. MaxAlphaValue = 1000;
  81. ColorSliderLeft = 40;
  82. ColorSliderWidth = 128;
  83. ColorSliderHeight = 16;
  84. ColorViewHeight = 7;
  85. ColorSliderMaxValue = ColorSliderWidth - 2;
  86. RTop = 8;
  87. GTop = 30;
  88. BTop = 52;
  89. ATop = 74;
  90. PreviewPanelLeft = 216;
  91. PreviewPanelTop = 10;
  92. PreviewPanelWidth = 65;
  93. PreviewPanelHeight = 74;
  94. AlphaCheckSize = 9;
  95. AlphaChecksHigh = 4;
  96. AlphaChecksWide = 7;
  97. procedure TRColorEditor.TBEChange(Sender: TObject);
  98. begin
  99. PAPreview.Color := RGB(RedValue, GreenValue, BlueValue);
  100. if (not updating) and Assigned(FOnChange) then FOnChange(Self);
  101. end;
  102. procedure TRColorEditor.SetColor(const val : THomogeneousFltVector);
  103. begin
  104. RedValue:=Round(val.X*255);
  105. GreenValue:=Round(val.Y*255);
  106. BlueValue:=Round(val.Z*255);
  107. AlphaValue:=Round(val.W*1000);
  108. ContentsChanged;
  109. end;
  110. function TRColorEditor.GetColor : THomogeneousFltVector;
  111. begin
  112. Result:=VectorMake(RedValue/255, GreenValue/255, BlueValue/255,
  113. AlphaValue/1000);
  114. end;
  115. procedure TRColorEditor.PAPreviewDblClick(Sender: TObject);
  116. begin
  117. ColorDialog.Color := PAPreview.Color;
  118. if ColorDialog.Execute then
  119. SetColor(ConvertWinColor(ColorDialog.Color));
  120. end;
  121. procedure TRColorEditor.ColorEditorPaintBoxPaint(Sender: TObject);
  122. begin
  123. with ColorEditorPaintBox,ColorEditorPaintBox.Canvas do
  124. begin
  125. Draw(0,0,WorkBitmap);
  126. end;
  127. RedEdit.Height := 16;
  128. GreenEdit.Height := 16;
  129. BlueEdit.Height := 16;
  130. AlphaEdit.Height := 16;
  131. end;
  132. constructor TRColorEditor.Create(AOwner: TComponent);
  133. begin
  134. inherited;
  135. WorkBitmap := TBitmap.Create;
  136. WorkBitmap.PixelFormat := pf24bit;
  137. WorkBitmap.HandleType := bmDib;
  138. RedValue := 200;
  139. GreenValue := 120;
  140. BlueValue := 60;
  141. AlphaValue := 450;
  142. end;
  143. destructor TRColorEditor.Destroy;
  144. begin
  145. inherited;
  146. WorkBitmap.Free;
  147. end;
  148. procedure TRColorEditor.FrameResize(Sender: TObject);
  149. begin
  150. WorkBitmap.Width := ColorEditorPaintBox.Width;
  151. WorkBitmap.Height := ColorEditorPaintBox.Height;
  152. With WorkBitmap.Canvas do
  153. begin
  154. Pen.Color := clLime;
  155. MoveTo(0,0);
  156. LineTo(Width-1,Height-1);
  157. MoveTo(Width-1,0);
  158. LineTo(0,Height-1);
  159. end;
  160. DrawCOntents;
  161. // Edits have an annoying habit of forgetting their height if they are small
  162. RedEdit.Height := 18;
  163. GreenEdit.Height := 18;
  164. BlueEdit.Height := 18;
  165. AlphaEdit.Height := 18;
  166. end;
  167. function ColorValueToColorViewPosition(ColorValue : integer) : integer;
  168. begin
  169. Result := Round( (ColorSliderMaxValue/(MaxColorValue+1)) * ColorValue);
  170. end;
  171. function AlphaValueToColorViewPosition(AlphaValue : integer) : integer;
  172. begin
  173. Result := Round( (ColorSliderMaxValue/(MaxAlphaValue+1)) * AlphaValue);
  174. end;
  175. function ColorViewPositionToColorValue(ColorViewPosition : integer) : integer;
  176. begin
  177. if ColorViewPosition < 0 then ColorViewPosition := 0;
  178. if ColorViewPosition > ColorSliderMaxValue then ColorViewPosition := ColorSliderMaxValue;
  179. Result := Round(ColorViewPosition / (ColorSliderMaxValue/(MaxColorValue)));
  180. end;
  181. function ColorViewPositionToAlphaValue(ColorViewPosition : integer) : integer;
  182. begin
  183. if ColorViewPosition < 0 then ColorViewPosition := 0;
  184. if ColorViewPosition > ColorSliderMaxValue then ColorViewPosition := ColorSliderMaxValue;
  185. Result := Round(ColorViewPosition / (ColorSliderMaxValue/(MaxAlphaValue)));
  186. end;
  187. procedure TRColorEditor.DrawContents;
  188. var
  189. Position : integer;
  190. tx,ty : integer;
  191. RViewColor : tColor;
  192. GViewColor : tColor;
  193. BViewColor : tColor;
  194. AViewColor : tColor;
  195. ViewLevel : integer;
  196. WhiteCheckColor : tColor;
  197. BlackCheckColor : tColor;
  198. AValue : single;
  199. begin
  200. with WorkBitmap.Canvas do
  201. begin
  202. Brush.Color := clBtnFace;
  203. FillRect(Rect(0,0,WorkBitmap.Width,WorkBitmap.Height));
  204. Font.Color := clBlack;
  205. Font.Name := 'Arial';
  206. Font.Height := 14;
  207. TextOut(6,5,'Red');
  208. TextOut(6,26,'Green');
  209. TextOut(6,48,'Blue');
  210. TextOut(6,70,'Alpha');
  211. Brush.Color := clBlack;
  212. FrameRect(Rect(ColorSliderLeft,RTop,ColorSliderLeft+ColorSliderWidth,RTop+ColorViewHeight));
  213. FrameRect(Rect(ColorSliderLeft,GTop,ColorSliderLeft+ColorSliderWidth,GTop+ColorViewHeight));
  214. FrameRect(Rect(ColorSliderLeft,BTop,ColorSliderLeft+ColorSliderWidth,BTop+ColorViewHeight));
  215. FrameRect(Rect(ColorSliderLeft,ATop,ColorSliderLeft+ColorSliderWidth,ATop+ColorViewHeight));
  216. // Color View Frames
  217. Pen.Color := clBtnShadow;
  218. PolyLine([ Point(ColorSliderLeft-1,RTop+ColorViewHeight),
  219. Point(ColorSliderLeft-1,RTop-1),
  220. Point(ColorSliderLeft+ColorSliderWidth+1,RTop-1) ]);
  221. PolyLine([ Point(ColorSliderLeft-1,GTop+ColorViewHeight),
  222. Point(ColorSliderLeft-1,GTop-1),
  223. Point(ColorSliderLeft+ColorSliderWidth+1,GTop-1) ]);
  224. PolyLine([ Point(ColorSliderLeft-1,BTop+ColorViewHeight),
  225. Point(ColorSliderLeft-1,BTop-1),
  226. Point(ColorSliderLeft+ColorSliderWidth+1,BTop-1) ]);
  227. PolyLine([ Point(ColorSliderLeft-1,ATop+ColorViewHeight),
  228. Point(ColorSliderLeft-1,ATop-1),
  229. Point(ColorSliderLeft+ColorSliderWidth+1,ATop-1) ]);
  230. Pen.Color := clBtnHighlight;
  231. PolyLine([ Point(ColorSliderLeft,RTop+ColorViewHeight),
  232. Point(ColorSliderLeft+ColorSliderWidth,RTop+ColorViewHeight),
  233. Point(ColorSliderLeft+ColorSliderWidth,RTop) ]);
  234. PolyLine([ Point(ColorSliderLeft,GTop+ColorViewHeight),
  235. Point(ColorSliderLeft+ColorSliderWidth,GTop+ColorViewHeight),
  236. Point(ColorSliderLeft+ColorSliderWidth,GTop) ]);
  237. PolyLine([ Point(ColorSliderLeft,BTop+ColorViewHeight),
  238. Point(ColorSliderLeft+ColorSliderWidth,BTop+ColorViewHeight),
  239. Point(ColorSliderLeft+ColorSliderWidth,BTop) ]);
  240. PolyLine([ Point(ColorSliderLeft,ATop+ColorViewHeight),
  241. Point(ColorSliderLeft+ColorSliderWidth,ATop+ColorViewHeight),
  242. Point(ColorSliderLeft+ColorSliderWidth,ATop) ]);
  243. // Color pointer triangles
  244. Pen.Color := clBlack;
  245. Position:=ColorValueToColorViewPosition(RedValue) + ColorSliderLeft;
  246. PolyLine([ Point(Position,RTop+ColorViewHeight+2),
  247. Point(Position+6,RTop+ColorViewHeight+8),
  248. Point(Position-6,RTop+ColorViewHeight+8),
  249. Point(Position,RTop+ColorViewHeight+2)]);
  250. Position:=ColorValueToColorViewPosition(GreenValue) + ColorSliderLeft;
  251. PolyLine([ Point(Position,GTop+ColorViewHeight+2),
  252. Point(Position+6,GTop+ColorViewHeight+8),
  253. Point(Position-6,GTop+ColorViewHeight+8),
  254. Point(Position,GTop+ColorViewHeight+2)]);
  255. Position:=ColorValueToColorViewPosition(BlueValue) + ColorSliderLeft;
  256. PolyLine([ Point(Position,BTop+ColorViewHeight+2),
  257. Point(Position+6,BTop+ColorViewHeight+8),
  258. Point(Position-6,BTop+ColorViewHeight+8),
  259. Point(Position,BTop+ColorViewHeight+2)]);
  260. Position:=AlphaValueToColorViewPosition(AlphaValue) + ColorSliderLeft;
  261. PolyLine([ Point(Position,ATop+ColorViewHeight+2),
  262. Point(Position+6,ATop+ColorViewHeight+8),
  263. Point(Position-6,ATop+ColorViewHeight+8),
  264. Point(Position,ATop+ColorViewHeight+2)]);
  265. // Color view spectrums
  266. For tx := 1 to ColorSliderWidth - 2 do
  267. begin
  268. ViewLevel := (tx * 256) div ColorSliderWidth;
  269. AViewColor := (ViewLevel) + (ViewLevel shl 8) + (viewLevel shl 16);
  270. RViewColor := (ViewLevel) + (GreenValue Shl 8) + (BlueValue Shl 16);
  271. GViewColor := (RedValue) + (ViewLevel shl 8) + (BlueValue Shl 16);
  272. BViewColor := (RedValue) + (GreenValue Shl 8) + (ViewLevel Shl 16);
  273. For ty := 1 to ColorViewHeight -2 do
  274. begin
  275. Pixels[ColorSliderLeft+tx,Rtop+Ty]:=RViewCOlor;
  276. Pixels[ColorSliderLeft+tx,Gtop+Ty]:=GViewColor;
  277. Pixels[ColorSliderLeft+tx,Btop+Ty]:=BViewColor;
  278. Pixels[ColorSliderLeft+tx,Atop+Ty]:=AViewColor;
  279. end;
  280. end;
  281. // Color preview panel
  282. Pen.Color := clBtnShadow;
  283. PolyLine([ Point(PreviewPanelLeft-1,PreviewPanelTop+PreviewPanelHeight),
  284. Point(PreviewPanelLeft-1,PreviewPanelTop-1),
  285. Point(PreviewPanelLeft+PreviewPanelWidth,PreviewPanelTop-1) ]);
  286. Pen.Color := clBtnHighlight;
  287. PolyLine([ Point(PreviewPanelLeft,PreviewPanelTop+PreviewPanelHeight),
  288. Point(PreviewPanelLeft+PreviewPanelWidth,PreviewPanelTop+PreviewPanelHeight),
  289. Point(PreviewPanelLeft+PreviewPanelWidth,PreviewPanelTop) ]);
  290. Brush.Color := (RedValue) + (GreenValue Shl 8) + (BlueValue Shl 16);
  291. Pen.Color := clBlack;
  292. Rectangle(Rect(PreviewPanelLeft,PreviewPanelTop,PreviewPanelLeft+PreviewPanelWidth,PreviewPanelTop+PreviewPanelHeight div 2 ) );
  293. PolyLine([ Point(PreviewPanelLeft,PreviewPanelTop+PreviewPanelHeight div 2 -1),
  294. Point(PreviewPanelLeft,PreviewPanelTop+PreviewPanelHeight -1),
  295. Point(PreviewPanelLeft+PreviewPanelWidth-1,PreviewPanelTop+PreviewPanelHeight-1),
  296. Point(PreviewPanelLeft+PreviewPanelWidth-1,PreviewPanelTop+PreviewPanelHeight div 2-1)
  297. ]);
  298. AValue := AlphaValue / MaxAlphaValue;
  299. BlackCheckColor := Round(RedValue * Avalue) + Round(GreenValue*AValue) shl 8 + Round(BlueValue*AValue) shl 16;
  300. WhiteCheckColor := Round(RedValue * Avalue + (255 * (1-AValue))) + Round(GreenValue*AValue + (255 * (1-AValue))) shl 8 + Round(BlueValue*AValue + (255 * (1-AValue))) shl 16;
  301. For ty := 0 to AlphaChecksHigh - 1 do
  302. begin
  303. For tx := 0 to AlphaChecksWide - 1 do
  304. begin
  305. if (tx+ty) and 1 = 0 then Brush.Color := BlackCheckColor else Brush.Color := WhiteCheckColor;
  306. FillRect(Rect( PreviewPanelLeft+1 + tx*AlphaCheckSize,
  307. PreviewPanelTop+PreviewPanelHeight Div 2 + ty*AlphaCheckSize,
  308. PreviewPanelLeft+1 + (tx+1)*AlphaCheckSize,
  309. PreviewPanelTop+PreviewPanelHeight Div 2 + (ty+1)*AlphaCheckSize
  310. ));
  311. end;
  312. end;
  313. end;
  314. end;
  315. procedure TRColorEditor.ColorEditorPaintBoxMouseDown(Sender: TObject;
  316. Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  317. begin
  318. DraggingValue := None;
  319. if Button = TMouseButton(mbLeft) then
  320. begin
  321. if (X > ColorSliderLeft-5) and ( X < (ColorSliderLeft+ColorSliderMaxValue+5)) then
  322. begin
  323. // In X range For Color Sliders
  324. If (Y > RTop) and ( (RTop+ColorSliderHeight) > Y ) then DraggingValue := Red;
  325. If (Y > GTop) and ( (GTop+ColorSliderHeight) > Y ) then DraggingValue := Green;
  326. If (Y > BTop) and ( (BTop+ColorSliderHeight) > Y ) then DraggingValue := Blue;
  327. If (Y > ATop) and ( (ATop+ColorSliderHeight) > Y ) then DraggingValue := Alpha;
  328. If DraggingValue <> None then DragColorSliderToPosition(X-ColorSliderLeft-1);
  329. end
  330. end;
  331. end;
  332. procedure TRColorEditor.DragColorSliderToPosition(XPos: integer);
  333. begin
  334. case DraggingValue of
  335. Red: RedValue := ColorViewPositionToColorValue(XPos);
  336. Green: GreenValue := ColorViewPositionToColorValue(XPos);
  337. Blue: BlueValue := ColorViewPositionToColorValue(XPos);
  338. Alpha: AlphaValue := ColorViewPositionToAlphaValue(XPos);
  339. end;
  340. ContentsChanged;
  341. end;
  342. procedure TRColorEditor.ContentsChanged;
  343. begin
  344. if Not Updating then
  345. begin
  346. UpDating := True;
  347. DrawContents;
  348. ColorEditorPaintBox.Canvas.Draw(0,0,WorkBitmap);
  349. RedEdit.Text := IntToStr(RedValue);
  350. GreenEdit.Text := IntToStr(GreenValue);
  351. BlueEdit.Text := IntToStr(BlueValue);
  352. AlphaEdit.Text := IntToStr(AlphaValue);
  353. PaPreview.Color := RedValue + (GreenValue Shl 8) + (BlueValue Shl 16);
  354. UpDating := False;
  355. TBEChange(Self);
  356. end;
  357. end;
  358. procedure TRColorEditor.ColorEditorPaintBoxMouseMove(Sender: TObject;
  359. Shift: TShiftState; X, Y: Integer);
  360. begin
  361. if DraggingValue <> None then DragColorSliderToPosition(X-ColorSliderLeft-1);
  362. end;
  363. procedure TRColorEditor.ColorEditorPaintBoxMouseUp(Sender: TObject;
  364. Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  365. begin
  366. if Button = TMouseButton(mbLeft) then DraggingValue := None;
  367. end;
  368. procedure TRColorEditor.RedEditChange(Sender: TObject);
  369. var
  370. IntValue : integer;
  371. begin
  372. IntValue := StrToIntDef(RedEdit.Text,-1);
  373. If (IntValue < 0) or (IntValue > MaxColorValue) then
  374. begin
  375. RedEdit.Color:=clRed;
  376. end
  377. else
  378. begin
  379. RedEdit.Color:=clWindow;
  380. RedValue := IntValue;
  381. ContentsChanged;
  382. end;
  383. end;
  384. procedure TRColorEditor.GreenEditChange(Sender: TObject);
  385. var
  386. IntValue : integer;
  387. begin
  388. IntValue := StrToIntDef(GreenEdit.Text,-1);
  389. If (IntValue < 0) or (IntValue > MaxColorValue) then
  390. begin
  391. GreenEdit.Color:=clRed;
  392. end
  393. else
  394. begin
  395. GreenEdit.Color:=clWindow;
  396. GreenValue := IntValue;
  397. ContentsChanged;
  398. end;
  399. end;
  400. procedure TRColorEditor.BlueEditChange(Sender: TObject);
  401. var
  402. IntValue : integer;
  403. begin
  404. IntValue := StrToIntDef(BlueEdit.Text,-1);
  405. If (IntValue < 0) or (IntValue > MaxColorValue) then
  406. begin
  407. BlueEdit.Color:=clRed;
  408. end
  409. else
  410. begin
  411. BlueEdit.Color:=clWindow;
  412. BlueValue := IntValue;
  413. ContentsChanged;
  414. end;
  415. end;
  416. procedure TRColorEditor.AlphaEditChange(Sender: TObject);
  417. var
  418. IntValue : integer;
  419. begin
  420. IntValue := StrToIntDef(AlphaEdit.Text,-1);
  421. If (IntValue < 0) or (IntValue > MaxAlphaValue) then
  422. begin
  423. AlphaEdit.Color:=clRed;
  424. end
  425. else
  426. begin
  427. AlphaEdit.Color:=clWindow;
  428. AlphaValue := IntValue;
  429. ContentsChanged;
  430. end;
  431. end;
  432. end.