source: trunk/Packages/bgracontrols/bgrashape.pas

Last change on this file was 2, checked in by chronos, 5 years ago
File size: 9.9 KB
Line 
1unit BGRAShape;
2
3{$mode objfpc}{$H+}
4
5interface
6
7uses
8 Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
9 BGRABitmap, BGRABitmapTypes, BCTypes;
10
11type
12 TBGRAShapeType = (stRegularPolygon, stEllipse);
13
14 { TBGRAShape }
15
16 TBGRAShape = class(TGraphicControl)
17 private
18 { Private declarations }
19 FBorderColor: TColor;
20 FBorderOpacity: byte;
21 FBorderStyle: TPenStyle;
22 FBorderWidth: integer;
23 FBorderGradient: TBCGradient;
24 FUseBorderGradient: boolean;
25 FFillColor: TColor;
26 FFillOpacity: byte;
27 FFillGradient: TBCGradient;
28 FUseFillGradient: boolean;
29 FRoundRadius: integer;
30 FBGRA: TBGRABitmap;
31 FSideCount: integer;
32 FRatioXY: single;
33 FUseRatioXY: boolean;
34 FAngle: single;
35 FShapeType: TBGRAShapeType;
36 procedure SetAngle(const AValue: single);
37 procedure SetBorderColor(const AValue: TColor);
38 procedure SetBorderGradient(const AValue: TBCGradient);
39 procedure SetBorderOpacity(const AValue: byte);
40 procedure SetBorderStyle(const AValue: TPenStyle);
41 procedure SetBorderWidth(AValue: integer);
42 procedure SetFillColor(const AValue: TColor);
43 procedure SetFillGradient(const AValue: TBCGradient);
44 procedure SetFillOpacity(const AValue: byte);
45 procedure SetRatioXY(const AValue: single);
46 procedure SetRoundRadius(AValue: integer);
47 procedure SetShapeType(const AValue: TBGRAShapeType);
48 procedure SetSideCount(AValue: integer);
49 procedure SetUseBorderGradient(const AValue: boolean);
50 procedure SetUseFillGradient(const AValue: boolean);
51 procedure SetUseRatioXY(const AValue: boolean);
52 protected
53 { Protected declarations }
54 procedure Paint; override;
55 procedure Resize; override;
56 public
57 { Public declarations }
58 constructor Create(AOwner: TComponent); override;
59 destructor Destroy; override;
60 published
61 { Published declarations }
62 property AutoSize;
63 property Align;
64 property Anchors;
65 property Angle: single Read FAngle Write SetAngle default 0;
66 property BorderWidth: integer Read FBorderWidth Write SetBorderWidth default 1;
67 property BorderOpacity: byte Read FBorderOpacity Write SetBorderOpacity default 255;
68 property BorderColor: TColor Read FBorderColor Write SetBorderColor;
69 property BorderGradient: TBCGradient Read FBorderGradient Write SetBorderGradient;
70 property BorderStyle: TPenStyle
71 Read FBorderStyle Write SetBorderStyle default psSolid;
72 property FillColor: TColor Read FFillColor Write SetFillColor;
73 property FillOpacity: byte Read FFillOpacity Write SetFillOpacity;
74 property FillGradient: TBCGradient Read FFillGradient Write SetFillGradient;
75 property SideCount: integer Read FSideCount Write SetSideCount default 4;
76 property RatioXY: single Read FRatioXY Write SetRatioXY default 1;
77 property UseRatioXY: boolean Read FUseRatioXY Write SetUseRatioXY default False;
78 property UseFillGradient: boolean Read FUseFillGradient
79 Write SetUseFillGradient default False;
80 property UseBorderGradient: boolean Read FUseBorderGradient
81 Write SetUseBorderGradient default False;
82 property ShapeType: TBGRAShapeType
83 Read FShapeType Write SetShapeType default stRegularPolygon;
84 property BorderSpacing;
85 property Caption;
86 property PopupMenu;
87 property RoundRadius: integer Read FRoundRadius Write SetRoundRadius default 0;
88 property Visible;
89
90 property OnClick;
91 property OnDblClick;
92 property OnMouseDown;
93 property OnMouseEnter;
94 property OnMouseLeave;
95 property OnMouseMove;
96 property OnMouseUp;
97 end;
98
99procedure Register;
100
101implementation
102
103uses BCTools;
104
105procedure Register;
106begin
107 {$I bgrashape_icon.lrs}
108 RegisterComponents('BGRA Controls', [TBGRAShape]);
109end;
110
111{ TBGRAShape }
112
113procedure TBGRAShape.SetBorderColor(const AValue: TColor);
114begin
115 if FBorderColor = AValue then
116 exit;
117 FBorderColor := AValue;
118 Invalidate;
119end;
120
121procedure TBGRAShape.SetBorderGradient(const AValue: TBCGradient);
122begin
123 if FBorderGradient = AValue then
124 exit;
125 FBorderGradient.Assign(AValue);
126 Invalidate;
127end;
128
129procedure TBGRAShape.SetAngle(const AValue: single);
130begin
131 if FAngle = AValue then
132 exit;
133 FAngle := AValue;
134 Invalidate;
135end;
136
137procedure TBGRAShape.SetBorderOpacity(const AValue: byte);
138begin
139 if FBorderOpacity = AValue then
140 exit;
141 FBorderOpacity := AValue;
142 Invalidate;
143end;
144
145procedure TBGRAShape.SetBorderStyle(const AValue: TPenStyle);
146begin
147 if FBorderStyle = AValue then
148 exit;
149 FBorderStyle := AValue;
150 Invalidate;
151end;
152
153procedure TBGRAShape.SetBorderWidth(AValue: integer);
154begin
155 if AValue < 0 then
156 AValue := 0;
157 if FBorderWidth = AValue then
158 exit;
159 FBorderWidth := AValue;
160 Invalidate;
161end;
162
163procedure TBGRAShape.SetFillColor(const AValue: TColor);
164begin
165 if FFillColor = AValue then
166 exit;
167 FFillColor := AValue;
168 Invalidate;
169end;
170
171procedure TBGRAShape.SetFillGradient(const AValue: TBCGradient);
172begin
173 if FFillGradient = AValue then
174 exit;
175 FFillGradient.Assign(AValue);
176 Invalidate;
177end;
178
179procedure TBGRAShape.SetFillOpacity(const AValue: byte);
180begin
181 if FFillOpacity = AValue then
182 exit;
183 FFillOpacity := AValue;
184 Invalidate;
185end;
186
187procedure TBGRAShape.SetRatioXY(const AValue: single);
188begin
189 if FRatioXY = AValue then
190 exit;
191 FRatioXY := AValue;
192 Invalidate;
193end;
194
195procedure TBGRAShape.SetRoundRadius(AValue: integer);
196begin
197 if AValue < 0 then
198 AValue := 0;
199 if FRoundRadius = AValue then
200 exit;
201 FRoundRadius := AValue;
202 Invalidate;
203end;
204
205procedure TBGRAShape.SetShapeType(const AValue: TBGRAShapeType);
206begin
207 if FShapeType = AValue then
208 exit;
209 FShapeType := AValue;
210 Invalidate;
211end;
212
213procedure TBGRAShape.SetSideCount(AValue: integer);
214begin
215 if AValue < 3 then
216 AValue := 3;
217 if FSideCount = AValue then
218 exit;
219 FSideCount := AValue;
220 Invalidate;
221end;
222
223procedure TBGRAShape.SetUseBorderGradient(const AValue: boolean);
224begin
225 if FUseBorderGradient = AValue then
226 exit;
227 FUseBorderGradient := AValue;
228 Invalidate;
229end;
230
231procedure TBGRAShape.SetUseFillGradient(const AValue: boolean);
232begin
233 if FUseFillGradient = AValue then
234 exit;
235 FUseFillGradient := AValue;
236 Invalidate;
237end;
238
239procedure TBGRAShape.SetUseRatioXY(const AValue: boolean);
240begin
241 if FUseRatioXY = AValue then
242 exit;
243 FUseRatioXY := AValue;
244 Invalidate;
245end;
246
247procedure TBGRAShape.Paint;
248var
249 cx, cy, rx, ry, curRatio, a: single;
250 coords: array of TPointF;
251 minCoord, maxCoord: TPointF;
252 i: integer;
253 borderGrad, fillGrad: TBGRACustomScanner;
254begin
255 FBGRA.FillTransparent;
256 FBGRA.PenStyle := FBorderStyle;
257 with FBGRA.Canvas2D do
258 begin
259 lineJoin := 'round';
260 if FUseBorderGradient then
261 begin
262 borderGrad := CreateGradient(FBorderGradient, Classes.rect(0, 0, Width, Height));
263 strokeStyle(borderGrad);
264 end
265 else
266 begin
267 borderGrad := nil;
268 strokeStyle(ColorToBGRA(ColorToRGB(FBorderColor), FBorderOpacity));
269 end;
270 lineStyle(FBGRA.CustomPenStyle);
271 lineWidth := FBorderWidth;
272 if FUseFillGradient then
273 begin
274 fillGrad := CreateGradient(FFillGradient, Classes.rect(0, 0, Width, Height));
275 fillStyle(fillGrad);
276 end
277 else
278 begin
279 fillGrad := nil;
280 fillStyle(ColorToBGRA(ColorToRGB(FFillColor), FFillOpacity));
281 end;
282 cx := Width / 2;
283 cy := Height / 2;
284 rx := (Width - FBorderWidth) / 2;
285 ry := (Height - FBorderWidth) / 2;
286 if FUseRatioXY and (ry <> 0) and (FRatioXY <> 0) then
287 begin
288 curRatio := rx / ry;
289 if FRatioXY > curRatio then
290 ry := ry / (FRatioXY / curRatio)
291 else
292 rx := rx / (curRatio / FRatioXY);
293 end;
294 if FShapeType = stRegularPolygon then
295 begin
296 setlength(coords, FSideCount);
297 for i := 0 to high(coords) do
298 begin
299 a := (i / FSideCount + FAngle / 360) * 2 * Pi;
300 coords[i] := PointF(sin(a), -cos(a));
301 end;
302 minCoord := coords[0];
303 maxCoord := coords[0];
304 for i := 1 to high(coords) do
305 begin
306 if coords[i].x < minCoord.x then
307 minCoord.x := coords[i].x;
308 if coords[i].y < minCoord.y then
309 minCoord.y := coords[i].y;
310 if coords[i].x > maxCoord.x then
311 maxCoord.x := coords[i].x;
312 if coords[i].y > maxCoord.y then
313 maxCoord.y := coords[i].y;
314 end;
315 for i := 0 to high(coords) do
316 begin
317 with (coords[i] - minCoord) do
318 coords[i] := PointF((x / (maxCoord.x - minCoord.x) - 0.5) *
319 2 * rx + cx, (y / (maxCoord.y - minCoord.y) - 0.5) * 2 * ry + cy);
320 end;
321 beginPath;
322 for i := 0 to high(coords) do
323 begin
324 lineTo((coords[i] + coords[(i + 1) mod length(coords)]) * (1 / 2));
325 arcTo(coords[(i + 1) mod length(coords)], coords[(i + 2) mod
326 length(coords)], FRoundRadius);
327 end;
328 closePath;
329 end
330 else
331 begin
332 save;
333 translate(cx, cy);
334 scale(rx, ry);
335 beginPath;
336 arc(0, 0, 1, 0, 2 * Pi);
337 restore;
338 end;
339
340 fill;
341 if FBorderWidth <> 0 then
342 stroke;
343
344 fillStyle(BGRAWhite);
345 strokeStyle(BGRABlack);
346
347 fillGrad.Free;
348 borderGrad.Free;
349 end;
350 FBGRA.Draw(Self.Canvas, 0, 0, False);
351end;
352
353procedure TBGRAShape.Resize;
354begin
355 if FBGRA <> nil then
356 FBGRA.SetSize(Width, Height);
357 inherited Resize;
358end;
359
360constructor TBGRAShape.Create(AOwner: TComponent);
361begin
362 inherited Create(AOwner);
363 with GetControlClassDefaultSize do
364 SetInitialBounds(0, 0, CX, CY);
365 FBGRA := TBGRABitmap.Create(Width, Height, BGRAPixelTransparent);
366
367 FBorderColor := clWindowText;
368 FBorderOpacity := 255;
369 FBorderWidth := 1;
370 FBorderStyle := psSolid;
371 FBorderGradient := TBCGradient.Create(Self);
372 FBorderGradient.Point2XPercent := 100;
373 FBorderGradient.StartColor := clWhite;
374 FBorderGradient.EndColor := clBlack;
375
376 FFillColor := clWindow;
377 FFillOpacity := 255;
378 FFillGradient := TBCGradient.Create(Self);
379
380 FRoundRadius := 0;
381 FSideCount := 4;
382 FRatioXY := 1;
383 FUseRatioXY := False;
384end;
385
386destructor TBGRAShape.Destroy;
387begin
388 FBGRA.Free;
389 FFillGradient.Free;
390 FBorderGradient.Free;
391 inherited Destroy;
392end;
393
394end.
Note: See TracBrowser for help on using the repository browser.