GR32_ColorPicker.pas 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318
  1. unit GR32_ColorPicker;
  2. (* ***** BEGIN LICENSE BLOCK *****
  3. * Version: MPL 1.1 or LGPL 2.1 with linking exception
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. * http://www.mozilla.org/MPL/
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. *
  15. * Alternatively, the contents of this file may be used under the terms of the
  16. * Free Pascal modified version of the GNU Lesser General Public License
  17. * Version 2.1 (the "FPC modified LGPL License"), in which case the provisions
  18. * of this license are applicable instead of those above.
  19. * Please see the file LICENSE.txt for additional information concerning this
  20. * license.
  21. *
  22. * The Original Code is Graphics32
  23. *
  24. * The Initial Developer of the Original Code is
  25. * Alex A. Denisov
  26. *
  27. * Portions created by the Initial Developer are Copyright (C) 2000-2009
  28. * the Initial Developer. All Rights Reserved.
  29. *
  30. * ***** END LICENSE BLOCK ***** *)
  31. interface
  32. {$include GR32.inc}
  33. {-$define GR32_FRAME3D}
  34. uses
  35. {$IFDEF FPC}
  36. LCLIntf, LCLType, LMessages, Types,
  37. {$IFDEF MSWINDOWS}
  38. Windows,
  39. {$ENDIF}
  40. {$ELSE}
  41. Windows, Messages, Types,
  42. {$ENDIF}
  43. Classes, Controls, Forms, GR32, GR32_Polygons, GR32_Containers,
  44. GR32_ColorGradients;
  45. type
  46. TScreenColorPickerForm = class(TCustomForm)
  47. private
  48. FSelectedColor: TColor32;
  49. FOnColorSelected: TNotifyEvent;
  50. protected
  51. procedure CreateParams(var Params: TCreateParams); override;
  52. procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  53. procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X: Integer; Y: Integer); override;
  54. procedure MouseMove(Shift: TShiftState; X: Integer; Y: Integer); override;
  55. {$IFDEF FPC}
  56. procedure WMEraseBkgnd(var Message: TLMEraseBkgnd); message LM_ERASEBKGND;
  57. {$ELSE}
  58. procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
  59. {$ENDIF}
  60. public
  61. constructor Create(AOwner: TComponent); override;
  62. function Execute: boolean;
  63. property SelectedColor: TColor32 read FSelectedColor write FSelectedColor;
  64. property OnColorSelected: TNotifyEvent read FOnColorSelected write FOnColorSelected;
  65. published
  66. property OnKeyUp;
  67. property OnKeyPress;
  68. property OnKeyDown;
  69. property OnMouseMove;
  70. property OnMouseUp;
  71. property OnMouseDown;
  72. end;
  73. THueCirclePolygonFiller = class(TCustomPolygonFiller)
  74. private
  75. FCenter: TFloatPoint;
  76. FWebSafe: Boolean;
  77. protected
  78. function GetFillLine: TFillLineEvent; override;
  79. procedure FillLine(Dst: PColor32; DstX, DstY, Length: Integer; AlphaValues: PColor32; CombineMode: TCombineMode); virtual;
  80. procedure FillLineWebSafe(Dst: PColor32; DstX, DstY, Length: Integer; AlphaValues: PColor32; CombineMode: TCombineMode); virtual;
  81. public
  82. constructor Create(Center: TFloatPoint; WebSafe: Boolean = False);
  83. property Center: TFloatPoint read FCenter write FCenter;
  84. property WebSafe: Boolean read FWebSafe write FWebSafe;
  85. end;
  86. THueSaturationCirclePolygonFiller = class(THueCirclePolygonFiller)
  87. private
  88. FRadius: Single;
  89. FInvRadius: Single;
  90. FValue: Single;
  91. procedure SetRadius(const Value: Single);
  92. protected
  93. procedure FillLine(Dst: PColor32; DstX, DstY, Length: Integer; AlphaValues: PColor32; CombineMode: TCombineMode); override;
  94. procedure FillLineWebSafe(Dst: PColor32; DstX, DstY, Length: Integer; AlphaValues: PColor32; CombineMode: TCombineMode); override;
  95. public
  96. constructor Create(Center: TFloatPoint; Radius, Value: Single; WebSafe: Boolean = False);
  97. property Radius: Single read FRadius write SetRadius;
  98. property Value: Single read FValue write FValue;
  99. end;
  100. TBarycentricGradientPolygonFillerEx = class(TBarycentricGradientPolygonFiller)
  101. private
  102. FWebSafe: Boolean;
  103. protected
  104. function GetFillLine: TFillLineEvent; override;
  105. procedure FillLineWebSafe(Dst: PColor32; DstX, DstY, Length: Integer; AlphaValues: PColor32; CombineMode: TCombineMode);
  106. public
  107. property WebSafe: Boolean read FWebSafe write FWebSafe;
  108. end;
  109. TVisualAid = set of (vaHueLine, vaSaturationCircle, vaSelection);
  110. TVisualAidRenderType = (vatSolid, vatInvert, vatBW);
  111. TAdjustCalc = procedure (X, Y: Single) of object;
  112. TVisualAidOptions = class(TPersistent)
  113. private
  114. FOwner: TPersistent;
  115. FRenderType: TVisualAidRenderType;
  116. FColor: TColor32;
  117. FLineWidth: Single;
  118. procedure SetRenderType(const Value: TVisualAidRenderType);
  119. procedure SetColor(const Value: TColor32);
  120. procedure SetLineWidth(const Value: Single);
  121. protected
  122. function GetOwner: TPersistent; override;
  123. procedure Changed; virtual;
  124. public
  125. constructor Create(AOwner: TPersistent); virtual;
  126. procedure Assign(Source: TPersistent); override;
  127. property Owner: TPersistent read FOwner;
  128. published
  129. property RenderType: TVisualAidRenderType read FRenderType write SetRenderType default vatInvert;
  130. property Color: TColor32 read FColor write SetColor;
  131. property LineWidth: Single read FLineWidth write SetLineWidth;
  132. end;
  133. TCustomColorPicker = class(TCustomControl)
  134. private
  135. FBuffer: TBitmap32;
  136. FAdjustCalc: TAdjustCalc;
  137. FSelectedColor: TColor32;
  138. FBufferValid: Boolean;
  139. FVisualAidOptions: TVisualAidOptions;
  140. FWebSafe: Boolean;
  141. FBorder: Boolean;
  142. FOnChanged: TNotifyEvent;
  143. procedure SetBorder(const Value: Boolean);
  144. procedure SetWebSafe(const Value: Boolean);
  145. procedure SetSelectedColor(const Value: TColor32);
  146. {$IFDEF FPC}
  147. procedure WMEraseBkgnd(var Message: TLMEraseBkgnd); message LM_ERASEBKGND;
  148. procedure WMGetDlgCode(var Msg: TLMessage); message LM_GETDLGCODE;
  149. {$ELSE}
  150. procedure WMEraseBkgnd(var Message: TWmEraseBkgnd); message WM_ERASEBKGND;
  151. procedure WMGetDlgCode(var Msg: TWmGetDlgCode); message WM_GETDLGCODE;
  152. {$ENDIF}
  153. protected
  154. procedure Paint; override;
  155. procedure PaintBackground; virtual;
  156. procedure PaintColorPicker; virtual; abstract;
  157. procedure SelectedColorChanged; virtual;
  158. public
  159. constructor Create(AOwner: TComponent); override;
  160. destructor Destroy; override;
  161. procedure Assign(Source: TPersistent); override;
  162. procedure Invalidate; override;
  163. procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
  164. property Border: Boolean read FBorder write SetBorder default False;
  165. property VisualAidOptions: TVisualAidOptions read FVisualAidOptions;
  166. property SelectedColor: TColor32 read FSelectedColor write SetSelectedColor;
  167. property WebSafe: Boolean read FWebSafe write SetWebSafe;
  168. property OnChanged: TNotifyEvent read FOnChanged write FOnChanged;
  169. end;
  170. TColorComponent = (ccRed, ccGreen, ccBlue, ccAlpha);
  171. TCustomColorPickerComponent = class(TCustomColorPicker)
  172. private
  173. FMouseDown: Boolean;
  174. FColorComponent: TColorComponent;
  175. procedure SetColorComponent(const Value: TColorComponent);
  176. protected
  177. procedure PaintColorPicker; override;
  178. procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X: Integer; Y: Integer); override;
  179. procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X: Integer; Y: Integer); override;
  180. procedure MouseMove(Shift: TShiftState; X: Integer; Y: Integer); override;
  181. public
  182. constructor Create(AOwner: TComponent); override;
  183. procedure Assign(Source: TPersistent); override;
  184. property ColorComponent: TColorComponent read FColorComponent write SetColorComponent;
  185. end;
  186. TCustomColorPickerRGBA = class(TCustomColorPicker)
  187. private
  188. FBarHeight: Integer;
  189. FSpaceHeight: Integer;
  190. procedure SetBarHeight(const Value: Integer);
  191. procedure SetSpaceHeight(const Value: Integer);
  192. procedure PickAlpha(X, Y: Single);
  193. procedure PickBlue(X, Y: Single);
  194. procedure PickGreen(X, Y: Single);
  195. procedure PickRed(X, Y: Single);
  196. protected
  197. procedure PaintColorPicker; override;
  198. procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X: Integer; Y: Integer); override;
  199. procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X: Integer; Y: Integer); override;
  200. procedure MouseMove(Shift: TShiftState; X: Integer; Y: Integer); override;
  201. public
  202. constructor Create(AOwner: TComponent); override;
  203. procedure Assign(Source: TPersistent); override;
  204. property BarHeight: Integer read FBarHeight write SetBarHeight default 24;
  205. property SpaceHeight: Integer read FSpaceHeight write SetSpaceHeight default 8;
  206. end;
  207. TMarkerType = (mtCross, mtCircle);
  208. TCustomColorPickerHS = class(TCustomColorPicker)
  209. private
  210. FHue: Single;
  211. FSaturation: Single;
  212. FLockValues: integer;
  213. FMarkerType: TMarkerType;
  214. procedure PickHue(X, Y: Single);
  215. procedure SetHue(const Value: Single);
  216. procedure SetSaturation(const Value: Single);
  217. procedure SetMarkerType(const Value: TMarkerType);
  218. procedure ApplyHS;
  219. protected
  220. procedure PaintColorPicker; override;
  221. procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X: Integer; Y: Integer); override;
  222. procedure MouseMove(Shift: TShiftState; X: Integer; Y: Integer); override;
  223. procedure SelectedColorChanged; override;
  224. public
  225. constructor Create(AOwner: TComponent); override;
  226. procedure Assign(Source: TPersistent); override;
  227. property MarkerType: TMarkerType read FMarkerType write SetMarkerType;
  228. property Hue: Single read FHue write SetHue;
  229. property Saturation: Single read FSaturation write SetSaturation;
  230. end;
  231. TCustomColorPickerHSV = class(TCustomColorPicker)
  232. private
  233. FHue: Single;
  234. FSaturation: Single;
  235. FValue: Single;
  236. FLockValues: integer;
  237. FCenter: TFloatPoint;
  238. FRadius: TFloat;
  239. FCircleSteps: Integer;
  240. FVisualAid: TVisualAid;
  241. procedure PickHue(X, Y: Single);
  242. procedure PickValue(X, Y: Single);
  243. procedure SetHue(const Value: Single);
  244. procedure SetSaturation(const Value: Single);
  245. procedure SetValue(const Value: Single);
  246. procedure SetVisualAid(const Value: TVisualAid);
  247. procedure ApplyHSV;
  248. protected
  249. procedure PaintColorPicker; override;
  250. procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X: Integer; Y: Integer); override;
  251. procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X: Integer; Y: Integer); override;
  252. procedure MouseMove(Shift: TShiftState; X: Integer; Y: Integer); override;
  253. procedure SelectedColorChanged; override;
  254. public
  255. constructor Create(AOwner: TComponent); override;
  256. procedure Assign(Source: TPersistent); override;
  257. procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
  258. property Hue: Single read FHue write SetHue;
  259. property Saturation: Single read FSaturation write SetSaturation;
  260. property Value: Single read FValue write SetValue;
  261. property VisualAid: TVisualAid read FVisualAid write SetVisualAid;
  262. end;
  263. TVisualAidGTK = set of (vagHueLine, vagSelection);
  264. TCustomColorPickerGTK = class(TCustomColorPicker)
  265. private
  266. FHue: Single;
  267. FSaturation: Single;
  268. FValue: Single;
  269. FLockValues: integer;
  270. FCenter: TFloatPoint;
  271. FRadius: TFloat;
  272. FInnerRadius: TFloat;
  273. FCircleSteps: Integer;
  274. FVisualAid: TVisualAidGTK;
  275. procedure PickHue(X, Y: Single);
  276. procedure PickSaturationValue(X, Y: Single);
  277. procedure SetHue(const Value: Single);
  278. procedure SetSaturation(const Value: Single);
  279. procedure SetValue(const Value: Single);
  280. procedure SetVisualAid(const Value: TVisualAidGTK);
  281. procedure SetRadius(const Value: TFloat);
  282. procedure ApplyHSV;
  283. protected
  284. procedure PaintColorPicker; override;
  285. procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X: Integer; Y: Integer); override;
  286. procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X: Integer; Y: Integer); override;
  287. procedure MouseMove(Shift: TShiftState; X: Integer; Y: Integer); override;
  288. procedure SelectedColorChanged; override;
  289. property Radius: TFloat read FRadius write SetRadius;
  290. property Center: TFloatPoint read FCenter write FCenter;
  291. public
  292. constructor Create(AOwner: TComponent); override;
  293. procedure Assign(Source: TPersistent); override;
  294. procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
  295. property Hue: Single read FHue write SetHue;
  296. property Saturation: Single read FSaturation write SetSaturation;
  297. property Value: Single read FValue write SetValue;
  298. property VisualAid: TVisualAidGTK read FVisualAid write SetVisualAid;
  299. end;
  300. TColorPickerComponent = class(TCustomColorPickerComponent)
  301. published
  302. property Border;
  303. property ColorComponent;
  304. property SelectedColor;
  305. property VisualAidOptions;
  306. property WebSafe default False;
  307. property OnChanged;
  308. property Align;
  309. property Anchors;
  310. property DragCursor;
  311. property DragKind;
  312. property Enabled;
  313. {$IFDEF HasParentBackground}
  314. // property ParentBackground;
  315. {$ENDIF}
  316. property Color; // Background color
  317. property ParentColor;
  318. property ParentShowHint;
  319. property PopupMenu;
  320. property TabOrder;
  321. property TabStop;
  322. {$IFNDEF PLATFORM_INDEPENDENT}
  323. property OnCanResize;
  324. {$ENDIF}
  325. property OnClick;
  326. property OnDblClick;
  327. property OnDragDrop;
  328. property OnDragOver;
  329. property OnEndDrag;
  330. property OnMouseDown;
  331. property OnMouseMove;
  332. property OnMouseUp;
  333. property OnMouseWheel;
  334. property OnMouseWheelDown;
  335. property OnMouseWheelUp;
  336. property OnMouseEnter;
  337. property OnMouseLeave;
  338. property OnResize;
  339. property OnStartDrag;
  340. end;
  341. TColorPickerRGBA = class(TCustomColorPickerRGBA)
  342. published
  343. property BarHeight;
  344. property Border;
  345. property SelectedColor;
  346. property SpaceHeight;
  347. property VisualAidOptions;
  348. property WebSafe default False;
  349. property OnChanged;
  350. property Align;
  351. property Anchors;
  352. property DragCursor;
  353. property DragKind;
  354. property Enabled;
  355. {$IFDEF HasParentBackground}
  356. // property ParentBackground;
  357. {$ENDIF}
  358. property Color; // Background color
  359. property ParentColor;
  360. property ParentShowHint;
  361. property PopupMenu;
  362. property TabOrder;
  363. property TabStop;
  364. {$IFNDEF PLATFORM_INDEPENDENT}
  365. property OnCanResize;
  366. {$ENDIF}
  367. property OnClick;
  368. property OnDblClick;
  369. property OnDragDrop;
  370. property OnDragOver;
  371. property OnEndDrag;
  372. property OnMouseDown;
  373. property OnMouseMove;
  374. property OnMouseUp;
  375. property OnMouseWheel;
  376. property OnMouseWheelDown;
  377. property OnMouseWheelUp;
  378. property OnMouseEnter;
  379. property OnMouseLeave;
  380. property OnResize;
  381. property OnStartDrag;
  382. end;
  383. TColorPickerHS = class(TCustomColorPickerHS)
  384. published
  385. property Hue;
  386. property MarkerType;
  387. property Saturation;
  388. property SelectedColor;
  389. property WebSafe default False;
  390. property OnChanged;
  391. property Align;
  392. property Anchors;
  393. property DragCursor;
  394. property DragKind;
  395. property Enabled;
  396. property ParentShowHint;
  397. property PopupMenu;
  398. property TabOrder;
  399. property TabStop;
  400. {$IFNDEF PLATFORM_INDEPENDENT}
  401. property OnCanResize;
  402. {$ENDIF}
  403. property OnClick;
  404. property OnDblClick;
  405. property OnDragDrop;
  406. property OnDragOver;
  407. property OnEndDrag;
  408. property OnMouseDown;
  409. property OnMouseMove;
  410. property OnMouseUp;
  411. property OnMouseWheel;
  412. property OnMouseWheelDown;
  413. property OnMouseWheelUp;
  414. property OnMouseEnter;
  415. property OnMouseLeave;
  416. property OnResize;
  417. property OnStartDrag;
  418. end;
  419. TColorPickerHSV = class(TCustomColorPickerHSV)
  420. published
  421. property Border;
  422. property Hue;
  423. property Saturation;
  424. property SelectedColor;
  425. property Value;
  426. property VisualAid default [vaHueLine, vaSaturationCircle, vaSelection];
  427. property VisualAidOptions;
  428. property WebSafe default False;
  429. property OnChanged;
  430. property Align;
  431. property Anchors;
  432. property DragCursor;
  433. property DragKind;
  434. property Enabled;
  435. {$IFDEF HasParentBackground}
  436. // property ParentBackground;
  437. {$ENDIF}
  438. property Color; // Background color
  439. property ParentColor;
  440. property ParentShowHint;
  441. property PopupMenu;
  442. property TabOrder;
  443. property TabStop;
  444. {$IFNDEF PLATFORM_INDEPENDENT}
  445. property OnCanResize;
  446. {$ENDIF}
  447. property OnClick;
  448. property OnDblClick;
  449. property OnDragDrop;
  450. property OnDragOver;
  451. property OnEndDrag;
  452. property OnMouseDown;
  453. property OnMouseMove;
  454. property OnMouseUp;
  455. property OnMouseWheel;
  456. property OnMouseWheelDown;
  457. property OnMouseWheelUp;
  458. property OnMouseEnter;
  459. property OnMouseLeave;
  460. property OnResize;
  461. property OnStartDrag;
  462. end;
  463. TColorPickerGTK = class(TCustomColorPickerGTK)
  464. published
  465. property Border;
  466. property Hue;
  467. property Saturation;
  468. property SelectedColor;
  469. property Value;
  470. property VisualAid default [vagHueLine, vagSelection];
  471. property VisualAidOptions;
  472. property WebSafe default False;
  473. property OnChanged;
  474. property Align;
  475. property Anchors;
  476. property DragCursor;
  477. property DragKind;
  478. property Enabled;
  479. {$IFDEF HasParentBackground}
  480. // property ParentBackground;
  481. {$ENDIF}
  482. property Color; // Background color
  483. property ParentColor;
  484. property ParentShowHint;
  485. property PopupMenu;
  486. property TabOrder;
  487. property TabStop;
  488. {$IFNDEF PLATFORM_INDEPENDENT}
  489. property OnCanResize;
  490. {$ENDIF}
  491. property OnClick;
  492. property OnDblClick;
  493. property OnDragDrop;
  494. property OnDragOver;
  495. property OnEndDrag;
  496. property OnMouseDown;
  497. property OnMouseMove;
  498. property OnMouseUp;
  499. property OnMouseWheel;
  500. property OnMouseWheelDown;
  501. property OnMouseWheelUp;
  502. property OnMouseEnter;
  503. property OnMouseLeave;
  504. property OnResize;
  505. property OnStartDrag;
  506. end;
  507. implementation
  508. uses
  509. Math, Graphics, GR32_Backends, GR32_Math, GR32_Blend, GR32_VectorUtils;
  510. procedure RoundToWebSafe(var Color: TColor32);
  511. begin
  512. with TColor32Entry(Color) do
  513. begin
  514. R := ((R + $19) div $33) * $33;
  515. G := ((G + $19) div $33) * $33;
  516. B := ((B + $19) div $33) * $33;
  517. end;
  518. end;
  519. {$IFDEF MSWINDOWS}
  520. function GetDesktopColor(const x, y: Integer): TColor32;
  521. var
  522. DC: HDC;
  523. begin
  524. DC := GetWindowDC(GetDesktopWindow);
  525. try
  526. Result := Color32(GetPixel(DC, x, y));
  527. finally
  528. ReleaseDC(GetDesktopWindow, DC);
  529. end;
  530. end;
  531. {$ENDIF}
  532. { TVisualAidOptions }
  533. constructor TVisualAidOptions.Create(AOwner: TPersistent);
  534. begin
  535. inherited Create;
  536. FOwner := AOwner;
  537. FColor := $AF000000;
  538. FRenderType := vatInvert;
  539. FLineWidth := 2;
  540. end;
  541. procedure TVisualAidOptions.Assign(Source: TPersistent);
  542. begin
  543. if (Source is TVisualAidOptions) then
  544. begin
  545. FRenderType := TVisualAidOptions(Source).RenderType;
  546. FColor := TVisualAidOptions(Source).Color;
  547. FLineWidth := TVisualAidOptions(Source).LineWidth;
  548. Changed;
  549. end else
  550. inherited;
  551. end;
  552. procedure TVisualAidOptions.Changed;
  553. begin
  554. if FOwner is TCustomColorPicker then
  555. TCustomColorPicker(Owner).Invalidate;
  556. end;
  557. function TVisualAidOptions.GetOwner: TPersistent;
  558. begin
  559. if FOwner is TPersistent then
  560. Result := TPersistent(FOwner)
  561. else
  562. Result := nil;
  563. end;
  564. procedure TVisualAidOptions.SetColor(const Value: TColor32);
  565. begin
  566. if FColor <> Value then
  567. begin
  568. FColor := Value;
  569. if FRenderType = vatSolid then
  570. Changed;
  571. end;
  572. end;
  573. procedure TVisualAidOptions.SetLineWidth(const Value: Single);
  574. begin
  575. if FLineWidth <> Value then
  576. begin
  577. FLineWidth := Value;
  578. Changed;
  579. end;
  580. end;
  581. procedure TVisualAidOptions.SetRenderType(const Value: TVisualAidRenderType);
  582. begin
  583. if FRenderType <> Value then
  584. begin
  585. FRenderType := Value;
  586. Changed;
  587. end;
  588. end;
  589. { TScreenColorPickerForm }
  590. constructor TScreenColorPickerForm.Create(AOwner: TComponent);
  591. begin
  592. inherited CreateNew(AOwner);
  593. ControlStyle := ControlStyle + [csOpaque];
  594. BorderIcons := [];
  595. BorderStyle := bsNone;
  596. Caption := 'Pick a color...';
  597. FormStyle := fsStayOnTop;
  598. Position := poDesigned;
  599. WindowState := wsMaximized;
  600. Cursor := crHandPoint;
  601. FSelectedColor := 0;
  602. end;
  603. procedure TScreenColorPickerForm.CreateParams(var Params: TCreateParams);
  604. begin
  605. inherited CreateParams(Params);
  606. Params.ExStyle := WS_EX_TRANSPARENT or WS_EX_TOPMOST;
  607. // Theoretically this should make Windows use a null brush when clearing the
  608. // background (i.e. do nothing), but unfortunately it doesn't seem to work.
  609. Params.WindowClass.hbrBackground := NULL_BRUSH;
  610. end;
  611. function TScreenColorPickerForm.Execute: boolean;
  612. begin
  613. Result := (ShowModal = mrOK);
  614. end;
  615. procedure TScreenColorPickerForm.KeyDown(var Key: Word; Shift: TShiftState);
  616. begin
  617. case Key of
  618. VK_ESCAPE:
  619. begin
  620. ModalResult := mrCancel;
  621. Key := 0;
  622. end;
  623. VK_RETURN:
  624. begin
  625. ModalResult := mrOK;
  626. Key := 0;
  627. end;
  628. else
  629. inherited;
  630. end;
  631. end;
  632. procedure TScreenColorPickerForm.MouseDown(Button: TMouseButton;
  633. Shift: TShiftState; X, Y: Integer);
  634. begin
  635. if Button = mbLeft then
  636. begin
  637. {$IFDEF MSWINDOWS}
  638. FSelectedColor := GetDesktopColor(X, Y);
  639. if Assigned(FOnColorSelected) then
  640. FOnColorSelected(Self);
  641. {$ENDIF}
  642. ModalResult := mrOk
  643. end
  644. else
  645. inherited;
  646. end;
  647. procedure TScreenColorPickerForm.MouseMove(Shift: TShiftState; X, Y: Integer);
  648. begin
  649. {$IFDEF MSWINDOWS}
  650. FSelectedColor := GetDesktopColor(X, Y);
  651. {$ENDIF}
  652. inherited;
  653. end;
  654. {$IFDEF FPC}
  655. procedure TScreenColorPickerForm.WMEraseBkgnd(var Message: TLMEraseBkgnd);
  656. {$ELSE}
  657. procedure TScreenColorPickerForm.WMEraseBkgnd(var Message: TWMEraseBkgnd);
  658. {$ENDIF}
  659. begin
  660. // Do not erase window background
  661. Message.Result := 1;
  662. // Note: Does not work with FPC. The message is processed but the background is still cleared.
  663. end;
  664. { THueCirclePolygonFiller }
  665. constructor THueCirclePolygonFiller.Create(Center: TFloatPoint;
  666. WebSafe: Boolean = False);
  667. begin
  668. FCenter := Center;
  669. FWebSafe := WebSafe;
  670. inherited Create;
  671. end;
  672. procedure THueCirclePolygonFiller.FillLine(Dst: PColor32; DstX, DstY,
  673. Length: Integer; AlphaValues: PColor32; CombineMode: TCombineMode);
  674. var
  675. X: Integer;
  676. H: Single;
  677. const
  678. CTwoPiInv = 1 / (2 * Pi);
  679. begin
  680. for X := DstX to DstX + Length - 1 do
  681. begin
  682. // calculate squared distance
  683. H := 0.5 + ArcTan2(DstY - FCenter.Y, X - FCenter.X) * CTwoPiInv;
  684. CombineMem(HSVtoRGB(H, 1, 1), Dst^, AlphaValues^);
  685. Inc(Dst);
  686. Inc(AlphaValues);
  687. end;
  688. end;
  689. procedure THueCirclePolygonFiller.FillLineWebSafe(Dst: PColor32; DstX, DstY,
  690. Length: Integer; AlphaValues: PColor32; CombineMode: TCombineMode);
  691. var
  692. X: Integer;
  693. H: Single;
  694. Color: TColor32;
  695. const
  696. CTwoPiInv = 1 / (2 * Pi);
  697. begin
  698. for X := DstX to DstX + Length - 1 do
  699. begin
  700. // calculate squared distance
  701. H := 0.5 + ArcTan2(DstY - FCenter.Y, X - FCenter.X) * CTwoPiInv;
  702. Color := HSVtoRGB(H, 1, 1);
  703. RoundToWebSafe(Color);
  704. CombineMem(Color, Dst^, AlphaValues^);
  705. Inc(Dst);
  706. Inc(AlphaValues);
  707. end;
  708. end;
  709. function THueCirclePolygonFiller.GetFillLine: TFillLineEvent;
  710. begin
  711. if FWebSafe then
  712. Result := FillLineWebSafe
  713. else
  714. Result := FillLine;
  715. end;
  716. { THueSaturationCirclePolygonFiller }
  717. constructor THueSaturationCirclePolygonFiller.Create(Center: TFloatPoint;
  718. Radius, Value: Single; WebSafe: Boolean = False);
  719. begin
  720. FRadius := Max(1, Radius);
  721. FInvRadius := 1 / FRadius;
  722. FValue := Value;
  723. inherited Create(Center, WebSafe);
  724. end;
  725. procedure THueSaturationCirclePolygonFiller.FillLine(Dst: PColor32; DstX, DstY,
  726. Length: Integer; AlphaValues: PColor32; CombineMode: TCombineMode);
  727. var
  728. X: Integer;
  729. SqrYDist, H, S: Single;
  730. const
  731. CTwoPiInv = 1 / (2 * Pi);
  732. begin
  733. SqrYDist := Sqr(DstY - FCenter.Y);
  734. for X := DstX to DstX + Length - 1 do
  735. begin
  736. // calculate squared distance
  737. H := 0.5 + ArcTan2(DstY - FCenter.Y, X - FCenter.X) * CTwoPiInv;
  738. S := Sqrt(Sqr(X - Center.X) + SqrYDist) * FInvRadius;
  739. if S > 1 then
  740. S := 1;
  741. CombineMem(HSVtoRGB(H, S, Value), Dst^, AlphaValues^);
  742. Inc(Dst);
  743. Inc(AlphaValues);
  744. end;
  745. end;
  746. procedure THueSaturationCirclePolygonFiller.FillLineWebSafe(Dst: PColor32; DstX, DstY,
  747. Length: Integer; AlphaValues: PColor32; CombineMode: TCombineMode);
  748. var
  749. X: Integer;
  750. SqrYDist, H, S: Single;
  751. Color: TColor32;
  752. const
  753. CTwoPiInv = 1 / (2 * Pi);
  754. begin
  755. SqrYDist := Sqr(DstY - FCenter.Y);
  756. for X := DstX to DstX + Length - 1 do
  757. begin
  758. // calculate squared distance
  759. H := 0.5 + ArcTan2(DstY - FCenter.Y, X - FCenter.X) * CTwoPiInv;
  760. S := Sqrt(Sqr(X - Center.X) + SqrYDist) * FInvRadius;
  761. if S > 1 then
  762. S := 1;
  763. Color := HSVtoRGB(H, S, Value);
  764. RoundToWebSafe(Color);
  765. CombineMem(Color, Dst^, AlphaValues^);
  766. Inc(Dst);
  767. Inc(AlphaValues);
  768. end;
  769. end;
  770. procedure THueSaturationCirclePolygonFiller.SetRadius(const Value: Single);
  771. begin
  772. if FRadius <> Value then
  773. begin
  774. FRadius := Value;
  775. FInvRadius := 1 / FRadius;
  776. end;
  777. end;
  778. { TBarycentricGradientPolygonFillerEx }
  779. procedure TBarycentricGradientPolygonFillerEx.FillLineWebSafe(Dst: PColor32; DstX,
  780. DstY, Length: Integer; AlphaValues: PColor32; CombineMode: TCombineMode);
  781. var
  782. X: Integer;
  783. Color32: TColor32;
  784. Temp, DotY1, DotY2: TFloat;
  785. Barycentric: array [0..1] of TFloat;
  786. BlendMemEx: TBlendMemEx;
  787. begin
  788. BlendMemEx := BLEND_MEM_EX[CombineMode]^;
  789. Temp := DstY - FColorPoints[2].Point.Y;
  790. DotY1 := FDists[0].X * Temp;
  791. DotY2 := FDists[1].X * Temp;
  792. for X := DstX to DstX + Length - 1 do
  793. begin
  794. Temp := (X - FColorPoints[2].Point.X);
  795. Barycentric[0] := FDists[0].Y * Temp + DotY1;
  796. Barycentric[1] := FDists[1].Y * Temp + DotY2;
  797. Color32 := Linear3PointInterpolation(FColorPoints[0].Color32,
  798. FColorPoints[1].Color32, FColorPoints[2].Color32,
  799. Barycentric[0], Barycentric[1], 1 - Barycentric[1] - Barycentric[0]);
  800. RoundToWebSafe(Color32);
  801. BlendMemEx(Color32, Dst^, AlphaValues^);
  802. Inc(Dst);
  803. Inc(AlphaValues);
  804. end;
  805. end;
  806. function TBarycentricGradientPolygonFillerEx.GetFillLine: TFillLineEvent;
  807. begin
  808. if FWebSafe then
  809. Result := FillLineWebSafe
  810. else
  811. Result := inherited GetFillLine;
  812. end;
  813. { TCustomColorPicker }
  814. constructor TCustomColorPicker.Create(AOwner: TComponent);
  815. begin
  816. inherited Create(AOwner);
  817. ControlStyle := ControlStyle + [csOpaque] - [csAcceptsControls];
  818. FBuffer := TBitmap32.Create;
  819. FSelectedColor := clSalmon32;
  820. FVisualAidOptions := TVisualAidOptions.Create(Self);
  821. end;
  822. destructor TCustomColorPicker.Destroy;
  823. begin
  824. FVisualAidOptions.Free;
  825. FBuffer.Free;
  826. inherited;
  827. end;
  828. procedure TCustomColorPicker.Assign(Source: TPersistent);
  829. begin
  830. inherited;
  831. if (Source is TCustomColorPicker) then
  832. begin
  833. FBorder := TCustomColorPicker(Source).Border;
  834. FVisualAidOptions.Assign(TCustomColorPicker(Source).VisualAidOptions);
  835. FSelectedColor := TCustomColorPicker(Source).SelectedColor;
  836. FWebSafe := TCustomColorPicker(Source).WebSafe;
  837. FOnChanged := TCustomColorPicker(Source).OnChanged;
  838. Invalidate;
  839. end;
  840. end;
  841. procedure TCustomColorPicker.Invalidate;
  842. begin
  843. FBufferValid := False;
  844. inherited;
  845. end;
  846. procedure TCustomColorPicker.Paint;
  847. begin
  848. if (Parent = nil) then
  849. Exit;
  850. if not FBufferValid then
  851. begin
  852. (FBuffer.Backend as IPaintSupport).ImageNeeded;
  853. PaintColorPicker;
  854. (FBuffer.Backend as IPaintSupport).CheckPixmap;
  855. FBufferValid := True;
  856. end;
  857. FBuffer.Lock;
  858. try
  859. (FBuffer.Backend as IDeviceContextSupport).DrawTo(Canvas.Handle, 0, 0);
  860. finally
  861. FBuffer.Unlock;
  862. end;
  863. end;
  864. procedure TCustomColorPicker.PaintBackground;
  865. var
  866. BackgroundColor: TColor;
  867. begin
  868. BackgroundColor := Color;
  869. {$ifdef FPC}
  870. if (BackgroundColor = clDefault) then
  871. BackgroundColor := GetDefaultColor(dctBrush);
  872. {$endif}
  873. FBuffer.Clear(Color32(BackgroundColor));
  874. end;
  875. procedure TCustomColorPicker.SelectedColorChanged;
  876. begin
  877. if Assigned(FOnChanged) then
  878. FOnChanged(Self);
  879. Invalidate;
  880. end;
  881. procedure TCustomColorPicker.SetBorder(const Value: Boolean);
  882. begin
  883. if FBorder <> Value then
  884. begin
  885. FBorder := Value;
  886. Invalidate;
  887. end;
  888. end;
  889. procedure TCustomColorPicker.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
  890. begin
  891. inherited;
  892. if (FBuffer <> nil) then
  893. FBuffer.SetSize(Width, Height);
  894. FBufferValid := False;
  895. end;
  896. procedure TCustomColorPicker.SetSelectedColor(const Value: TColor32);
  897. begin
  898. if FSelectedColor <> Value then
  899. begin
  900. FSelectedColor := Value;
  901. SelectedColorChanged;
  902. end;
  903. end;
  904. procedure TCustomColorPicker.SetWebSafe(const Value: Boolean);
  905. begin
  906. if FWebSafe <> Value then
  907. begin
  908. FWebSafe := Value;
  909. Invalidate;
  910. end;
  911. end;
  912. procedure TCustomColorPicker.WMEraseBkgnd(var Message: {$IFDEF FPC}TLmEraseBkgnd{$ELSE}TWmEraseBkgnd{$ENDIF});
  913. begin
  914. Message.Result := 1;
  915. end;
  916. procedure TCustomColorPicker.WMGetDlgCode(var Msg: {$IFDEF FPC}TLMessage{$ELSE}TWmGetDlgCode{$ENDIF});
  917. begin
  918. with Msg do
  919. Result := Result or DLGC_WANTARROWS;
  920. end;
  921. { TCustomColorPickerComponent }
  922. constructor TCustomColorPickerComponent.Create(AOwner: TComponent);
  923. begin
  924. inherited;
  925. FVisualAidOptions.Color := clBlack32;
  926. FVisualAidOptions.LineWidth := 1.5;
  927. end;
  928. procedure TCustomColorPickerComponent.Assign(Source: TPersistent);
  929. begin
  930. inherited;
  931. if (Source is TCustomColorPickerComponent) then
  932. begin
  933. FColorComponent := TCustomColorPickerComponent(Source).ColorComponent;
  934. end;
  935. end;
  936. procedure TCustomColorPickerComponent.MouseDown(Button: TMouseButton;
  937. Shift: TShiftState; X, Y: Integer);
  938. begin
  939. FMouseDown := (Button = mbLeft);
  940. inherited;
  941. end;
  942. procedure TCustomColorPickerComponent.MouseMove(Shift: TShiftState; X,
  943. Y: Integer);
  944. var
  945. Value: Single;
  946. Color: TColor32Entry;
  947. begin
  948. if FMouseDown then
  949. begin
  950. Value := EnsureRange((X - 3) / (Width - 3), 0, 1);
  951. Color := TColor32Entry(SelectedColor);
  952. case FColorComponent of
  953. ccRed:
  954. Color.R := Round(Value * 255);
  955. ccGreen:
  956. Color.G := Round(Value * 255);
  957. ccBlue:
  958. Color.B := Round(Value * 255);
  959. ccAlpha:
  960. Color.A := Round(Value * 255);
  961. end;
  962. SelectedColor := Color.ARGB;
  963. end;
  964. inherited;
  965. end;
  966. procedure TCustomColorPickerComponent.MouseUp(Button: TMouseButton;
  967. Shift: TShiftState; X, Y: Integer);
  968. begin
  969. if (Button = mbLeft) then
  970. FMouseDown := False;
  971. inherited;
  972. end;
  973. procedure TCustomColorPickerComponent.PaintColorPicker;
  974. var
  975. Polygon: TArrayOfFloatPoint;
  976. InvertFiller: TInvertPolygonFiller;
  977. procedure RenderPolygon;
  978. begin
  979. case FVisualAidOptions.RenderType of
  980. vatInvert:
  981. PolygonFS(FBuffer, Polygon, InvertFiller);
  982. vatBW:
  983. if Intensity(FSelectedColor) < 127 then
  984. PolygonFS(FBuffer, Polygon, clWhite32)
  985. else
  986. PolygonFS(FBuffer, Polygon, clBlack32);
  987. else
  988. PolygonFS(FBuffer, Polygon, FVisualAidOptions.Color);
  989. end;
  990. end;
  991. var
  992. X, Y: Integer;
  993. ScanLine: PColor32Array;
  994. Value: Single;
  995. LeftColor, RightColor: TColor32Entry;
  996. OddY: Boolean;
  997. BorderOffset: Integer;
  998. GradientFiller: TLinearGradientPolygonFiller;
  999. const
  1000. CByteScale = 1 / 255;
  1001. CCheckerBoardColor: array [Boolean] of TColor32 = ($FFA0A0A0, $FF5F5F5F);
  1002. // Size of indicator triangles
  1003. IndicatorWidth = 3;
  1004. IndicatorHeight = 5;
  1005. begin
  1006. PaintBackground;
  1007. BorderOffset := Integer(FBorder);
  1008. InvertFiller := TInvertPolygonFiller.Create;
  1009. try
  1010. LeftColor := TColor32Entry(FSelectedColor);
  1011. RightColor := TColor32Entry(FSelectedColor);
  1012. case FColorComponent of
  1013. ccRed:
  1014. begin
  1015. Value := LeftColor.R * CByteScale;
  1016. LeftColor.R := 0;
  1017. RightColor.R := 255;
  1018. LeftColor.A := 255;
  1019. RightColor.A := 255;
  1020. end;
  1021. ccGreen:
  1022. begin
  1023. Value := LeftColor.G * CByteScale;
  1024. LeftColor.G := 0;
  1025. RightColor.G := 255;
  1026. LeftColor.A := 255;
  1027. RightColor.A := 255;
  1028. end;
  1029. ccBlue:
  1030. begin
  1031. Value := LeftColor.B * CByteScale;
  1032. LeftColor.B := 0;
  1033. RightColor.B := 255;
  1034. LeftColor.A := 255;
  1035. RightColor.A := 255;
  1036. end;
  1037. ccAlpha:
  1038. begin
  1039. Value := LeftColor.A * CByteScale;
  1040. LeftColor.A := 0;
  1041. RightColor.A := 255;
  1042. for Y := 0 to Height - 1 do
  1043. begin
  1044. OddY := Odd(Y div 8);
  1045. ScanLine := FBuffer.ScanLine[Y];
  1046. for X := IndicatorWidth to Width - IndicatorWidth - 1 do
  1047. ScanLine^[X] := CCheckerBoardColor[Odd(X shr 3) = OddY];
  1048. end;
  1049. end
  1050. else
  1051. Exit;
  1052. end;
  1053. GradientFiller := TLinearGradientPolygonFiller.Create;
  1054. try
  1055. GradientFiller.SimpleGradientX(IndicatorWidth, LeftColor.ARGB, Width - IndicatorWidth, RightColor.ARGB);
  1056. PolygonFS(FBuffer, Rectangle(FloatRect(IndicatorWidth, 0, Width - IndicatorWidth, Height)), GradientFiller);
  1057. finally
  1058. GradientFiller.Free;
  1059. end;
  1060. if FBorder then
  1061. begin
  1062. FBuffer.FrameRectTS(IndicatorWidth, 0, Width - IndicatorWidth, Height, $DF000000);
  1063. {$ifdef GR32_FRAME3D}
  1064. FBuffer.RaiseRectTS(IndicatorWidth+1, 0, Width - IndicatorWidth - 1, Height - 1, 20);
  1065. {$endif}
  1066. end;
  1067. SetLength(Polygon, 3);
  1068. Polygon[0] := FloatPoint(IndicatorWidth + Value * (Width - 2*IndicatorWidth), Height - BorderOffset - IndicatorHeight);
  1069. Polygon[1] := FloatPoint(Polygon[0].X - IndicatorWidth, Polygon[0].Y + IndicatorHeight);
  1070. Polygon[2] := FloatPoint(Polygon[0].X + IndicatorWidth, Polygon[0].Y + IndicatorHeight);
  1071. RenderPolygon;
  1072. Polygon[0].Y := BorderOffset + IndicatorHeight;
  1073. Polygon[1].Y := BorderOffset;
  1074. Polygon[2].Y := BorderOffset;
  1075. RenderPolygon;
  1076. finally
  1077. InvertFiller.Free;
  1078. end;
  1079. inherited;
  1080. end;
  1081. procedure TCustomColorPickerComponent.SetColorComponent(
  1082. const Value: TColorComponent);
  1083. begin
  1084. if FColorComponent <> Value then
  1085. begin
  1086. FColorComponent := Value;
  1087. Invalidate;
  1088. end;
  1089. end;
  1090. { TCustomColorPickerRGBA }
  1091. constructor TCustomColorPickerRGBA.Create(AOwner: TComponent);
  1092. begin
  1093. inherited;
  1094. FBarHeight := 24;
  1095. FSpaceHeight := 8;
  1096. FVisualAidOptions.Color := clBlack32;
  1097. FVisualAidOptions.LineWidth := 1.5;
  1098. Height := 4*FBarHeight + 3*FSpaceHeight;
  1099. Width := 3*Height;
  1100. end;
  1101. procedure TCustomColorPickerRGBA.Assign(Source: TPersistent);
  1102. begin
  1103. inherited;
  1104. if (Source is TCustomColorPickerRGBA) then
  1105. begin
  1106. FBarHeight := TCustomColorPickerRGBA(Source).BarHeight;
  1107. FSpaceHeight := TCustomColorPickerRGBA(Source).SpaceHeight;
  1108. end;
  1109. end;
  1110. procedure TCustomColorPickerRGBA.PickRed(X, Y: Single);
  1111. var
  1112. Value: Single;
  1113. Color: TColor32Entry;
  1114. begin
  1115. Value := EnsureRange((X - 3) / (Width - 3), 0, 1);
  1116. Color := TColor32Entry(SelectedColor);
  1117. Color.R := Round(Value * 255);
  1118. SelectedColor := Color.ARGB;
  1119. end;
  1120. procedure TCustomColorPickerRGBA.PickGreen(X, Y: Single);
  1121. var
  1122. Value: Single;
  1123. Color: TColor32Entry;
  1124. begin
  1125. Value := EnsureRange((X - 3) / (Width - 3), 0, 1);
  1126. Color := TColor32Entry(SelectedColor);
  1127. Color.G := Round(Value * 255);
  1128. SelectedColor := Color.ARGB;
  1129. end;
  1130. procedure TCustomColorPickerRGBA.PickBlue(X, Y: Single);
  1131. var
  1132. Value: Single;
  1133. Color: TColor32Entry;
  1134. begin
  1135. Value := EnsureRange((X - 3) / (Width - 3), 0, 1);
  1136. Color := TColor32Entry(SelectedColor);
  1137. Color.B := Round(Value * 255);
  1138. SelectedColor := Color.ARGB;
  1139. end;
  1140. procedure TCustomColorPickerRGBA.PickAlpha(X, Y: Single);
  1141. var
  1142. Value: Single;
  1143. Color: TColor32Entry;
  1144. begin
  1145. Value := EnsureRange((X - 3) / (Width - 3), 0, 1);
  1146. Color := TColor32Entry(SelectedColor);
  1147. Color.A := Round(Value * 255);
  1148. SelectedColor := Color.ARGB;
  1149. end;
  1150. procedure TCustomColorPickerRGBA.MouseDown(Button: TMouseButton;
  1151. Shift: TShiftState; X, Y: Integer);
  1152. var
  1153. Index: Integer;
  1154. begin
  1155. if (Button = mbLeft) and (X >= 3) or (X <= Width - 3) then
  1156. begin
  1157. Index := Y div (FBarHeight + FSpaceHeight);
  1158. case Index of
  1159. 0:
  1160. FAdjustCalc := PickRed;
  1161. 1:
  1162. FAdjustCalc := PickGreen;
  1163. 2:
  1164. FAdjustCalc := PickBlue;
  1165. 3:
  1166. FAdjustCalc := PickAlpha;
  1167. end;
  1168. end;
  1169. if Assigned(FAdjustCalc) then
  1170. FAdjustCalc(X, Y);
  1171. inherited;
  1172. end;
  1173. procedure TCustomColorPickerRGBA.MouseMove(Shift: TShiftState; X, Y: Integer);
  1174. begin
  1175. if (ssLeft in Shift) and Assigned(FAdjustCalc) then
  1176. FAdjustCalc(X, Y);
  1177. inherited;
  1178. end;
  1179. procedure TCustomColorPickerRGBA.MouseUp(Button: TMouseButton;
  1180. Shift: TShiftState; X, Y: Integer);
  1181. begin
  1182. FAdjustCalc := nil;
  1183. inherited;
  1184. end;
  1185. procedure TCustomColorPickerRGBA.PaintColorPicker;
  1186. var
  1187. Polygon: TArrayOfFloatPoint;
  1188. InvertFiller: TInvertPolygonFiller;
  1189. procedure RenderPolygon;
  1190. begin
  1191. case FVisualAidOptions.RenderType of
  1192. vatInvert:
  1193. PolygonFS(FBuffer, Polygon, InvertFiller);
  1194. vatBW:
  1195. if Intensity(FSelectedColor) < 127 then
  1196. PolygonFS(FBuffer, Polygon, clWhite32)
  1197. else
  1198. PolygonFS(FBuffer, Polygon, clBlack32);
  1199. else
  1200. PolygonFS(FBuffer, Polygon, FVisualAidOptions.Color);
  1201. end;
  1202. end;
  1203. var
  1204. X, Y, Index: Integer;
  1205. ScanLine: PColor32Array;
  1206. Value: Single;
  1207. LeftColor, RightColor: TColor32Entry;
  1208. ValueRect: TRect;
  1209. OddY: Boolean;
  1210. BorderOffset: Integer;
  1211. GradientFiller: TLinearGradientPolygonFiller;
  1212. const
  1213. CByteScale = 1 / 255;
  1214. CCheckerBoardColor: array [Boolean] of TColor32 = ($FFA0A0A0, $FF5F5F5F);
  1215. // Size of indicator triangles
  1216. IndicatorWidth = 3;
  1217. IndicatorHeight = 5;
  1218. begin
  1219. PaintBackground;
  1220. BorderOffset := Integer(FBorder);
  1221. SetLength(Polygon, 3);
  1222. InvertFiller := TInvertPolygonFiller.Create;
  1223. try
  1224. for Index := 0 to 3 do
  1225. begin
  1226. ValueRect := Rect(IndicatorWidth, Index * (FBarHeight + FSpaceHeight), Width - IndicatorWidth, Index * (FBarHeight + FSpaceHeight) + FBarHeight);
  1227. LeftColor := TColor32Entry(FSelectedColor);
  1228. RightColor := TColor32Entry(FSelectedColor);
  1229. case Index of
  1230. 0:
  1231. begin
  1232. Value := LeftColor.R * CByteScale;
  1233. LeftColor.R := 0;
  1234. RightColor.R := 255;
  1235. LeftColor.A := 255;
  1236. RightColor.A := 255;
  1237. end;
  1238. 1:
  1239. begin
  1240. Value := LeftColor.G * CByteScale;
  1241. LeftColor.G := 0;
  1242. RightColor.G := 255;
  1243. LeftColor.A := 255;
  1244. RightColor.A := 255;
  1245. end;
  1246. 2:
  1247. begin
  1248. Value := LeftColor.B * CByteScale;
  1249. LeftColor.B := 0;
  1250. RightColor.B := 255;
  1251. LeftColor.A := 255;
  1252. RightColor.A := 255;
  1253. end;
  1254. 3:
  1255. begin
  1256. Value := LeftColor.A * CByteScale;
  1257. LeftColor.A := 0;
  1258. RightColor.A := 255;
  1259. for Y := ValueRect.Top to Min(ValueRect.Bottom, Height) - 1 do
  1260. begin
  1261. OddY := Odd(Y div 8);
  1262. ScanLine := FBuffer.ScanLine[Y];
  1263. for X := ValueRect.Left to ValueRect.Right - 1 do
  1264. ScanLine^[X] := CCheckerBoardColor[Odd(X shr 3) = OddY];
  1265. end;
  1266. end;
  1267. else
  1268. Exit;
  1269. end;
  1270. GradientFiller := TLinearGradientPolygonFiller.Create;
  1271. try
  1272. GradientFiller.SimpleGradientX(ValueRect.Left, LeftColor.ARGB, ValueRect.Right, RightColor.ARGB);
  1273. PolygonFS(FBuffer, Rectangle(FloatRect(ValueRect)), GradientFiller);
  1274. finally
  1275. GradientFiller.Free;
  1276. end;
  1277. if FBorder then
  1278. begin
  1279. FBuffer.FrameRectTS(ValueRect, $DF000000);
  1280. {$ifdef GR32_FRAME3D}
  1281. FBuffer.RaiseRectTS(ValueRect.Left + 1, ValueRect.Top + 1, ValueRect.Right - 1, ValueRect.Bottom - 1, 20);
  1282. {$endif}
  1283. end;
  1284. Polygon[0] := FloatPoint(IndicatorWidth + Value * (Width - 2*IndicatorWidth), ValueRect.Bottom - BorderOffset - IndicatorHeight);
  1285. Polygon[1] := FloatPoint(Polygon[0].X - IndicatorWidth, Polygon[0].Y + IndicatorHeight);
  1286. Polygon[2] := FloatPoint(Polygon[0].X + IndicatorWidth, Polygon[0].Y + IndicatorHeight);
  1287. RenderPolygon;
  1288. Polygon[0].Y := ValueRect.Top + BorderOffset + IndicatorHeight;
  1289. Polygon[1].Y := ValueRect.Top + BorderOffset;
  1290. Polygon[2].Y := ValueRect.Top + BorderOffset;
  1291. RenderPolygon;
  1292. end;
  1293. finally
  1294. InvertFiller.Free;
  1295. end;
  1296. inherited;
  1297. end;
  1298. procedure TCustomColorPickerRGBA.SetBarHeight(const Value: Integer);
  1299. begin
  1300. if FBarHeight <> Value then
  1301. begin
  1302. FBarHeight := Value;
  1303. Invalidate;
  1304. end;
  1305. end;
  1306. procedure TCustomColorPickerRGBA.SetSpaceHeight(const Value: Integer);
  1307. begin
  1308. if FSpaceHeight <> Value then
  1309. begin
  1310. FSpaceHeight := Value;
  1311. Invalidate;
  1312. end;
  1313. end;
  1314. { TCustomColorPickerHS }
  1315. constructor TCustomColorPickerHS.Create(AOwner: TComponent);
  1316. var
  1317. Luminance: Single;
  1318. begin
  1319. inherited;
  1320. FVisualAidOptions.Color := clBlack32;
  1321. FVisualAidOptions.LineWidth := 1.5;
  1322. RGBtoHSL(FSelectedColor, FHue, FSaturation, Luminance);
  1323. end;
  1324. procedure TCustomColorPickerHS.Assign(Source: TPersistent);
  1325. begin
  1326. inherited;
  1327. if (Source is TCustomColorPickerHS) then
  1328. begin
  1329. FMarkerType := TCustomColorPickerHS(Source).MarkerType;
  1330. FHue := TCustomColorPickerHS(Source).Hue;
  1331. FSaturation := TCustomColorPickerHS(Source).Saturation;
  1332. end;
  1333. end;
  1334. procedure TCustomColorPickerHS.MouseDown(Button: TMouseButton;
  1335. Shift: TShiftState; X, Y: Integer);
  1336. begin
  1337. if Button = mbLeft then
  1338. PickHue(X, Y);
  1339. inherited;
  1340. end;
  1341. procedure TCustomColorPickerHS.MouseMove(Shift: TShiftState; X, Y: Integer);
  1342. begin
  1343. if (ssLeft in Shift) then
  1344. PickHue(X, Y);
  1345. inherited;
  1346. end;
  1347. procedure TCustomColorPickerHS.PaintColorPicker;
  1348. var
  1349. X, Y: Integer;
  1350. Saturation, InvWidth, InvHeight: Single;
  1351. Line: PColor32Array;
  1352. Pos: TFloatPoint;
  1353. VectorData: TArrayOfArrayOfFloatPoint;
  1354. InvertFiller: TInvertPolygonFiller;
  1355. begin
  1356. InvWidth := 1 / FBuffer.Width;
  1357. InvHeight := 1 / FBuffer.Height;
  1358. if FWebSafe then
  1359. for Y := 0 to FBuffer.Height - 1 do
  1360. begin
  1361. Line := FBuffer.ScanLine[Y];
  1362. Saturation := 1 - Y * InvHeight;
  1363. for X := 0 to FBuffer.Width - 1 do
  1364. begin
  1365. Line^[X] := HSLtoRGB(X * InvWidth, Saturation, 0.5);
  1366. RoundToWebSafe(Line^[X]);
  1367. end;
  1368. end
  1369. else
  1370. for Y := 0 to FBuffer.Height - 1 do
  1371. begin
  1372. Line := FBuffer.ScanLine[Y];
  1373. Saturation := 1 - Y * InvHeight;
  1374. for X := 0 to FBuffer.Width - 1 do
  1375. Line^[X] := HSLtoRGB(X * InvWidth, Saturation, 0.5);
  1376. end;
  1377. Pos.X := Round(FHue * FBuffer.Width);
  1378. Pos.Y := Round((1 - FSaturation) * FBuffer.Height);
  1379. case FMarkerType of
  1380. mtCross:
  1381. begin
  1382. SetLength(VectorData, 4);
  1383. VectorData[0] := HorzLine(Pos.X - 5, Pos.Y, Pos.X - 2);
  1384. VectorData[1] := HorzLine(Pos.X + 2, Pos.Y, Pos.X + 5);
  1385. VectorData[2] := VertLine(Pos.X, Pos.Y - 5, Pos.Y - 2);
  1386. VectorData[3] := VertLine(Pos.X, Pos.Y + 2, Pos.Y + 5);
  1387. case FVisualAidOptions.RenderType of
  1388. vatSolid:
  1389. PolyPolylineFS(FBuffer, VectorData, FVisualAidOptions.Color, False, FVisualAidOptions.LineWidth);
  1390. vatInvert:
  1391. begin
  1392. InvertFiller := TInvertPolygonFiller.Create;
  1393. try
  1394. PolyPolylineFS(FBuffer, VectorData, InvertFiller, False, FVisualAidOptions.LineWidth)
  1395. finally
  1396. InvertFiller.Free;
  1397. end;
  1398. end;
  1399. vatBW:
  1400. PolyPolylineFS(FBuffer, VectorData, FVisualAidOptions.Color, False, FVisualAidOptions.LineWidth);
  1401. end;
  1402. end;
  1403. mtCircle:
  1404. begin
  1405. SetLength(VectorData, 1);
  1406. VectorData[0] := Circle(Pos, 4, 12);
  1407. PolygonFS(FBuffer, VectorData[0], FSelectedColor);
  1408. case FVisualAidOptions.RenderType of
  1409. vatSolid:
  1410. PolylineFS(FBuffer, VectorData[0], FVisualAidOptions.Color, True, FVisualAidOptions.LineWidth);
  1411. vatInvert:
  1412. begin
  1413. InvertFiller := TInvertPolygonFiller.Create;
  1414. try
  1415. PolylineFS(FBuffer, VectorData[0], InvertFiller, True, 1.5)
  1416. finally
  1417. InvertFiller.Free;
  1418. end;
  1419. end;
  1420. vatBW:
  1421. PolylineFS(FBuffer, VectorData[0], FVisualAidOptions.Color, True, 1.5);
  1422. end;
  1423. end;
  1424. end;
  1425. end;
  1426. procedure TCustomColorPickerHS.ApplyHS;
  1427. var
  1428. H, S, L: Single;
  1429. begin
  1430. RGBtoHSL(FSelectedColor, H, S, L);
  1431. Inc(FLockValues);
  1432. try
  1433. SelectedColor := HSLtoRGB(FHue, FSaturation, L, SelectedColor shr 24);
  1434. finally
  1435. Dec(FLockValues);
  1436. end;
  1437. end;
  1438. procedure TCustomColorPickerHS.PickHue(X, Y: Single);
  1439. begin
  1440. FHue := EnsureRange(X / FBuffer.Width, 0, 1);
  1441. FSaturation := EnsureRange(1 - Y / FBuffer.Height, 0, 1);
  1442. ApplyHS;
  1443. end;
  1444. procedure TCustomColorPickerHS.SelectedColorChanged;
  1445. var
  1446. H, S, L: Single;
  1447. begin
  1448. if (FLockValues = 0) then
  1449. begin
  1450. RGBtoHSL(FSelectedColor, H, S, L);
  1451. FHue := H;
  1452. FSaturation := S;
  1453. end;
  1454. inherited;
  1455. end;
  1456. procedure TCustomColorPickerHS.SetHue(const Value: Single);
  1457. begin
  1458. if FHue <> Value then
  1459. begin
  1460. FHue := Value;
  1461. ApplyHS;
  1462. end;
  1463. end;
  1464. procedure TCustomColorPickerHS.SetSaturation(const Value: Single);
  1465. begin
  1466. if FSaturation <> Value then
  1467. begin
  1468. FSaturation := Value;
  1469. ApplyHS;
  1470. end;
  1471. end;
  1472. procedure TCustomColorPickerHS.SetMarkerType(const Value: TMarkerType);
  1473. begin
  1474. if FMarkerType <> Value then
  1475. begin
  1476. FMarkerType := Value;
  1477. Invalidate;
  1478. end;
  1479. end;
  1480. { TCustomColorPickerHSV }
  1481. constructor TCustomColorPickerHSV.Create(AOwner: TComponent);
  1482. begin
  1483. inherited Create(AOwner);
  1484. FVisualAid := [vaHueLine, vaSaturationCircle, vaSelection];
  1485. FVisualAidOptions.LineWidth := 1.5;
  1486. RGBToHSV(FSelectedColor, FHue, FSaturation, FValue);
  1487. { Setting a initial size here will cause the control to crash under LCL }
  1488. {$IFNDEF FPC}
  1489. Height := 192;
  1490. Width := 256;
  1491. {$ENDIF}
  1492. end;
  1493. procedure TCustomColorPickerHSV.Assign(Source: TPersistent);
  1494. begin
  1495. inherited;
  1496. if (Source is TCustomColorPickerHSV) then
  1497. begin
  1498. FHue := TCustomColorPickerHSV(Source).Hue;
  1499. FSaturation := TCustomColorPickerHSV(Source).Saturation;
  1500. FValue := TCustomColorPickerHSV(Source).Value;
  1501. FVisualAid := TCustomColorPickerHSV(Source).VisualAid;
  1502. end;
  1503. end;
  1504. procedure TCustomColorPickerHSV.PaintColorPicker;
  1505. var
  1506. Polygon: TArrayOfFloatPoint;
  1507. ValueRect: TRect;
  1508. GradientFiller: TLinearGradientPolygonFiller;
  1509. HueSaturationFiller: THueSaturationCirclePolygonFiller;
  1510. InvertFiller: TInvertPolygonFiller;
  1511. LineWidth: Single;
  1512. begin
  1513. PaintBackground;
  1514. Polygon := Circle(FCenter, FRadius, FCircleSteps);
  1515. HueSaturationFiller := THueSaturationCirclePolygonFiller.Create(FCenter, FRadius, FValue, FWebSafe);
  1516. try
  1517. PolygonFS(FBuffer, Polygon, HueSaturationFiller);
  1518. finally
  1519. HueSaturationFiller.Free;
  1520. end;
  1521. if FBorder then
  1522. PolylineFS(FBuffer, Polygon, clBlack32, True, 1);
  1523. LineWidth := FVisualAidOptions.LineWidth;
  1524. InvertFiller := TInvertPolygonFiller.Create;
  1525. try
  1526. if vaSaturationCircle in FVisualAid then
  1527. begin
  1528. Polygon := Circle(FCenter, FSaturation * FRadius, -1);
  1529. case FVisualAidOptions.RenderType of
  1530. vatInvert:
  1531. PolylineFS(FBuffer, Polygon, InvertFiller, True, LineWidth);
  1532. vatBW:
  1533. if Intensity(FSelectedColor) < 127 then
  1534. PolylineFS(FBuffer, Polygon, clWhite32, True, LineWidth)
  1535. else
  1536. PolylineFS(FBuffer, Polygon, clBlack32, True, LineWidth);
  1537. else
  1538. PolylineFS(FBuffer, Polygon, FVisualAidOptions.Color, True, LineWidth);
  1539. end;
  1540. end;
  1541. if vaHueLine in FVisualAid then
  1542. begin
  1543. SetLength(Polygon, 2);
  1544. Polygon[0] := FCenter;
  1545. Polygon[1] := FloatPoint(
  1546. FCenter.X - FRadius * Cos(2 * Pi * FHue),
  1547. FCenter.Y - FRadius * Sin(2 * Pi * FHue));
  1548. case FVisualAidOptions.RenderType of
  1549. vatInvert:
  1550. PolylineFS(FBuffer, Polygon, InvertFiller, False, LineWidth);
  1551. vatBW:
  1552. if Intensity(FSelectedColor) < 127 then
  1553. PolylineFS(FBuffer, Polygon, clWhite32, False, LineWidth)
  1554. else
  1555. PolylineFS(FBuffer, Polygon, clBlack32, False, LineWidth);
  1556. else
  1557. PolylineFS(FBuffer, Polygon, FVisualAidOptions.Color, False, LineWidth);
  1558. end;
  1559. end;
  1560. if vaSelection in FVisualAid then
  1561. begin
  1562. Polygon := Circle(
  1563. FCenter.X - FSaturation * FRadius * Cos(2 * Pi * FHue),
  1564. FCenter.Y - FSaturation * FRadius * Sin(2 * Pi * FHue), 4, 8);
  1565. PolygonFS(FBuffer, Polygon, FSelectedColor);
  1566. case FVisualAidOptions.RenderType of
  1567. vatInvert:
  1568. PolylineFS(FBuffer, Polygon, InvertFiller, True, LineWidth);
  1569. vatBW:
  1570. if Intensity(FSelectedColor) < 127 then
  1571. PolylineFS(FBuffer, Polygon, clWhite32, True, LineWidth)
  1572. else
  1573. PolylineFS(FBuffer, Polygon, clBlack32, True, LineWidth);
  1574. else
  1575. PolylineFS(FBuffer, Polygon, FVisualAidOptions.Color, True, LineWidth);
  1576. end;
  1577. end;
  1578. ValueRect := Rect(Width - 24, 8, Width - 8, Height - 8);
  1579. Polygon := Rectangle(FloatRect(ValueRect));
  1580. GradientFiller := TLinearGradientPolygonFiller.Create;
  1581. try
  1582. GradientFiller.SimpleGradientY(ValueRect.Top, clWhite32,
  1583. ValueRect.Bottom, clBlack32);
  1584. PolygonFS(FBuffer, Polygon, GradientFiller);
  1585. finally
  1586. GradientFiller.Free;
  1587. end;
  1588. SetLength(Polygon, 3);
  1589. Polygon[0] := FloatPoint(Width - 8, 8 + (1 - FValue) * (Height - 16));
  1590. Polygon[1] := FloatPoint(Polygon[0].X + 7, Polygon[0].Y - 4);
  1591. Polygon[2] := FloatPoint(Polygon[0].X + 7, Polygon[0].Y + 4);
  1592. case FVisualAidOptions.RenderType of
  1593. vatInvert:
  1594. PolygonFS(FBuffer, Polygon, InvertFiller);
  1595. vatBW:
  1596. if Intensity(FSelectedColor) < 127 then
  1597. PolygonFS(FBuffer, Polygon, clWhite32)
  1598. else
  1599. PolygonFS(FBuffer, Polygon, clBlack32);
  1600. else
  1601. PolygonFS(FBuffer, Polygon, FVisualAidOptions.Color);
  1602. end;
  1603. if FBorder then
  1604. begin
  1605. FBuffer.FrameRectTS(ValueRect, $DF000000);
  1606. {$ifdef GR32_FRAME3D}
  1607. FBuffer.RaiseRectTS(ValueRect.Left + 1, ValueRect.Top + 1, ValueRect.Right - 1, ValueRect.Bottom - 1, 20);
  1608. {$endif}
  1609. end;
  1610. finally
  1611. InvertFiller.Free;
  1612. end;
  1613. inherited;
  1614. end;
  1615. procedure TCustomColorPickerHSV.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
  1616. Y: Integer);
  1617. begin
  1618. if Button = mbLeft then
  1619. begin
  1620. if X > Width - 28 then
  1621. FAdjustCalc := PickValue
  1622. else
  1623. FAdjustCalc := PickHue;
  1624. end;
  1625. if Assigned(FAdjustCalc) then
  1626. FAdjustCalc(X, Y);
  1627. inherited;
  1628. end;
  1629. procedure TCustomColorPickerHSV.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
  1630. Y: Integer);
  1631. begin
  1632. FAdjustCalc := nil;
  1633. inherited;
  1634. end;
  1635. procedure TCustomColorPickerHSV.MouseMove(Shift: TShiftState; X, Y: Integer);
  1636. begin
  1637. if (ssLeft in Shift) and Assigned(FAdjustCalc) then
  1638. FAdjustCalc(X, Y);
  1639. inherited;
  1640. end;
  1641. procedure TCustomColorPickerHSV.ApplyHSV;
  1642. begin
  1643. Inc(FLockValues);
  1644. try
  1645. SelectedColor := HSVtoRGB(FHue, FSaturation, FValue, SelectedColor shr 24);
  1646. finally
  1647. Dec(FLockValues);
  1648. end;
  1649. end;
  1650. procedure TCustomColorPickerHSV.PickHue(X, Y: Single);
  1651. const
  1652. CTwoPiInv = 1 / (2 * Pi);
  1653. begin
  1654. FHue := 0.5 + ArcTan2(Y - FCenter.Y, X - FCenter.X) * CTwoPiInv;
  1655. FSaturation := Sqrt(Sqr(Y - FCenter.Y) + Sqr(X - FCenter.X)) / FRadius;
  1656. if FSaturation > 1 then
  1657. FSaturation := 1;
  1658. ApplyHSV;
  1659. end;
  1660. procedure TCustomColorPickerHSV.PickValue(X, Y: Single);
  1661. begin
  1662. Value := 1 - EnsureRange((Y - 8) / (Height - 16), 0, 1);
  1663. end;
  1664. procedure TCustomColorPickerHSV.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
  1665. begin
  1666. inherited;
  1667. if Height < Width then
  1668. begin
  1669. FRadius := Min(0.5 * Width - 1 - 16, 0.5 * Height - 1);
  1670. FCircleSteps := CalculateCircleSteps(FRadius);
  1671. FCenter := FloatPoint(0.5 * Width - 16, 0.5 * Height);
  1672. end
  1673. else
  1674. begin
  1675. FRadius := Min(0.5 * Width - 1, 0.5 * Height - 1 - 16);
  1676. FCircleSteps := CalculateCircleSteps(FRadius);
  1677. FCenter := FloatPoint(0.5 * Width, 0.5 * Height - 16);
  1678. end;
  1679. end;
  1680. procedure TCustomColorPickerHSV.SetHue(const Value: Single);
  1681. begin
  1682. if FHue <> Value then
  1683. begin
  1684. FHue := Value;
  1685. ApplyHSV;
  1686. end;
  1687. end;
  1688. procedure TCustomColorPickerHSV.SetSaturation(const Value: Single);
  1689. begin
  1690. if FSaturation <> Value then
  1691. begin
  1692. FSaturation := Value;
  1693. ApplyHSV;
  1694. end;
  1695. end;
  1696. procedure TCustomColorPickerHSV.SelectedColorChanged;
  1697. var
  1698. H, S, V: Single;
  1699. begin
  1700. if (FLockValues = 0) then
  1701. begin
  1702. RGBtoHSV(FSelectedColor, H, S, V);
  1703. FHue := H;
  1704. FSaturation := S;
  1705. FValue := V;
  1706. end;
  1707. inherited;
  1708. end;
  1709. procedure TCustomColorPickerHSV.SetValue(const Value: Single);
  1710. begin
  1711. if FValue <> Value then
  1712. begin
  1713. FValue := Value;
  1714. ApplyHSV;
  1715. end;
  1716. end;
  1717. procedure TCustomColorPickerHSV.SetVisualAid(const Value: TVisualAid);
  1718. begin
  1719. if FVisualAid <> Value then
  1720. begin
  1721. FVisualAid := Value;
  1722. Invalidate;
  1723. end;
  1724. end;
  1725. { TCustomColorPickerGTK }
  1726. constructor TCustomColorPickerGTK.Create(AOwner: TComponent);
  1727. begin
  1728. inherited Create(AOwner);
  1729. FVisualAid := [vagHueLine, vagSelection];
  1730. FVisualAidOptions.RenderType := vatBW;
  1731. FVisualAidOptions.LineWidth := 2;
  1732. RGBToHSV(FSelectedColor, FHue, FSaturation, FValue);
  1733. { Setting a initial size here will cause the control to crash under LCL }
  1734. {$IFNDEF FPC}
  1735. Height := 192;
  1736. Width := 192;
  1737. {$ENDIF}
  1738. end;
  1739. procedure TCustomColorPickerGTK.Assign(Source: TPersistent);
  1740. begin
  1741. inherited;
  1742. if (Source is TCustomColorPickerGTK) then
  1743. begin
  1744. FHue := TCustomColorPickerGTK(Source).Hue;
  1745. FSaturation := TCustomColorPickerGTK(Source).Saturation;
  1746. FValue := TCustomColorPickerGTK(Source).Value;
  1747. FVisualAid := TCustomColorPickerGTK(Source).VisualAid;
  1748. end;
  1749. end;
  1750. procedure TCustomColorPickerGTK.PaintColorPicker;
  1751. var
  1752. Polygon: TArrayOfFloatPoint;
  1753. HueBand: TArrayOfArrayOfFloatPoint;
  1754. GradientFiller: TBarycentricGradientPolygonFillerEx;
  1755. HueFiller: THueCirclePolygonFiller;
  1756. InvertFiller: TInvertPolygonFiller;
  1757. Pos: TFloatPoint;
  1758. HalfInnerRadius: Single;
  1759. LineWidth: Single;
  1760. const
  1761. CY = 1.7320508075688772935274463415059;
  1762. begin
  1763. PaintBackground;
  1764. // Don't use BuildPolyPolyline to build HueBand; We need both inner and outer
  1765. // polygons to be free of self-intersections as we use them to draw the border.
  1766. HueBand := [
  1767. Circle(FCenter, FRadius, FCircleSteps),
  1768. ReversePolygon(Circle(FCenter, FInnerRadius, FCircleSteps))
  1769. ];
  1770. HueFiller := THueCirclePolygonFiller.Create(FCenter, FWebSafe);
  1771. try
  1772. PolyPolygonFS(FBuffer, HueBand, HueFiller);
  1773. finally
  1774. HueFiller.Free;
  1775. end;
  1776. LineWidth := FVisualAidOptions.LineWidth;
  1777. if vagHueLine in FVisualAid then
  1778. begin
  1779. SetLength(Polygon, 2);
  1780. Polygon[0] := FloatPoint(
  1781. FCenter.X - FInnerRadius * Cos(2 * Pi * FHue),
  1782. FCenter.Y - FInnerRadius * Sin(2 * Pi * FHue));
  1783. Polygon[1] := FloatPoint(
  1784. FCenter.X - FRadius * Cos(2 * Pi * FHue),
  1785. FCenter.Y - FRadius * Sin(2 * Pi * FHue));
  1786. case FVisualAidOptions.RenderType of
  1787. vatSolid:
  1788. PolylineFS(FBuffer, Polygon, FVisualAidOptions.Color, False, LineWidth);
  1789. vatInvert:
  1790. begin
  1791. InvertFiller := TInvertPolygonFiller.Create;
  1792. try
  1793. PolylineFS(FBuffer, Polygon, InvertFiller, False, LineWidth);
  1794. finally
  1795. InvertFiller.Free;
  1796. end;
  1797. end;
  1798. vatBW:
  1799. if Intensity(HSVtoRGB(FHue, 1, 1)) < 127 then
  1800. PolylineFS(FBuffer, Polygon, $F0FFFFFF, True, LineWidth)
  1801. else
  1802. PolylineFS(FBuffer, Polygon, $F0000000, True, LineWidth)
  1803. end;
  1804. end;
  1805. SetLength(Polygon, 3);
  1806. GR32_Math.SinCos(2 * Pi * FHue, Pos.Y, Pos.X);
  1807. Polygon[0] := FloatPoint(
  1808. FCenter.X - FInnerRadius * Pos.X,
  1809. FCenter.Y - FInnerRadius * Pos.Y);
  1810. HalfInnerRadius := 0.5 * FInnerRadius;
  1811. Pos := FloatPoint(Pos.X + CY * Pos.Y, Pos.X * CY - Pos.Y);
  1812. Polygon[1] := FloatPoint(
  1813. FCenter.X + HalfInnerRadius * Pos.X,
  1814. FCenter.Y - HalfInnerRadius * Pos.Y);
  1815. HalfInnerRadius := 0.5 * HalfInnerRadius;
  1816. Pos := FloatPoint(Pos.X - CY * Pos.Y, Pos.Y + Pos.X * CY);
  1817. Polygon[2] := FloatPoint(
  1818. FCenter.X - HalfInnerRadius * Pos.X,
  1819. FCenter.Y + HalfInnerRadius * Pos.Y);
  1820. GradientFiller := TBarycentricGradientPolygonFillerEx.Create;
  1821. try
  1822. GradientFiller.SetPoints(Polygon);
  1823. GradientFiller.Color[0] := HSVtoRGB(Hue, 1, 1);
  1824. GradientFiller.Color[1] := clWhite32;
  1825. GradientFiller.Color[2] := clBlack32;
  1826. GradientFiller.WebSafe := FWebSafe;
  1827. PolygonFS(FBuffer, Polygon, GradientFiller);
  1828. finally
  1829. GradientFiller.Free;
  1830. end;
  1831. if FBorder then
  1832. begin
  1833. PolyPolygonFS(FBuffer, BuildPolyPolyline(HueBand, True, 1), clBlack32);
  1834. PolylineFS(FBuffer, Polygon, clBlack32, True, 1);
  1835. end;
  1836. if vagSelection in FVisualAid then
  1837. begin
  1838. Polygon := Circle(
  1839. Polygon[2].X + FValue * (Polygon[1].X + FSaturation * (Polygon[0].X - Polygon[1].X) - Polygon[2].X),
  1840. Polygon[2].Y + FValue * (Polygon[1].Y + FSaturation * (Polygon[0].Y - Polygon[1].Y) - Polygon[2].Y),
  1841. 4, 12);
  1842. PolygonFS(FBuffer, Polygon, FSelectedColor);
  1843. case FVisualAidOptions.RenderType of
  1844. vatSolid:
  1845. PolylineFS(FBuffer, Polygon, FVisualAidOptions.Color, True, LineWidth);
  1846. vatInvert:
  1847. begin
  1848. InvertFiller := TInvertPolygonFiller.Create;
  1849. try
  1850. PolylineFS(FBuffer, Polygon, InvertFiller, True, LineWidth);
  1851. finally
  1852. InvertFiller.Free;
  1853. end;
  1854. end;
  1855. vatBW:
  1856. if Intensity(FSelectedColor) < 127 then
  1857. PolylineFS(FBuffer, Polygon, clWhite32, True, LineWidth)
  1858. else
  1859. PolylineFS(FBuffer, Polygon, clBlack32, True, LineWidth)
  1860. end
  1861. end;
  1862. inherited;
  1863. end;
  1864. procedure TCustomColorPickerGTK.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
  1865. Y: Integer);
  1866. begin
  1867. if Button = mbLeft then
  1868. begin
  1869. if Sqrt(Sqr(X - FCenter.X) + Sqr(Y - FCenter.Y)) > FInnerRadius then
  1870. FAdjustCalc := PickHue
  1871. else
  1872. FAdjustCalc := PickSaturationValue;
  1873. end;
  1874. if Assigned(FAdjustCalc) then
  1875. FAdjustCalc(X, Y);
  1876. inherited;
  1877. end;
  1878. procedure TCustomColorPickerGTK.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
  1879. Y: Integer);
  1880. begin
  1881. FAdjustCalc := nil;
  1882. inherited;
  1883. end;
  1884. procedure TCustomColorPickerGTK.MouseMove(Shift: TShiftState; X, Y: Integer);
  1885. begin
  1886. if (ssLeft in Shift) and Assigned(FAdjustCalc) then
  1887. FAdjustCalc(X, Y);
  1888. inherited;
  1889. end;
  1890. procedure TCustomColorPickerGTK.ApplyHSV;
  1891. begin
  1892. Inc(FLockValues);
  1893. try
  1894. SelectedColor := HSVtoRGB(FHue, FSaturation, FValue, SelectedColor shr 24);
  1895. finally
  1896. Dec(FLockValues);
  1897. end;
  1898. end;
  1899. procedure TCustomColorPickerGTK.PickHue(X, Y: Single);
  1900. const
  1901. CTwoPiInv = 1 / (2 * Pi);
  1902. begin
  1903. Hue := 0.5 + ArcTan2(Y - FCenter.Y, X - FCenter.X) * CTwoPiInv;
  1904. end;
  1905. procedure TCustomColorPickerGTK.PickSaturationValue(X, Y: Single);
  1906. var
  1907. Sampler: TBarycentricGradientSampler;
  1908. Pos: TFloatPoint;
  1909. Color: TColor32;
  1910. H: Single;
  1911. const
  1912. CY = 1.7320508075688772935274463415059;
  1913. begin
  1914. Sampler := TBarycentricGradientSampler.Create;
  1915. try
  1916. GR32_Math.SinCos(2 * Pi * FHue, Pos.Y, Pos.X);
  1917. Sampler.Point[0] := FloatPoint(
  1918. FCenter.X - FInnerRadius * Pos.X,
  1919. FCenter.Y - FInnerRadius * Pos.Y);
  1920. Pos := FloatPoint(-0.5 * (Pos.X + CY * Pos.Y), 0.5 * (Pos.X * CY - Pos.Y));
  1921. Sampler.Point[1] := FloatPoint(
  1922. FCenter.X - FInnerRadius * Pos.X,
  1923. FCenter.Y - FInnerRadius * Pos.Y);
  1924. Pos := FloatPoint(-0.5 * (Pos.X + CY * Pos.Y), 0.5 * (Pos.X * CY - Pos.Y));
  1925. Sampler.Point[2] := FloatPoint(
  1926. FCenter.X - FInnerRadius * Pos.X,
  1927. FCenter.Y - FInnerRadius * Pos.Y);
  1928. Sampler.Color[0] := HSVtoRGB(FHue, 1, 1);
  1929. Sampler.Color[1] := clWhite32;
  1930. Sampler.Color[2] := clBlack32;
  1931. Sampler.PrepareSampling;
  1932. Color := Sampler.GetSampleFloatInTriangle(X, Y);
  1933. finally
  1934. Sampler.Free;
  1935. end;
  1936. RGBtoHSV(Color, H, FSaturation, FValue);
  1937. ApplyHSV;
  1938. end;
  1939. procedure TCustomColorPickerGTK.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
  1940. begin
  1941. inherited;
  1942. Radius := Min(0.5 * Width - 1, 0.5 * Height - 1);
  1943. Center := FloatPoint(0.5 * Width, 0.5 * Height);
  1944. end;
  1945. procedure TCustomColorPickerGTK.SetHue(const Value: Single);
  1946. begin
  1947. if FHue <> Value then
  1948. begin
  1949. FHue := Value;
  1950. ApplyHSV;
  1951. end;
  1952. end;
  1953. procedure TCustomColorPickerGTK.SetRadius(const Value: TFloat);
  1954. begin
  1955. if FRadius <> Value then
  1956. begin
  1957. FRadius := Value;
  1958. FInnerRadius := 0.8 * FRadius;
  1959. FCircleSteps := CalculateCircleSteps(FRadius);
  1960. end;
  1961. end;
  1962. procedure TCustomColorPickerGTK.SetSaturation(const Value: Single);
  1963. begin
  1964. if FSaturation <> Value then
  1965. begin
  1966. FSaturation := Value;
  1967. ApplyHSV;
  1968. end;
  1969. end;
  1970. procedure TCustomColorPickerGTK.SelectedColorChanged;
  1971. var
  1972. H, S, V: Single;
  1973. begin
  1974. if (FLockValues = 0) then
  1975. begin
  1976. RGBtoHSV(FSelectedColor, H, S, V);
  1977. FHue := H;
  1978. FSaturation := S;
  1979. FValue := V;
  1980. end;
  1981. inherited;
  1982. end;
  1983. procedure TCustomColorPickerGTK.SetValue(const Value: Single);
  1984. begin
  1985. if FValue <> Value then
  1986. begin
  1987. FValue := Value;
  1988. ApplyHSV;
  1989. end;
  1990. end;
  1991. procedure TCustomColorPickerGTK.SetVisualAid(const Value: TVisualAidGTK);
  1992. begin
  1993. if FVisualAid <> Value then
  1994. begin
  1995. FVisualAid := Value;
  1996. Invalidate;
  1997. end;
  1998. end;
  1999. end.