You've already forked lazarus-ccr
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@6508 8e941d3f-bd1b-0410-a28a-d453659cc2b4
3224 lines
94 KiB
ObjectPascal
3224 lines
94 KiB
ObjectPascal
{*********************************************************}
|
|
{* VPNAVBAR.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): *}
|
|
{* *}
|
|
{* ***** END LICENSE BLOCK ***** *}
|
|
|
|
{$I vp.inc}
|
|
|
|
{$DEFINE PAINTER}
|
|
|
|
unit VpNavBar;
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFDEF LCL}
|
|
LMessages, LCLProc, LCLType, LCLIntf, LCLVersion,
|
|
{$ELSE}
|
|
Windows, Messages, MMSystem,
|
|
{$ENDIF}
|
|
Controls, Graphics, Forms, Buttons, SysUtils, StdCtrls, Classes, ExtCtrls, Math,
|
|
VpBase, VpConst, VpMisc, VpSR;
|
|
|
|
type
|
|
{Forward Declaration}
|
|
TVpNavFolder = class;
|
|
TVpCustomNavBar = class;
|
|
|
|
TVpIconSize = (isLarge, isSmall);
|
|
TVpBackgroundMethod = (bmNone, bmNormal, bmStretch, bmTile);
|
|
TVpFolderDrawingStyle = (dsDefButton, dsEtchedButton, dsCoolTab, dsStandardTab);
|
|
TVpFolderType = (ftDefault, ftContainer);
|
|
TVpItemTheme = (itNoTheme, itPushButton, itToolbar);
|
|
|
|
TVpFolderContainer = class(TPanel)
|
|
protected{Private}
|
|
FNavBar: TVpCustomNavBar;
|
|
FIndex: Integer;
|
|
procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
|
|
function GetChildOwner: TComponent; override;
|
|
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
property Index: Integer Read FIndex;
|
|
property NavBar: TVpCustomNavBar read FNavBar;
|
|
end;
|
|
|
|
TVpNavBtnItem = class(TVpCollectionItem)
|
|
protected {private}
|
|
{property variables}
|
|
FFolder: TVpNavFolder;
|
|
FCaption: string;
|
|
FDescription: String;
|
|
FIconIndex: Integer;
|
|
FIconRect: TRect;
|
|
FLabelRect: TRect;
|
|
FTag: Integer;
|
|
{internal variables}
|
|
liDisplayName : string;
|
|
{property methods}
|
|
procedure SetCaption(const Value: string);
|
|
procedure SetIconIndex(Value: Integer);
|
|
public
|
|
constructor Create(Collection: TCollection); override;
|
|
destructor Destroy; override;
|
|
property Folder: TVpNavFolder read FFolder;
|
|
procedure Assign(Source: TPersistent); override;
|
|
property DisplayName: String read liDisplayName write liDisplayName; // wp: needed by painter
|
|
property IconRect: TRect read FIconRect write FIconRect; // wp: Setter needed by painter
|
|
property LabelRect: TRect read FLabelRect write FLabelRect; // wp: Setter needed by painter
|
|
published
|
|
property Caption: string read FCaption write SetCaption;
|
|
property Description: string read FDescription write FDescription;
|
|
property IconIndex: Integer read FIconIndex write SetIconIndex;
|
|
property Name;
|
|
property Tag: Integer read FTag write FTag;
|
|
end;
|
|
|
|
TVpNavFolder = class(TVpCollectionItem)
|
|
protected {private}
|
|
{property variables}
|
|
FNavBar: TVpCustomNavBar;
|
|
FCaption: string;
|
|
FEnabled: Boolean;
|
|
FIconSize: TVpIconSize;
|
|
FFolderType: TVpFolderType;
|
|
FContainerIndex: Integer;
|
|
FItems: TVpCollection;
|
|
{internal variables}
|
|
lfDisplayName: string;
|
|
lfRect: TRect;
|
|
FTag: Integer;
|
|
{property methods}
|
|
function GetItem(Index: Integer): TVpNavBtnItem;
|
|
function GetItemCount: Integer;
|
|
procedure SetCaption(const Value: string);
|
|
procedure SetEnabled(Value: Boolean);
|
|
procedure SetFolderType(Value: TVpFolderType);
|
|
function CreateContainer: Integer;
|
|
procedure SetIconSize(Value: TVpIconSize);
|
|
procedure SetItem(Index: Integer; Value: TVpNavBtnItem);
|
|
procedure lfGetEditorCaption(var Caption: string);
|
|
procedure lfItemChange(Sender: TObject);
|
|
procedure DefineProperties(Filer: TFiler); override;
|
|
procedure ReadIndex(Reader: TReader);
|
|
procedure WriteIndex(Writer: TWriter);
|
|
|
|
public
|
|
constructor Create(Collection: TCollection); override;
|
|
destructor Destroy; override;
|
|
function GetContainer: TVpFolderContainer;
|
|
function ItemByName(AName: String): TVpNavBtnItem;
|
|
|
|
property Items[Index: Integer]: TVpNavBtnItem read GetItem;
|
|
property ItemCount: Integer read GetItemCount;
|
|
property ContainerIndex: Integer read FContainerIndex write FContainerIndex;
|
|
property DisplayName: String read lfDisplayName; // made public for painter
|
|
property Rect: TRect read lfRect write lfRect; // made public for painter
|
|
|
|
published
|
|
property Caption: string read FCaption write SetCaption;
|
|
property Enabled: Boolean read FEnabled write SetEnabled;
|
|
property FolderType: TVpFolderType read FFolderType write SetFolderType;
|
|
property ItemCollection: TVpCollection read FItems write FItems;
|
|
property IconSize: TVpIconSize read FIconSize write SetIconSize;
|
|
property Name;
|
|
property Tag: Integer read FTag write FTag;
|
|
end;
|
|
|
|
TVpRenameEdit = class(TCustomMemo)
|
|
private
|
|
protected
|
|
procedure KeyPress(var Key: Char); override;
|
|
public
|
|
FolderIndex: Integer;
|
|
ItemIndex: Integer;
|
|
constructor Create(AOwner: TComponent); override;
|
|
end;
|
|
|
|
{NavBar Events}
|
|
TVpFolderClickEvent = procedure(Sender: TObject; Button: TMouseButton;
|
|
Shift: TShiftState; Index: Integer) of object;
|
|
|
|
TVpItemClickEvent = procedure(Sender: TObject; Button: TMouseButton;
|
|
Shift: TShiftState; Index: Integer) of object;
|
|
|
|
TVpFolderChangeEvent = procedure(Sender: TObject; Index: Integer;
|
|
var AllowChange: Boolean; Dragging: Boolean) of object;
|
|
|
|
TVpFolderChangedEvent = procedure(Sender: TObject; Index: Integer) of object;
|
|
|
|
TVpNABDragOverEvent = procedure(Sender, Source: TObject; X, Y: Integer;
|
|
State: TDragState; var AcceptFolder, AcceptItem: Boolean) of object;
|
|
|
|
TVpNABDragDropEvent = procedure(Sender, Source: TObject; X, Y: Integer;
|
|
FolderIndex, ItemIndex: Integer) of object;
|
|
|
|
TVpMouseOverItemEvent = procedure(Sender: TObject; Item: TVpNavBtnItem) of object;
|
|
|
|
TVpCustomNavBar = class(TVpCustomControl)
|
|
protected {private}
|
|
{property variables}
|
|
FActiveFolder: Integer;
|
|
FActiveItem: Integer;
|
|
FAllowRearrange: Boolean;
|
|
FBackgroundColor: TColor;
|
|
FBackgroundImage: TBitmap;
|
|
FBackgroundMethod: TVpBackgroundMethod;
|
|
// FBorderStyle: TBorderStyle;
|
|
FButtonHeight: Integer;
|
|
FCanvasScaleFactor: Double;
|
|
FContainers: TVpContainerList;
|
|
FDrawingStyle: TVpFolderDrawingStyle;
|
|
FFolders: TVpCollection;
|
|
FHotFolder: Integer;
|
|
FImages: TImageList;
|
|
FImagesWidth: Integer;
|
|
FItemFont: TFont;
|
|
FItemSpacing: Integer;
|
|
FPreviousFolder: Integer;
|
|
FPreviousItem: Integer;
|
|
FPlaySounds: Boolean;
|
|
FSelectedItem: Integer;
|
|
FSelectedItemFont: TFont;
|
|
FScrollDelta: Integer;
|
|
FShowButtons: Boolean;
|
|
FSoundAlias: string;
|
|
FLoadingFolder: Integer;
|
|
FMouseDownPt: TPoint;
|
|
FAllowInplaceEdit: Boolean;
|
|
FItemTheme: TVpItemTheme;
|
|
|
|
{event variables}
|
|
FOnArrange: TNotifyEvent;
|
|
FOnDragDrop: TVpNABDragDropEvent;
|
|
FOnDragOver: TVpNABDragOverEvent;
|
|
FOnFolderChange: TVpFolderChangeEvent;
|
|
FOnFolderChanged: TVpFolderChangedEvent;
|
|
FOnFolderClick: TVpFolderClickEvent;
|
|
FOnItemClick: TVpItemClickEvent;
|
|
FOnMouseOverItem: TVpMouseOverItemEvent;
|
|
FOnPlaySound: TVpPlaySoundEvent;
|
|
|
|
{internal variables}
|
|
nabChanging: Boolean;
|
|
nabEdit: TVpRenameEdit;
|
|
nabTopItem: Integer;
|
|
nabExternalDrag: Boolean;
|
|
nabDragFromItem: Integer;
|
|
nabDragFromFolder: Integer;
|
|
nabDragToItem: Integer;
|
|
nabDragToFolder: Integer;
|
|
nabDropY: Integer;
|
|
nabHitTest: TPoint; {location of mouse cursor}
|
|
nabItemsRect: TRect;
|
|
nabMouseDown: Boolean;
|
|
nabOverButton: Boolean;
|
|
nabScrollDownBtn: TSpeedButton;
|
|
nabScrollUpBtn: TSpeedButton;
|
|
nabTimer: Integer; {timer-pool handle}
|
|
nabExternalDragItem: Integer;
|
|
nabFolderAccept: Boolean;
|
|
nabItemAccept: Boolean;
|
|
nabCursorOverItem: Boolean;
|
|
nabAcceptAny: Boolean;
|
|
nabLastMouseOverItem: Integer;
|
|
|
|
{property methods}
|
|
function GetFolder(Index: Integer): TVpNavFolder;
|
|
function GetFolderCount: Integer;
|
|
function GetContainer(Index: Integer): TVpFolderContainer;
|
|
function IsStoredItemSpacing: boolean;
|
|
procedure SetActiveFolder(Value: Integer);
|
|
procedure SetBackgroundColor(Value: TColor);
|
|
procedure SetBackgroundImage(Value: TBitmap);
|
|
procedure SetBackgroundMethod(Value: TVpBackgroundMethod);
|
|
procedure SetDrawingStyle(Value: TVpFolderDrawingStyle);
|
|
// procedure SetBorderStyle(const Value: TBorderStyle);
|
|
procedure SetButtonHeight(Value: Integer);
|
|
procedure SetImages(Value: TImageList);
|
|
procedure SetImagesWidth(const AValue: Integer);
|
|
procedure SetItemFont(Value: TFont);
|
|
procedure SetItemSpacing(Value: Integer);
|
|
procedure SetSelectedItemFont(Value: TFont);
|
|
procedure SetScrollDelta(Value: Integer);
|
|
|
|
{internal methods}
|
|
function nabButtonRect(Index: Integer): TRect;
|
|
procedure nabCommitEdit(Sender: TObject);
|
|
procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); override;
|
|
function nabDropHitTest(X, Y: Integer): Boolean;
|
|
procedure nabFolderChange(Sender: TObject);
|
|
procedure nabFolderSelected(Sender: TObject; Index: Integer);
|
|
procedure nabFontChanged(Sender: TObject);
|
|
procedure nabGetEditorCaption(var Caption: string);
|
|
function nabGetFolderArea(Index: Integer): TRect;
|
|
procedure nabGetHitTest(X, Y: Integer; out FolderIndex, ItemIndex: Integer);
|
|
procedure nabImagesChanged(Sender: TObject);
|
|
procedure nabRecalcDisplayNames;
|
|
procedure nabScrollDownBtnClick(Sender: TObject);
|
|
procedure nabScrollUpBtnClick(Sender: TObject);
|
|
function nabShowScrollUp: Boolean;
|
|
function nabShowScrollDown: Boolean;
|
|
procedure nabTimerEvent(Sender: TObject; Handle: Integer; Interval: Cardinal; ElapsedTime: LongInt);
|
|
procedure nabProcessContainers;
|
|
|
|
{VCL message methods}
|
|
procedure CMDesignHitTest(var Msg: TCMDesignHitTest); message CM_DESIGNHITTEST;
|
|
{$IFNDEF LCL}
|
|
procedure CMCtl3DChanged(var Msg: TMessage); message CM_CTL3DCHANGED;
|
|
procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
|
|
procedure CMParentColorChanged(var Message: TMessage); message CM_PARENTCOLORCHANGED;
|
|
{windows message response methods}
|
|
procedure WMEraseBkGnd(var Msg: TWMEraseBkGnd); message WM_ERASEBKGND;
|
|
procedure WMGetDlgCode(var Msg: TWMGetDlgCode); message WM_GETDLGCODE;
|
|
procedure WMNCHitTest(var Msg: TWMNCHitTest); message WM_NCHITTEST;
|
|
procedure WMSetCursor(var Msg: TWMSetCursor); message WM_SETCURSOR;
|
|
{$ELSE}
|
|
procedure CMFontChanged(var Msg: TLMessage); message CM_FONTCHANGED;
|
|
procedure CMParentColorChanged(var Msg: TLMessage); message CM_PARENTCOLORCHANGED;
|
|
{windows message response methods}
|
|
procedure WMEraseBkGnd(var Msg: TLMEraseBkGnd); message LM_ERASEBKGND;
|
|
procedure WMNCHitTest(var Msg: TLMNCHitTest); message LM_NCHITTEST;
|
|
procedure WMSetCursor(var Msg: TLMSetCursor); message LM_SETCURSOR;
|
|
{$IF LCL_FullVersion >= 1080000}
|
|
procedure DoAutoAdjustLayout(const AMode: TLayoutAdjustmentPolicy;
|
|
const AXProportion, AYProportion: Double); override;
|
|
{$ENDIF}
|
|
procedure CreateParams(var Params: TCreateParams); override;
|
|
procedure CreateWnd; override;
|
|
|
|
{Compound component streaming methods}
|
|
procedure Loaded; override;
|
|
procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
|
|
function GetChildOwner: TComponent; override;
|
|
function AddContainer(Container: TVpFOlderContainer): Integer;
|
|
procedure RemoveContainer(Container: TVpFolderContainer);
|
|
|
|
procedure DblClick; override;
|
|
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
procedure MouseLeave; override;
|
|
procedure MouseMove(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 DoArrange;
|
|
procedure DoFolderChange(Index: Integer; var AllowChange: Boolean);
|
|
procedure DoFolderChanged(Index: Integer);
|
|
procedure DoFolderClick(Button: TMouseButton; Shift: TShiftState; Index: Integer);
|
|
procedure DoItemClick(Button: TMouseButton; Shift: TShiftState; Index: Integer);
|
|
procedure DoMouseOverItem(X, Y, ItemIndex: Integer);
|
|
|
|
{properties}
|
|
property ActiveFolder: Integer read FActiveFolder write SetActiveFolder;
|
|
property AllowInplaceEdit: Boolean read FAllowInplaceEdit write FAllowInplaceEdit default false;
|
|
property AllowRearrange: Boolean read FAllowRearrange write FAllowRearrange;
|
|
property BackgroundColor: TColor read FBackgroundColor write SetBackgroundColor default clWindow;
|
|
property BackgroundImage: TBitmap read FBackgroundImage write SetBackgroundImage;
|
|
property BackgroundMethod: TVpBackgroundMethod read FBackgroundMethod write SetBackgroundMethod;
|
|
property ButtonHeight: Integer read FButtonHeight write SetButtonHeight default 0;
|
|
property DrawingStyle: TVpFolderDrawingStyle read FDrawingStyle write SetDrawingStyle;
|
|
property FolderCollection: TVpCollection read FFolders write FFolders;
|
|
property Images: TImageList read FImages write SetImages;
|
|
{$IF LCL_FullVersion >= 1090000}
|
|
property ImagesWidth: Integer read FImagesWidth write SetImagesWidth default 0;
|
|
{$ENDIF}
|
|
property ItemFont: TFont read FItemFont write SetItemFont;
|
|
property ItemSpacing: Integer read FItemSpacing write SetItemSpacing stored IsStoredItemSpacing;
|
|
property ItemTheme: TVpItemTheme read FItemTheme write FItemTheme default itNoTheme;
|
|
property PlaySounds: Boolean read FPlaySounds write FPlaySounds default false;
|
|
property ScrollDelta: Integer read FScrollDelta write SetScrollDelta default 2;
|
|
property SelectedItem: Integer read FSelectedItem write FSelectedItem;
|
|
property SelectedItemFont: TFont read FSelectedItemFont write SetSelectedItemFont;
|
|
property ShowButtons: Boolean read FShowButtons write FShowButtons;
|
|
property SoundAlias: string read FSoundAlias write FSoundAlias;
|
|
{ property Storage: TOvcAbstractStore read FStorage write SetStorage;}
|
|
|
|
{inherited Events}
|
|
property AfterEnter;
|
|
property AfterExit;
|
|
property OnMouseWheel;
|
|
|
|
{events}
|
|
property OnArrange: TNotifyEvent read FOnArrange write FOnArrange;
|
|
property OnDragDrop: TVpNABDragDropEvent read FOnDragDrop write FOnDragDrop;
|
|
property OnDragOver: TVpNABDragOverEvent read FOnDragOver write FOnDragOver;
|
|
property OnFolderClick: TVpFolderClickEvent read FOnFolderClick write FOnFolderClick;
|
|
property OnItemClick: TVpItemClickEvent read FOnItemClick write FOnItemClick;
|
|
property OnFolderChange: TVpFolderChangeEvent read FOnFolderChange write FOnFolderChange;
|
|
property OnFolderChanged: TVpFolderChangedEvent read FOnFolderChanged write FOnFolderChanged;
|
|
property OnMouseOverItem: TVpMouseOverItemEvent read FOnMouseOverItem write FOnMouseOverItem;
|
|
property OnPlaySound: TVpPlaySoundEvent read FOnPlaySound write FOnPlaySound;
|
|
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
|
|
{ Declared public because TControl's DragDrop is public. }
|
|
procedure DragDrop(Source: TObject; X, Y: Integer); override;
|
|
|
|
procedure BeginUpdate;
|
|
procedure ItemChanged(FolderIndex, ItemIndex: Integer);
|
|
procedure FolderChanged(FolderIndex: Integer);
|
|
procedure EndUpdate;
|
|
function GetFolderAt(X, Y: Integer): Integer;
|
|
function GetItemAt(X, Y: Integer): Integer;
|
|
function Container: TVpFolderContainer;
|
|
function GetRealButtonHeight: Integer;
|
|
procedure InsertFolder(const ACaption: string; AFolderIndex: Integer);
|
|
procedure AddFolder(const ACaption: string);
|
|
procedure RemoveFolder(AFolderIndex: Integer);
|
|
procedure RenameFolder(AFolderIndex: Integer);
|
|
procedure InsertItem(const ACaption: string; AFolderIndex, AItemIndex, AIconIndex: Integer);
|
|
procedure AddItem(const ACaption: string; AFolderIndex, AIconIndex: Integer);
|
|
procedure InvalidateItem(FolderIndex, ItemIndex: Integer);
|
|
procedure RemoveItem(AFolderIndex, AItemIndex: Integer);
|
|
procedure RenameItem(AFolderIndex, AItemIndex: Integer);
|
|
procedure PlaySound(const AWavFile: String; APlaySoundMode: TVpPlaySoundMode);
|
|
|
|
{$IF VP_LCL_SCALING = 2}
|
|
procedure ScaleFontsPPI(const AToPPI: Integer; const AProportion: Double); override;
|
|
{$ELSEIF VP_LCL_SCALING = 1}
|
|
procedure ScaleFontsPPI(const AProportion: Double); override;
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
|
|
property ActiveItem: Integer read FActiveItem;
|
|
property Containers[Index: Integer]: TVpFolderContainer read GetContainer;
|
|
property Folders[Index: Integer]: TVpNavFolder read GetFolder;
|
|
property FolderCount: Integer read GetFolderCount;
|
|
property PreviousFolder : Integer read FPreviousFolder;
|
|
property PreviousItem : Integer read FPreviousItem;
|
|
end;
|
|
|
|
TVpNavBar = class(TVpCustomNavBar)
|
|
published
|
|
{$IFDEF LCL}
|
|
property BorderSpacing;
|
|
{$ENDIF}
|
|
property ActiveFolder;
|
|
property AllowInplaceEdit;
|
|
property AllowRearrange;
|
|
property BackgroundColor;
|
|
property BackgroundImage;
|
|
property BackgroundMethod;
|
|
property BorderStyle default bsNone;
|
|
property ButtonHeight;
|
|
property DrawingStyle;
|
|
property FolderCollection;
|
|
property Images;
|
|
{$IFDEF LCL}{$IF LCL_FullVersion >= 1090000}
|
|
property ImagesWidth;
|
|
{$ENDIF}{$ENDIF}
|
|
property ItemFont;
|
|
property ItemSpacing;
|
|
property ItemTheme;
|
|
property PlaySounds;
|
|
property ScrollDelta;
|
|
property SelectedItem;
|
|
property SelectedItemFont;
|
|
property ShowButtons;
|
|
property SoundAlias;
|
|
// property Storage;
|
|
|
|
{inherited Events}
|
|
property AfterEnter;
|
|
property AfterExit;
|
|
property OnMouseWheel;
|
|
|
|
{events}
|
|
property OnArrange;
|
|
property OnDragDrop;
|
|
property OnDragOver;
|
|
property OnFolderClick;
|
|
property OnItemClick;
|
|
property OnFolderChange;
|
|
property OnFolderChanged;
|
|
property OnMouseOverItem;
|
|
|
|
{inherited properties}
|
|
{$IFDEF VERSION4}
|
|
property Anchors;
|
|
property Constraints;
|
|
property DragKind;
|
|
{$ENDIF}
|
|
property Align;
|
|
property DragCursor;
|
|
property Enabled;
|
|
property Font;
|
|
(*
|
|
The following properties are not published to avoid conflicts with
|
|
OnFolderClick and OnItemClick.
|
|
property OnClick;
|
|
property OnDblClick;
|
|
*)
|
|
property OnEndDrag;
|
|
property OnMouseDown;
|
|
property OnMouseMove;
|
|
property OnMouseUp;
|
|
property OnStartDrag;
|
|
property ParentColor;
|
|
property ParentFont;
|
|
property ParentShowHint;
|
|
property PopupMenu;
|
|
property ShowHint;
|
|
property Visible;
|
|
end;
|
|
|
|
|
|
implementation
|
|
|
|
uses
|
|
{$IFDEF WINDOWS}
|
|
mmSystem,
|
|
{$ENDIF}
|
|
Themes,
|
|
VpNavBarPainter;
|
|
|
|
const
|
|
DEFAULT_ITEMSPACING = 8;
|
|
|
|
{$IFNDEF PAINTER}
|
|
{DrawNavTab - returns the usable text area inside the tab rect.}
|
|
function DrawNavTab(Canvas: TCanvas; const Client: TRect; BevelWidth: Integer;
|
|
TabColor: TColor; TabNumber: Integer; CoolTab, IsFocused, IsMouseOver: Boolean): TRect;
|
|
var
|
|
R: TRect;
|
|
{$IFNDEF VERSION4}
|
|
Points: array[1..5] of TPoint;
|
|
{$ENDIF}
|
|
begin
|
|
R := Client;
|
|
|
|
with Canvas do begin
|
|
Brush.Color := clBtnFace;
|
|
Brush.Style := bsSolid;
|
|
Pen.Color := TabColor;
|
|
|
|
{fill the tab area}
|
|
Polygon([
|
|
Point(R.Left, R.Bottom),
|
|
Point(R.Left, R.Top),
|
|
Point(R.Right, R.Top),
|
|
Point(R.Right, R.Bottom)
|
|
]);
|
|
|
|
if CoolTab then
|
|
begin
|
|
{ --- Draw Cool Tabs --- }
|
|
Pen.Color := clBlack;
|
|
|
|
{Draw the bottom, left line}
|
|
MoveTo(R.Left, R.Bottom - 1);
|
|
LineTo(R.Left + 5, R.Bottom - 1);
|
|
|
|
{Draw the bottom, left curve}
|
|
{$IFNDEF VERSION4}
|
|
Points[1] := Point(R.Left + 5, R.Bottom - 1);
|
|
Points[2] := Point(R.Left + 11, R.Bottom - 2);
|
|
Points[3] := Point(R.Left + 12, R.Bottom - 7);
|
|
Points[4] := Point(R.Left + 13, R.Bottom - 9);
|
|
{$IFDEF CBuilder}
|
|
Canvas.PolyBezier(Points);
|
|
{$ELSE}
|
|
Canvas.Polyline(Points);
|
|
{$ENDIF}
|
|
{$ELSE}
|
|
PolyBezier([
|
|
Point(R.Left + 5, R.Bottom - 1), {StartPoint}
|
|
Point(R.Left + 11, R.Bottom - 2), {ControlPoint}
|
|
Point(R.Left + 12, R.Bottom - 7), {ControlPoint}
|
|
Point(R.Left + 13, R.Bottom - 9) {EndPoint}
|
|
]);
|
|
{$ENDIF}
|
|
|
|
{Draw the left side of the tab}
|
|
MoveTo(R.Left + 13, R.Bottom - 9);
|
|
LineTo(R.Left + 13, R.Top + 9);
|
|
|
|
{Draw the top, left corner of the tab}
|
|
{$IFNDEF VERSION4}
|
|
Points[1] := Point(R.Left + 13, R.Top + 9);
|
|
Points[2] := Point(R.Left + 14, R.Top + 7);
|
|
Points[3] := Point(R.Left + 15, R.Top + 2);
|
|
Points[4] := Point(R.Left + 21, R.Top + 1);
|
|
{$IFDEF CBuilder}
|
|
Canvas.PolyBezier(Points);
|
|
{$ELSE}
|
|
Canvas.Polyline(Points);
|
|
{$ENDIF}
|
|
{$ELSE}
|
|
PolyBezier([
|
|
Point(R.Left + 13, R.Top + 9), {StartPoint}
|
|
Point(R.Left + 14, R.Top + 7), {ControlPoint}
|
|
Point(R.Left + 15, R.Top + 2), {ControlPoint}
|
|
Point(R.Left + 21, R.Top + 1) {EndPoint}
|
|
]);
|
|
{$ENDIF}
|
|
|
|
{Draw the top of the tab}
|
|
MoveTo(R.Left + 21, R.Top + 1);
|
|
LineTo(R.Right - 16, R.Top + 1);
|
|
|
|
{Draw the Top, Right corner of the tab}
|
|
{$IFNDEF VERSION4}
|
|
Points[1] := Point(R.Right - 16, R.Top + 1);
|
|
Points[2] := Point(R.Right - 10, R.Top + 2);
|
|
Points[3] := Point(R.Right - 9, R.Top + 7);
|
|
Points[4] := Point(R.Right - 8, R.Top + 9);
|
|
{$IFDEF CBuilder}
|
|
Canvas.PolyBezier(Points);
|
|
{$ELSE}
|
|
Canvas.Polyline(Points);
|
|
{$ENDIF}
|
|
{$ELSE}
|
|
PolyBezier([
|
|
Point(R.Right - 16, R.Top + 1), {StartPoint}
|
|
Point(R.Right - 10, R.Top + 2), {ControlPoint}
|
|
Point(R.Right - 9, R.Top + 7), {ControlPoint}
|
|
Point(R.Right - 8, R.Top + 9) {EndPoint}
|
|
]);
|
|
{$ENDIF}
|
|
|
|
{Draw the right side of the tab}
|
|
MoveTo(R.Right - 8, R.Top + 9);
|
|
LineTo(R.Right - 8, R.Bottom - 9);
|
|
|
|
{Draw the bottom, Right curve of the tab which should finish against the
|
|
right side.}
|
|
{$IFNDEF VERSION4}
|
|
Points[1] := Point(R.Right - 8, R.Bottom - 9);
|
|
Points[2] := Point(R.Right - 7, R.Bottom - 7);
|
|
Points[3] := Point(R.Right - 6, R.Bottom - 2);
|
|
Points[4] := Point(R.Right, R.Bottom - 1);
|
|
{$IFDEF CBuilder}
|
|
Canvas.PolyBezier(Points);
|
|
{$ELSE}
|
|
Canvas.Polyline(Points);
|
|
{$ENDIF}
|
|
{$ELSE}
|
|
PolyBezier([
|
|
Point(R.Right - 8, R.Bottom - 9), {StartPoint}
|
|
Point(R.Right - 7, R.Bottom - 7), {ControlPoint}
|
|
Point(R.Right - 6, R.Bottom - 2), {ControlPoint}
|
|
Point(R.Right, R.Bottom - 1) {EndPoint}
|
|
]);
|
|
{$ENDIF}
|
|
end
|
|
else
|
|
begin
|
|
{Draw Standard Tabs}
|
|
if TabNumber > 0 then begin
|
|
Brush.Color := TabColor;
|
|
Brush.Style := bsSolid;
|
|
Pen.Color := TabColor;
|
|
|
|
{fill the tab area}
|
|
Polygon([
|
|
Point(R.Left, R.Bottom),
|
|
Point(R.Left, R.Top),
|
|
Point(R.Right, R.Top),
|
|
Point(R.Right, R.Bottom)
|
|
]);
|
|
end;
|
|
|
|
Brush.Color := TabColor;
|
|
Brush.Style := bsSolid;
|
|
|
|
{Draw Tab}
|
|
Pen.Color := TabColor;
|
|
Polygon([
|
|
Point(R.Left + 10, R.Bottom - 1),
|
|
Point(R.Left + 10, R.Top + 3),
|
|
Point(R.Left + 12, R.Top + 1),
|
|
Point(R.Right - 4, R.Top + 1),
|
|
Point(R.Right - 2, R.Top + 3),
|
|
Point(R.Right - 2, R.Bottom - 1)
|
|
]);
|
|
|
|
{highlight tab}
|
|
Pen.Color := clBtnHighlight;
|
|
PolyLine([
|
|
Point(R.Left, R.Bottom - 2),
|
|
Point(R.Left + 8, R.Bottom - 2),
|
|
Point(R.Left + 9, R.Bottom - 3),
|
|
Point(R.Left + 9, R.Top + 3),
|
|
Point(R.Left + 11, R.Top + 1),
|
|
Point(R.Right - 1, R.Top + 1)
|
|
]);
|
|
|
|
{draw border}
|
|
Pen.Color := clBlack;
|
|
PolyLine([
|
|
Point(R.Left, R.Bottom - 1),
|
|
Point(R.Left + 9, R.Bottom - 1),
|
|
Point(R.Left + 10, R.Bottom - 2),
|
|
Point(R.Left + 10, R.Top + 4),
|
|
Point(R.Left + 11, R.Top + 3),
|
|
Point(R.Left + 12, R.Top + 2),
|
|
Point(R.Right - 2, R.Top + 2),
|
|
Point(R.Right - 1, R.Top + 3),
|
|
Point(R.Right - 1, R.Bottom - 1)]);
|
|
|
|
{draw shadow}
|
|
end;
|
|
end;
|
|
|
|
Result := Rect(Client.Left + 1, Client.Top + 1, Client.Right - 2, Client.Bottom - 2);
|
|
if IsFocused then OffsetRect(Result, 1, 1);
|
|
end;
|
|
{$ENDIF}
|
|
|
|
{===== TVpFolderContainer ===========================================}
|
|
|
|
constructor TVpFolderContainer.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FNavBar := TVpCustomNavBar(AOwner);
|
|
Width := 0;
|
|
Height := 0;
|
|
Visible := false;
|
|
{Add self to container list}
|
|
FIndex := FNavBar.AddContainer(Self);
|
|
end;
|
|
{=====}
|
|
|
|
destructor TVpFolderContainer.Destroy;
|
|
begin
|
|
{FComponentList.Free;}
|
|
inherited;
|
|
end;
|
|
{=====}
|
|
|
|
function TVpFolderContainer.GetChildOwner: TComponent;
|
|
begin
|
|
Result := Owner.Owner;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpFolderContainer.GetChildren(Proc: TGetChildProc; Root: TComponent);
|
|
var
|
|
I: Integer;
|
|
C: TControl;
|
|
begin
|
|
Unused(Root);
|
|
|
|
inherited GetChildren(Proc, Self);
|
|
for I := 0 to ControlCount - 1 do begin
|
|
C := Controls[I];
|
|
C.Parent := Self;
|
|
Proc(C);
|
|
end;
|
|
end;
|
|
|
|
|
|
{===== TRenameEdit ===================================================}
|
|
|
|
constructor TVpRenameEdit.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
Visible := False;
|
|
WantReturns := False;
|
|
FolderIndex := -1;
|
|
ItemIndex := -1;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpRenameEdit.KeyPress(var Key: Char);
|
|
begin
|
|
if Key = #13 then begin
|
|
Key := #0;
|
|
DoExit;
|
|
end else
|
|
if Key = #27 then begin
|
|
FolderIndex := -1;
|
|
ItemIndex := -1;
|
|
Key := #0;
|
|
DoExit;
|
|
end;
|
|
inherited; // wp: was missing
|
|
end;
|
|
|
|
|
|
{===== Miscellaneous routines ========================================}
|
|
|
|
function RectWidth(Rect: TRect): Integer;
|
|
begin
|
|
Result := Rect.Right - Rect.Left;
|
|
end;
|
|
{=====}
|
|
|
|
function RectHeight(Rect: TRect): Integer;
|
|
begin
|
|
Result := Rect.Bottom - Rect.Top;
|
|
end;
|
|
|
|
|
|
{===== TVpNavBtnItem ===============================================}
|
|
|
|
constructor TVpNavBtnItem.Create(Collection: TCollection);
|
|
begin
|
|
inherited Create(Collection);
|
|
FFolder := TVpNavFolder((TVpCollection(Collection)).GetOwner);
|
|
FIconIndex := -1;
|
|
Name := Format('Item%d_%d', [FFolder.Index, Index]);
|
|
FFolder.FNavBar.Invalidate;
|
|
end;
|
|
{=====}
|
|
|
|
destructor TVpNavBtnItem.Destroy;
|
|
var
|
|
NaBar: TVpCustomNavBar;
|
|
FolderIndex: Integer;
|
|
begin
|
|
NaBar := FFolder.FNavBar;
|
|
FolderIndex := FFolder.Index;
|
|
inherited Destroy;
|
|
NaBar.FolderChanged(FolderIndex);
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpNavBtnItem.Assign(Source: TPersistent);
|
|
begin
|
|
if Source is TVpNavBtnItem then begin
|
|
Caption := TVpNavBtnItem(Source).Caption;
|
|
Description := TVpNavBtnItem(Source).Description;
|
|
IconIndex := TVpNavBtnItem(Source).IconIndex;
|
|
Tag := TVpNavBtnItem(Source).Tag;
|
|
end else
|
|
inherited Assign(Source);
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpNavBtnItem.SetCaption(const Value: string);
|
|
begin
|
|
if Value <> FCaption then begin
|
|
FCaption := Value;
|
|
Changed(false);
|
|
FFolder.FNavBar.ItemChanged(FFolder.Index, Index);
|
|
end;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpNavBtnItem.SetIconIndex(Value: Integer);
|
|
begin
|
|
if Value <> FIconIndex then begin
|
|
FIconIndex := Value;
|
|
Changed(false);
|
|
FFolder.FNavBar.ItemChanged(FFolder.Index, Index);
|
|
end;
|
|
end;
|
|
|
|
|
|
{===== TVpNavBtnFolder =============================================}
|
|
|
|
constructor TVpNavFolder.Create(Collection: TCollection);
|
|
begin
|
|
inherited Create(Collection);
|
|
// RegisterClass(TVpFolderContainer);
|
|
FNavBar := TVpCustomNavBar(TVpCollection(Collection).GetOwner);
|
|
FNavBar.ActiveFolder := Index;
|
|
FItems := TVpCollection.Create(Self, TVpNavBtnItem);
|
|
Name := 'NavFolder' + IntToStr(Index);
|
|
FEnabled := True;
|
|
FIconSize := isLarge;
|
|
end;
|
|
{=====}
|
|
|
|
destructor TVpNavFolder.Destroy;
|
|
begin
|
|
{Change the Active Folder to one that will still exist}
|
|
if not(csDestroying in FNavBar.ComponentState) then begin
|
|
if Index > 0 then
|
|
FNavBar.ActiveFolder := Index - 1
|
|
else if Collection.Count > 1 then
|
|
FNavBar.ActiveFolder := 0
|
|
else
|
|
FNavBar.ActiveFolder := -1;
|
|
FNavBar.FolderChanged(Index);
|
|
end;
|
|
|
|
FItems.Free;
|
|
FItems := nil;
|
|
inherited Destroy;
|
|
end;
|
|
{=====}
|
|
|
|
function TVpNavFolder.GetItem(Index: Integer): TVpNavBtnItem;
|
|
begin
|
|
Result := TVpNavBtnItem(FItems[Index]);
|
|
end;
|
|
{=====}
|
|
|
|
function TVpNavFolder.GetItemCount: Integer;
|
|
begin
|
|
Result := FItems.Count;
|
|
end;
|
|
{=====}
|
|
|
|
function TVpNavFolder.GetContainer: TVpFolderContainer;
|
|
begin
|
|
if FolderType = ftContainer then
|
|
result := FNavBar.FContainers[FContainerIndex]
|
|
else
|
|
result := nil;
|
|
end;
|
|
{=====}
|
|
|
|
function TVpNavFolder.ItemByName(AName: String): TVpNavBtnItem;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i:=0 to ItemCount-1 do begin
|
|
Result := Items[i];
|
|
if Result.Name = AName then
|
|
exit;
|
|
end;
|
|
Result := nil;
|
|
end;
|
|
|
|
procedure TVpNavFolder.lfGetEditorCaption(var Caption: string);
|
|
begin
|
|
Caption := RSEditingItems;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpNavFolder.lfItemChange(Sender: TObject);
|
|
begin
|
|
if (TVpCollection(Collection).GetOwner is TComponent) then
|
|
if not (csDestroying in
|
|
TComponent(TVpCollection(Collection).GetOwner).ComponentState)
|
|
then begin
|
|
TVpNavBar(TVpCollection(Collection).GetOwner).nabRecalcDisplayNames;
|
|
TVpNavBar(TVpCollection(Collection).GetOwner).Invalidate;
|
|
end;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpNavFolder.DefineProperties(Filer: TFiler);
|
|
begin
|
|
Filer.DefineProperty('ContainerIndex', ReadIndex, WriteIndex,
|
|
FFolderType = ftContainer);
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpNavFolder.ReadIndex(Reader: TReader);
|
|
begin
|
|
ContainerIndex := trunc(Reader.ReadFloat);
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpNavFolder.WriteIndex(Writer: TWriter);
|
|
begin
|
|
Writer.WriteFloat(ContainerIndex);
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpNavFolder.SetCaption(const Value: string);
|
|
begin
|
|
if FCaption <> Value then begin
|
|
FCaption := Value;
|
|
Changed(false);
|
|
FNavBar.FolderChanged(Index);
|
|
end;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpNavFolder.SetEnabled(Value: Boolean);
|
|
begin
|
|
if Value <> FEnabled then begin
|
|
FEnabled := Value;
|
|
Changed(false);
|
|
FNavBar.FolderChanged(Index);
|
|
end;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpNavFolder.SetFolderType(Value: TVpFolderType);
|
|
begin
|
|
if Value <> FFolderType then begin
|
|
FFolderType := Value;
|
|
|
|
if not (csLoading in FNavBar.ComponentState) then begin
|
|
if FFolderType = ftContainer then
|
|
ContainerIndex := CreateContainer
|
|
else begin
|
|
FNavBar.FContainers.Delete(FContainerIndex);
|
|
FContainerIndex := -1;
|
|
end;
|
|
FNavBar.FolderChanged(Index);
|
|
end;
|
|
end;
|
|
end;
|
|
{=====}
|
|
|
|
function TVpNavFolder.CreateContainer: Integer;
|
|
var
|
|
New: TVpFolderContainer;
|
|
begin
|
|
New := TVpFolderContainer.Create(FNavBar);
|
|
New.Parent := FNavBar;
|
|
result := New.Index;
|
|
New.Name := 'Container' + IntToStr(Result);
|
|
New.Caption := '';
|
|
New.BevelOuter := bvNone;
|
|
New.BevelInner := bvNone;
|
|
New.Color := FNavBar.FBackgroundColor;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpNavFolder.SetIconSize(Value: TVpIconSize);
|
|
begin
|
|
if FIconSize <> Value then begin
|
|
FIconSize := Value;
|
|
Changed(false);
|
|
FNavBar.FolderChanged(Index);
|
|
end;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpNavFolder.SetItem(Index: Integer; Value: TVpNavBtnItem);
|
|
begin
|
|
SetItem(Index, Value);
|
|
end;
|
|
|
|
|
|
{===== TVpNavBar ================================================}
|
|
|
|
constructor TVpCustomNavBar.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
BorderStyle := bsNone;
|
|
|
|
FContainers := TVpContainerList.Create(Self);
|
|
|
|
FLoadingFolder := -1;
|
|
FShowButtons := True;
|
|
|
|
if Classes.GetClass(TVpNavFolder.ClassName) = nil then
|
|
Classes.RegisterClass(TVpNavFolder);
|
|
if Classes.GetClass(TVpNavBtnItem.ClassName) = nil then
|
|
Classes.RegisterClass(TVpNavBtnItem);
|
|
|
|
FFolders := TVpCollection.Create(Self, TVpNavFolder);
|
|
FFolders.OnChanged := nabFolderChange;
|
|
FFolders.OnGetEditorCaption := nabGetEditorCaption;
|
|
FFolders.OnItemSelected := nabFolderSelected;
|
|
|
|
FItemFont := TFont.Create;
|
|
FItemFont.Name := Font.Name;
|
|
FItemFont.OnChange := nabFontChanged;
|
|
FItemFont.Color := clWindowText;
|
|
|
|
FItemSpacing := DEFAULT_ITEMSPACING;
|
|
{$IF VP_LCL_SCALING = 0}
|
|
FItemSpacing := ScaleY(FItemSpacing, DesignTimeDPI);
|
|
{$ENDIF}
|
|
|
|
FSelectedItemFont := TFont.Create;
|
|
FSelectedItemFont.Name := Font.Name;
|
|
FSelectedItemFont.OnChange := nabFontChanged;
|
|
FSelectedItemFont.Color := FItemFont.Color;
|
|
FSelectedItemFont.Style := FItemFont.Style;
|
|
FSelectedItemFont.Size := FItemFont.Size;
|
|
|
|
{force drivers to load by playing empty wave data}
|
|
{ HSnd := FindResource(HInstance, 'VPEMPTYWAVE', RT_RCDATA);
|
|
if HSnd > 0 then begin
|
|
HSnd := LoadResource(HInstance, HSnd);
|
|
if HSnd > 0 then begin
|
|
sndPlaySound(LockResource(HSnd), SND_ASYNC or SND_MEMORY);
|
|
FreeResource(HSnd);
|
|
end;
|
|
end;}
|
|
|
|
nabScrollUpBtn := TSpeedButton.Create(Self);
|
|
with nabScrollUpBtn do begin
|
|
Visible := False;
|
|
Parent := Self;
|
|
OnClick := nabScrollUpBtnClick;
|
|
{$IFDEF NEW_ICONS}
|
|
LoadGlyphFromRCDATA(Glyph, 'VPUPARROW', -1, 150, 200);
|
|
{$ELSE}
|
|
Glyph.LoadFromResourceName(HINSTANCE, 'VPUPARROW');
|
|
{$ENDIF}
|
|
NumGlyphs := 1;
|
|
Left := -20;
|
|
Height := ScaleY(15, DesignTimeDPI);
|
|
Width := ScaleX(17, DesignTimeDPI);
|
|
end;
|
|
|
|
nabScrollDownBtn := TSpeedButton.Create(Self);
|
|
with nabScrollDownBtn do begin
|
|
Visible := False;
|
|
Parent := Self;
|
|
OnClick := nabScrollDownBtnClick;
|
|
{$IFDEF NEW_ICONS}
|
|
LoadGlyphFromRCDATA(Glyph, 'VPDOWNARROW', -1, 150, 200);
|
|
{$ELSE}
|
|
Glyph.LoadFromResourceName(HINSTANCE, 'VPDOWNARROW');
|
|
{$ENDIF}
|
|
NumGlyphs := 1;
|
|
Left := -20;
|
|
Height := ScaleY(15, DesignTimeDPI);
|
|
Width := ScaleX(17, DesignTimeDPI);
|
|
end;
|
|
|
|
{create edit control}
|
|
if not (csDesigning in ComponentState) then begin
|
|
nabEdit := TVpRenameEdit.Create(Self);
|
|
nabEdit.Parent := Self;
|
|
nabEdit.OnExit := nabCommitEdit;
|
|
end;
|
|
|
|
Height := ScaleY(240, DesignTimeDPI);
|
|
Width := ScaleY(120, DesignTimeDPI);
|
|
ParentColor := False;
|
|
|
|
FAllowRearrange := True;
|
|
FBackgroundColor := clWindow;
|
|
FBackgroundImage := TBitmap.Create;
|
|
FBackgroundMethod := bmNormal;
|
|
// FBorderStyle := bsSingle;
|
|
FButtonHeight := 0;
|
|
FActiveFolder := -1;
|
|
FActiveItem := -1;
|
|
FSelectedItem := -1;
|
|
FHotFolder := -1;
|
|
FPreviousFolder := -1;
|
|
FPreviousItem := -1;
|
|
FPlaySounds := False;
|
|
FScrollDelta := 2;
|
|
FSoundAlias := 'MenuCommand';
|
|
|
|
nabMouseDown := False;
|
|
nabChanging := False;
|
|
nabTopItem := 0;
|
|
nabDragFromItem := -1;
|
|
nabDragFromFolder := -1;
|
|
nabDropY := -1;
|
|
nabTimer := -1;
|
|
nabLastMouseOverItem := -1;
|
|
end;
|
|
{=====}
|
|
|
|
destructor TVpCustomNavBar.Destroy;
|
|
begin
|
|
{$IFDEF DELPHI} // not sure if this is correct. In Lazarus, at least, next line causes an error in Linux.
|
|
Images := nil; {unregister any image list notification}
|
|
{$ENDIF}
|
|
|
|
nabChanging := True;
|
|
|
|
nabEdit.Free;
|
|
|
|
FContainers.Free;
|
|
|
|
FFolders.Free;
|
|
FFolders := nil;
|
|
|
|
FItemFont.Free;
|
|
FItemFont := nil;
|
|
|
|
FSelectedItemFont.Free;
|
|
FSelectedItemFont := nil;
|
|
|
|
FBackgroundImage.Free;
|
|
FBackgroundImage := nil;
|
|
|
|
inherited Destroy;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.BeginUpdate;
|
|
begin
|
|
nabChanging := True;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.ItemChanged(FolderIndex, ItemIndex: Integer);
|
|
begin
|
|
InvalidateItem(FolderIndex, ItemIndex);
|
|
if not (csDestroying in ComponentState) then
|
|
RecreateWnd{$IFDEF LCL}(self){$ENDIF};
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.FolderChanged(FolderIndex: Integer);
|
|
begin
|
|
Unused(FolderIndex);
|
|
Invalidate;
|
|
if not (csDestroying in ComponentState) then
|
|
RecreateWnd{$IFDEF LCL}(self){$ENDIF};
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.CMDesignHitTest(var Msg: TCMDesignHitTest);
|
|
begin
|
|
Msg.Result := LongInt(nabOverButton);
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.CMFontChanged(var Msg: {$IFDEF LCL}TLMessage{$ELSE}TMessage{$ENDIF});
|
|
begin
|
|
Unused(Msg);
|
|
nabRecalcDisplayNames;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.CMParentColorChanged(var Msg: {$IFDEF LCL}TLMessage{$ELSE}TMessage{$ENDIF});
|
|
begin
|
|
inherited;
|
|
if ParentColor then
|
|
SetBackgroundColor(Color);
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.CreateParams(var Params: TCreateParams);
|
|
begin
|
|
inherited CreateParams(Params);
|
|
with Params do
|
|
Style := LongInt(Style) or BorderStyles[BorderStyle];
|
|
if NewStyleControls {and Ctl3D }and (BorderStyle = bsSingle) then begin
|
|
Params.Style := Params.Style and not WS_BORDER;
|
|
Params.ExStyle := Params.ExStyle or WS_EX_CLIENTEDGE;
|
|
end;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.CreateWnd;
|
|
begin
|
|
if (csDestroying in ComponentState) then exit;
|
|
inherited CreateWnd;
|
|
nabRecalcDisplayNames;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.Loaded;
|
|
begin
|
|
inherited Loaded;
|
|
{
|
|
if DrawingStyle = dsEtchedButton then
|
|
BorderStyle := bsNone;
|
|
}
|
|
if FolderCollection.Count > 0 then
|
|
FActiveFolder := 0
|
|
else
|
|
FActiveFolder := -1;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.GetChildren(Proc: TGetChildProc; Root: TComponent);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Unused(Root);
|
|
for I := 0 to FContainers.Count - 1 do
|
|
Proc(TComponent(FContainers[I]));
|
|
end;
|
|
{=====}
|
|
|
|
function TVpCustomNavBar.AddContainer(Container: TVpFolderContainer): Integer;
|
|
begin
|
|
result := FContainers.Add(Container);
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.RemoveContainer(Container: TVpFolderContainer);
|
|
begin
|
|
FContainers.Remove(Container);
|
|
Container.Free;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.DoArrange;
|
|
begin
|
|
if Assigned(FOnArrange) then
|
|
FOnArrange(Self);
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.DoFolderChange(Index: Integer; var AllowChange: Boolean);
|
|
begin
|
|
if Assigned(FOnFolderChange) then
|
|
FOnFolderChange(Self, Index, AllowChange, nabDragFromItem <> -1);
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.DoFolderChanged(Index: Integer);
|
|
begin
|
|
if Assigned(FOnFolderChanged) then
|
|
FOnFolderChanged(Self, Index);
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.DoFolderClick(Button: TMouseButton; Shift: TShiftState;
|
|
Index: Integer);
|
|
begin
|
|
if Assigned(FOnFolderClick) then
|
|
FOnFolderClick(Self, Button, Shift, Index);
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.DoItemClick(Button: TMouseButton; Shift: TShiftState;
|
|
Index: Integer);
|
|
begin
|
|
if Assigned(FOnItemClick) then
|
|
FOnItemClick(Self, Button, Shift, Index);
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.DoMouseOverItem(X, Y, ItemIndex: Integer);
|
|
begin
|
|
Unused(ItemIndex);
|
|
if Assigned(FOnMouseOverItem) then
|
|
FOnMouseOverItem(Self, Folders[ActiveFolder].Items[GetItemAt(X, Y)]);
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.EndUpdate;
|
|
begin
|
|
nabChanging := False;
|
|
nabRecalcDisplayNames;
|
|
end;
|
|
{=====}
|
|
|
|
function TVpCustomNavBar.GetFolderCount: Integer;
|
|
begin
|
|
Result := FFolders.Count;
|
|
end;
|
|
{=====}
|
|
|
|
function TVpCustomNavBar.GetFolder(Index: Integer): TVpNavFolder;
|
|
begin
|
|
Result := TVpNavFolder(FFolders.GetItem(Index));
|
|
end;
|
|
{=====}
|
|
|
|
function TVpCustomNavBar.GetFolderAt(X, Y: Integer): Integer;
|
|
var
|
|
Dummy: Integer;
|
|
begin
|
|
nabGetHitTest(X, Y, Result, Dummy);
|
|
end;
|
|
{=====}
|
|
|
|
function TVpCustomNavBar.GetContainer(Index: Integer): TVpFolderContainer;
|
|
begin
|
|
try
|
|
result := FContainers[Index];
|
|
except
|
|
result := nil;
|
|
end;
|
|
end;
|
|
{=====}
|
|
|
|
function TVpCustomNavBar.GetItemAt(X, Y: Integer): Integer;
|
|
var
|
|
Dummy: Integer;
|
|
begin
|
|
nabGetHitTest(X, Y, Dummy, Result);
|
|
end;
|
|
{=====}
|
|
|
|
function TVpCustomNavBar.GetRealButtonHeight: Integer;
|
|
begin
|
|
if FButtonHeight = 0 then begin
|
|
if Font.IsDefault then
|
|
Canvas.Font.Assign(Screen.SystemFont)
|
|
else
|
|
Canvas.Font.Assign(Font);
|
|
Result := Canvas.TextHeight('Tg') + ScaleY(4, DesignTimeDPI) + 1;
|
|
end else
|
|
Result := ScaleY(FButtonHeight, DesignTimeDPI);
|
|
end;
|
|
|
|
function TVpCustomNavBar.IsStoredItemSpacing: Boolean;
|
|
begin
|
|
Result := FItemSpacing <> DEFAULT_ITEMSPACING;
|
|
end;
|
|
|
|
function TVpCustomNavBar.Container: TVpFolderContainer;
|
|
begin
|
|
if Folders[FActiveFolder].FolderType = ftContainer then
|
|
Result := FContainers[Folders[FActiveFolder].ContainerIndex]
|
|
else
|
|
Result := nil;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.InsertFolder(const ACaption: string; AFolderIndex: Integer);
|
|
{$IFNDEF VERSION4}
|
|
var
|
|
I: Integer;
|
|
{$ENDIF}
|
|
begin
|
|
{$IFNDEF VERSION4}
|
|
FFolders.Add;
|
|
for I := AFolderIndex to FFolders.Count - 2 do begin
|
|
Folders[I].Index := I + 1;
|
|
end;
|
|
Folders[FFolders.Count - 1].Index := AFolderIndex;
|
|
{$ELSE}
|
|
FFolders.Insert(AFolderIndex);
|
|
{$ENDIF}
|
|
Folders[AFolderIndex].Caption := ACaption;
|
|
if FolderCount = 1 then begin
|
|
FActiveFolder := 0;
|
|
FActiveItem := -1;
|
|
FSelectedItem := -1;
|
|
end;
|
|
nabRecalcDisplayNames;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.AddFolder(const ACaption: string);
|
|
var
|
|
NewFolder: TVpNavFolder;
|
|
begin
|
|
NewFolder := TVpNavFolder(FFolders.Add);
|
|
NewFolder.Caption := ACaption;
|
|
if FolderCount = 1 then begin
|
|
FActiveFolder := 0;
|
|
FActiveItem := -1;
|
|
FSelectedItem := -1;
|
|
end;
|
|
nabRecalcDisplayNames;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.RemoveFolder(AFolderIndex: Integer);
|
|
var
|
|
Folder: TVpNavFolder;
|
|
begin
|
|
Folder := TVpNavFolder(FolderCollection.Items[AFolderIndex]);
|
|
Folder.Free;
|
|
{$IFDEF VERSION5}
|
|
FolderCollection.Delete(AFolderIndex);
|
|
{$ENDIF}
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.RenameFolder(AFolderIndex: Integer);
|
|
var
|
|
Folder: TVpNavFolder;
|
|
begin
|
|
Folder := Folders[AFolderIndex];
|
|
nabEdit.FolderIndex := AFolderIndex;
|
|
nabEdit.ItemIndex := -1;
|
|
nabEdit.Font.Size := Font.Size;
|
|
nabEdit.BorderStyle := bsNone;
|
|
nabEdit.Top := Folder.lfRect.Top+2;
|
|
nabEdit.Left := Folder.lfRect.Left+2;
|
|
nabEdit.Height := HeightOf(Folder.lfRect)-5;
|
|
nabEdit.Width := Folder.lfRect.Right - Folder.lfRect.Left-5;
|
|
nabEdit.Visible := True;
|
|
nabEdit.Text := Folder.Caption;
|
|
nabEdit.SelectAll;
|
|
nabEdit.SetFocus;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.InsertItem(const ACaption: string;
|
|
AFolderIndex, AItemIndex, AIconIndex: Integer);
|
|
var
|
|
AFolder: TVpNavFolder;
|
|
{$IFNDEF VERSION4}
|
|
I: Integer;
|
|
{$ENDIF}
|
|
begin
|
|
AFolder := Folders[AFolderIndex];
|
|
{$IFNDEF VERSION4}
|
|
AFolder.FItems.Add;
|
|
for I := AFolderIndex to AFolder.FItems.Count - 2 do
|
|
AFolder.Items[I].Index := I + 1;
|
|
AFolder.Items[AFolder.FItems.Count-1].Index := AFolderIndex;
|
|
{$ELSE}
|
|
AFolder.FItems.Insert(AItemIndex);
|
|
{$ENDIF}
|
|
AFolder.Items[AItemIndex].Caption := ACaption;
|
|
AFolder.Items[AItemIndex].IconIndex := AIconIndex;
|
|
Invalidate;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.AddItem(const ACaption: string;
|
|
AFolderIndex, AIconIndex: Integer);
|
|
var
|
|
AFolder : TVpNavFolder;
|
|
AItem: TVpNavBtnItem;
|
|
begin
|
|
AFolder := Folders[AFolderIndex];
|
|
AItem := TVpNavBtnItem(AFolder.FItems.Add);
|
|
AItem.Caption := ACaption;
|
|
AItem.IconIndex := AIconIndex;
|
|
Invalidate;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.RemoveItem(AFolderIndex, AItemIndex: Integer);
|
|
var
|
|
Folder: TVpNavFolder;
|
|
begin
|
|
Folder := TVpNavFolder(FolderCollection.GetItem(AFolderIndex));
|
|
Folder.Items[AItemIndex].Free;
|
|
{$IFDEF VERSION5}
|
|
FolderCollection.Delete(AItemIndex);
|
|
{$ENDIF}
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.InvalidateItem(FolderIndex, ItemIndex: Integer);
|
|
var
|
|
F: TRect;
|
|
R: TRect;
|
|
begin
|
|
R := TVpNavBtnItem(Folders[FolderIndex].Items[ItemIndex]).FIconRect;
|
|
{expand rect}
|
|
Dec(R.Top);
|
|
Dec(R.Left);
|
|
Inc(R.Bottom, 2);
|
|
Inc(R.Right, 2);
|
|
{ Might be a hidden folder. }
|
|
if (not ((FolderCount = 1) and (Folders[0].Caption = ''))) or (csDesigning in ComponentState)
|
|
then
|
|
F := nabGetFolderArea(FolderIndex)
|
|
else
|
|
F := R;
|
|
R.Top := Max(R.Top, F.Top);
|
|
R.Bottom := Min(R.Bottom, F.Bottom);
|
|
if RectHeight(R) > 0 then
|
|
InvalidateRect(Handle, @R, False);
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.RenameItem(AFolderIndex, AItemIndex: Integer);
|
|
var
|
|
Item: TVpNavBtnItem;
|
|
begin
|
|
Item := Folders[AFolderIndex].Items[AItemIndex];
|
|
nabEdit.FolderIndex := AFolderIndex;
|
|
nabEdit.ItemIndex := AItemIndex;
|
|
nabEdit.Font.Size := ItemFont.Size;
|
|
nabEdit.BorderStyle := bsNone;
|
|
nabEdit.Top := Item.LabelRect.Top-1;
|
|
nabEdit.Left := 10;
|
|
nabEdit.Height := HeightOf(Item.LabelRect) + 2;
|
|
nabEdit.Width := Width - 24;
|
|
nabEdit.Visible := True;
|
|
nabEdit.Text := Item.Caption;
|
|
nabEdit.SelectAll;
|
|
nabEdit.SetFocus;
|
|
end;
|
|
{=====}
|
|
|
|
function TVpCustomNavBar.nabButtonRect(Index: Integer): TRect;
|
|
begin
|
|
Result := Folders[Index].lfRect;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.nabCommitEdit(Sender: TObject);
|
|
var
|
|
Folder: TVpNavFolder;
|
|
Item: TVpNavBtnItem;
|
|
begin
|
|
if not Assigned(nabEdit) then
|
|
Exit;
|
|
|
|
if (nabEdit.FolderIndex > -1) then begin
|
|
if nabEdit.ItemIndex = -1 then begin
|
|
{rename the folder}
|
|
Folder := Folders[nabEdit.FolderIndex];
|
|
Folder.Caption := nabEdit.Text;
|
|
end else begin
|
|
Item := Folders[nabEdit.FolderIndex].Items[nabEdit.ItemIndex];
|
|
Item.Caption := nabEdit.Text;
|
|
end;
|
|
end;
|
|
nabEdit.FolderIndex := -1;
|
|
nabEdit.ItemIndex := -1;
|
|
nabEdit.Visible := False;
|
|
Update;
|
|
end;
|
|
{=====}
|
|
|
|
function TVpCustomNavBar.nabDropHitTest(X, Y: Integer): Boolean;
|
|
{given an X, Y, is this a legal spot to drop a folder?}
|
|
var
|
|
I: Integer;
|
|
SpaceTop: Integer;
|
|
SpaceBottom: Integer;
|
|
OldDrop: Integer;
|
|
Folder: TVpNavFolder;
|
|
begin
|
|
Result := False;
|
|
{assume that X,Y aren't on a folder or item}
|
|
OldDrop := nabDropY;
|
|
try
|
|
nabDragToFolder := -1;
|
|
nabDragToItem := -1;
|
|
if FolderCount = 0 then
|
|
Exit;
|
|
|
|
Folder := Folders[FActiveFolder];
|
|
if Y <= Folder.lfRect.Bottom then
|
|
Exit;
|
|
|
|
if FolderCount > FActiveFolder+1 then
|
|
if Y >= Folders[FActiveFolder+1].lfRect.Top then
|
|
Exit;
|
|
|
|
if (X < 0) or (X > ClientWidth) then
|
|
Exit;
|
|
|
|
{we're somewhere in the active folder}
|
|
if Folder.ItemCount = 0 then begin
|
|
{the active folder is empty}
|
|
nabDropY := Folders[FActiveFolder].lfRect.Bottom + 3;
|
|
nabDragToFolder := FActiveFolder;
|
|
nabDragToItem := 0;
|
|
Result := True;
|
|
Exit;
|
|
end;
|
|
|
|
for I := nabTopItem to Folder.ItemCount-1 do begin
|
|
{is there space above this item?}
|
|
if I = nabTopItem then
|
|
SpaceTop := Folder.lfRect.Bottom+1
|
|
else
|
|
SpaceTop := TVpNavBtnItem(Folder.Items[I - 1]).FLabelRect.Bottom + 1;
|
|
SpaceBottom := TVpNavBtnItem(Folder.Items[I]).FIconRect.Top - 1;
|
|
if (Y >= SpaceTop) and (Y <= SpaceBottom) then begin
|
|
if SpaceTop - SpaceBottom < 6 then
|
|
nabDropY := SpaceTop + (SpaceBottom - SpaceTop) div 2
|
|
else
|
|
nabDropY := SpaceTop + 3;
|
|
Result := True;
|
|
nabDragToFolder := FActiveFolder;
|
|
nabDragToItem := I;
|
|
nabExternalDragItem := I;
|
|
Exit;
|
|
end;
|
|
end;
|
|
|
|
{check below the last item...}
|
|
SpaceTop := TVpNavBtnItem(Folder.Items[Folder.ItemCount - 1]).FLabelRect.Bottom+1;
|
|
SpaceBottom := nabItemsRect.Bottom - 1;
|
|
if (Y >= SpaceTop) and (Y <= SpaceBottom) then begin
|
|
nabDropY := SpaceTop + 3;
|
|
nabDragToFolder := FActiveFolder;
|
|
nabDragToItem := Folder.ItemCount;
|
|
if nabFolderAccept then
|
|
nabExternalDragItem := nabDragToItem
|
|
else
|
|
nabExternalDragItem := Folder.ItemCount - 1;
|
|
Result := True;
|
|
end;
|
|
|
|
finally
|
|
if (nabDropY <> OldDrop) then
|
|
Repaint;
|
|
end;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.nabFolderChange(Sender: TObject);
|
|
var
|
|
ParentForm: TCustomForm;
|
|
begin
|
|
if not (csDestroying in ComponentState) then begin
|
|
if FolderCount = 0 then
|
|
FActiveFolder := -1
|
|
else begin
|
|
if Folders[FActiveFolder].FolderType = ftContainer then begin
|
|
ParentForm := GetParentForm(Self);
|
|
if ParentForm <> nil then
|
|
if ContainsControl(ParentForm.ActiveControl) then
|
|
ParentForm.ActiveControl := Self;
|
|
end;
|
|
if FActiveFolder = -1 then
|
|
FActiveFolder := 0;
|
|
if FActiveFolder >= FolderCount then
|
|
FActiveFolder := 0;
|
|
end;
|
|
nabTopItem := 0;
|
|
nabRecalcDisplayNames;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.nabFolderSelected(Sender: TObject; Index: Integer);
|
|
begin
|
|
if not (csDestroying in ComponentState) then
|
|
ActiveFolder := Index;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.nabFontChanged(Sender: TObject);
|
|
begin
|
|
Perform(CM_FONTCHANGED, 0, 0);
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.nabGetEditorCaption(var Caption: string);
|
|
begin
|
|
Caption := RSEditingFolders;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.nabGetHitTest(X, Y: Integer;
|
|
out FolderIndex, ItemIndex: Integer);
|
|
var
|
|
I: Integer;
|
|
Item: TVpNavBtnItem;
|
|
Folder: TVpNavFolder;
|
|
begin
|
|
FolderIndex := -1;
|
|
ItemIndex := -1;
|
|
|
|
if FolderCount > 0 then begin
|
|
{see if we've hit a folder}
|
|
for I := 0 to FolderCount-1 do begin
|
|
Folder := Folders[I];
|
|
if PtInRect(Folder.lfRect, Point(X, Y)) then begin
|
|
nabCursorOverItem := False;
|
|
FolderIndex := I;
|
|
Exit;
|
|
end;
|
|
end;
|
|
|
|
{nope, check the active folder to see if we've hit an item}
|
|
Folder := Folders[FActiveFolder];
|
|
for I := nabTopItem to Folder.ItemCount-1 do begin
|
|
Item := Folder.Items[I];
|
|
if PtInRect(Item.FIconRect, Point(X,Y)) or
|
|
(PtInRect(Item.FLabelRect, Point(X,Y)) and (Item.Caption <> ''))
|
|
then begin
|
|
if nabExternalDrag then begin
|
|
nabCursorOverItem := True;
|
|
nabExternalDragItem := I;
|
|
end;
|
|
ItemIndex := I;
|
|
Exit;
|
|
end else
|
|
if nabExternalDrag then
|
|
nabCursorOverItem := False;
|
|
end;
|
|
end;
|
|
end;
|
|
{=====}
|
|
|
|
function TVpCustomNavBar.nabGetFolderArea(Index: Integer): TRect;
|
|
var
|
|
I : Integer;
|
|
btnHeight: Integer;
|
|
begin
|
|
Unused(Index);
|
|
|
|
Result := ClientRect;
|
|
btnHeight := GetRealButtonHeight;
|
|
for I := 0 to ActiveFolder do
|
|
Inc(Result.Top, btnHeight);
|
|
for I := FolderCount-1 downto ActiveFolder+1 do
|
|
Dec(Result.Bottom, btnHeight);
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.nabImagesChanged(Sender: TObject);
|
|
begin
|
|
Invalidate;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.nabRecalcDisplayNames;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if not HandleAllocated then
|
|
exit;
|
|
Canvas.Font := Self.Font;
|
|
{figure out display names for each folder...}
|
|
for I := 0 to FolderCount-1 do
|
|
Folders[I].lfDisplayName := GetDisplayString(Canvas, Folders[I].Caption, 1,
|
|
ClientWidth);
|
|
Invalidate;
|
|
end;
|
|
{=====}
|
|
|
|
function TVpCustomNavBar.nabShowScrollDown: Boolean;
|
|
var
|
|
Folder: TVpNavFolder;
|
|
Item: TVpNavBtnItem;
|
|
begin
|
|
Result := False;
|
|
if (FolderCount > 0) then begin
|
|
Folder := Folders[FActiveFolder];
|
|
if Folder.ItemCount > 0 then begin
|
|
Item := Folder.Items[Folder.ItemCount-1];
|
|
Result := Item.FLabelRect.Bottom > nabItemsRect.Bottom;
|
|
end;
|
|
end;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.nabScrollDownBtnClick(Sender: TObject);
|
|
begin
|
|
if nabShowScrollDown then begin
|
|
Inc(nabTopItem);
|
|
InvalidateRect(Handle, @nabItemsRect, False);
|
|
end;
|
|
end;
|
|
{=====}
|
|
|
|
function TVpCustomNavBar.nabShowScrollUp: Boolean;
|
|
begin
|
|
Result := nabTopItem > 0;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.nabScrollUpBtnClick(Sender: TObject);
|
|
begin
|
|
if nabTopItem > 0 then begin
|
|
Dec(nabTopItem);
|
|
InvalidateRect(Handle, @nabItemsRect, False);
|
|
end;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.nabTimerEvent(Sender: TObject; Handle: Integer;
|
|
Interval: Cardinal; ElapsedTime: LongInt);
|
|
var
|
|
Pt: TPoint = (x:0; y:0);
|
|
Form: TCustomForm;
|
|
begin
|
|
Unused(Handle, Interval, ElapsedTime);
|
|
|
|
GetCursorPos(Pt);
|
|
Pt := ScreenToClient(Pt);
|
|
if not PtInRect(ClientRect, Pt) then begin
|
|
if not nabMouseDown then begin
|
|
{we're not doing internal dragging anymore}
|
|
nabMouseDown := False;
|
|
nabDragFromFolder := -1;
|
|
nabDragFromItem := -1;
|
|
if nabDropY <> -1 then begin
|
|
nabDropY := -1;
|
|
Repaint;
|
|
end;
|
|
if FActiveItem <> -1 then begin
|
|
InvalidateItem(FActiveFolder, FActiveItem);
|
|
FActiveItem := -1;
|
|
end;
|
|
end else if FAllowRearrange then begin
|
|
Form := GetParentForm(Self);
|
|
if (Form <> nil) then
|
|
if Form.Active then begin
|
|
SetCursor(Screen.Cursors[crNoDrop]);
|
|
nabDropY := -1;
|
|
Repaint;
|
|
end;
|
|
end;
|
|
end else begin
|
|
if nabDragFromItem <> -1 then begin
|
|
{we're still doing internal dragging - update the cursor}
|
|
if nabDropHitTest(Pt.X, Pt.Y) then
|
|
SetCursor(Screen.Cursors[DragCursor])
|
|
else begin
|
|
SetCursor(Screen.Cursors[crNoDrop]);
|
|
nabDropY := -1;
|
|
Repaint;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.DblClick;
|
|
var
|
|
folder: TVpNavFolder;
|
|
begin
|
|
inherited;
|
|
|
|
if FAllowInplaceEdit and (FActiveFolder <> -1) then
|
|
begin
|
|
folder := Folders[FActiveFolder];
|
|
if PtInRect(folder.Rect, FMouseDownPt) then
|
|
RenameFolder(FActiveFolder)
|
|
else
|
|
if (FSelectedItem <> -1) then
|
|
begin
|
|
if PtInRect(folder.Items[FSelectedItem].LabelRect, FMouseDownPt) then
|
|
RenameItem(FActiveFolder, FSelectedItem);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TVpCustomNavBar.MouseDown(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer);
|
|
begin
|
|
FMouseDownPt := Point(X,Y);
|
|
|
|
{complete any editing}
|
|
nabCommitEdit(nil);
|
|
|
|
{get folder/item clicked}
|
|
nabGetHitTest(X, Y, FPreviousFolder, FPreviousItem);
|
|
|
|
{was it a click on a folder button?}
|
|
if FPreviousFolder <> -1 then begin
|
|
if Folders[FPreviousFolder].Enabled or (csDesigning in ComponentState) then
|
|
begin
|
|
if (Button = mbLeft) then begin
|
|
nabMouseDown := True;
|
|
Invalidate;
|
|
end;
|
|
Exit;
|
|
end;
|
|
end;
|
|
|
|
if FPreviousItem <> -1 then begin
|
|
if Folders[FActiveFolder].Enabled or (csDesigning in ComponentState) then
|
|
begin
|
|
if (Button = mbLeft) then begin
|
|
InvalidateItem(FActiveFolder, FPreviousItem);
|
|
nabMouseDown := True;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
inherited MouseDown(Button, Shift, X, Y);
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.MouseLeave;
|
|
begin
|
|
FHotFolder := -1;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TVpCustomNavBar.MouseMove(Shift: TShiftState; X, Y: Integer);
|
|
var
|
|
ItemIndex: Integer;
|
|
FolderIndex: Integer;
|
|
begin
|
|
nabGetHitTest(X, Y, FolderIndex, ItemIndex);
|
|
|
|
{if FActiveItem is valid, and mouse is down, we're starting dragging}
|
|
if nabMouseDown or nabExternalDrag then begin
|
|
if nabScrollDownBtn.Visible then begin
|
|
if Y > nabScrollDownBtn.Top then begin
|
|
Inc(nabTopItem);
|
|
InvalidateRect(Handle, @nabItemsRect, False);
|
|
inherited MouseMove(Shift, X, Y);
|
|
Exit;
|
|
end;
|
|
end;
|
|
if nabScrollUpBtn.Visible then begin
|
|
if Y < (nabScrollUpBtn.Top + nabScrollUpBtn.Height) then
|
|
begin
|
|
Dec(nabTopItem);
|
|
InvalidateRect(Handle, @nabItemsRect, False);
|
|
inherited MouseMove(Shift, X, Y);
|
|
Exit;
|
|
end;
|
|
end;
|
|
if (FActiveItem <> -1) and (ItemIndex = -1) and FAllowRearrange then
|
|
begin
|
|
nabDragFromFolder := FActiveFolder;
|
|
nabDragFromItem := FActiveItem;
|
|
if (FolderIndex = -1) then begin
|
|
if nabDropHitTest(X, Y) then
|
|
SetCursor(Screen.Cursors[DragCursor])
|
|
else begin
|
|
SetCursor(Screen.Cursors[crNoDrop]);
|
|
nabDropY := -1;
|
|
Repaint;
|
|
end;
|
|
end;
|
|
end;
|
|
if (FolderIndex <> -1) and FAllowRearrange then
|
|
begin
|
|
ActiveFolder := FolderIndex;
|
|
nabDropY := -1;
|
|
FActiveItem := -1;
|
|
Repaint;
|
|
end;
|
|
end else
|
|
begin
|
|
if ItemIndex <> -1 then begin
|
|
if (ItemIndex <> FActiveItem) then begin
|
|
if FActiveItem <> -1 then
|
|
{invalidate the old activeItem}
|
|
InvalidateItem(FActiveFolder, FActiveItem);
|
|
FActiveItem := ItemIndex;
|
|
if FActiveItem <> -1 then begin
|
|
{invalidate the new active item}
|
|
InvalidateItem(FActiveFolder, FActiveItem);
|
|
end;
|
|
end;
|
|
end else if FActiveItem <> -1 then begin
|
|
InvalidateItem(FActiveFolder, FActiveItem);
|
|
FActiveItem := -1;
|
|
end;
|
|
if FolderIndex <> -1 then begin
|
|
if (FolderIndex <> FHotFolder) then begin
|
|
if FHotFolder <> -1 then
|
|
{invalidate the old activeItem}
|
|
Invalidate;
|
|
FHotFolder := FolderIndex;
|
|
if FHotFolder <> -1 then begin
|
|
{invalidate the new active item}
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
end else if FHotFolder <> -1 then begin
|
|
Invalidate;
|
|
FHotFolder := -1;
|
|
end;
|
|
end;
|
|
|
|
if ItemIndex <> - 1 then begin
|
|
if nabLastMouseOverItem <> ItemIndex then
|
|
DoMouseOverItem(X, Y, ItemIndex);
|
|
nabLastMouseOverItem := ItemIndex;
|
|
end else
|
|
nabLastMouseOverItem := -1;
|
|
|
|
inherited MouseMove(Shift, X, Y);
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.MouseUp(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer);
|
|
var
|
|
FolderIndex: Integer;
|
|
ItemIndex: Integer;
|
|
Folder: TVpNavFolder;
|
|
Item: TVpNavBtnItem;
|
|
FromItem: TVpNavBtnItem;
|
|
SourceName: string;
|
|
begin
|
|
if nabMouseDown then begin
|
|
try
|
|
nabGetHitTest(X, Y, FolderIndex, ItemIndex);
|
|
|
|
if (FActiveItem <> -1) and (ItemIndex <> -1) then begin
|
|
FSelectedItem := ItemIndex;
|
|
InvalidateItem(FActiveFolder, ItemIndex);
|
|
if FActiveItem = ItemIndex then
|
|
DoItemClick(Button, Shift, ItemIndex);
|
|
end;
|
|
|
|
if nabDragFromItem <> -1 then begin
|
|
if nabDropHitTest(X, Y) then begin
|
|
{get the old item}
|
|
Folder := Folders[nabDragFromFolder];
|
|
FromItem := TVpNavBtnItem(Folder.Items[nabDragFromItem]);
|
|
{create the new item}
|
|
Folder := Folders[nabDragToFolder];
|
|
Item := TVpNavBtnItem(Folder.FItems.Insert(nabDragToItem));
|
|
Item.Assign(FromItem);
|
|
SourceName := FromItem.Name;
|
|
FromItem.Free;
|
|
Item.Name := SourceName;
|
|
nabRecalcDisplayNames;
|
|
DoArrange;
|
|
end;
|
|
nabDragFromFolder := -1;
|
|
nabDragFromItem := -1;
|
|
end;
|
|
|
|
if (ItemIndex = -1) then begin
|
|
{ Fire the OnFolderClick event. }
|
|
DoFolderClick(Button, Shift, FolderIndex);
|
|
ActiveFolder := FolderIndex;
|
|
end;
|
|
finally
|
|
Invalidate;
|
|
nabMouseDown := False;
|
|
end;
|
|
end;
|
|
|
|
inherited MouseUp(Button, Shift, X, Y);
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.Notification(AComponent: TComponent;
|
|
Operation: TOperation);
|
|
begin
|
|
inherited Notification(AComponent, Operation);
|
|
if Operation = opRemove then begin
|
|
if AComponent = FImages then
|
|
FImages := nil;
|
|
end;
|
|
end;
|
|
{=====}
|
|
|
|
{$IFDEF PAINTER}
|
|
procedure TVpCustomNavBar.Paint;
|
|
var
|
|
painter: TVpNavBarPainter;
|
|
begin
|
|
{$IFDEF LCL}{$IF LCL_FullVersion >= 1090000}
|
|
FCanvasScaleFactor := GetCanvasScaleFactor;
|
|
{$IFEND}{$ENDIF}
|
|
|
|
painter := TVpNavBarPainter.Create(Self);
|
|
try
|
|
painter.Paint;
|
|
finally
|
|
painter.Free;
|
|
end;
|
|
|
|
nabProcessContainers;
|
|
end;
|
|
|
|
{$ELSE}
|
|
procedure TVpCustomNavBar.Paint;
|
|
var
|
|
I, J: Integer;
|
|
X: Integer;
|
|
W, H: Integer;
|
|
CurPos: Integer;
|
|
lOffset: Integer;
|
|
BkMode: Integer;
|
|
LabelWidth: Integer;
|
|
Flags: Integer;
|
|
MyRect: TRect;
|
|
TR: TRect;
|
|
// ContainerRect: TRect;
|
|
// FolderType: TVpFolderType;
|
|
BkColor: TColor;
|
|
Folder: TVpNavFolder;
|
|
Item: TVpNavBtnItem;
|
|
DrawBmp: TBitmap;
|
|
Text: string;
|
|
Buf: array[0..255] of Char;
|
|
DrawFolder: Boolean;
|
|
BM: TBitmap;
|
|
RowStart: Integer;
|
|
ILeft: Integer;
|
|
IHeight: Integer;
|
|
IWidth: integer;
|
|
Details: TThemedElementDetails;
|
|
TB: TThemedButton;
|
|
begin
|
|
if nabChanging then
|
|
Exit;
|
|
|
|
DrawBmp := TBitMap.Create;
|
|
try
|
|
DrawBmp.Width := ClientWidth;
|
|
DrawBmp.Height := ClientHeight;
|
|
|
|
DrawBmp.Canvas.Font := Self.Font;
|
|
with DrawBmp.Canvas do begin
|
|
Pen.Color := FBackgroundColor;
|
|
Brush.Color := FBackgroundColor;
|
|
|
|
MyRect := ClientRect;
|
|
|
|
DrawFolder := (FolderCount > 0);
|
|
if DrawFolder then
|
|
TR := nabGetFolderArea(FActiveFolder)
|
|
else
|
|
TR := ClientRect;
|
|
|
|
if FBackgroundImage.Empty or (FBackgroundMethod = bmNone) then
|
|
Rectangle(TR.Left, TR.Top, TR.Right, TR.Bottom)
|
|
else begin
|
|
case FBackgroundMethod of
|
|
bmNormal:
|
|
Draw(TR.Left, TR.Top, FBackgroundImage);
|
|
bmStretch:
|
|
StretchDraw(TR, FBackgroundImage);
|
|
bmTile:
|
|
begin
|
|
{Tile the background in the default folder}
|
|
RowStart := 0;
|
|
IHeight := FBackgroundImage.Height;
|
|
IWidth := FBackgroundImage.Width;
|
|
ILeft := 0;
|
|
while (RowStart < ClientRect.Bottom) do begin
|
|
while (ILeft < ClientRect.Right) do begin
|
|
Draw(TR.Left + ILeft, RowStart, FBackgroundImage);
|
|
Inc(ILeft, IWidth);
|
|
end;
|
|
ILeft := 0;
|
|
Inc(RowStart, IHeight)
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
CurPos := 0;
|
|
if FolderCount = 0 then begin
|
|
nabScrollUpBtn.Visible := False;
|
|
nabScrollDownBtn.Visible := False;
|
|
Exit;
|
|
end;
|
|
|
|
{draw the folder buttons at the top}
|
|
if DrawFolder then begin
|
|
for I := 0 to FActiveFolder do begin
|
|
MyRect.Top := CurPos;
|
|
MyRect.Bottom := CurPos + FButtonHeight;
|
|
Folders[I].lfRect := MyRect;
|
|
|
|
{Draw the top tabs based on the selected style...}
|
|
case FDrawingStyle of
|
|
dsDefButton:
|
|
begin
|
|
{Draw regular buttons}
|
|
if ThemeServices.ThemesEnabled then begin
|
|
if (I = nabLastMouseOverItem) then
|
|
TB := tbPushButtonHot
|
|
else
|
|
if (I = FHotFolder) and nabMouseDown then
|
|
TB := tbPushButtonPressed
|
|
else
|
|
TB := tbPushButtonNormal;
|
|
Details := ThemeServices.GetElementDetails(TB);
|
|
ThemeServices.DrawElement(Handle, details, MyRect);
|
|
TR := MyRect;
|
|
InflateRect(TR, -1, -1);
|
|
if I = FHotFolder then OffsetRect(TR, -1, -1); // Focused
|
|
end;
|
|
//TODO: TR := DrawButtonFace(DrawBmp.Canvas, MyRect, 1, bsNew, False,
|
|
// (I = FHotFolder) and nabMouseDown, False);
|
|
end;
|
|
|
|
dsEtchedButton:
|
|
begin
|
|
{Draw regular etched (Win98 style) buttons}
|
|
Brush.Color := clBtnFace;
|
|
FillRect(MyRect);
|
|
Pen.Color := clBtnShadow;
|
|
Brush.Style := bsClear;
|
|
Rectangle(MyRect.Left, MyRect.Top, MyRect.Right - 1, MyRect.Bottom);
|
|
Pen.Color := clBtnHighlight;
|
|
MoveTo(MyRect.Left + 1, MyRect.Bottom - 2);
|
|
LineTo(MyRect.Left + 1, MyRect.Top + 1);
|
|
LineTo(MyRect.Right - 2, MyRect.Top + 1);
|
|
{ Draw border around control. }
|
|
MoveTo(Width - 1, Top);
|
|
LineTo(Width - 1, Height - 1);
|
|
LineTo(0, Height - 1);
|
|
Pen.Color := clWindowFrame;
|
|
MoveTo(Width - 1, MyRect.Bottom);
|
|
LineTo(1, MyRect.Bottom);
|
|
LineTo(1, Height - 1);
|
|
TR := MyRect;
|
|
end;
|
|
|
|
dsCoolTab:
|
|
begin
|
|
{Draw cool (Netscape Sidebar style) tabs}
|
|
TR := DrawNavTab(
|
|
DrawBmp.Canvas, {Canvas}
|
|
MyRect, {Client Rect}
|
|
1, {Bevel Width}
|
|
FBackgroundColor, {Tab Color}
|
|
I, {Tab Number}
|
|
true, {Cool Tabs?}
|
|
(I = FHotFolder), {Is Focused}
|
|
(I = nabLastMouseOverItem) {MouseOverItem}
|
|
);
|
|
end;
|
|
|
|
dsStandardTab:
|
|
begin
|
|
{Draw regular old tabs}
|
|
TR := DrawNavTab(
|
|
DrawBmp.Canvas, {Canvas}
|
|
MyRect, {Client Rect}
|
|
1, {Bevel Width}
|
|
FBackgroundColor, {Tab Color}
|
|
I, {Tab Number}
|
|
false, {Cool Tabs?}
|
|
(I = FHotFolder), {Is Focused}
|
|
(I = nabLastMouseOverItem) {MouseOverItem}
|
|
);
|
|
end;
|
|
|
|
end;
|
|
StrPLCopy(Buf, Folders[I].lfDisplayName, 255);
|
|
Inc(TR.Top);
|
|
Flags := DT_CENTER or DT_VCENTER or DT_SINGLELINE or DT_NOPREFIX;
|
|
if Folders[I].Enabled then begin
|
|
DrawText(DrawBmp.Canvas.Handle, Buf, StrLen(Buf), TR, Flags);
|
|
if (I = FHotFolder) and not nabMouseDown then begin
|
|
case FDrawingStyle of
|
|
dsDefButton:
|
|
begin
|
|
{ Regular button style. }
|
|
InflateRect(TR,1,1);
|
|
inc(TR.Left);
|
|
DrawBmp.Canvas.Frame3D(TR, 1,bvRaised);
|
|
end;
|
|
|
|
dsEtchedButton:
|
|
begin
|
|
{ Etched style (Outlook98). }
|
|
Pen.Color := clWindowFrame;
|
|
MoveTo(TR.Right - 2, TR.Top);
|
|
LineTo(TR.Right - 2, TR.Bottom - 1);
|
|
LineTo(0, TR.Bottom - 1);
|
|
Pen.Color := clBtnShadow;
|
|
if I = ActiveFolder then
|
|
lOffset := 1
|
|
else
|
|
lOffset := 2;
|
|
MoveTo(TR.Right - 3, TR.Top - 2);
|
|
LineTo(TR.Right - 3, TR.Bottom - lOffset);
|
|
LineTo(1, TR.Bottom - lOffset);
|
|
if I = ActiveFolder then
|
|
Pixels[1, TR.Bottom - lOffset] := clBtnHighlight;
|
|
end;
|
|
end; // case
|
|
end;
|
|
end else
|
|
begin
|
|
{use shadow text for inactive folder text}
|
|
DrawBmp.Canvas.Font.Color := clHighlightText;
|
|
SetBkMode(Canvas.Handle, OPAQUE);
|
|
DrawText(DrawBmp.Canvas.Handle, Buf, -1, TR, Flags);
|
|
SetBkMode(DrawBmp.Canvas.Handle, TRANSPARENT);
|
|
DrawBmp.Canvas.Font.Color := clBtnShadow;
|
|
OffsetRect(TR, -2, -1);
|
|
DrawText(DrawBmp.Canvas.Handle, Buf, -1, TR, Flags);
|
|
DrawBmp.Canvas.Font.Color := Self.Font.Color;
|
|
end;
|
|
Inc(CurPos, FButtonHeight);
|
|
end;
|
|
end else
|
|
begin
|
|
if FDrawingStyle = dsEtchedButton then begin
|
|
{ Draw border around control. }
|
|
Pen.Color := clBtnHighlight;
|
|
MoveTo(Width - 1, Top);
|
|
LineTo(Width - 1, Height - 1);
|
|
LineTo(0, Height - 1);
|
|
Pen.Color := clWindowFrame;
|
|
MoveTo(0, Height - 1);
|
|
LineTo(0, 1);
|
|
LineTo(Width - 2, 1);
|
|
end;
|
|
CurPos := 0;
|
|
end;
|
|
|
|
//TODO:
|
|
{ BkMode := GetBkMode(Handle);
|
|
BkColor := GetBkColor(Handle);
|
|
SetBkColor(Handle, DWord(FBackgroundColor));
|
|
SetBkMode(Handle, TRANSPARENT);
|
|
}
|
|
{ draw the items for the active folder }
|
|
Folder := Folders[FActiveFolder];
|
|
|
|
if Folder.FolderType = ftDefault then
|
|
if Folder.ItemCount > 0 then begin
|
|
Inc(CurPos, 8);
|
|
with nabItemsRect do begin
|
|
Top := CurPos;
|
|
Left := 0;
|
|
Right := ClientWidth;
|
|
Bottom := ClientHeight - (FolderCount - FActiveFolder - 1) * FButtonHeight + 1;
|
|
end;
|
|
|
|
for J := 0 to Folder.ItemCount-1 do
|
|
TVpNavBtnItem(Folder.Items[J]).FLabelRect.Bottom := nabItemsRect.Bottom + 1;
|
|
|
|
for J := nabTopItem to Folder.ItemCount-1 do begin
|
|
if (FSelectedItem = J) then
|
|
DrawBmp.Canvas.Font := FSelectedItemFont
|
|
else
|
|
DrawBmp.Canvas.Font := FItemFont;
|
|
|
|
Item := Folder.Items[J];
|
|
{ If the caption is empty at designtime then display the item's }
|
|
{ name instead }
|
|
if (csDesigning in ComponentState) and (Item.Caption = '') then
|
|
Text := Item.Name
|
|
else
|
|
Text := Item.Caption;
|
|
|
|
if Folder.IconSize = isLarge then begin {large icons}
|
|
{ glyph is at the top }
|
|
with Item.FIconRect do begin
|
|
{ If an image list is assigned then use the image }
|
|
{ size. If no image list is assinged then assume }
|
|
{ a 32 x 32 image size. }
|
|
if Assigned(FImages) then begin
|
|
W := FImages.Width + 2;
|
|
H := FImages.Height + 2;
|
|
end else begin
|
|
W := 32;
|
|
H := 32;
|
|
end;
|
|
Top := CurPos;
|
|
Bottom := CurPos + H;
|
|
Left := (ClientWidth - W) shr 1;
|
|
Right := Left + W;
|
|
if Top > nabItemsRect.Bottom then
|
|
Break;
|
|
|
|
if FShowButtons then begin
|
|
if FActiveItem = J then begin
|
|
if nabMouseDown then
|
|
Pen.Color := clBlack
|
|
else
|
|
Pen.Color := clWhite;
|
|
MoveTo(Left-1, Bottom+1);
|
|
LineTo(Left-1, Top-1);
|
|
LineTo(Right+1, Top-1);
|
|
if nabMouseDown then
|
|
Pen.Color := clWhite
|
|
else
|
|
Pen.Color := clBlack;
|
|
LineTo(Right+1, Bottom+1);
|
|
LineTo(Left-1, Bottom+1);
|
|
end else begin
|
|
Pen.Color := FBackgroundColor;
|
|
Brush.Color := FBackgroundColor;
|
|
end;
|
|
if Assigned(FImages) and
|
|
(Item.IconIndex >= 0) and
|
|
(Item.IconIndex < FImages.Count) then
|
|
FImages.Draw(DrawBmp.Canvas, Item.FIconRect.Left + 2,
|
|
Item.FIconRect.Top + 2, Item.IconIndex);
|
|
{make the icon's bottom blend into the label's top}
|
|
Item.FIconRect.Bottom := Item.FIconRect.Bottom + 4;
|
|
end;
|
|
end;
|
|
Inc(CurPos, H + 4);
|
|
|
|
{now, draw the text}
|
|
with Item.FLabelRect do begin
|
|
Top := CurPos;
|
|
Bottom := CurPos + (FButtonHeight shl 1) - 7;
|
|
Left := 0;
|
|
Right := ClientWidth - 1;
|
|
Item.liDisplayName := GetLargeIconDisplayName(DrawBmp.Canvas, Item.FLabelRect, Text);
|
|
X := DrawBmp.Canvas.TextWidth(Item.liDisplayName);
|
|
Left := (ClientWidth - X) div 2;
|
|
if Left < 5 then
|
|
Left := 5;
|
|
Right := Left + X;
|
|
if Right > ClientWidth-5 then
|
|
Right := ClientWidth-5;
|
|
if Top > nabItemsRect.Bottom then
|
|
Break;
|
|
end;
|
|
|
|
StrPLCopy(Buf, Item.liDisplayName, 255);
|
|
DrawText(DrawBmp.Canvas.Handle, Buf, Length(Item.liDisplayName), Item.FLabelRect,
|
|
DT_CENTER or DT_VCENTER or DT_WORDBREAK or DT_CALCRECT);
|
|
LabelWidth := RectWidth(Item.FLabelRect);
|
|
with Item.FLabelRect do begin
|
|
Left := (ClientWidth - LabelWidth) div 2;
|
|
Right := Left + LabelWidth + 1;
|
|
end;
|
|
BkMode := SetBkMode(DrawBmp.Canvas.Handle, TRANSPARENT);
|
|
Inc(CurPos, DrawText(
|
|
DrawBmp.Canvas.Handle, Buf, Length(Item.liDisplayName),
|
|
Item.FLabelRect, DT_CENTER or DT_VCENTER or DT_WORDBREAK)
|
|
);
|
|
SetBkMode(DrawBmp.Canvas.Handle, BkMode);
|
|
|
|
Inc(CurPos, FItemSpacing);
|
|
end else begin {small icons}
|
|
{glyph is at the left}
|
|
with Item.FIconRect do begin
|
|
Top := CurPos;
|
|
lOffset := Abs(DrawBmp.Canvas.Font.Height) div 2;
|
|
if lOffset > 8 then
|
|
Top := Top + lOffset - 8;
|
|
Bottom := Top + 16;
|
|
Left := 8;
|
|
Right := Left + 16;
|
|
if Top > nabItemsRect.Bottom then
|
|
Break;
|
|
|
|
if FShowButtons then begin
|
|
if FActiveItem = J then begin
|
|
if nabMouseDown then
|
|
Pen.Color := clBlack
|
|
else
|
|
Pen.Color := clWhite;
|
|
MoveTo(Left-1, Bottom+1);
|
|
LineTo(Left-1, Top-1);
|
|
LineTo(Right+1, Top-1);
|
|
if nabMouseDown then
|
|
Pen.Color := clWhite
|
|
else
|
|
Pen.Color := clBlack;
|
|
LineTo(Right+1, Bottom+1);
|
|
LineTo(Left-1, Bottom+1);
|
|
Brush.Color := FBackgroundColor;
|
|
end else begin
|
|
Pen.Color := FBackgroundColor;
|
|
Brush.Color := FBackgroundColor;
|
|
Rectangle(
|
|
Item.FIconRect.Left - 1,
|
|
Item.FIconRect.Top - 1,
|
|
Item.FIconRect.Right + 1,
|
|
Item.FIconRect.Bottom + 1
|
|
);
|
|
end;
|
|
if Assigned(FImages) then begin
|
|
BM := TBitmap.Create;
|
|
try
|
|
BM.Width := FImages.Width;
|
|
BM.Height := FImages.Height;
|
|
FImages.Draw(BM.Canvas, 0, 0, Item.IconIndex);
|
|
//TODO: DrawBmp.Canvas.BrushCopy(Item.FIconRect, BM,
|
|
// Rect(0, 0, BM.Width, BM.Height), BM.Canvas.Pixels[0,
|
|
// BM.Height-1]);
|
|
finally
|
|
BM.Free;
|
|
end;
|
|
end;
|
|
end;
|
|
{make the icon's right blend into the label's left}
|
|
Item.FIconRect.Right := Item.FIconRect.Right + 3;
|
|
end;
|
|
|
|
{now, draw the text}
|
|
with Item.FLabelRect do begin
|
|
Top := CurPos;
|
|
Bottom := CurPos + (FButtonHeight shl 1) -7;
|
|
Left := Item.FIconRect.Right;
|
|
X := Self.ClientWidth - Left - 7;
|
|
Right := Left + X;
|
|
if Top > nabItemsRect.Bottom then
|
|
Break;
|
|
end;
|
|
Item.liDisplayName :=
|
|
GetDisplayString(DrawBmp.Canvas, Text, 1, RectWidth(Item.FLabelRect));
|
|
StrPLCopy(Buf, Item.liDisplayName, 255);
|
|
DrawText(DrawBmp.Canvas.Handle, Buf, Length(Item.liDisplayName),
|
|
Item.FLabelRect, DT_LEFT or DT_VCENTER or DT_CALCRECT);
|
|
LabelWidth := RectWidth(Item.FLabelRect);
|
|
with Item.FLabelRect do
|
|
Right := Left + LabelWidth + 1;
|
|
DrawText(DrawBmp.Canvas.Handle, Buf, Length(Item.liDisplayName),
|
|
Item.FLabelRect, DT_LEFT or DT_VCENTER);
|
|
|
|
Inc(CurPos, FItemSpacing);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{now, draw the folder buttons at the bottom}
|
|
DrawBmp.Canvas.Font := Self.Font;
|
|
SetBkMode(Handle, BkMode);
|
|
SetBkColor(Handle, BkColor);
|
|
|
|
case FDrawingStyle of
|
|
{ Regular button style. }
|
|
dsDefButton :
|
|
CurPos := ClientHeight - FButtonHeight;
|
|
{ Etched style (Outlook98). }
|
|
dsEtchedButton :
|
|
CurPos := ClientHeight - FButtonHeight - 1;
|
|
{ Cool Tab }
|
|
dsCoolTab:
|
|
CurPos := ClientHeight - FButtonHeight;
|
|
{ Regular Tab }
|
|
dsStandardTab:
|
|
CurPos := ClientHeight - FButtonHeight;
|
|
end;
|
|
|
|
for I := FolderCount-1 downto FActiveFolder+1 do begin
|
|
MyRect.Top := CurPos;
|
|
MyRect.Bottom := CurPos + FButtonHeight;
|
|
Folders[I].lfRect := MyRect;
|
|
case FDrawingStyle of
|
|
dsDefButton :
|
|
begin
|
|
{Regular Old Buttons}
|
|
if ThemeServices.ThemesEnabled then begin
|
|
if (I = nabLastMouseOverItem) then
|
|
TB := tbPushButtonHot
|
|
else
|
|
if (I = FHotFolder) and nabMouseDown then
|
|
TB := tbPushButtonPressed
|
|
else
|
|
TB := tbPushButtonNormal;
|
|
Details := ThemeServices.GetElementDetails(TB);
|
|
ThemeServices.DrawElement(Handle, details, MyRect);
|
|
TR := MyRect;
|
|
InflateRect(TR, -1, -1);
|
|
if I = FHotFolder then OffsetRect(TR, -1, -1); // Focused
|
|
end;
|
|
|
|
//TODO: TR := DrawButtonFace(DrawBmp.Canvas, MyRect, 1, bsNew, False,
|
|
// (I = FHotFolder) and nabMouseDown, False);
|
|
end;
|
|
|
|
dsEtchedButton :
|
|
begin
|
|
{Etched (Outlook98 style) buttons}
|
|
Brush.Color := clBtnFace;
|
|
FillRect(MyRect);
|
|
Pen.Color := clBtnShadow;
|
|
Brush.Style := bsClear;
|
|
Rectangle(MyRect.Left, MyRect.Top, MyRect.Right - 1, MyRect.Bottom);
|
|
Pen.Color := clBtnHighlight;
|
|
MoveTo(MyRect.Left + 1, MyRect.Bottom - 2);
|
|
LineTo(MyRect.Left + 1, MyRect.Top + 1);
|
|
LineTo(MyRect.Right - 2, MyRect.Top + 1);
|
|
Pen.Color := clBtnHighlight;
|
|
MoveTo(Width - 1, 0);
|
|
LineTo(Width - 1, Height);
|
|
TR := MyRect;
|
|
end;
|
|
|
|
dsCoolTab:
|
|
begin
|
|
{Draw cool (Netscape Sidebar style) tabs}
|
|
TR := DrawNavTab(
|
|
DrawBmp.Canvas, {Canvas}
|
|
MyRect, {Client Rect}
|
|
1, {Bevel Width}
|
|
FBackgroundColor, {Tab Color}
|
|
I, {Tab Number}
|
|
true, {Cool Tabs?}
|
|
(I = FHotFolder), {Is Focused}
|
|
(I = nabLastMouseOverItem) {MouseOverItem}
|
|
);
|
|
end;
|
|
|
|
dsStandardTab:
|
|
begin
|
|
{Draw regular old tabs}
|
|
TR := DrawNavTab(
|
|
DrawBmp.Canvas, {Canvas}
|
|
MyRect, {Client Rect}
|
|
1, {Bevel Width}
|
|
FBackgroundColor, {Tab Color}
|
|
I, {Tab Number}
|
|
false, {Cool Tabs?}
|
|
(I = FHotFolder), {Is Focused}
|
|
(I = nabLastMouseOverItem) {MouseOverItem}
|
|
);
|
|
end;
|
|
|
|
end;
|
|
Inc(TR.Top);
|
|
StrPLCopy(Buf, Folders[I].lfDisplayName, 255);
|
|
Flags := DT_CENTER or DT_VCENTER or DT_SINGLELINE or DT_NOPREFIX;
|
|
if Folders[I].Enabled then begin
|
|
DrawText(DrawBmp.Canvas.Handle, Buf, StrLen(Buf), TR, Flags);
|
|
if (I = FHotFolder) and not nabMouseDown then begin
|
|
case FDrawingStyle of
|
|
dsDefButton:
|
|
begin
|
|
{ Regular button style. }
|
|
InflateRect(TR,1,1);
|
|
inc(TR.Left);
|
|
DrawBmp.Canvas.Frame3D(TR,1,bvRaised);
|
|
end;
|
|
|
|
dsEtchedButton :
|
|
begin
|
|
{ Etched (Outlook98 style). }
|
|
Pen.Color := clWindowFrame;
|
|
MoveTo(TR.Right - 2, TR.Top);
|
|
LineTo(TR.Right - 2, TR.Bottom - 1);
|
|
LineTo(0, TR.Bottom - 1);
|
|
Pen.Color := clBtnShadow;
|
|
MoveTo(TR.Right - 3, TR.Top - 2);
|
|
LineTo(TR.Right - 3, TR.Bottom - 2);
|
|
LineTo(1, TR.Bottom - 2);
|
|
end;
|
|
end;
|
|
end;
|
|
end else begin
|
|
{use shadow text for inactive folder text}
|
|
DrawBmp.Canvas.Font.Color := clHighlightText;
|
|
SetBkMode(Canvas.Handle, OPAQUE);
|
|
DrawText(DrawBmp.Canvas.Handle, Buf, -1, TR, Flags);
|
|
SetBkMode(DrawBmp.Canvas.Handle, TRANSPARENT);
|
|
DrawBmp.Canvas.Font.Color := clBtnShadow;
|
|
OffsetRect(TR, -2, -1);
|
|
DrawText(DrawBmp.Canvas.Handle, Buf, -1, TR, Flags);
|
|
DrawBmp.Canvas.Font.Color := Self.Font.Color;
|
|
end;
|
|
Dec(CurPos, FButtonHeight);
|
|
end;
|
|
|
|
if not (csDesigning in ComponentState) then begin
|
|
{show the top scroll button}
|
|
if nabShowScrollUp then begin
|
|
nabScrollUpBtn.Top := Folders[FActiveFolder].lfRect.Bottom + 5;
|
|
nabScrollUpBtn.Left := ClientWidth - 20;
|
|
nabScrollUpBtn.Visible := True;
|
|
end else
|
|
nabScrollUpBtn.Visible := False;
|
|
|
|
{show the bottom scroll button}
|
|
if nabShowScrollDown then begin
|
|
if FActiveFolder = FolderCount-1 then
|
|
{there are no folders beyond the active one}
|
|
nabScrollDownBtn.Top := ClientHeight -20
|
|
else
|
|
nabScrollDownBtn.Top := Folders[FActiveFolder+1].lfRect.Top - 20;
|
|
nabScrollDownBtn.Left := ClientWidth - 20;
|
|
nabScrollDownBtn.Visible := True;
|
|
end else
|
|
nabScrollDownBtn.Visible := False;
|
|
end;
|
|
|
|
{if we're dragging, show the drag marker}
|
|
if (nabDragFromItem <> -1) or nabExternalDrag then begin
|
|
if (nabDropY <> -1) then begin
|
|
{ Don't draw the drag marker if we're doing external }
|
|
{ dragging and the cursor is over an item. }
|
|
if nabExternalDrag then
|
|
if not nabFolderAccept or nabCursorOverItem then
|
|
Exit;
|
|
Pen.Color := clBlack;
|
|
Brush.Color := clBlack;
|
|
MoveTo(5, nabDropY);
|
|
LineTo(ClientWidth - 5, nabDropY);
|
|
DrawBmp.Canvas.Polygon([
|
|
Point(3, nabDropY+4),
|
|
Point(7, nabDropY),
|
|
Point(3, nabDropY-4)
|
|
]);
|
|
DrawBmp.Canvas.FloodFill(5, nabDropY, clBlack, fsBorder);
|
|
DrawBmp.Canvas.Polygon([
|
|
Point(ClientWidth-3,nabDropY+4),
|
|
Point(ClientWidth-7,nabDropY),
|
|
Point(ClientWidth-3,nabDropY-4)
|
|
]);
|
|
DrawBmp.Canvas.FloodFill(ClientWidth-5, nabDropY, clBlack, fsBorder);
|
|
end;
|
|
end;
|
|
end;
|
|
finally
|
|
Canvas.CopyMode := cmSrcCopy;
|
|
Canvas.CopyRect(ClientRect, DrawBmp.Canvas, ClientRect);
|
|
DrawBmp.Free;
|
|
end;
|
|
|
|
{For container style folders...}
|
|
|
|
{Hide the containers for all inactive folders}
|
|
for I := 0 to FFolders.Count - 1 do begin
|
|
if I <> FActiveFolder then begin
|
|
if Folders[i].FolderType = ftContainer then
|
|
with Containers[Folders[i].ContainerIndex] do begin
|
|
Width := 0;
|
|
Height := 0;
|
|
Visible := false;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
Folder := Folders[FActiveFolder];
|
|
TR := nabGetFolderArea(FActiveFolder);
|
|
|
|
if Folder.FolderType = ftContainer then
|
|
with Containers[Folder.ContainerIndex] do begin
|
|
{Position and show the folder's container}
|
|
Height := TR.Bottom - TR.Top;
|
|
Top := TR.Top;
|
|
Left := TR.Left;
|
|
Width := TR.Right - TR.Left;
|
|
Visible := true;
|
|
BringToFront;
|
|
|
|
for I := 0 to ControlCount - 1 do
|
|
Controls[i].Invalidate;
|
|
end;
|
|
end;
|
|
{$ENDIF}
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.PlaySound(const AWavFile: String;
|
|
APlaySoundMode: TVpPlaySoundMode);
|
|
begin
|
|
if Assigned(FOnPlaySound) then
|
|
FOnPlaySound(Self, AWavFile, APlaySoundMode)
|
|
else begin
|
|
{$IFDEF WINDOWS}
|
|
case APlaySoundMode of
|
|
psmSync : SndPlaySound(PChar(AWavFile), SND_SYNC);
|
|
psmAsync : SndPlaySound(PChar(AWavFile), SND_ASYNC);
|
|
psmStop : SndPlaySound(nil, 0);
|
|
end;
|
|
{$ENDIF}
|
|
end;
|
|
end;
|
|
|
|
procedure TVpCustomNavBar.SetActiveFolder(Value: Integer);
|
|
var
|
|
Y: Integer;
|
|
YDelta: Integer;
|
|
R: TRect;
|
|
R2: TRect;
|
|
AllowChange: Boolean;
|
|
btnHeight: Integer;
|
|
begin
|
|
if Value <> FActiveFolder then begin
|
|
|
|
if FolderCount = 0 then
|
|
FActiveFolder := -1
|
|
else
|
|
if (Value > -1) and (Value < FolderCount) then begin
|
|
btnHeight := GetRealButtonHeight;
|
|
{ Fire DoFolderChange only if not dragging. }
|
|
if nabDragFromItem = -1 then begin
|
|
{ Default for AllowChange is True. }
|
|
AllowChange := True;
|
|
{ Fire the OnFolderChange event. }
|
|
DoFolderChange(Value, AllowChange);
|
|
{ If AllowChange is False then bail out. }
|
|
if not AllowChange then
|
|
Exit;
|
|
end;
|
|
{animated scroll}
|
|
if FActiveFolder > -1 then begin
|
|
{play sound}
|
|
if not (csDesigning in ComponentState) and FPlaySounds and
|
|
(FSoundAlias <> '') and FileExists(FSoundAlias)
|
|
then
|
|
PlaySound(FSoundAlias, psmAsync);
|
|
(*
|
|
if FPlaySounds and (FSoundAlias > '') then begin
|
|
StrPLCopy(Buf, FSoundAlias, SizeOf(Buf)-1);
|
|
{$IFNDEF LCL}
|
|
FPlaySounds := PlaySound(@Buf, 0, SND_ASYNC);
|
|
{$ENDIF}
|
|
end;
|
|
*)
|
|
|
|
if Parent <> nil then begin
|
|
{scroll selection}
|
|
Canvas.Brush.Color := FBackgroundColor;
|
|
R := nabGetFolderArea(FActiveFolder);
|
|
R2 := R;
|
|
if Value > FActiveFolder then begin
|
|
{up}
|
|
YDelta := -FScrollDelta;
|
|
Inc(R.Bottom, Abs(Value-FActiveFolder)*btnHeight);
|
|
R2.Top := R2.Bottom+Abs(Value-FActiveFolder)*btnHeight;
|
|
R2.Bottom := R2.Top;
|
|
end else begin
|
|
{down}
|
|
YDelta := +FScrollDelta;
|
|
Dec(R.Top, Abs(Value-FActiveFolder)*btnHeight);
|
|
R2.Bottom := R2.Top-Abs(Value-FActiveFolder)*btnHeight;
|
|
R2.Top := R2.Bottom;
|
|
end;
|
|
Y := RectHeight(R)-FScrollDelta;
|
|
while Y > 0 do begin
|
|
ScrollWindow(Handle, 0, YDelta, @R, @R);
|
|
Dec(Y, FScrollDelta);
|
|
{fill scrolled area}
|
|
if YDelta > 0 then
|
|
Inc(R2.Bottom, FScrollDelta)
|
|
else
|
|
Dec(R2.Top, FScrollDelta);
|
|
Canvas.FillRect(R2);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
FActiveFolder := Value;
|
|
nabTopItem := 0;
|
|
FActiveItem := -1;
|
|
FSelectedItem := -1;
|
|
Invalidate;
|
|
|
|
end;
|
|
{ Fire the OnFolderChanged event. }
|
|
DoFolderChanged(FActiveFolder)
|
|
end;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.SetBackgroundColor(Value: TColor);
|
|
begin
|
|
if Value <> FBackgroundColor then begin
|
|
FBackgroundColor := Value;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.SetBackgroundImage(Value: TBitmap);
|
|
begin
|
|
if Assigned(Value) then
|
|
FBackgroundImage.Assign(Value)
|
|
else begin
|
|
FBackgroundImage.Free;
|
|
FBackgroundImage := TBitmap.Create;
|
|
end;
|
|
Invalidate;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.SetBackgroundMethod(Value: TVpBackgroundMethod);
|
|
begin
|
|
if Value <> FBackgroundMethod then begin
|
|
FBackgroundMethod := Value;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
{=====}
|
|
(*
|
|
procedure TVpCustomNavBar.SetBorderStyle(const Value: TBorderStyle);
|
|
begin
|
|
if Value <> FBorderStyle then begin
|
|
FBorderStyle := Value;
|
|
RecreateWnd{$IFDEF LCL}(self){$ENDIF};
|
|
end;
|
|
end;
|
|
{=====}
|
|
*)
|
|
|
|
procedure TVpCustomNavBar.SetButtonHeight(Value: Integer);
|
|
begin
|
|
if Value <> FButtonHeight then begin
|
|
{Minimum ButtonHeight for CoolTabs is 17}
|
|
if FDrawingStyle = dsCoolTab then begin
|
|
if (Value < 17) and (FButtonHeight <> 0)
|
|
then FButtonHeight := 17
|
|
else FButtonHeight := Value;
|
|
end else
|
|
FButtonHeight := Value;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.SetDrawingStyle(Value: TVpFolderDrawingStyle);
|
|
begin
|
|
if Value <> FDrawingStyle then begin
|
|
FDrawingStyle := Value;
|
|
{
|
|
if FDrawingStyle = dsEtchedButton then
|
|
BorderStyle := bsNone
|
|
else
|
|
BorderStyle := bsSingle;
|
|
}
|
|
{Minimum ButtonHeight for CoolTabs is 17}
|
|
if (FDrawingStyle = dsCoolTab) and (FButtonHeight < 17) then
|
|
FButtonHeight := 17;
|
|
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
|
|
begin
|
|
inherited SetBounds(ALeft, ATop, AWidth, AHeight);
|
|
nabRecalcDisplayNames;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.SetImages(Value: TImageList);
|
|
begin
|
|
if FImages <> nil then
|
|
FImages.OnChange := nil;
|
|
FImages := Value;
|
|
if FImages <> nil then begin
|
|
Images.OnChange := nabImagesChanged;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.SetImagesWidth(const AValue: Integer);
|
|
begin
|
|
if AValue = FImagesWidth then exit;
|
|
FImagesWidth := AValue;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TVpCustomNavBar.SetItemFont(Value: TFont);
|
|
begin
|
|
if Assigned(Value) then
|
|
FItemFont.Assign(Value);
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.SetItemSpacing(Value: Integer);
|
|
begin
|
|
if (FItemSpacing = Value) then
|
|
exit;
|
|
FItemSpacing := Value;
|
|
Invalidate;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.SetSelectedItemFont(Value: TFont);
|
|
begin
|
|
if Assigned(Value) then
|
|
FSelectedItemFont.Assign(Value);
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.SetScrollDelta(Value: Integer);
|
|
begin
|
|
if Value <= 0 then
|
|
FScrollDelta := 1
|
|
else
|
|
FScrollDelta := Value;
|
|
end;
|
|
{=====}
|
|
|
|
{$IFDEF LCL}
|
|
procedure TVpCustomNavBar.WMEraseBkGnd(var Msg: TLMEraseBkGnd);
|
|
{$ELSE}
|
|
procedure TVpCustomNavBar.WMEraseBkGnd(var Msg: TWMEraseBkGnd);
|
|
{$ENDIF}
|
|
begin
|
|
Msg.Result := 1; {don't erase background}
|
|
end;
|
|
{=====}
|
|
|
|
{$IFNDEF LCL}
|
|
procedure TVpCustomNavBar.WMGetDlgCode(var Msg: TWMGetDlgCode);
|
|
begin
|
|
{tell windows we are a static control to avoid receiving the focus}
|
|
Msg.Result := DLGC_STATIC;
|
|
end;
|
|
{$ENDIF}
|
|
{=====}
|
|
|
|
{$IFDEF LCL}
|
|
procedure TVpCustomNavBar.WMNCHitTest(var Msg: TLMNCHitTest);
|
|
{$ELSE}
|
|
procedure TVpCustomNavBar.WMNCHitTest(var Msg: TWMNCHitTest);
|
|
{$ENDIF}
|
|
begin
|
|
inherited;
|
|
nabHitTest.X := Msg.Pos.X;
|
|
nabHitTest.Y := Msg.Pos.Y;
|
|
end;
|
|
{=====}
|
|
|
|
{$IFDEF LCL}
|
|
procedure TVpCustomNavBar.WMSetCursor(var Msg: TLMSetCursor);
|
|
{$ELSE}
|
|
procedure TVpCustomNavBar.WMSetCursor(var Msg: TWMSetCursor);
|
|
{$ENDIF}
|
|
var
|
|
I : Integer;
|
|
R : TRect;
|
|
begin
|
|
if csDesigning in ComponentState then begin
|
|
if (Msg.HitTest = HTCLIENT) then begin
|
|
nabOverButton := False;
|
|
nabHitTest := ScreenToClient(nabHitTest);
|
|
{check if mouse is over a button}
|
|
for I := 0 to FolderCount-1 do begin
|
|
R := nabButtonRect(I);
|
|
if PtInRect(R, nabHitTest) then begin
|
|
nabOverButton := True;
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
inherited;
|
|
end;
|
|
{=====}
|
|
|
|
{ Overridden DragOver method. }
|
|
procedure TVpCustomNavBar.DragOver(Source: TObject; X, Y: Integer;
|
|
State: TDragState; var Accept: Boolean);
|
|
var
|
|
ItemIndex: Integer;
|
|
FolderIndex: Integer;
|
|
begin
|
|
{ If State is dsDragLeave then the user has dragged }
|
|
{ outside us. Invalidate the component to get rid }
|
|
{ of any left-over drawing and exit. }
|
|
if State = dsDragLeave then begin
|
|
nabExternalDrag := False;
|
|
nabFolderAccept := False;
|
|
nabItemAccept := False;
|
|
nabMouseDown := False;
|
|
nabChanging := False;
|
|
nabTopItem := 0;
|
|
nabDragFromItem := -1;
|
|
nabDragFromFolder := -1;
|
|
Invalidate;
|
|
nabAcceptAny := False;
|
|
inherited DragOver(Source, X, Y, State, nabAcceptAny);
|
|
Exit;
|
|
end;
|
|
|
|
nabFolderAccept := True;
|
|
nabItemAccept := True;
|
|
{ Call the user's OnDragOver. }
|
|
if Assigned(FOnDragOver) then
|
|
FOnDragOver(Self, Source, X, Y, State, nabFolderAccept, nabItemAccept);
|
|
|
|
{ Might have to scroll the items in the folder. }
|
|
if nabScrollDownBtn.Visible then begin
|
|
if Y > nabScrollDownBtn.Top then begin
|
|
Inc(nabTopItem);
|
|
InvalidateRect(Handle, @nabItemsRect, False);
|
|
end;
|
|
end;
|
|
if nabScrollUpBtn.Visible then begin
|
|
if Y < (nabScrollUpBtn.Top + nabScrollUpBtn.Height)then begin
|
|
Dec(nabTopItem);
|
|
InvalidateRect(Handle, @nabItemsRect, False);
|
|
end;
|
|
end;
|
|
|
|
Accept := nabFolderAccept or nabItemAccept;
|
|
if nabFolderAccept or nabItemAccept then begin
|
|
nabGetHitTest(X, Y, FolderIndex, ItemIndex);
|
|
nabDropHitTest(X, Y);
|
|
nabExternalDrag := True;
|
|
{ Change folder if necessary. }
|
|
if (FolderIndex <> -1) and (FolderIndex <> FActiveFolder) then
|
|
ActiveFolder := FolderIndex;
|
|
if nabItemAccept then
|
|
FActiveItem := ItemIndex;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
{=====}
|
|
|
|
procedure TVpCustomNavBar.DragDrop(Source: TObject; X, Y: Integer);
|
|
begin
|
|
if Assigned(FOnDragDrop) then
|
|
FOnDragDrop(Self, Source, X, Y, FActiveFolder, nabExternalDragItem);
|
|
nabExternalDrag := False;
|
|
nabFolderAccept := False;
|
|
nabItemAccept := False;
|
|
nabMouseDown := False;
|
|
nabChanging := False;
|
|
nabTopItem := 0;
|
|
nabDragFromFolder := -1;
|
|
Invalidate;
|
|
inherited DragDrop(Source, X, Y);
|
|
end;
|
|
{=====}
|
|
|
|
function TVpCustomNavBar.GetChildOwner: TComponent;
|
|
begin
|
|
Result := Self;
|
|
end;
|
|
|
|
procedure TVpCustomNavBar.nabProcessContainers;
|
|
var
|
|
I: Integer;
|
|
folder: TVpNavFolder;
|
|
TR: TRect;
|
|
begin
|
|
if FActiveFolder = -1 then
|
|
exit;
|
|
|
|
{For container style folders...}
|
|
|
|
{Hide the containers for all inactive folders}
|
|
for I := 0 to FFolders.Count - 1 do begin
|
|
if I <> FActiveFolder then begin
|
|
if Folders[i].FolderType = ftContainer then
|
|
with Containers[Folders[i].ContainerIndex] do begin
|
|
Width := 0;
|
|
Height := 0;
|
|
Visible := false;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
Folder := Folders[FActiveFolder];
|
|
TR := nabGetFolderArea(FActiveFolder);
|
|
|
|
if Folder.FolderType = ftContainer then
|
|
with Containers[Folder.ContainerIndex] do begin
|
|
{Position and show the folder's container}
|
|
Height := TR.Bottom - TR.Top;
|
|
Top := TR.Top;
|
|
Left := TR.Left;
|
|
Width := TR.Right - TR.Left;
|
|
Visible := true;
|
|
BringToFront;
|
|
|
|
for I := 0 to ControlCount - 1 do
|
|
Controls[i].Invalidate;
|
|
end;
|
|
end;
|
|
|
|
{$IF LCL_FullVersion >= 1080000}
|
|
procedure TVpCustomNavBar.DoAutoAdjustLayout(const AMode: TLayoutAdjustmentPolicy;
|
|
const AXProportion, AYProportion: Double);
|
|
begin
|
|
inherited DoAutoAdjustLayout(AMode, AXProportion, AYProportion);
|
|
if AMode in [lapAutoAdjustWithoutHorizontalScrolling, lapAutoAdjustForDPI] then
|
|
begin
|
|
DisableAutoSizing;
|
|
try
|
|
// FButtonHeight := round(FButtonHeight * AYProportion);
|
|
if not IsStoredItemSpacing then
|
|
FItemSpacing := round(FItemSpacing * AYProportion);
|
|
finally
|
|
EnableAutoSizing;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{$IF VP_LCL_SCALING = 2}
|
|
procedure TVpCustomNavBar.ScaleFontsPPI(const AToPPI: Integer;
|
|
const AProportion: Double);
|
|
begin
|
|
inherited;
|
|
DoScaleFontPPI(FItemFont, AToPPI, AProportion);
|
|
DoScaleFontPPI(FSelectedItemFont, AToPPI, AProportion);
|
|
end;
|
|
{$ELSEIF VP_LCL_SCALING = 1}
|
|
procedure TVpCustomNavBar.ScaleFontsPPI(const AProportion: Double);
|
|
begin
|
|
inherited;
|
|
DoScaleFontPPI(FItemFont, AProportion);
|
|
DoScaleFontPPI(FSelectedItemFont, AProportion);
|
|
end;
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
|
|
initialization
|
|
RegisterClass(TVpFolderContainer);
|
|
|
|
end.
|
|
|
|
|