lazarus-ccr/components/spktoolbar/SpkToolbar/spkt_Pane.pas
blikblum e333deef99 Cleanup
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@2457 8e941d3f-bd1b-0410-a28a-d453659cc2b4
2012-06-09 16:11:47 +00:00

1062 lines
33 KiB
ObjectPascal

unit spkt_Pane;
{$mode delphi}
{.$Define EnhancedRecordSupport}
(*******************************************************************************
* *
* Plik: spkt_Pane.pas *
* Opis: Komponent tafli toolbara *
* Copyright: (c) 2009 by Spook. Jakiekolwiek u¿ycie komponentu bez *
* uprzedniego uzyskania licencji od autora stanowi z³amanie *
* prawa autorskiego! *
* *
*******************************************************************************)
interface
uses Graphics, Controls, Classes, SysUtils, Math, Dialogs,
SpkGraphTools, SpkGUITools, SpkMath,
spkt_Appearance, spkt_Const, spkt_Dispatch, spkt_Exceptions,
spkt_BaseItem, spkt_Items, spkt_Types;
type TSpkPaneState = (psIdle, psHover);
type TSpkMousePaneElementType = (peNone, pePaneArea, peItem);
TSpkMousePaneElement = record
ElementType : TSpkMousePaneElementType;
ElementIndex : integer;
end;
T2DIntRectArray = array of T2DIntRect;
TSpkPaneItemsLayout = record
Rects : T2DIntRectArray;
Width : integer;
end;
type TSpkPane = class;
TSpkPane = class(TSpkComponent)
private
FPaneState : TSpkPaneState;
FMouseHoverElement : TSpkMousePaneElement;
FMouseActiveElement : TSpkMousePaneElement;
protected
FCaption : string;
FRect : T2DIntRect;
FToolbarDispatch : TSpkBaseToolbarDispatch;
FAppearance : TSpkToolbarAppearance;
FImages : TImageList;
FDisabledImages : TImageList;
FLargeImages : TImageList;
FDisabledLargeImages : TImageList;
FVisible : boolean;
FItems : TSpkItems;
// *** Generowanie layoutu elementów ***
function GenerateLayout: TSpkPaneItemsLayout;
// *** Obs³uga designtime i DFM ***
procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
procedure DefineProperties(Filer : TFiler); override;
procedure Loaded; override;
// *** Gettery i settery ***
procedure SetCaption(const Value: string);
procedure SetVisible(const Value: boolean);
procedure SetAppearance(const Value: TSpkToolbarAppearance);
procedure SetImages(const Value: TImageList);
procedure SetDisabledImages(const Value : TImageList);
procedure SetLargeImages(const Value: TImageList);
procedure SetDisabledLargeImages(const Value : TImageList);
procedure SetRect(ARect : T2DIntRect);
procedure SetToolbarDispatch(const Value: TSpkBaseToolbarDispatch);
public
// *** Konstruktor, destruktor ***
constructor Create(AOwner : TComponent); override;
destructor Destroy; override;
// *** Obs³uga gryzonia ***
procedure MouseLeave;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
procedure MouseMove(Shift: TShiftState; X, Y: Integer);
procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
// *** Geometria i rysowanie ***
function GetWidth : integer;
procedure Draw(ABuffer : TBitmap; ClipRect : T2DIntRect);
function FindItemAt(x, y: integer): integer;
// *** Obs³uga elementów ***
procedure FreeingItem(AItem : TSpkBaseItem);
property ToolbarDispatch : TSpkBaseToolbarDispatch read FToolbarDispatch write SetToolbarDispatch;
property Appearance : TSpkToolbarAppearance read FAppearance write SetAppearance;
property Rect : T2DIntRect read FRect write SetRect;
property Images : TImageList read FImages write SetImages;
property DisabledImages : TImageList read FDisabledImages write SetDisabledImages;
property LargeImages : TImageList read FLargeImages write SetLargeImages;
property DisabledLargeImages : TImageList read FDisabledLargeImages write SetDisabledLargeImages;
property Items : TSpkItems read FItems;
published
property Caption : string read FCaption write SetCaption;
property Visible : boolean read FVisible write SetVisible;
end;
type TSpkPanes = class(TSpkCollection)
private
protected
FToolbarDispatch : TSpkBaseToolbarDispatch;
FAppearance : TSpkToolbarAppearance;
FImages : TImageList;
FDisabledImages : TImageList;
FLargeImages : TImageList;
FDisabledLargeImages : TImageList;
// *** Gettery i settery ***
procedure SetToolbarDispatch(const Value: TSpkBaseToolbarDispatch);
function GetItems(index: integer): TSpkPane; reintroduce;
procedure SetAppearance(const Value: TSpkToolbarAppearance);
procedure SetImages(const Value: TImageList);
procedure SetDisabledImages(const Value : TImageList);
procedure SetLargeImages(const Value: TImageList);
procedure SetDisabledLargeImages(const Value : TImageList);
public
// *** Dodawanie i wstawianie elementów ***
function Add : TSpkPane;
function Insert(index : integer) : TSpkPane;
// *** Reakcja na zmiany listy ***
procedure Notify(Item: TComponent; Operation : TOperation); override;
procedure Update; override;
property Items[index : integer] : TSpkPane read GetItems; default;
property ToolbarDispatch : TSpkBaseToolbarDispatch read FToolbarDispatch write SetToolbarDispatch;
property Appearance : TSpkToolbarAppearance read FAppearance write SetAppearance;
property Images : TImageList read FImages write SetImages;
property DisabledImages : TImageList read FDisabledImages write SetDisabledImages;
property LargeImages : TImageList read FLargeImages write SetLargeImages;
property DisabledLargeImages : TImageList read FDisabledLargeImages write SetDisabledLargeImages;
end;
implementation
{ TSpkPane }
procedure TSpkPane.SetRect(ARect: T2DIntRect);
var Pt : T2DIntPoint;
i : integer;
Layout : TSpkPaneItemsLayout;
begin
FRect:=ARect;
// Obliczamy layout
Layout:=GenerateLayout;
{$IFDEF EnhancedRecordSupport}
Pt:=T2DIntPoint.create(ARect.left + PANE_BORDER_SIZE + PANE_LEFT_PADDING, ARect.top + PANE_BORDER_SIZE);
{$ELSE}
Pt.create(ARect.left + PANE_BORDER_SIZE + PANE_LEFT_PADDING, ARect.top + PANE_BORDER_SIZE);
{$ENDIF}
if length(Layout.Rects)>0 then
begin
for i := 0 to high(Layout.Rects) do
FItems[i].Rect:=Layout.Rects[i] + Pt;
end;
end;
procedure TSpkPane.SetToolbarDispatch(const Value: TSpkBaseToolbarDispatch);
begin
FToolbarDispatch := Value;
FItems.ToolbarDispatch:=FToolbarDispatch;
end;
constructor TSpkPane.Create(AOwner : TComponent);
begin
inherited Create(AOwner);
FPaneState:=psIdle;
FMouseHoverElement.ElementType:=peNone;
FMouseHoverElement.ElementIndex:=-1;
FMouseActiveElement.ElementType:=peNone;
FMouseActiveElement.ElementIndex:=-1;
FCaption:='Pane';
{$IFDEF EnhancedRecordSupport}
FRect:=T2DIntRect.create(0,0,0,0);
{$ELSE}
FRect.create(0,0,0,0);
{$ENDIF}
FToolbarDispatch:=nil;
FAppearance:=nil;
FImages:=nil;
FDisabledImages:=nil;
FLargeImages:=nil;
FDisabledLargeImages:=nil;
FVisible:=true;
FItems:=TSpkItems.Create(self);
FItems.ToolbarDispatch:=FToolbarDispatch;
FItems.Appearance:=FAppearance;
end;
procedure TSpkPane.DefineProperties(Filer: TFiler);
begin
inherited DefineProperties(Filer);
Filer.DefineProperty('Items',FItems.ReadNames,FItems.WriteNames,true);
end;
destructor TSpkPane.Destroy;
begin
FItems.Free;
inherited Destroy;
end;
procedure TSpkPane.Draw(ABuffer: TBitmap; ClipRect: T2DIntRect);
var x: Integer;
y: Integer;
BgFromColor, BgToColor, CaptionColor, FontColor, BorderLightColor,
BorderDarkColor : TColor;
i: Integer;
begin
// W niektórych warunkach nie jesteœmy w stanie rysowaæ:
// * Brak dyspozytora
if FToolbarDispatch=nil then
exit;
// * Brak appearance
if FAppearance=nil then
exit;
if FPaneState = psIdle then
begin
// psIdle
BgFromColor:=FAppearance.Pane.GradientFromColor;
BgToColor:=FAppearance.Pane.GradientToColor;
CaptionColor:=FAppearance.Pane.CaptionBgColor;
FontColor:=FAppearance.Pane.CaptionFont.Color;
BorderLightColor:=FAppearance.Pane.BorderLightColor;
BorderDarkColor:=FAppearance.Pane.BorderDarkColor;
end else
begin
// psHover
BgFromColor:=TColorTools.Brighten(FAppearance.Pane.GradientFromColor,20);
BgToColor:=TColorTools.Brighten(FAppearance.Pane.GradientToColor,20);
CaptionColor:=TColorTools.Brighten(FAppearance.Pane.CaptionBgColor,20);
FontColor:=TColorTools.Brighten(FAppearance.Pane.CaptionFont.Color,20);
BorderLightColor:=TColorTools.Brighten(FAppearance.Pane.BorderLightColor,20);
BorderDarkColor:=TColorTools.Brighten(FAppearance.Pane.BorderDarkColor,20);
end;
// T³o
TGuiTools.DrawRoundRect(ABuffer.Canvas,
{$IFDEF EnhancedRecordSupport}
T2DIntRect.Create(FRect.left,
FRect.top,
FRect.right - PANE_BORDER_HALF_SIZE,
FRect.Bottom - PANE_BORDER_HALF_SIZE),
{$ELSE}
Create2DIntRect(FRect.left,
FRect.top,
FRect.right - PANE_BORDER_HALF_SIZE,
FRect.Bottom - PANE_BORDER_HALF_SIZE),
{$ENDIF}
PANE_CORNER_RADIUS,
BgFromColor,
BgToColor,
FAppearance.Pane.GradientType,
ClipRect);
// T³o etykiety tafli
TGuiTools.DrawRoundRect(ABuffer.Canvas,
{$IFDEF EnhancedRecordSupport}
T2DIntRect.Create(FRect.Left,
FRect.Bottom - PANE_CAPTION_HEIGHT - PANE_BORDER_HALF_SIZE,
FRect.right - PANE_BORDER_HALF_SIZE,
FRect.bottom - PANE_BORDER_HALF_SIZE),
{$ELSE}
Create2DIntRect(FRect.Left,
FRect.Bottom - PANE_CAPTION_HEIGHT - PANE_BORDER_HALF_SIZE,
FRect.right - PANE_BORDER_HALF_SIZE,
FRect.bottom - PANE_BORDER_HALF_SIZE),
{$ENDIF}
PANE_CORNER_RADIUS,
CaptionColor,
clNone,
bkSolid,
ClipRect,
false,
false,
true,
true);
// Etykieta tafli
ABuffer.Canvas.Font.assign(FAppearance.Pane.CaptionFont);
x:=FRect.left + (FRect.width - ABuffer.Canvas.TextWidth(FCaption)) div 2;
y:=FRect.Bottom - PANE_BORDER_SIZE - PANE_CAPTION_HEIGHT + 1 +
(PANE_CAPTION_HEIGHT - ABuffer.Canvas.TextHeight('Wy')) div 2;
TGUITools.DrawText(ABuffer.Canvas,
x,
y,
FCaption,
FontColor,
ClipRect);
// Ramki
TGUITools.DrawAARoundFrame(ABuffer,
{$IFDEF EnhancedRecordSupport}
T2DIntRect.create(FRect.left+1,
FRect.top+1,
FRect.Right,
FRect.bottom),
{$ELSE}
Create2DIntRect(FRect.left+1,
FRect.top+1,
FRect.Right,
FRect.bottom),
{$ENDIF}
PANE_CORNER_RADIUS,
BorderLightColor,
ClipRect);
TGUITools.DrawAARoundFrame(ABuffer,
{$IFDEF EnhancedRecordSupport}
T2DIntRect.create(FRect.left,
FRect.top,
FRect.Right-1,
FRect.bottom-1),
{$ELSE}
Create2DIntRect(FRect.left,
FRect.top,
FRect.Right-1,
FRect.bottom-1),
{$ENDIF}
PANE_CORNER_RADIUS,
BorderDarkColor,
ClipRect);
// Elementy
if FItems.Count>0 then
for i := 0 to FItems.Count - 1 do
begin
if FItems[i].Visible then
Fitems[i].Draw(ABuffer, ClipRect);
end;
end;
function TSpkPane.FindItemAt(x, y : integer) : integer;
var i : integer;
begin
result:=-1;
i:=FItems.count-1;
while (i>=0) and (result=-1) do
begin
if FItems[i].Visible then
begin
{$IFDEF EnhancedRecordSupport}
if FItems[i].Rect.Contains(T2DIntVector.create(x,y)) then
{$ELSE}
if FItems[i].Rect.Contains(x,y) then
{$ENDIF}
result:=i;
end;
dec(i);
end;
end;
procedure TSpkPane.FreeingItem(AItem: TSpkBaseItem);
begin
FItems.RemoveReference(AItem);
end;
function TSpkPane.GenerateLayout: TSpkPaneItemsLayout;
type TLayoutRow = array of integer;
TLayoutColumn = array of TLayoutRow;
TLayout = array of TLayoutColumn;
var Layout : TLayout;
CurrentColumn : integer;
CurrentRow : integer;
CurrentItem : integer;
c, r, i: Integer;
ItemTableBehaviour : TSpkItemTableBehaviour;
ItemGroupBehaviour : TSpkItemGroupBehaviour;
ItemSize : TSpkItemSize;
ForceNewColumn : boolean;
LastX : integer;
MaxRowX : integer;
ColumnX : integer;
rows: Integer;
ItemWidth: Integer;
tmpRect : T2DIntRect;
begin
setlength(result.Rects,FItems.count);
result.Width:=0;
if FItems.count=0 then
exit;
// Notatka: algorytm jest skonstruowany w ten sposób, ¿e trójka: CurrentColumn,
// CurrentRow oraz CurrentItem wskazuje na element, którego jeszcze nie
// ma (zaraz za ostatnio dodanym elementem).
setlength(Layout,1);
CurrentColumn:=0;
setlength(Layout[CurrentColumn],1);
CurrentRow:=0;
setlength(Layout[CurrentColumn][CurrentRow],0);
CurrentItem:=0;
ForceNewColumn:=false;
for i := 0 to FItems.count - 1 do
begin
ItemTableBehaviour := FItems[i].GetTableBehaviour;
ItemSize := FItems[i].GetSize;
// Rozpoczêcie nowej kolumny?
if (i=0) or
(ItemSize = isLarge) or
(ItemTableBehaviour = tbBeginsColumn) or
((ItemTableBehaviour = tbBeginsRow) and (CurrentRow = 2)) or
(ForceNewColumn) then
begin
// Jeœli ju¿ jesteœmy na pocz¹tku nowej kolumny, nie ma nic do roboty.
if (CurrentRow<>0) or (CurrentItem<>0) then
begin
setlength(Layout, length(Layout)+1);
CurrentColumn:=high(Layout);
setlength(Layout[CurrentColumn], 1);
CurrentRow:=0;
setlength(Layout[CurrentColumn][CurrentRow],0);
CurrentItem:=0;
end;
end else
// Rozpoczêcie nowego wiersza?
if (ItemTableBehaviour = tbBeginsRow) then
begin
// Jeœli ju¿ jesteœmy na pocz¹tku nowego wiersza, nie ma nic do roboty.
if CurrentItem <> 0 then
begin
setlength(Layout[CurrentColumn], length(Layout[CurrentColumn])+1);
inc(CurrentRow);
CurrentItem:=0;
end;
end;
ForceNewColumn:=ItemSize = isLarge;
// Jeœli element jest widoczny, dodajemy go w aktualnej kolumnie i aktualnym
// wierszu.
if FItems[i].Visible then
begin
setlength(Layout[CurrentColumn][CurrentRow], length(Layout[CurrentColumn][CurrentRow])+1);
Layout[CurrentColumn][CurrentRow][CurrentItem]:=i;
inc(CurrentItem);
end;
end;
// W tym miejscu mamy gotowy layout. Teraz trzeba obliczyæ pozycje i rozmiary
// Rectów.
// Najpierw wype³niamy je pustymi danymi, które zape³ni¹ miejsce elementów
// niewidocznych.
{$IFDEF EnhancedRecordSupport}
for i := 0 to FItems.count - 1 do
result.Rects[i]:=T2DIntRect.create(-1, -1, -1, -1);
{$ELSE}
for i := 0 to FItems.count - 1 do
result.Rects[i].create(-1, -1, -1, -1);
{$ENDIF}
MaxRowX:=0;
// Teraz iterujemy po layoucie, ustalaj¹c recty.
if length(Layout)>0 then
for c := 0 to high(Layout) do
begin
if c>0 then
begin
LastX:=MaxRowX + PANE_COLUMN_SPACER;
MaxRowX:=LastX;
end
else
begin
LastX:=MaxRowX;
end;
ColumnX:=LastX;
rows:=length(Layout[c]);
if rows>0 then
for r := 0 to rows - 1 do
begin
LastX:=ColumnX;
if length(Layout[c][r])>0 then
for i := 0 to high(Layout[c][r]) do
begin
ItemGroupBehaviour:=FItems[Layout[c][r][i]].GetGroupBehaviour;
ItemSize:=FItems[Layout[c][r][i]].GetSize;
ItemWidth:=FItems[Layout[c][r][i]].GetWidth;
if ItemSize = isLarge then
begin
tmpRect.top:=PANE_FULL_ROW_TOPPADDING;
tmpRect.bottom:=tmpRect.top + PANE_FULL_ROW_HEIGHT - 1;
tmpRect.left:=LastX;
tmpRect.right:=LastX + ItemWidth - 1;
LastX:=tmpRect.right + 1;
if LastX>MaxRowX then
MaxRowX:=LastX;
end
else
begin
if ItemGroupBehaviour in [gbContinuesGroup, gbEndsGroup] then
begin
tmpRect.Left:=LastX;
tmpRect.right:=tmpRect.Left + ItemWidth - 1;
end
else
begin
// Jeœli element nie jest pierwszy, musi zostaæ
// odsuniêty marginesem od poprzedniego
if i>0 then
tmpRect.Left:=LastX + PANE_GROUP_SPACER else
tmpRect.Left:=LastX;
tmpRect.right:=tmpRect.Left + ItemWidth - 1;
end;
{$REGION 'Obliczanie tmpRect.top i bottom'}
case rows of
1 : begin
tmpRect.top:=PANE_ONE_ROW_TOPPADDING;
tmpRect.bottom:=tmpRect.top + PANE_ROW_HEIGHT - 1;
end;
2 : begin
case r of
0 : begin
tmpRect.top:=PANE_TWO_ROWS_TOPPADDING;
tmpRect.bottom:=tmpRect.top + PANE_ROW_HEIGHT - 1;
end;
1 : begin
tmpRect.top:=PANE_TWO_ROWS_TOPPADDING + PANE_ROW_HEIGHT + PANE_TWO_ROWS_VSPACER;
tmpRect.bottom:=tmpRect.top + PANE_ROW_HEIGHT - 1;
end;
end;
end;
3 : begin
case r of
0 : begin
tmpRect.top:=PANE_THREE_ROWS_TOPPADDING;
tmpRect.bottom:=tmpRect.top + PANE_ROW_HEIGHT - 1;
end;
1 : begin
tmpRect.top:=PANE_THREE_ROWS_TOPPADDING + PANE_ROW_HEIGHT + PANE_THREE_ROWS_VSPACER;
tmpRect.bottom:=tmpRect.top + PANE_ROW_HEIGHT - 1;
end;
2 : begin
tmpRect.top:=PANE_THREE_ROWS_TOPPADDING + 2 * PANE_ROW_HEIGHT + 2 * PANE_THREE_ROWS_VSPACER;
tmpRect.bottom:=tmpRect.top + PANE_ROW_HEIGHT - 1;
end;
end;
end;
end;
{$ENDREGION}
LastX:=tmpRect.right + 1;
if LastX>MaxRowX then
MaxRowX:=LastX;
end;
Result.Rects[Layout[c][r][i]]:=tmpRect;
end;
end;
end;
// W tym miejscu MaxRowX wskazuje na pierwszy piksel za najbardziej wysuniêtym
// w prawo elementem - ergo jest równy szerokoœci ca³ego layoutu.
Result.Width:=MaxRowX;
end;
procedure TSpkPane.GetChildren(Proc: TGetChildProc; Root: TComponent);
var
i: Integer;
begin
inherited;
if FItems.Count>0 then
for i := 0 to FItems.Count - 1 do
Proc(FItems.Items[i]);
end;
function TSpkPane.GetWidth: integer;
var tmpBitmap : TBitmap;
PaneCaptionWidth, PaneElementsWidth : integer;
TextW : integer;
ElementsW : integer;
Layout : TSpkPaneItemsLayout;
begin
// Przygotowywanie...
result:=-1;
if FToolbarDispatch=nil then
exit;
if FAppearance=nil then
exit;
tmpBitmap:=FToolbarDispatch.GetTempBitmap;
if tmpBitmap=nil then
exit;
tmpBitmap.Canvas.font.assign(FAppearance.Pane.CaptionFont);
// *** Minimalna szerokoϾ tafli (tekstu) ***
TextW:=tmpBitmap.Canvas.TextWidth(FCaption);
PaneCaptionWidth:=2*PANE_BORDER_SIZE +
2*PANE_CAPTION_HMARGIN +
TextW;
// *** Szerokoœæ elementów tafli ***
Layout:=GenerateLayout;
ElementsW:=Layout.Width;
PaneElementsWidth:=PANE_BORDER_SIZE + PANE_LEFT_PADDING + ElementsW + PANE_RIGHT_PADDING + PANE_BORDER_SIZE;
// *** Ustawianie szerokoœci tafli ***
result:=max(PaneCaptionWidth, PaneElementsWidth);
end;
procedure TSpkPane.Loaded;
begin
inherited;
if FItems.ListState = lsNeedsProcessing then
FItems.ProcessNames(self.Owner);
end;
procedure TSpkPane.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
Y: Integer);
begin
if FMouseActiveElement.ElementType = peItem then
begin
if FMouseActiveElement.ElementIndex<>-1 then
FItems[FMouseActiveElement.ElementIndex].MouseDown(Button, Shift, X, Y);
end else
if FMouseActiveElement.ElementType = pePaneArea then
begin
FPaneState:=psHover;
end else
if FMouseActiveElement.ElementType = peNone then
begin
if FMouseHoverElement.ElementType = peItem then
begin
if FMouseHoverElement.ElementIndex<>-1 then
begin
FMouseActiveElement.ElementType:=peItem;
FMouseActiveElement.ElementIndex:=FMouseHoverElement.ElementIndex;
FItems[FMouseHoverElement.ElementIndex].MouseDown(Button, Shift, X, Y);
end
else
begin
FMouseActiveElement.ElementType:=pePaneArea;
FMouseActiveElement.ElementIndex:=-1;
end;
end else
if FMouseHoverElement.ElementType = pePaneArea then
begin
FMouseActiveElement.ElementType:=pePaneArea;
FMouseActiveElement.ElementIndex:=-1;
// Placeholder, jeœli zajdzie potrzeba obs³ugi tego zdarzenia.
end;
end;
end;
procedure TSpkPane.MouseLeave;
begin
if FMouseActiveElement.ElementType = peNone then
begin
if FMouseHoverElement.ElementType = peItem then
begin
if FMouseHoverElement.ElementIndex<>-1 then
FItems[FMouseHoverElement.ElementIndex].MouseLeave;
end else
if FMouseHoverElement.ElementType = pePaneArea then
begin
// Placeholder, jeœli zajdzie potrzeba obs³ugi tego zdarzenia.
end;
end;
FMouseHoverElement.ElementType:=peNone;
FMouseHoverElement.ElementIndex:=-1;
// Niezale¿nie od tego, który element by³ aktywny / pod mysz¹, trzeba
// wygasiæ HotTrack.
if FPaneState<>psIdle then
begin
FPaneState:=psIdle;
if assigned(FToolbarDispatch) then
FToolbarDispatch.NotifyVisualsChanged;
end;
end;
procedure TSpkPane.MouseMove(Shift: TShiftState; X, Y: Integer);
var i : integer;
NewMouseHoverElement : TSpkMousePaneElement;
begin
// MouseMove jest wywo³ywany tylko, gdy tafla jest aktywna, b¹dŸ gdy
// mysz rusza siê wewn¹trz jej obszaru. Wobec tego zawsze nale¿y
// w tej sytuacji zapaliæ HotTrack.
if FPaneState = psIdle then
begin
FPaneState:=psHover;
if assigned(FToolbarDispatch) then
FToolbarDispatch.NotifyVisualsChanged;
end;
// Szukamy obiektu pod mysz¹
i:=FindItemAt(x, y);
if i<>-1 then
begin
NewMouseHoverElement.ElementType:=peItem;
NewMouseHoverElement.ElementIndex:=i;
end else
if (X>=FRect.left) and (Y>=FRect.top) and
(X<=FRect.right) and (Y<=FRect.bottom) then
begin
NewMouseHoverElement.ElementType:=pePaneArea;
NewMouseHoverElement.ElementIndex:=-1;
end else
begin
NewMouseHoverElement.ElementType:=peNone;
NewMouseHoverElement.ElementIndex:=-1;
end;
if FMouseActiveElement.ElementType = peItem then
begin
if FMouseActiveElement.ElementIndex<>-1 then
FItems[FMouseActiveElement.ElementIndex].MouseMove(Shift, X, Y);
end else
if FMouseActiveElement.ElementType = pePaneArea then
begin
// Placeholder, jeœli zajdzie potrzeba obs³ugi tego zdarzenia
end else
if FMouseActiveElement.ElementType = peNone then
begin
// Jeœli element pod mysz¹ siê zmienia, informujemy poprzedni element o
// tym, ¿e mysz opuszcza jego obszar
if (NewMouseHoverElement.ElementType<>FMouseHoverElement.ELementType) or
(NewMouseHoverElement.ElementIndex<>FMouseHoverElement.ElementIndex) then
begin
if FMouseHoverElement.ElementType = peItem then
begin
if FMouseHoverElement.ElementIndex<>-1 then
FItems[FMouseHoverElement.ElementIndex].MouseLeave;
end else
if FMouseHoverElement.ElementType = pePaneArea then
begin
// Placeholder, jeœli zajdzie potrzeba obs³ugi tego zdarzenia
end;
end;
if NewMouseHoverElement.ElementType = peItem then
begin
if NewMouseHoverElement.ElementIndex<>-1 then
FItems[NewMouseHoverElement.ElementIndex].MouseMove(Shift, X, Y);
end else
if NewMouseHoverElement.ElementType = pePaneArea then
begin
// Placeholder, jeœli zajdzie potrzeba obs³ugi tego zdarzenia
end;
end;
FMouseHoverElement:=NewMouseHoverElement;
end;
procedure TSpkPane.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
Y: Integer);
var ClearActive : boolean;
begin
ClearActive:=not(ssLeft in Shift) and not(ssMiddle in Shift) and not(ssRight in Shift);
if FMouseActiveElement.ElementType = peItem then
begin
if FMouseActiveElement.ElementIndex<>-1 then
FItems[FMouseActiveElement.ElementIndex].MouseUp(Button, Shift, X, Y);
end else
if FMouseActiveElement.ElementType = pePaneArea then
begin
// Placeholder, jeœli zajdzie potrzeba obs³ugi tego zdarzenia.
end;
if ClearActive and
(FMouseActiveElement.ElementType<>FMouseHoverElement.ElementType) or
(FMouseActiveElement.ElementIndex<>FMouseHoverElement.ElementIndex) then
begin
if FMouseActiveElement.ElementType = peItem then
begin
if FMouseActiveElement.ElementIndex<>-1 then
FItems[FMouseActiveElement.ElementIndex].MouseLeave;
end else
if FMouseActiveElement.ElementType = pePaneArea then
begin
// Placeholder, jeœli zajdzie potrzeba obs³ugi tego zdarzenia.
end;
if FMouseHoverElement.ElementType = peItem then
begin
if FMouseActiveElement.ElementIndex<>-1 then
FItems[FMouseActiveElement.ElementIndex].MouseMove(Shift, X, Y);
end else
if FMouseHoverElement.ElementType = pePaneArea then
begin
// Placeholder, jeœli zajdzie potrzeba obs³ugi tego zdarzenia.
end else
if FMouseHoverElement.ElementType = peNone then
begin
if FPaneState<>psIdle then
begin
FPaneState:=psIdle;
if assigned(FToolbarDispatch) then
FToolbarDispatch.NotifyVisualsChanged;
end;
end;
end;
if ClearActive then
begin
FMouseActiveElement.ElementType:=peNone;
FMouseActiveElement.ElementIndex:=-1;
end;
end;
procedure TSpkPane.SetAppearance(const Value: TSpkToolbarAppearance);
begin
FAppearance := Value;
FItems.Appearance := Value;
end;
procedure TSpkPane.SetCaption(const Value: string);
begin
FCaption := Value;
if assigned(FToolbarDispatch) then
FToolbarDispatch.NotifyMetricsChanged;
end;
procedure TSpkPane.SetDisabledImages(const Value: TImageList);
begin
FDisabledImages := Value;
FItems.DisabledImages:=FDisabledImages;
end;
procedure TSpkPane.SetDisabledLargeImages(const Value: TImageList);
begin
FDisabledLargeImages := Value;
FItems.DisabledLargeImages:=FDisabledLargeImages;
end;
procedure TSpkPane.SetImages(const Value: TImageList);
begin
FImages := Value;
FItems.Images:=FImages;
end;
procedure TSpkPane.SetLargeImages(const Value: TImageList);
begin
FLargeImages := Value;
FItems.LargeImages:=FLargeImages;
end;
procedure TSpkPane.SetVisible(const Value: boolean);
begin
FVisible := Value;
if assigned(FToolbarDispatch) then
FToolbarDispatch.NotifyItemsChanged;
end;
{ TSpkPanes }
function TSpkPanes.Add: TSpkPane;
begin
Result:=TSpkPane.Create(FRootComponent);
Result.Parent:=FRootComponent;
AddItem(Result);
end;
function TSpkPanes.GetItems(index: integer): TSpkPane;
begin
result:=TSpkPane(inherited Items[index]);
end;
function TSpkPanes.Insert(index: integer): TSpkPane;
var Owner, Parent : TComponent;
i: Integer;
begin
if (index<0) or (index>self.Count) then
raise InternalException.create('TSpkPanes.Insert: Nieprawid³owy indeks!');
if FRootComponent<>nil then
begin
Owner:=FRootComponent.Owner;
Parent:=FRootComponent;
end
else
begin
Owner:=nil;
Parent:=nil;
end;
result:=TSpkPane.Create(Owner);
result.Parent:=Parent;
if FRootComponent<>nil then
begin
i:=0;
while FRootComponent.Owner.FindComponent('SpkPane'+inttostr(i))<>nil do
inc(i);
result.Name:='SpkPane'+inttostr(i);
end;
InsertItem(index,result);
end;
procedure TSpkPanes.Notify(Item: TComponent;
Operation : TOperation);
begin
inherited Notify(Item, Operation);
case Operation of
opInsert: begin
// Ustawienie dyspozytora na nil spowoduje, ¿e podczas
// przypisywania w³asnoœci nie bêd¹ wo³ane metody Notify*
TSpkPane(Item).ToolbarDispatch:=nil;
TSpkPane(Item).Appearance:=FAppearance;
TSpkPane(Item).Images:=FImages;
TSpkPane(Item).DisabledImages:=FDisabledImages;
TSpkPane(Item).LargeImages:=FLargeImages;
TSpkPane(Item).DisabledLargeImages:=FDisabledLargeImages;
TSpkPane(Item).ToolbarDispatch:=FToolbarDispatch;
end;
opRemove: begin
if not(csDestroying in Item.ComponentState) then
begin
TSpkPane(Item).ToolbarDispatch:=nil;
TSpkPane(Item).Appearance:=nil;
TSpkPane(Item).Images:=nil;
TSpkPane(Item).DisabledImages:=nil;
TSpkPane(Item).LargeImages:=nil;
TSpkPane(Item).DisabledLargeImages:=nil;
end;
end;
end;
end;
procedure TSpkPanes.SetImages(const Value: TImageList);
var
I: Integer;
begin
FImages := Value;
if self.Count>0 then
for I := 0 to self.count - 1 do
Items[i].Images:=Value;
end;
procedure TSpkPanes.SetLargeImages(const Value: TImageList);
var
I: Integer;
begin
FLargeImages := Value;
if self.Count>0 then
for I := 0 to self.count - 1 do
Items[i].LargeImages:=Value;
end;
procedure TSpkPanes.SetToolbarDispatch(const Value: TSpkBaseToolbarDispatch);
var i : integer;
begin
FToolbarDispatch := Value;
if self.Count>0 then
for i := 0 to self.count - 1 do
Items[i].ToolbarDispatch:=FToolbarDispatch;
end;
procedure TSpkPanes.SetAppearance(const Value: TSpkToolbarAppearance);
var i: Integer;
begin
FAppearance := Value;
if self.Count>0 then
for i := 0 to self.count - 1 do
Items[i].Appearance:=FAppearance;
if FToolbarDispatch<>nil then
FToolbarDispatch.NotifyMetricsChanged;
end;
procedure TSpkPanes.SetDisabledImages(const Value: TImageList);
var I: Integer;
begin
FDisabledImages := Value;
if self.Count>0 then
for I := 0 to self.count - 1 do
Items[i].DisabledImages:=Value;
end;
procedure TSpkPanes.SetDisabledLargeImages(const Value: TImageList);
var
I: Integer;
begin
FDisabledLargeImages := Value;
if self.Count>0 then
for I := 0 to self.count - 1 do
Items[i].DisabledLargeImages:=Value;
end;
procedure TSpkPanes.Update;
begin
inherited Update;
if assigned(FToolbarDispatch) then
FToolbarDispatch.NotifyItemsChanged;
end;
end.