lazarus-ccr/components/industrialstuff/source/indsliders.pas
wp_xxyyzz 6b58ffe795 industrial: Add MultiSlider component.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@6850 8e941d3f-bd1b-0410-a28a-d453659cc2b4
2019-04-21 21:18:00 +00:00

854 lines
27 KiB
ObjectPascal

{
/***************************************************************************
indSliders
----------
sliders for the Industrial package
The initial version of this unit was published in the Lazarus forum
by user bylaardt
(https://forum.lazarus.freepascal.org/index.php/topic,45063.msg318180.html#msg318180)
and extended by wp.
License: modified LGPL like Lazarus LCL
*****************************************************************************
}
unit indSliders;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Graphics, Controls, Types;
const
DEFAULT_SIZE = 28;
DEFAULT_TRACK_THICKNESS = 7;
DEFAULT_MULTISLIDER_WIDTH = 250;
DEFAULT_MULTISLIDER_HEIGHT = DEFAULT_SIZE * 5 div 4;
Type
{ TMultiSlider }
TSliderMode = (smSingle, smMinMax, smMinValueMax);
TThumbKind = (tkMin, tkMax, tkValue);
TThumbstyle = (tsGrip, tsCircle, tsRect, tsRoundedRect,
tsTriangle, tsTriangleOtherSide);
TSliderPositionEvent = procedure (
Sender: TObject; AKind: TThumbKind; AValue: Integer) of object;
TMultiSlider = class(TCustomControl)
private
FAutoRotate: Boolean;
FTrackSize: TPoint;
FBtnSize: TPoint;
FCapture: ShortInt;
FCaptureOffset, FTrackStart: Integer;
FColorAbove: TColor;
FColorBelow: TColor;
FColorBetween: TColor;
FColorThumb: TColor;
FFlat: Boolean;
FVertical: boolean;
FMaxPosition, FMinPosition, FPosition: Integer;
FDefaultSize: Integer;
FSliderMode: TSliderMode;
FThumbStyle: TThumbstyle;
FTrackThickness: Integer;
FOnPositionChange: TSliderPositionEvent;
FRangeMax, FRangeMin: Integer;
function IsDefaultSizeStored: Boolean;
function IsTrackThicknessStored: Boolean;
procedure SetColorAbove(AValue: TColor);
procedure SetColorBelow(AValue: TColor);
procedure SetColorBetween(AValue: TColor);
procedure SetColorThumb(AValue: TColor);
procedure SetDefaultSize(AValue: Integer);
procedure SetFlat(AValue: Boolean);
procedure SetMaxPosition(AValue: Integer);
procedure SetMinPosition(AValue: Integer);
procedure SetPosition(AValue: Integer);
procedure SetRangeMax(AValue: Integer);
procedure SetRangeMin(AValue: Integer);
procedure SetSliderMode(AValue: TSliderMode);
procedure SetThumbStyle(AValue: TThumbStyle);
procedure SetTrackThickness(AValue: Integer);
procedure SetVertical(AValue: Boolean);
protected
function BtnLength: Integer;
procedure DoAutoAdjustLayout(const AMode: TLayoutAdjustmentPolicy;
const AXProportion, AYProportion: Double); override;
procedure DoPositionChange(AKind: TThumbKind; AValue: Integer);
function ExtendedThumbs: Boolean;
function GetRectFromPoint(APosition: Integer; Alignment: TAlignment): TRect;
function GetThumbCenter(ARect: TRect): TPoint;
function GetTrackLength: Integer;
function IsInFirstHalf(APoint: TPoint; ARect: TRect): Boolean;
procedure Loaded; override;
function PointToPosition(P: TPoint): Integer;
procedure UpdateBounds;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Paint; override;
procedure Resize; override;
procedure MouseDown(Button: TMouseButton; Shift:TShiftState; X,Y:Integer); override;
procedure MouseMove(Shift: TShiftState; X,Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift:TShiftState; X,Y:Integer); override;
procedure MouseLeave; override;
published
property AutoRotate: Boolean
read FAutoRotate write FAutoRotate default true;
property ColorAbove: TColor
read FColorAbove write SetColorAbove default clInactiveCaption;
property ColorBelow: TColor
read FColorBelow write SetColorBelow default clInactiveCaption;
property ColorBetween: TColor
read FColorBetween write SetColorBetween default clActiveCaption;
property ColorThumb: TColor
read FColorThumb write SetColorThumb default clBtnFace;
property DefaultSize: Integer
read FDefaultSize write SetDefaultSize stored IsDefaultSizeStored;
property Flat: Boolean
read FFlat write SetFlat default false;
property MaxPosition: Integer
read FMaxPosition write SetMaxPosition default 80;
property MinPosition: Integer
read FMinPosition write SetMinPosition default 20;
property Position: Integer
read FPosition write SetPosition default 50;
property RangeMax: Integer
read FRangeMax write SetRangeMax default 100;
property RangeMin: Integer
read FRangeMin write SetRangeMin default 0;
property SliderMode: TSliderMode
read FSliderMode write SetSliderMode default smMinMax;
property ThumbStyle: TThumbStyle
read FThumbStyle write SetThumbStyle default tsGrip;
property TrackThickness: integer
read FTrackThickness write SetTrackThickness stored IsTrackThicknessStored;
property Vertical: boolean
read FVertical write SetVertical default false;
property Height default DEFAULT_SIZE;
property Width default DEFAULT_MULTISLIDER_WIDTH;
property OnPositionChange: TSliderPositionEvent
read FOnPositionChange write FOnPositionChange;
property Align;
property BorderSpacing;
property Constraints;
property Enabled;
// property Font;
property HelpContext;
property HelpKeyword;
property HelpType;
property Left;
// property ParentFont;
property ParentShowHint;
property PopupMenu;
property ShowHint;
property Tag;
property Top;
property Visible;
property OnChangeBounds;
property OnClick;
property OnContextPopup;
property OnDblClick;
property OnMouseDown;
property OnMouseEnter;
property OnMouseLeave;
property OnMouseMove;
property OnMouseUp;
property OnMouseWheel;
property OnMouseWheelDown;
property OnMouseWheelUp;
property OnMouseWheelHorz;
property OnMouseWheelLeft;
property OnMouseWheelRight;
property OnResize;
end;
implementation
uses
Math;
constructor TMultiSlider.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FAutoRotate := true;
FCapture := -1;
FColorAbove := clInactiveCaption;
FColorBelow := clInactiveCaption;
FColorBetween := clActiveCaption;
FColorThumb := clBtnFace;
FDefaultSize := Scale96ToFont(DEFAULT_SIZE);
FTrackThickness := Scale96ToFont(DEFAULT_TRACK_THICKNESS);
FTrackStart := FDefaultSize*9 div 16 + 2;
SetVertical(false);
FRangeMin := 0;
FRangeMax := 100;
FMinPosition := 20;
FMaxPosition := 80;
FPosition := 50;
FSliderMode := smMinMax;
Width := DEFAULT_MULTISLIDER_WIDTH;
Height := DEFAULT_MULTISLIDER_HEIGHT;
Enabled := true;
end;
destructor TMultiSlider.Destroy;
begin
inherited Destroy;
end;
function TMultiSlider.BtnLength: Integer;
begin
Result := IfThen(FVertical, FBtnSize.Y, FBtnSize.X) div 2;
end;
procedure TMultiSlider.DoAutoAdjustLayout(
const AMode: TLayoutAdjustmentPolicy;
const AXProportion, AYProportion: Double);
begin
inherited DoAutoAdjustLayout(AMode, AXProportion, AYProportion);
if AMode in [lapAutoAdjustWithoutHorizontalScrolling, lapAutoAdjustForDPI] then
begin
DisableAutosizing;
try
if IsTrackThicknessStored then
if FVertical then
FTrackThickness := Round(FTrackThickness * AXProportion)
else
FTrackThickness := Round(FTrackThickness * AYProportion);
finally
EnableAutoSizing;
end;
end;
end;
procedure TMultiSlider.DoPositionChange(AKind: TThumbKind; AValue: Integer);
begin
if Assigned(FOnPositionChange) then FOnPositionChange(self, AKind, AValue);
end;
function TMultiSlider.ExtendedThumbs: Boolean;
begin
Result := not (FThumbStyle in [tsTriangle, tsTriangleOtherSide]);
end;
function TMultiSlider.GetRectFromPoint(APosition: Integer;
Alignment: TAlignment): TRect;
var
relPos: Double;
begin
relPos := (APosition - FRangeMin) / (FRangeMax - FRangeMin);
if FVertical then begin
if ExtendedThumbs then
case Alignment of
taLeftJustify:
Result.Top := FTrackStart + Round(FTrackSize.Y * relPos) - FBtnSize.Y;
taCenter:
if FSliderMode = smSingle then
Result.Top := FTrackStart + Round((FTrackSize.Y + FBtnSize.Y) * relPos) - FBtnSize.Y
else
Result.Top := FTrackStart + Round((FTrackSize.Y - FBtnSize.Y) * relPos);
taRightJustify:
Result.Top := FTrackStart + Round(FTrackSize.Y * relPos);
end
else
Result.Top := FTrackStart + Round(FTrackSize.Y * relPos) - FBtnSize.Y div 2;
Result.Left := (Width - FBtnSize.X) div 2;
end else begin
if ExtendedThumbs then
case Alignment of
taLeftJustify:
Result.Left := FTrackStart + Round(FTrackSize.X * relpos) - FBtnSize.X;
taCenter:
if FSliderMode = smSingle then
Result.Left := FTrackStart + Round((FTrackSize.X + FBtnSize.X) * relPos) - FBtnSize.X
else
Result.Left := FTrackStart + Round((FTrackSize.X - FBtnSize.X) * relPos);
taRightJustify:
Result.Left := FTrackStart + Round(FTrackSize.X * relPos);
end
else
Result.Left := FTrackStart + Round(FTrackSize.X * relPos) - FBtnSize.X div 2;
Result.Top := (Height - FBtnSize.Y) div 2;
end;
Result.Right := Result.Left + FBtnSize.X;
Result.Bottom := Result.Top + FBtnSize.Y;
end;
function TMultiSlider.GetThumbCenter(ARect: TRect): TPoint;
begin
Result := Point((ARect.Left + ARect.Right) div 2, (ARect.Top + ARect.Bottom) div 2);
end;
function TMultiSlider.GetTrackLength: Integer;
begin
if FVertical then
Result := FTrackSize.Y
else
Result := FTrackSize.X;
end;
function TMultiSlider.IsDefaultSizeStored: Boolean;
begin
Result := FDefaultSize <> Scale96ToFont(DEFAULT_SIZE);
end;
function TMultiSlider.IsInFirstHalf(APoint: TPoint; ARect: TRect): Boolean;
begin
if FVertical then begin
ARect.Right := GetThumbCenter(ARect).X;
Result := PtInRect(ARect, APoint);
end else begin
ARect.Bottom := GetThumbCenter(ARect).Y;
Result := PtInRect(ARect, APoint);
end;
end;
function TMultiSlider.IsTrackThicknessStored: Boolean;
begin
Result := FTrackThickness <> Scale96ToFont(DEFAULT_TRACK_THICKNESS);
end;
procedure TMultiSlider.Loaded;
begin
inherited;
exit;
if FAutoRotate then begin
if (FVertical and (Width > Height)) or ((not FVertical) and (Width < Height)) then
SetBounds(Left, Top, Height, Width);
end;
end;
procedure TMultiSlider.MouseDown(Button: TMouseButton; Shift: TShiftState;
X,Y: Integer);
var
p: TPoint;
btn1, btn2, btn3: TRect;
inFirstHalf3: Boolean;
begin
if Enabled then begin
p := Point(x,y);
btn1 := GetRectFromPoint(FMinPosition, taLeftJustify);
btn2 := GetRectFromPoint(FMaxPosition, taRightJustify);
btn3 := GetRectFromPoint(FPosition, taCenter);
FCapture := -1;
if (FSliderMode <> smSingle) and PtInRect(btn1, p) then begin
FCapture := ord(tkMin);
if ExtendedThumbs then
FCaptureOffset := IfThen(FVertical, Y - btn1.Bottom, X - btn1.Right)
else
FCaptureOffset := IfThen(FVertical, Y - GetThumbCenter(btn1).Y, X - GetThumbCenter(btn1).X);
end else
if (FSliderMode <> smSingle) and PtInRect(btn2, p) then begin
FCapture := ord(tkMax);
if ExtendedThumbs then
FCaptureOffset := IfThen(FVertical, Y - btn2.Top, X - btn2.Left)
else
FCaptureOffset := IfThen(FVertical, Y - GetThumbCenter(btn2).Y, X - GetThumbCenter(btn2).X)
end else
if (FSliderMode <> smMinMax) and PtInRect(btn3, p) then begin
FCapture := ord(tkValue);
if ExtendedThumbs then
FCaptureOffset := IfThen(FVertical, Y - btn3.Top, X - btn3.Left)
else
FCaptureOffset := IfThen(FVertical, Y - GetThumbCenter(btn3).Y, X - GetThumbCenter(btn3).X);
end;
if (FCapture > -1) and (not ExtendedThumbs and PtInRect(btn3, p)) then begin
inFirstHalf3 := IsInFirstHalf(p, btn3);
if (TThumbKind(FCapture) in [tkMin, tkMax]) and (
(inFirstHalf3 and (FThumbStyle = tsTriangleOtherSide)) or
((not inFirstHalf3) and (FThumbStyle = tsTriangle))
) then
begin
FCapture := ord(tkValue);
end;
end;
end;
inherited MouseDown(Button, Shift, X, Y);
end;
procedure TMultiSlider.MouseMove(Shift: TShiftState; X, Y: Integer);
var
p: TPoint;
btn: TRect;
pos: Integer;
begin
if Enabled then begin
p := Point(X, Y);
case FCapture of
-1: begin
btn := GetRectFromPoint(FMinPosition, taLeftJustify);
if PtInRect(btn, p) then begin
Cursor := crHandPoint;
end else begin
btn := GetRectFromPoint(FMaxPosition, taRightJustify);
if PtInRect(btn, p) then begin
Cursor := crHandPoint;
end else
Cursor := crDefault;
end;
end;
else
pos := PointToPosition(p);
case TThumbKind(FCapture) of
tkMin: if FSliderMode <> smSingle then SetMinPosition(pos);
tkMax: if FSliderMode <> smSingle then SetMaxPosition(pos);
tkValue: if FSliderMode <> smMinMax then SetPosition(pos);
end;
end;
end;
inherited MouseMove(Shift,x,y);
end;
procedure TMultiSlider.MouseLeave;
begin
inherited MouseLeave;
FCapture := -1;
end;
procedure TMultiSlider.MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
FCapture := -1;
inherited MouseUp(Button,Shift,x,y);
end;
procedure TMultiSlider.Paint;
procedure DrawLine(ARect: TRect; AColor, AShadow, AHilight: TColor);
var
start, ending, distances, centerpoint, loop: Integer;
begin
distances := FDefaultSize div 8;
start := ARect.Left + FBtnSize.x div 2 - distances*8 div 5;
ending := start + distances*16 div 5;
centerPoint := (ARect.Bottom - ARect.Top) div 2 + ARect.Top;
for loop := -1 to 1 do begin
Canvas.Pen.Color := AHilight;
Canvas.MoveTo(start, centerPoint - 1 + loop * distances);
Canvas.LineTo(ending, centerPoint - 1 + loop * distances);
Canvas.Pen.Color := AColor;
Canvas.MoveTo(start, centerPoint + loop * distances);
Canvas.LineTo(ending, centerPoint + loop * distances);
Canvas.Pen.Color := AShadow;
Canvas.MoveTo(start, centerPoint + 1 + loop * distances);
Canvas.LineTo(ending, centerPoint + 1 + loop * distances);
end;
end;
procedure DrawRect(ARect: TRect; X1,Y1, X2,Y2, R: Integer; AColor: TColor);
begin
Canvas.Pen.Color := AColor;
Canvas.Pen.Width := 1;
Canvas.Brush.Color := Canvas.Pen.Color;
Canvas.RoundRect(
ARect.Left + X1,
ARect.Top + Y1,
ARect.Right + X2,
ARect.Bottom + Y2,
R, R);
end;
procedure DrawThumb(ARect, ATrackRect: TRect; InFirstHalf: Boolean);
var
radius: Integer;
center: TPoint;
P: array[0..2] of TPoint;
begin
case FThumbStyle of
tsGrip, tsRoundedRect:
begin
radius := Min(FBtnSize.X, FBtnSize.Y) div 2;
if FFlat then
DrawRect(ARect, 0, 0, 0, 0, radius, FColorThumb)
else begin
DrawRect(ARect, 0, 0, -1, -1, radius, clBtnHighlight);
DrawRect(ARect, 1, 1, 0, 0, radius, clBtnShadow);
DrawRect(ARect, 1, 1, -1, -1, radius, FColorThumb);
end;
if FThumbStyle = tsGrip then
DrawLine(ARect, FColorThumb, clBtnShadow, clBtnHighlight);
end;
tsCircle:
begin
center := Point((ARect.Left + ARect.Right) div 2, (ARect.Top + ARect.Bottom) div 2);
radius := Min(ARect.Right - ARect.Left, ARect.Bottom - ARect.Top) div 2;
if not FFlat then begin
Canvas.Brush.Style := bsClear;
Canvas.Pen.Color := clBtnHighlight;
Canvas.Ellipse(center.X - radius - 1, center.Y - radius - 1, center.X + radius - 1, center.Y + radius - 1);
Canvas.Pen.Color := clBtnShadow;
Canvas.Ellipse(center.X - radius + 1, center.Y - radius + 1, center.X + radius + 1, center.Y + radius + 1);
end;
Canvas.Brush.Style := bsSolid;
Canvas.Brush.Color := FColorThumb;
Canvas.Pen.Color := FColorThumb;
Canvas.Ellipse(center.X - radius, center.Y - radius, center.X + radius, center.Y + radius);
end;
tsRect:
begin
if not FFlat then begin
Canvas.Brush.Style := bsClear;
Canvas.Pen.Color := clBtnHighlight;
Canvas.Rectangle(ARect.Left - 1, ARect.Top - 1, ARect.Right - 1, ARect.Bottom - 1);
Canvas.Pen.Color := clBtnShadow;
Canvas.Rectangle(ARect.Left + 1, ARect.Top + 1, ARect.Right + 1, ARect.Bottom + 1);
end;
Canvas.Brush.Style := bsSolid;
Canvas.Brush.Color := FColorThumb;
Canvas.Pen.Color := FColorThumb;
Canvas.Rectangle(ARect);
end;
tsTriangle, tsTriangleOtherSide:
begin
if FVertical then begin
if InFirstHalf then begin
P[0] := Point(ARect.Left, ARect.Top);
P[1] := Point(ARect.Left, ARect.Bottom);
P[2] := Point(ATrackRect.Left, GetThumbCenter(ARect).Y);
end else begin
P[0] := Point(ARect.Right, ARect.Top);
P[1] := Point(ARect.Right, ARect.Bottom);
P[2] := Point(ATrackRect.Right, GetThumbCenter(ARect).Y);
end;
end else begin
if InFirstHalf then begin
P[0] := Point(ARect.Left, ARect.Bottom);
P[1] := Point(ARect.Right, ARect.Bottom);
P[2] := Point(GetThumbCenter(ARect).X, ATrackRect.Bottom);
end else begin
P[0] := Point(ARect.Left, ARect.Top);
P[1] := Point(ARect.Right, ARect.Top);
P[2] := Point(GetThumbCenter(ARect).X, ATrackRect.Top);
end;
end;
if not FFlat then begin
Canvas.Brush.Style := bsClear;
Canvas.Pen.Color := clBtnHighlight;
Canvas.Polygon([Point(P[0].X-1, P[0].Y-1), Point(P[1].X-1, P[1].Y-1), Point(P[2].X-1, P[2].Y-1)]);
Canvas.Pen.Color := clBtnShadow;
Canvas.Polygon([Point(P[0].X+1, P[0].Y+1), Point(P[1].X+1, P[1].Y+1), Point(P[2].X+1, P[2].Y+1)]);
end;
Canvas.Brush.Style := bsSolid;
Canvas.Brush.Color := FColorThumb;
Canvas.Pen.Color := FColorThumb;
Canvas.Polygon(P);
end;
end;
end;
var
R: Integer;
track, rang, btn1, btn2, btn: TRect;
rectBelow, rectAbove: TRect;
dx, dy: Integer;
begin
if FVertical then begin
track.Left := (Width - FTrackSize.X) div 2;
track.Top := FTrackStart;
end else begin
track.Left := FTrackStart;
track.Top := (Height - FTrackSize.Y) div 2;
end;
track.Right := track.Left + FTrackSize.x;
track.Bottom := track.Top + FTrackSize.y;
btn1 := GetRectFromPoint(FMinPosition, taLeftJustify);
btn2 := GetRectFromPoint(FMaxPosition, taRightJustify);
btn := GetRectFromPoint(FPosition, taCenter);
if FVertical then begin
dx := 0;
dy := IfThen(ExtendedThumbs, FBtnSize.Y, 0);
rang.Top := IfThen(ExtendedThumbs, btn1.Bottom, GetThumbCenter(btn1).Y);
rang.Bottom := IfThen(ExtendedThumbs, btn2.Top, GetThumbCenter(btn2).Y);
rang.Left := track.Left;
rang.Right := track.Right;
if FSliderMode = smSingle then begin
rectBelow := Rect(track.Left, track.Top, track.Right, IfThen(ExtendedThumbs, btn.Top, GetThumbCenter(btn).Y));
rectAbove := Rect(track.Left, IfThen(ExtendedThumbs, btn.Bottom, GetThumbCenter(btn).Y), track.Right, track.bottom);
end else begin
rectBelow := Rect(track.Left, track.Top, track.Right, rang.Top);
rectAbove := Rect(track.Left, rang.Bottom, track.Right, track.Bottom);
end;
end else begin
dx := IfThen(ExtendedThumbs, FBtnSize.X, 0);
dy := 0;
rang.Top := track.Top;
rang.Bottom := track.Bottom;
rang.Left := IfThen(ExtendedThumbs, btn1.Right, GetThumbCenter(btn1).X);
rang.Right := IfThen(ExtendedThumbs, btn2.Left, GetThumbCenter(btn2).X);
if FSliderMode = smSingle then begin
rectBelow := Rect(track.Left, track.Top, IfThen(ExtendedThumbs, btn.Left, GetThumbCenter(btn).X), track.Bottom);
rectAbove := Rect(IfThen(ExtendedThumbs, btn.Right, GetThumbCenter(btn).X), track.Top, track.Right, track.Bottom);
end else begin
rectBelow := Rect(track.Left, track.Top, rang.Left, track.Bottom);
rectAbove := Rect(rang.Right, track.Top, track.Right, track.Bottom)
end;
end;
R := IfThen(ExtendedThumbs, Min(FTrackSize.X, FTrackSize.Y), 0);
if not Flat then begin
DrawRect(track, -(dx+2), -(dy+2), dx, dy, R, clBtnShadow);
DrawRect(track, -dx, -dy, dx+2, dy+2, R, clBtnHighlight);
end;
DrawRect(rectBelow, -(dx+1), -(dy+1), dx+1, dy+1, R, FColorBelow);
DrawRect(rectAbove, -(dx+1), -(dy+1), dx+1, dy+1, R, FColorAbove);
if FSliderMode <> smSingle then
DrawRect(rang, -1, -1, 1, 1, 0, FColorBetween);
if (FSliderMode <> smSingle) then begin
DrawThumb(btn1, track, FThumbStyle = tsTriangleOtherSide);
DrawThumb(btn2, track, FThumbStyle = tsTriangleOtherSide);
end;
if (FSliderMode <> smMinMax) then
DrawThumb(btn, track, FThumbStyle <> tsTriangleOtherSide);
end;
function TMultiSlider.PointToPosition(P: TPoint): Integer;
var
pos_start, pos_range: Integer;
coord: Integer;
coord_range: Integer;
coord_start: Integer;
btn1, btn2: TRect;
begin
if FVertical then
coord := P.Y
else
coord := P.X;
if (TThumbKind(FCapture) = tkValue) and (FSliderMode <> smSingle) then begin
btn1 := GetRectFromPoint(FMinPosition, taLeftJustify);
btn2 := GetRectFromPoint(FMaxPosition, taRightJustify);
pos_start := FMinPosition;
pos_range := FMaxPosition - FMinPosition;
if ExtendedThumbs then begin
if FVertical then begin
coord_start := btn1.Bottom + FCaptureOffset;
coord_range := btn2.Top - btn1.Bottom;
end else begin
coord_start := btn1.Right + FCaptureOffset;
coord_range := btn2.Left - btn1.Right;
end;
end else begin
if FVertical then begin
coord_start := GetThumbCenter(btn1).Y + FCaptureOffset;
coord_range := btn2.Top - btn1.Top;
end else begin
coord_start := GetThumbCenter(btn1).X + FCaptureOffset;
coord_range := btn2.Left - btn1.Left;
end;
end;
{
if FThumbStyle = tsTriangle then begin
if FVertical then begin
end else begin
coord_start := (btn1.Left + btn1.Right) div 2 + FCaptureOffset;
coord_range := btn2.Left - btn1.Left;
end
end else begin
if FVertical then begin
coord_start := btn1.Top + FCaptureOffset;
coord_range := btn2.Top - btn1.Bottom;
end else begin
coord_start := btn1.Right + FCaptureOffset;
coord_range := btn2.Left - btn1.Right;
end;
end;
}
end else begin
pos_start := FRangeMin;
pos_range := FRangeMax - FRangeMin;
coord_start := FTrackStart + FCaptureOffset;
coord_range := GetTracklength;
end;
Result := round(pos_start + pos_range * (coord - coord_start) / coord_range);
end;
procedure TMultiSlider.Resize;
begin
inherited;
UpdateBounds;
end;
{
procedure TMultiSlider.SetColor(AValue: TColor);
begin
inherited;
if AValue = clNone then
ControlStyle := ControlStyle - [csOpaque]
else
ControlStyle := ControlStyle + [csOpaque];
end; }
procedure TMultiSlider.SetColorAbove(AValue: TColor);
begin
if AValue = FColorAbove then exit;
FColorAbove := AValue;
Invalidate;
end;
procedure TMultiSlider.SetColorBelow(AValue: TColor);
begin
if AValue = FColorBelow then exit;
FColorBelow := AValue;
Invalidate;
end;
procedure TMultiSlider.SetColorBetween(AValue: TColor);
begin
if AValue = FColorBetween then exit;
FColorBetween := AValue;
Invalidate;
end;
procedure TMultiSlider.SetColorThumb(AValue: TColor);
begin
if AValue = FColorThumb then exit;
FColorThumb := AValue;
Invalidate;
end;
procedure TMultiSlider.SetDefaultSize(AValue: Integer);
begin
if FDefaultSize = AValue then exit;
FDefaultSize := AValue;
if AutoSize then begin
if FVertical then Width := FDefaultSize else Height := FDefaultSize;
end;
UpdateBounds;
end;
procedure TMultiSlider.SetFlat(AValue: Boolean);
begin
if FFlat = AValue then exit;
FFlat := AValue;
Invalidate;
end;
procedure TMultiSlider.SetMaxPosition(AValue: Integer);
var
newPos: Integer;
begin
newPos := Min(Max(AValue, FRangeMin), FRangeMax);
if (newPos = FMaxPosition) then exit;
if (newPos < FMinPosition) and (FSliderMode <> smSingle) then newPos := FMinPosition;
if (newPos < FPosition) and (FSliderMode <> smMinMax) then newPos := FPosition;
FMaxPosition := newPos;
DoPositionChange(tkMax, FMaxPosition);
Invalidate;
end;
procedure TMultiSlider.SetMinPosition(AValue: Integer);
var
newPos: Integer;
begin
newPos := Max(Min(AValue, FRangeMax), FRangeMin);
if (newPos = FMinPosition) then exit;
if (newPos > FMaxPosition) and (FSliderMode <> smSingle) then newPos := FMaxPosition;
if (newPos > FPosition) and (FSliderMode <> smMinMax) then newPos := FPosition;
FMinPosition := newPos;
DoPositionChange(tkMin, FMinPosition);
Invalidate;
end;
procedure TMultiSlider.SetPosition(AValue: Integer);
var
newPos: Integer;
begin
newPos := Max(Min(AValue, FRangeMax), FRangeMin);
if (newPos = FPosition) then exit;
if (FSliderMode <> smSingle) then begin
if (newPos < FMinPosition) then newPos := FMinPosition;
if (newPos > FMaxPosition) then newPos := FMaxPosition;
end;
FPosition := newPos;
DoPositionChange(tkValue, FPosition);
Invalidate;
end;
procedure TMultiSlider.SetRangeMax(AValue:Integer);
begin
if FRangeMax = AValue then exit;
FRangeMax := AValue;
DoPositionChange(tkMax, FRangeMax);
Invalidate;
end;
procedure TMultiSlider.SetRangeMin(AValue: Integer);
begin
if FRangeMin = AValue then exit;
FRangeMin := AValue;
DoPositionChange(tkMin, FRangeMin);
Invalidate;
end;
procedure TMultiSlider.SetThumbStyle(AValue: TThumbStyle);
begin
if FThumbStyle = AValue then exit;
FThumbStyle := AValue;
Invalidate;
end;
procedure TMultiSlider.SetTrackThickness(AValue: Integer);
begin
if FTrackThickness = AValue then exit;
FTrackThickness := AValue;
UpdateBounds;
end;
procedure TMultiSlider.SetVertical(AValue: Boolean);
begin
if FVertical = AValue then exit;
FVertical := AValue;
//if not (csLoading in ComponentState) then begin
if FAutoRotate then begin
if (FVertical and (Width > Height)) or ((not FVertical) and (Width < Height)) then
SetBounds(Left, Top, Height, Width);
end;
UpdateBounds;
//end;
end;
procedure TMultiSlider.SetSliderMode(AValue: TSliderMode);
begin
if FSliderMode = AValue then exit;
FSliderMode := AValue;
Invalidate;
end;
procedure TMultiSlider.UpdateBounds;
var
buttonSize: Integer;
begin
buttonSize := FDefaultSize*5 div 8;
if FVertical then begin
FBtnSize := Point(FDefaultSize, buttonSize);
FTrackSize := Point(FTrackThickness, Height - FTrackStart * 2);
end else begin
FBtnSize:= Point(buttonSize, FDefaultSize);
FTrackSize := Point(Width - FTrackStart * 2, FTrackThickness);
end;
Invalidate;
end;
end.