Files
lazarus-ccr/components/tvplanit/source/vpcontactbuttons.pas

589 lines
16 KiB
ObjectPascal
Raw Normal View History

{*********************************************************}
{* VPCONTACTBUTTONS.PAS 1.03 *}
{*********************************************************}
{* ***** BEGIN LICENSE BLOCK ***** *}
{* Version: MPL 1.1 *}
{* *}
{* The contents of this file are subject to the Mozilla Public License *}
{* Version 1.1 (the "License"); you may not use this file except in *}
{* compliance with the License. You may obtain a copy of the License at *}
{* http://www.mozilla.org/MPL/ *}
{* *}
{* Software distributed under the License is distributed on an "AS IS" basis, *}
{* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License *}
{* for the specific language governing rights and limitations under the *}
{* License. *}
{* *}
{* The Original Code is TurboPower Visual PlanIt *}
{* *}
{* The Initial Developer of the Original Code is TurboPower Software *}
{* *}
{* Portions created by TurboPower Software Inc. are Copyright (C) 2002 *}
{* TurboPower Software Inc. All Rights Reserved. *}
{* *}
{* Contributor(s): *}
{* Steve Forbes *}
{* *}
{* ***** END LICENSE BLOCK ***** *}
{ TurboPower Software Company wishes to thank Steve Forbes for }
{ providing this component, and allowing us to include it. }
{ Thanks Steve! }
{$I vp.inc}
unit VpContactButtons;
interface
uses
{$IFDEF LCL}
LCLProc, LCLType, LCLIntf,
{$ELSE}
Windows,
{$ENDIF}
SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
VpBase, VpContactGrid, VpMisc;
const
VP_MIN_BUTTONS = 2;
VP_LETTERS_IN_ALPHABET = 26;
VP_MAX_BUTTONS = VP_LETTERS_IN_ALPHABET + 1;
VP_LETTER_A_UC = Ord('A');
VP_LETTER_A_LC = Ord('a');
type
TVpButtonRec = packed record
Rect: TRect;
Caption: String;
end;
TVpButtonArray = array[0..VP_MAX_BUTTONS - 1] of TVpButtonRec;
TVpButtonCaptionStyle = (csLowercase, csUppercase);
TVpButtonBarOrientation = (baHorizontal, baVertical);
TVpButtonBarClickEvent = procedure(Sender: TObject; ButtonIndex: Integer;
SearchString: String) of object;
TVpContactButtonBar = class(TVPCustomControl)
private
FOnContactNotFound: TNotifyEvent;
protected {private}
FBarOrientation: TVpButtonBarOrientation;
FBorderWidth: Integer;
FButtonPressed: Integer;
FButtonColor: TColor;
FButtonCount: Integer;
FButtonHeight: Integer;
FButtonsArray: TVpButtonArray;
FButtonWidth: Integer;
FCaptionStyle: TVpButtonCaptionStyle;
FContactGrid: TVpContactGrid;
FDrawingStyle: TVpDrawingStyle;
FOnButtonClick: TVpButtonBarClickEvent;
FShowNumberButton: Boolean;
FRadioStyle: Boolean;
{internal variables}
bbSearchString: string;
{internal methods}
procedure bbPopulateSearchString;
procedure CreateButtons;
procedure DrawButton(Index: Integer; Pressed: Boolean);
procedure SelectContact;
{ Property setter methods }
procedure SetBarOrientation(const Value: TVpButtonBarOrientation);
procedure SetBorderWidth(const Value: Integer);
procedure SetButtonColor(const Value: TColor);
procedure SetButtonHeight(const Value: Integer);
procedure SetButtonWidth(const Value: Integer);
procedure SetCaptionStyle(const Value: TVpButtonCaptionStyle);
procedure SetContactGrid(Value: TVpContactGrid);
procedure SetDrawingStyle(const Value: TVpDrawingStyle);
procedure SetShowNumberButton(const Value: Boolean);
{ Overridden methods }
procedure Loaded; override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); override;
procedure Notification(AComponent: TComponent;
Operation: TOperation); override;
procedure Paint; override;
procedure Resize; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property BarOrientation: TVpButtonBarOrientation
read FBarOrientation write SetBarOrientation default baVertical;
property BorderWidth: Integer
read FBorderWidth write SetBorderWidth default 2;
property ButtonColor: TColor
read FButtonColor write SetButtonColor default clBtnFace;
property ButtonHeight: Integer
read FButtonHeight write SetButtonHeight default 18;
property ButtonWidth: Integer
read FButtonWidth write SetButtonWidth default 34;
property CaptionStyle: TVpButtonCaptionStyle
read FCaptionStyle write SetCaptionStyle default csLowerCase;
property ContactGrid: TVpContactGrid
read FContactGrid write SetContactGrid;
property DrawingStyle: TVpDrawingStyle
read FDrawingStyle write SetDrawingStyle default ds3d;
property ShowNumberButton: Boolean
read FShowNumberButton write SetShowNumberButton default True;
property OnButtonClick: TVpButtonBarClickEvent
read FOnButtonClick write FOnButtonClick;
property OnContactNotFound: TNotifyEvent
read FOnContactNotFound write FOnContactNotFound;
property RadioStyle: Boolean
read FRadioStyle write FRadioStyle default true;
property Align;
property Anchors;
property BiDiMode;
{$IFDEF LCL}
property BorderSpacing;
{$ENDIF}
property Color;
property Constraints;
property Cursor;
property DragCursor;
property DragKind;
property DragMode;
property Enabled;
property Font;
property ParentBiDiMode;
property ParentColor;
property ParentFont;
property ParentShowHint;
property PopupMenu;
property ShowHint;
property Visible;
{events}
{$IFNDEF LCL}
property OnCanResize;
{$ENDIF}
property OnClick;
property OnConstrainedResize;
property OnDblClick;
property OnDockDrop;
property OnDockOver;
property OnDragDrop;
property OnDragOver;
property OnEndDock;
property OnEndDrag;
property OnGetSiteInfo;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnResize;
property OnStartDock;
property OnStartDrag;
property OnUnDock;
end;
implementation
uses
VpConst;
{ TVpContactButtonBar }
constructor TVpContactButtonBar.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Width := 40;
Height := 280;
{$IFDEF VERSION4}
DoubleBuffered := True;
{$ENDIF}
FBarOrientation := baVertical;
FBorderWidth := 2;
FButtonColor := clBtnFace;
FButtonHeight := 18;
FButtonWidth := 34;
FCaptionStyle := csLowercase;
FDrawingStyle := ds3d;
FRadioStyle := true;
FShowNumberButton := True;
end;
{=====}
destructor TVpContactButtonBar.Destroy;
begin
inherited Destroy;
end;
{=====}
procedure TVpContactButtonBar.CreateButtons;
var
I: Integer;
TotalXY: Integer;
StartLetter, EndLetter: Char;
ButtonLetters: Single;
ButtonCaption: String;
Offset: Integer;
MaxButtons: Integer;
MinButtons: Integer;
btnHeight: Integer;
btnWidth: Integer;
brdrWidth: Integer;
VP_Letter_A: integer;
begin
I := 0;
if FShowNumberButton then begin
MaxButtons := VP_MAX_BUTTONS;
MinButtons := VP_MIN_BUTTONS + 1;
end else begin
MaxButtons := VP_LETTERS_IN_ALPHABET;
MinButtons := VP_MIN_BUTTONS;
end;
case FCaptionStyle of
csUppercase: VP_Letter_A := VP_LETTER_A_UC;
csLowercase: VP_Letter_A := VP_LETTER_A_LC;
end;
btnHeight := ScaleY(FButtonHeight, DesignTimeDPI);
btnWidth := ScaleX(FButtonWidth, DesignTimeDPI);
brdrWidth := ScaleX(FBorderWidth, DesignTimeDPI);
if FBarOrientation = baVertical then begin
TotalXY := FBorderWidth;
while ((TotalXY + btnHeight + brdrWidth < ClientHeight) and (I < MaxButtons))
or (I < MinButtons)
do begin
FButtonsArray[I].Rect := Rect(brdrWidth, TotalXY, ClientWidth - brdrWidth, TotalXY + btnHeight);
Inc(I);
TotalXY := TotalXY + btnHeight + brdrWidth;
end;
FButtonCount := I;
end else begin
TotalXY := brdrWidth;
while ((TotalXY + btnWidth + brdrWidth < ClientWidth) and (I < MaxButtons))
or (I < MinButtons)
do begin
FButtonsArray[i].Rect := Rect(TotalXY, brdrWidth, TotalXY + btnWidth, ClientHeight - brdrWidth);
Inc(I);
TotalXY := TotalXY + btnWidth + brdrWidth;
end;
FButtonCount := I;
end;
Offset := 0;
if FShowNumberButton then begin
ButtonLetters := VP_LETTERS_IN_ALPHABET / (FButtonCount - 1);
FButtonsArray[0].Caption := '123';
Offset := 1;
end else
ButtonLetters := VP_LETTERS_IN_ALPHABET / FButtonCount;
for i := 0 to FButtonCount - Offset - 1 do begin
StartLetter := Chr(round(VP_Letter_A + ButtonLetters * I));
EndLetter := Chr(round(VP_Letter_A + ButtonLetters * (I + 1) - 1));
if Ord(EndLetter) = Ord(StartLetter) then
ButtonCaption := StartLetter
else begin
if Ord(EndLetter) = Ord(StartLetter) + 1 then
ButtonCaption := StartLetter + EndLetter
else begin
if Ord(EndLetter) = Ord(StartLetter) + 2 then
ButtonCaption := StartLetter + Succ(StartLetter) + EndLetter
else
ButtonCaption := StartLetter + '-' + EndLetter;
end;
end;
FButtonsArray[I + Offset].Caption := ButtonCaption;
end;
end;
{=====}
procedure TVpContactButtonBar.DrawButton(Index: Integer; Pressed: Boolean);
var
ButtonRect: TRect;
begin
with Canvas do begin
Font := Self.Font;
ButtonRect := FButtonsArray[Index].Rect;
Brush.Color := FButtonColor;
FillRect(ButtonRect);
case FDrawingStyle of
dsFlat:
begin
if Pressed then
Pen.Color := clBtnShadow else
Pen.Color := clBtnHighlight;
PolyLine([
Point(ButtonRect.Right - 1, ButtonRect.Top),
Point(ButtonRect.Left, ButtonRect.Top),
Point(ButtonRect.Left, ButtonRect.Bottom - 1)
]);
if Pressed then
Pen.Color := clBtnHighlight else
Pen.Color := clBtnShadow;
PolyLine([
Point(ButtonRect.Left, ButtonRect.Bottom - 1),
Point(ButtonRect.Right - 1, ButtonRect.Bottom - 1),
Point(ButtonRect.Right - 1, ButtonRect.Top)
]);
InflateRect(ButtonRect, -2, -2);
end;
ds3D:
begin
if Pressed then
DrawFrameControl(Handle, ButtonRect, DFC_BUTTON, DFCS_BUTTONPUSH or DFCS_PUSHED)
else
DrawFrameControl(Handle, ButtonRect, DFC_BUTTON, DFCS_BUTTONPUSH);
InflateRect(ButtonRect, -2, -2);
FillRect(ButtonRect);
end;
dsNoBorder:
begin
if Pressed then begin
Pen.Color := clBtnShadow;
Rectangle(ButtonRect);
end;
end;
end;
if Pressed then begin
ButtonRect.Left := ButtonRect.Left + 2;
ButtonRect.Top := ButtonRect.Top + 2;
end;
DrawText(Handle, PChar(FButtonsArray[Index].Caption),
Length(FButtonsArray[Index].Caption), ButtonRect,
{DrawTextBiDiModeFlagsReadingOnly or }DT_SINGLELINE or DT_CENTER or DT_VCENTER);
end;
end;
{=====}
procedure TVpContactButtonBar.SelectContact;
var
I: Integer;
begin
if FContactGrid <> nil then begin
FContactGrid.SetFocus;
for I := 1 to Length(bbSearchString) do
if FContactGrid.SelectContactByName(bbSearchString[I]) then
Exit;
if Assigned(FOnContactNotFound) then
FOnContactNotFound(self);
end;
end;
{=====}
procedure TVpContactButtonBar.Loaded;
begin
inherited Loaded;
CreateButtons;
end;
{=====}
procedure TVpContactButtonBar.MouseDown(Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
I: Integer;
P: TPoint;
R: TRect;
found: Boolean;
begin
inherited MouseDown(Button, Shift, X, Y);
if Button = mbLeft then begin
found := false;
P := Point(X, Y);
for I := 0 to pred(FButtonCount) do begin
R := FButtonsArray[I].Rect;
if PointInRect(P, R) then begin
found := True;
{ if RadioStyle then un-press the last clicked button. }
if RadioStyle then
DrawButton(FButtonPressed, False);
FButtonPressed := I;
bbPopulateSearchString;
DrawButton(I, True);
Break;
end;
end;
if found then begin
if Assigned(FOnButtonClick) then
FOnButtonClick(Self, FButtonPressed, bbSearchString)
else
SelectContact;
end;
end;
end;
{=====}
procedure TVpContactButtonBar.MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
inherited MouseUp(Button, Shift, X, Y);
if not RadioStyle then
DrawButton(FButtonPressed, False);
end;
{=====}
procedure TVpContactButtonBar.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if (AComponent = FContactGrid) and (Operation = opRemove) then
FContactGrid := nil;
end;
{=====}
procedure TVpContactButtonBar.Paint;
var
I: Integer;
begin
for I := 0 to FButtonCount - 1 do begin
if RadioStyle and (FButtonPressed = I) then
DrawButton(I, True)
else
DrawButton(I, False);
end;
end;
{=====}
procedure TVpContactButtonBar.Resize;
begin
inherited Resize;
CreateButtons;
end;
{=====}
procedure TVpContactButtonBar.SetDrawingStyle(const Value: TVpDrawingStyle);
begin
if FDrawingStyle <> Value then begin
FDrawingStyle := Value;
Repaint;
end;
end;
{=====}
procedure TVpContactButtonBar.SetCaptionStyle(const Value: TVpButtonCaptionStyle);
begin
if (FCaptionStyle <> Value) then begin
FCaptionStyle := Value;
CreateButtons;
Invalidate;
end;
end;
procedure TVpContactButtonBar.SetContactGrid(Value: TVpContactGrid);
begin
if (FContactGrid <> Value) then begin
FContactGrid := Value;
if FContactGrid <> nil then begin
Height := FContactGrid.Height;
Repaint;
end;
end;
end;
procedure TVpContactButtonBar.bbPopulateSearchString;
var
BC: string; // button caption
I: integer;
begin
bc := FButtonsArray[FButtonPressed].Caption;
if FButtonPressed = 0 then
bbSearchString := '0123456789'
else if (pos('-', BC) > 0) then begin
bbSearchString := '';
for I := ord(BC[1]) to ord(BC[Length(BC)]) do
bbSearchString := bbSearchString + chr(I);
end else
bbSearchString := FButtonsArray[FButtonPressed].Caption;
end;
{=====}
procedure TVpContactButtonBar.SetBarOrientation(const Value: TVpButtonBarOrientation);
begin
if (FBarOrientation <> Value) then begin
FBarOrientation := Value;
CreateButtons;
Repaint;
end;
end;
{=====}
procedure TVpContactButtonBar.SetBorderWidth(const Value: Integer);
begin
if (FBorderWidth <> Value) then begin
FBorderWidth := Value;
if FBorderWidth < 0 then
FBorderWidth := 0;
CreateButtons;
Repaint;
end;
end;
{=====}
procedure TVpContactButtonBar.SetButtonColor(const Value: TColor);
begin
if (FButtonColor <> Value) then begin
FButtonColor := Value;
Repaint;
end;
end;
{=====}
procedure TVpContactButtonBar.SetButtonHeight(const Value: Integer);
begin
if (FButtonHeight <> Value) then begin
FButtonHeight := Value;
if FButtonHeight < 18 then
FButtonHeight := 18;
CreateButtons;
Repaint;
end;
end;
{=====}
procedure TVpContactButtonBar.SetButtonWidth(const Value: Integer);
begin
if (FButtonWidth <> Value) then begin
FButtonWidth := Value;
if FButtonWidth < 34 then
FButtonWidth := 34;
CreateButtons;
Repaint;
end;
end;
{=====}
procedure TVpContactButtonBar.SetShowNumberButton(const Value: Boolean);
begin
if (FShowNumberButton <> Value) then begin
FShowNumberButton := Value;
CreateButtons;
Repaint;
end;
end;
{=====}
end.