| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056 |
- // SPDX-License-Identifier: GPL-3.0-only
- unit UMainFormLayout;
- {$mode objfpc}{$H+}
- interface
- uses
- Classes, LCLType, SysUtils, UMenu, Forms, LazPaintType, UZoom, ExtCtrls, ComCtrls,
- Menus, UPaletteToolbar, BGRABitmapTypes, Controls, UImageView;
- const SelectionPaintDelay = 100/(1000*60*60*24);
- VerticalSplitterWidth = 4;
- type
- TOnPictureAreaChange = procedure(ASender: TObject; ANewArea: TRect) of object;
- TToolWindowDocking = (twNone, twWindow, twLeft, twTop, twRight, twBottom);
- TLayoutStage = (lsAfterTopToolbar, lsAfterDockedToolBox, lsAfterPaletteToolbar,
- lsAfterDockedControlsPanel, lsAfterVerticalSplitter, lsAfterStatusBar);
- { TMainFormLayout }
- TMainFormLayout = class(TCustomMainFormLayout)
- private
- FForm: TForm;
- FOnPaintPicture: TNotifyEvent;
- FOnPictureMouseBefore: TPictureMouseBeforeEvent;
- FOnPictureMouseMove: TPictureMouseMoveEvent;
- FOnToolbarUpdate: TNotifyEvent;
- FZoom: TZoom;
- FMenu: TMainFormMenu;
- FLazPaintInstance: TLazPaintCustomInstance;
- FToolBoxDocking: TToolWindowDocking;
- FInSetToolBoxDocking: boolean;
- FPanelToolBox: TPanel;
- FDockedToolBoxToolBar: TToolBar;
- FPaletteToolbar: TPaletteToolbar;
- FStatusBarVisible: boolean;
- FStatusBar: TPanel;
- FStatusText: string;
- FStatusTextSplit: TStringList;
- FDarkTheme: boolean;
- FDockedControlsPanel: TPanel;
- FDockedChooseColorSplitter: TSplitter;
- FVerticalSplitter: TSplitter;
- FPaintBox: TOpaquePaintBox;
- FImageView: TImageView;
- FArranging: boolean;
- function GetFillSelectionHighlight: boolean;
- function GetMouseButtonState: TShiftState;
- function GetPaletteVisible: boolean;
- function GetPopupToolbox: TPopupMenu;
- function GetStatusBarVisible: boolean;
- function GetStatusText: string;
- function GetToolBoxVisible: boolean;
- function GetUpdatingPopup: boolean;
- procedure ImageToolbarUpdate(Sender: TObject);
- procedure ImageViewMouseBefore({%H-}ASender: TObject; AShift: TShiftState);
- procedure ImageViewMouseMove(Sender: TObject; APosition: TPointF);
- procedure ImageViewOnPaint(Sender: TObject);
- procedure SetFillSelectionHighlight(AValue: boolean);
- procedure SetOnPaintPicture(AValue: TNotifyEvent);
- procedure SetUpdatingPopup(AValue: boolean);
- procedure StatusBar_Paint(Sender: TObject);
- procedure ToolboxGroupMainButton_MouseMove(Sender: TObject; {%H-}Shift: TShiftState; {%H-}X,
- {%H-}Y: Integer);
- procedure SetDarkTheme(AValue: boolean);
- procedure SetLazPaintInstance(AValue: TLazPaintCustomInstance);
- procedure SetPaletteVisible(AValue: boolean);
- procedure SetPopupToolbox(AValue: TPopupMenu);
- procedure SetStatusBarVisible(AValue: boolean);
- procedure SetStatusText(AValue: string);
- procedure SetToolBoxDocking(AValue: TToolWindowDocking);
- procedure SetToolBoxVisible(AValue: boolean);
- function GetDefaultToolboxDocking: TToolWindowDocking;
- procedure ToolboxGroupButton_Click(Sender: TObject);
- procedure ToolboxGroupTimer_Timer(Sender: TObject);
- procedure ToolboxGroupToolbarButton_MouseEnter(Sender: TObject);
- procedure ToolboxGroupToolbarButton_MouseLeave(Sender: TObject);
- procedure ToolboxSimpleButton_Click(Sender: TObject);
- procedure PaletteVisibilityChangedByUser(Sender: TObject);
- procedure VerticalSplitterMoved(Sender: TObject);
- procedure ZoomChanged(sender: TZoom; ANewZoom: single);
- protected
- FDockedToolboxGroup: array of record
- Button: TToolButton;
- Panel: TPanel;
- Toolbar: TToolBar;
- Timer: TTimer;
- end;
- function GetWorkArea: TRect; override;
- function GetWorkAreaAt(AStage: TLayoutStage): TRect;
- function VerticalSplitterNeeded: boolean;
- procedure DoArrange;
- procedure ApplyTheme;
- function DockedControlsPanelWidth: integer;
- function DockedControlsPanelInnerMargin: integer;
- procedure ApplyThemeToDockedToolboxGroup(AGroupIndex: integer);
- procedure ShowToolboxGroup(AGroupIndex: integer);
- procedure HideToolboxGroup(AGroupIndex: integer);
- procedure HideToolboxGroups;
- public
- DelayedPaintPicture: boolean;
- constructor Create(AForm: TForm; AZoom: TZoom);
- destructor Destroy; override;
- function CatchToolKeyDown(var AKey: Word): boolean;
- function CatchToolKeyPress(var AKey: TUTF8Char): boolean;
- function CatchToolKeyUp(var AKey: Word): boolean;
- procedure Arrange;
- procedure FocusImage;
- procedure CheckDelayedUpdate;
- procedure DockedToolBoxAddButton(AAction: TBasicAction);
- procedure DockedToolBoxAddGroup(AActions: array of TBasicAction);
- procedure DockedToolBoxSetImages(AImages: TImageList);
- procedure AddColorToPalette(AColor : TBGRAPixel);
- procedure RemoveColorFromPalette(AColor : TBGRAPixel);
- procedure AddDockedControl(AControl: TControl);
- procedure RemoveDockedControl(AControl: TControl);
- procedure PaintPictureNow;
- procedure InvalidatePicture(AInvalidateAll: boolean);
- procedure ShowNoPicture;
- property Menu: TMainFormMenu read FMenu write FMenu;
- property Arranging: boolean read FArranging;
- property ToolBoxDocking: TToolWindowDocking read FToolBoxDocking write SetToolBoxDocking;
- property ToolBoxVisible: boolean read GetToolBoxVisible write SetToolBoxVisible;
- property LazPaintInstance: TLazPaintCustomInstance read FLazPaintInstance write SetLazPaintInstance;
- property ToolboxPopup: TPopupMenu read GetPopupToolbox write SetPopupToolbox;
- property PaletteVisible: boolean read GetPaletteVisible write SetPaletteVisible;
- property PaletteToolbar: TPaletteToolbar read FPaletteToolbar;
- property StatusBarVisible: boolean read GetStatusBarVisible write SetStatusBarVisible;
- property StatusText: string read GetStatusText write SetStatusText;
- property DefaultToolboxDocking: TToolWindowDocking read GetDefaultToolboxDocking;
- property DarkTheme: boolean read FDarkTheme write SetDarkTheme;
- property OnPaintPicture: TNotifyEvent read FOnPaintPicture write SetOnPaintPicture;
- property OnToolbarUpdate: TNotifyEvent read FOnToolbarUpdate write FOnToolbarUpdate;
- property OnPictureMouseMove: TPictureMouseMoveEvent read FOnPictureMouseMove write FOnPictureMouseMove;
- property OnPictureMouseBefore: TPictureMouseBeforeEvent read FOnPictureMouseBefore write FOnPictureMouseBefore;
- property FillSelectionHighlight: boolean read GetFillSelectionHighlight write SetFillSelectionHighlight;
- property UpdatingPopup: boolean read GetUpdatingPopup write SetUpdatingPopup;
- property MouseButtonState: TShiftState read GetMouseButtonState;
- end;
- function ToolWindowDockingToStr(AValue: TToolWindowDocking): string;
- function StrToToolWindowDocking(AValue: string): TToolWindowDocking;
- implementation
- uses Graphics, Toolwin, math, UDarkTheme, LCScaleDPI;
- function ToolWindowDockingToStr(AValue: TToolWindowDocking): string;
- begin
- case AValue of
- twNone: result := 'None';
- twWindow: result := 'Window';
- twLeft: result := 'Left';
- twRight: result := 'Right';
- twTop: result := 'Top';
- twBottom: result := 'Bottom';
- else
- result := 'Window';
- end;
- end;
- function StrToToolWindowDocking(AValue: string): TToolWindowDocking;
- begin
- if CompareText(AValue,'None') = 0 then
- result := twNone
- else if CompareText(AValue,'Window') = 0 then
- result := twWindow
- else if CompareText(AValue,'Left') = 0 then
- result := twLeft
- else if CompareText(AValue,'Top') = 0 then
- result := twTop
- else if CompareText(AValue,'Right') = 0 then
- result := twRight
- else if CompareText(AValue,'Bottom') = 0 then
- result := twBottom
- else
- result := twWindow;
- end;
- { TMainFormLayout }
- constructor TMainFormLayout.Create(AForm: TForm; AZoom: TZoom);
- begin
- FForm := AForm;
- FZoom := AZoom;
- FZoom.OnZoomChanged:=@ZoomChanged;
- FZoom.Layout := self;
- FPanelToolBox := TPanel.Create(nil);
- FPanelToolBox.BevelInner := bvNone;
- FPanelToolBox.BevelOuter := bvNone;
- FPanelToolBox.Width := 20;
- FPanelToolBox.Visible := false;
- FPanelToolBox.Cursor := crArrow;
- FDockedToolBoxToolBar := TToolBar.Create(FPanelToolBox);
- FDockedToolBoxToolBar.Align := alClient;
- FDockedToolBoxToolBar.EdgeBorders := [ebLeft,ebRight];
- FDockedToolBoxToolBar.Indent := 0;
- FDockedToolBoxToolBar.EdgeInner := esNone;
- FDockedToolBoxToolBar.EdgeOuter := esNone;
- FDockedToolBoxToolBar.ShowHint := true;
- FDockedToolBoxToolBar.Cursor := crArrow;
- FPanelToolBox.InsertControl(FDockedToolBoxToolBar);
- FForm.InsertControl(FPanelToolBox);
- FPaletteToolbar := TPaletteToolbar.Create;
- FPaletteToolbar.DarkTheme:= DarkTheme;
- FPaletteToolbar.OnVisibilityChangedByUser:= @PaletteVisibilityChangedByUser;
- FPaletteToolbar.Container := FForm;
- FVerticalSplitter := TSplitter.Create(nil);
- FVerticalSplitter.Visible := False;
- FVerticalSplitter.Align := alNone;
- FVerticalSplitter.Width := DoScaleX(VerticalSplitterWidth, OriginalDPI);
- FVerticalSplitter.Anchors := [akRight,akTop,akBottom];
- FForm.InsertControl(FVerticalSplitter);
- FDockedControlsPanel := TPanel.Create(nil);
- FDockedControlsPanel.Visible := false;
- FDockedControlsPanel.Anchors:= [akRight,akTop,akBottom];
- FForm.InsertControl(FDockedControlsPanel);
- FStatusBar := TPanel.Create(nil);
- FStatusBar.Align := alNone;
- FStatusBar.Visible := false;
- FStatusBar.Anchors := [akLeft,akRight,akBottom];
- FStatusBar.BevelOuter:= bvNone;
- FStatusBar.BevelInner:= bvNone;
- FStatusBar.Height := DoScaleY(15, OriginalDPI);
- FStatusBar.Font.Height := -DoScaleY(12, OriginalDPI);
- FStatusBar.OnPaint:=@StatusBar_Paint;
- FStatusTextSplit := TStringList.Create;
- FForm.InsertControl(FStatusBar);
- FPaintBox := TOpaquePaintBox.Create(nil);
- FForm.InsertControl(FPaintBox,0);
- FImageView := nil;
- FArranging := false;
- ApplyTheme;
- end;
- destructor TMainFormLayout.Destroy;
- begin
- FZoom.Layout := nil;
- if not FDockedControlsPanel.Visible then
- LazPaintInstance.Config.SetDefaultDockLayersAndColorsWidth(0);
- FreeAndNil(FImageView);
- FreeAndNil(FPaintBox);
- FreeAndNil(FDockedControlsPanel);
- FreeAndNil(FVerticalSplitter);
- FreeAndNil(FStatusBar);
- FreeAndNil(FStatusTextSplit);
- FreeAndNil(FPaletteToolbar);
- FreeAndNil(FPanelToolBox);
- FreeAndNil(FMenu);
- inherited Destroy;
- end;
- function TMainFormLayout.CatchToolKeyDown(var AKey: Word): boolean;
- begin
- if Assigned(FImageView) then
- begin
- result := FImageView.CatchToolKeyDown(AKey);
- if not result and Assigned(FPaletteToolbar) then
- result := FPaletteToolbar.CatchToolKeyDown(AKey);
- end else result := false;
- end;
- function TMainFormLayout.CatchToolKeyUp(var AKey: Word): boolean;
- begin
- if Assigned(FImageView) then
- begin
- result := FImageView.CatchToolKeyUp(AKey);
- if not result and Assigned(FPaletteToolbar) then
- result := FPaletteToolbar.CatchToolKeyUp(AKey);
- end else result := false;
- end;
- function TMainFormLayout.CatchToolKeyPress(var AKey: TUTF8Char): boolean;
- begin
- if Assigned(FImageView) then
- result := FImageView.CatchToolKeyPress(AKey)
- else result := false;
- end;
- procedure TMainFormLayout.SetToolBoxDocking(AValue: TToolWindowDocking);
- begin
- if FInSetToolBoxDocking or (FToolBoxDocking=AValue) then Exit;
- FInSetToolBoxDocking := true;
- FToolBoxDocking:=AValue;
- if Assigned(FLazPaintInstance) then
- begin
- FLazPaintInstance.ToolboxVisible := AValue <> twNone;
- if AValue <> twNone then
- FLazPaintInstance.Config.SetDefaultToolboxDocking(ToolWindowDockingToStr(AValue));
- end;
- DoArrange;
- FInSetToolBoxDocking := false;
- end;
- function TMainFormLayout.GetToolBoxVisible: boolean;
- begin
- result := LazPaintInstance.ToolboxVisible;
- end;
- function TMainFormLayout.GetUpdatingPopup: boolean;
- begin
- if Assigned(FImageView) then
- result := FImageView.UpdatingPopup
- else result := False;
- end;
- procedure TMainFormLayout.ImageToolbarUpdate(Sender: TObject);
- begin
- if Assigned(FOnToolbarUpdate) then
- FOnToolbarUpdate(self);
- end;
- procedure TMainFormLayout.ImageViewMouseBefore(ASender: TObject;
- AShift: TShiftState);
- begin
- if Assigned(FOnPictureMouseBefore) then
- FOnPictureMouseBefore(self, AShift);
- end;
- procedure TMainFormLayout.ImageViewMouseMove(Sender: TObject; APosition: TPointF);
- begin
- if Assigned(FOnPictureMouseMove) then
- FOnPictureMouseMove(self, APosition);
- end;
- procedure TMainFormLayout.ImageViewOnPaint(Sender: TObject);
- begin
- if Assigned(FOnPaintPicture) then
- FOnPaintPicture(self);
- end;
- procedure TMainFormLayout.SetFillSelectionHighlight(AValue: boolean);
- begin
- if Assigned(FImageView) then
- FImageView.FillSelectionHighlight := AValue;
- end;
- procedure TMainFormLayout.SetOnPaintPicture(AValue: TNotifyEvent);
- begin
- if FOnPaintPicture=AValue then Exit;
- FOnPaintPicture:=AValue;
- end;
- procedure TMainFormLayout.SetUpdatingPopup(AValue: boolean);
- begin
- if Assigned(FImageView) then
- FImageView.UpdatingPopup := AValue;
- end;
- procedure TMainFormLayout.StatusBar_Paint(Sender: TObject);
- var
- colWidth, spacing, i, x: Integer;
- begin
- if FStatusTextSplit.Count > 0 then
- begin
- FStatusBar.Canvas.Brush.Style := bsClear;
- spacing := DoScaleX(6, OriginalDPI);
- colWidth := (FStatusBar.ClientWidth - spacing*2) div FStatusTextSplit.Count;
- if colWidth > spacing*2 then
- begin
- FStatusBar.Canvas.Pen.Color := DarkThemeInstance.GetColorPanelHighlight(DarkTheme);
- FStatusBar.Canvas.Line(0,0, FStatusBar.Width,0);
- x := 0;
- for i := 0 to FStatusTextSplit.Count-1 do
- begin
- FStatusBar.Canvas.Font := FStatusBar.Font;
- FStatusBar.Canvas.Font.Color := DarkThemeInstance.GetColorButtonText(DarkTheme);
- FStatusBar.Canvas.TextOut(x + spacing,
- (FStatusBar.ClientHeight - FStatusBar.Canvas.TextHeight('Hg')) div 2,
- FStatusTextSplit[i]);
- if i > 0 then
- begin
- FStatusBar.Canvas.Pen.Color := DarkThemeInstance.GetColorPanelShadow(DarkTheme);
- FStatusBar.Canvas.Line(x-1,0, x-1,FStatusBar.Height);
- FStatusBar.Canvas.Pen.Color := DarkThemeInstance.GetColorPanelHighlight(DarkTheme);
- FStatusBar.Canvas.Line(x,0, x,FStatusBar.Height);
- end;
- inc(x, max(colWidth, FStatusBar.Canvas.TextWidth(FStatusTextSplit[i]) + 2*spacing));
- end;
- end;
- end;
- end;
- procedure TMainFormLayout.ToolboxGroupMainButton_MouseMove(Sender: TObject;
- Shift: TShiftState; X, Y: Integer);
- var
- button: TToolButton;
- begin
- button := Sender as TToolButton;
- ShowToolboxGroup(button.Tag);
- end;
- procedure TMainFormLayout.SetDarkTheme(AValue: boolean);
- begin
- if FDarkTheme=AValue then Exit;
- FDarkTheme:=AValue;
- ApplyTheme;
- if Assigned(FPaletteToolbar) then
- FPaletteToolbar.DarkTheme:= AValue;
- if Assigned(FMenu) then
- FMenu.DarkTheme:= AValue;
- InvalidatePicture(true);
- end;
- procedure TMainFormLayout.SetLazPaintInstance(AValue: TLazPaintCustomInstance);
- begin
- if FLazPaintInstance=AValue then Exit;
- FLazPaintInstance:=AValue;
- FPaletteToolbar.LazPaintInstance:= AValue;
- FStatusBarVisible := LazPaintInstance.Config.GetStatusBarVisible;
- if Assigned(FImageView) then FreeAndNil(FImageView);
- FImageView := TImageView.Create(FLazPaintInstance, FZoom, FPaintBox);
- FImageView.OnPaint:=@ImageViewOnPaint;
- FImageView.OnToolbarUpdate:=@ImageToolbarUpdate;
- FImageView.OnMouseMove:=@ImageViewMouseMove;
- FImageView.OnMouseBefore:=@ImageViewMouseBefore;
- end;
- procedure TMainFormLayout.SetPaletteVisible(AValue: boolean);
- begin
- if FPaletteToolbar.Visible=AValue then Exit;
- FPaletteToolbar.Visible:=AValue;
- Arrange;
- end;
- function TMainFormLayout.GetPopupToolbox: TPopupMenu;
- begin
- result := FPanelToolBox.PopupMenu;
- end;
- function TMainFormLayout.GetStatusBarVisible: boolean;
- begin
- result := FStatusBarVisible;
- end;
- function TMainFormLayout.GetStatusText: string;
- begin
- result := FStatusText;
- end;
- procedure TMainFormLayout.PaletteVisibilityChangedByUser(Sender: TObject);
- begin
- Arrange;
- end;
- procedure TMainFormLayout.VerticalSplitterMoved(Sender: TObject);
- begin
- LazPaintInstance.Config.SetDefaultDockLayersAndColorsWidth(
- FDockedControlsPanel.Width - DockedControlsPanelInnerMargin);
- if Assigned(FImageView) then
- FImageView.InvalidatePicture(true);
- end;
- procedure TMainFormLayout.ZoomChanged(sender: TZoom; ANewZoom: single);
- begin
- if Assigned(FImageView) then
- begin
- if not LazPaintInstance.Image.SelectionMaskEmpty then
- FImageView.ShowSelection := false;
- FImageView.OnZoomChanged(sender, ANewZoom);
- end;
- PaintPictureNow;
- end;
- function TMainFormLayout.GetPaletteVisible: boolean;
- begin
- result := FPaletteToolbar.Visible;
- end;
- function TMainFormLayout.GetFillSelectionHighlight: boolean;
- begin
- if Assigned(FImageView) then
- result := FillSelectionHighlight
- else result := false;
- end;
- function TMainFormLayout.GetMouseButtonState: TShiftState;
- begin
- if Assigned(FImageView) then
- result := FImageView.MouseButtonState
- else result := [];
- end;
- procedure TMainFormLayout.SetPopupToolbox(AValue: TPopupMenu);
- begin
- FPanelToolBox.PopupMenu := AValue;
- if LazPaintInstance <> nil then
- LazPaintInstance.ToolboxWindowPopup := AValue;
- end;
- procedure TMainFormLayout.SetStatusBarVisible(AValue: boolean);
- begin
- FStatusBarVisible := AValue;
- LazPaintInstance.Config.SetStatusBarVisible(AValue);
- Arrange;
- end;
- procedure TMainFormLayout.SetStatusText(AValue: string);
- begin
- if AValue = FStatusText then exit;
- FStatusText := AValue;
- FStatusTextSplit.Delimiter:= '|';
- FStatusTextSplit.StrictDelimiter:= true;
- FStatusTextSplit.DelimitedText := FStatusText;
- FStatusBar.Invalidate;
- end;
- procedure TMainFormLayout.SetToolBoxVisible(AValue: boolean);
- begin
- if AValue then
- ToolBoxDocking:= DefaultToolBoxDocking
- else
- ToolBoxDocking := twNone;
- end;
- function TMainFormLayout.GetDefaultToolboxDocking: TToolWindowDocking;
- begin
- result := StrToToolWindowDocking(FLazPaintInstance.Config.DefaultToolboxDocking);
- end;
- procedure TMainFormLayout.ToolboxGroupButton_Click(Sender: TObject);
- var
- button: TToolButton;
- tb: TToolBar;
- groupIndex: integer;
- begin
- button := Sender as TToolButton;
- tb := button.Parent as TToolBar;
- groupIndex := tb.Tag;
- FDockedToolboxGroup[groupIndex].Button.Action := button.Action;
- end;
- procedure TMainFormLayout.ToolboxGroupTimer_Timer(Sender: TObject);
- var
- groupIdx: integer;
- begin
- groupIdx := (Sender as TTimer).Tag;
- HideToolboxGroup(groupIdx);
- end;
- procedure TMainFormLayout.ToolboxGroupToolbarButton_MouseEnter(Sender: TObject);
- var
- button: TToolButton;
- groupIndex: integer;
- tb: TToolBar;
- begin
- button := Sender as TToolButton;
- tb := button.Parent as TToolbar;
- groupIndex := tb.Tag;
- FDockedToolboxGroup[groupIndex].Timer.Enabled := false;
- end;
- procedure TMainFormLayout.ToolboxGroupToolbarButton_MouseLeave(Sender: TObject);
- var
- button: TToolButton;
- groupIndex: integer;
- tb: TToolBar;
- begin
- button := Sender as TToolButton;
- tb := button.Parent as TToolbar;
- groupIndex := tb.Tag;
- FDockedToolboxGroup[groupIndex].Timer.Enabled := true;
- end;
- procedure TMainFormLayout.ToolboxSimpleButton_Click(Sender: TObject);
- var
- i: Integer;
- begin
- for i := 0 to high(FDockedToolboxGroup) do
- begin
- FDockedToolboxGroup[i].Panel.Visible:= false;
- FDockedToolboxGroup[i].Timer.Enabled:= false;
- end;
- end;
- function TMainFormLayout.GetWorkArea: TRect;
- begin
- result := GetWorkAreaAt(high(TLayoutStage));
- end;
- function TMainFormLayout.GetWorkAreaAt(AStage: TLayoutStage): TRect;
- begin
- result := Rect(0,0,FForm.ClientWidth,FForm.ClientHeight);
- if Assigned(FMenu) then
- result.top += FMenu.ToolbarsHeight;
- if AStage = lsAfterTopToolbar then exit;
- if FToolBoxDocking = twLeft then result.Left += FPanelToolBox.Width else
- if FToolBoxDocking = twRight then result.Right -= FPanelToolBox.Width;
- if AStage = lsAfterDockedToolBox then exit;
- if PaletteVisible then result.Right -= FPaletteToolbar.Width;
- if AStage = lsAfterPaletteToolbar then exit;
- if VerticalSplitterNeeded then result.Right -= DockedControlsPanelWidth;
- if AStage = lsAfterDockedControlsPanel then exit;
- if (AStage = lsAfterVerticalSplitter) and VerticalSplitterNeeded then
- result.Right -= DoScaleX(VerticalSplitterWidth, OriginalDPI);
- if AStage = lsAfterVerticalSplitter then exit;
- if StatusBarVisible then result.Bottom -= FStatusBar.Height;
- if AStage = lsAfterStatusBar then exit;
- end;
- function TMainFormLayout.VerticalSplitterNeeded: boolean;
- begin
- result := FDockedControlsPanel.ControlCount > 0;
- end;
- procedure TMainFormLayout.DoArrange;
- var nbY,nbX,w,i: integer;
- updateChooseColorHeight: Boolean;
- begin
- if Assigned(FMenu) then
- FMenu.ArrangeToolbars(FForm.ClientWidth);
- if FToolBoxDocking in [twLeft,twRight] then
- begin
- with GetWorkAreaAt(lsAfterTopToolbar) do
- begin
- if FToolBoxDocking = twLeft then FDockedToolBoxToolBar.Align:= alLeft
- else FDockedToolBoxToolBar.Align:= alRight;
- FPanelToolBox.Top := top;
- FPanelToolBox.Height:= bottom-top;
- nbY := FPanelToolBox.ClientHeight div FDockedToolBoxToolBar.ButtonHeight;
- if nbY = 0 then nbY := 1;
- nbX := (FDockedToolBoxToolBar.ButtonCount+nbY-1) div nbY;
- if nbX> 5 then nbX := 5;
- w := FDockedToolBoxToolBar.ButtonWidth * nbX+2;
- FDockedToolBoxToolBar.Width := w;
- FPanelToolBox.Width := w;
- if FToolBoxDocking = twLeft then
- begin
- FPanelToolBox.Left:= Left;
- FPanelToolBox.Anchors:= [akLeft,akTop,akBottom];
- end else
- begin
- FPanelToolBox.Left:= Right-FPanelToolBox.Width;
- FPanelToolBox.Anchors:= [akRight,akTop,akBottom];
- end;
- for i := 0 to FDockedToolBoxToolBar.ButtonCount-1 do
- FDockedToolBoxToolBar.Buttons[i].Top := i*FDockedToolBoxToolBar.ButtonHeight;
- end;
- if not FPanelToolBox.Visible then
- begin
- FPanelToolBox.Visible := true;
- FPanelToolBox.SendToBack;
- end;
- end else
- FPanelToolBox.Visible := false;
- if PaletteVisible then
- with GetWorkAreaAt(lsAfterDockedToolBox) do
- FPaletteToolbar.SetBounds(Right - FPaletteToolbar.Width,Top,FPaletteToolbar.Width,Bottom-Top);
- //temporarily disable controlside anchors
- FVerticalSplitter.OnMoved:= nil;
- FDockedControlsPanel.AnchorSideLeft.Control := nil;
- FDockedControlsPanel.Anchors := FDockedControlsPanel.Anchors - [akLeft];
- FPaintBox.AnchorSideRight.Control := nil;
- FPaintBox.Anchors := FPaintBox.Anchors - [akRight];
- FStatusBar.AnchorSideRight.Control := nil;
- if FDockedControlsPanel.ControlCount > 0 then
- begin
- with GetWorkAreaAt(lsAfterPaletteToolbar) do
- begin
- w := DockedControlsPanelWidth;
- updateChooseColorHeight := (FDockedControlsPanel.Width <> w) or not FDockedControlsPanel.Visible;
- FDockedControlsPanel.SetBounds(Right - w, Top, w, Bottom - Top);
- for i := 0 to FDockedControlsPanel.ControlCount-1 do
- if FDockedControlsPanel.Controls[i].Name = 'ChooseColorControl' then
- begin
- FDockedControlsPanel.Controls[i].Width := w - DockedControlsPanelInnerMargin;
- if updateChooseColorHeight then
- LazPaintInstance.AdjustChooseColorHeight;
- end;
- end;
- if not FDockedControlsPanel.Visible then
- begin
- FDockedControlsPanel.Visible:= true;
- FDockedControlsPanel.SendToBack;
- end;
- end else
- FDockedControlsPanel.Visible:= false;
- if StatusBarVisible then
- begin
- with GetWorkAreaAt(lsAfterVerticalSplitter) do
- FStatusBar.SetBounds(Left,Bottom-FStatusBar.Height,Right-Left,FStatusBar.Height);
- if not FStatusBar.Visible then
- begin
- FStatusBar.Visible := true;
- FStatusBar.SendToBack;
- end;
- end
- else FStatusBar.Visible := false;
- if Assigned(FImageView) then
- with WorkArea do
- FImageView.SetBounds(Left, Top, Width, Height);
- // enable controlside anchors
- if VerticalSplitterNeeded then
- begin
- FVerticalSplitter.Left := FDockedControlsPanel.Left - FVerticalSplitter.Width;
- FVerticalSplitter.Top := FDockedControlsPanel.Top;
- FVerticalSplitter.Height := FDockedControlsPanel.Height;
- FDockedControlsPanel.AnchorSideLeft.Side := asrRight;
- FDockedControlsPanel.AnchorSideLeft.Control := FVerticalSplitter;
- FDockedControlsPanel.Anchors := FDockedControlsPanel.Anchors + [akLeft];
- FPaintBox.AnchorSideRight.Side := asrLeft;
- FPaintBox.AnchorSideRight.Control := FVerticalSplitter;
- FPaintBox.Anchors := FPaintBox.Anchors + [akRight];
- FStatusBar.AnchorSideRight.Side := asrLeft;
- FStatusBar.AnchorSideRight.Control := FVerticalSplitter;
- if not FVerticalSplitter.Visible then
- begin
- FVerticalSplitter.Visible := true;
- FVerticalSplitter.SendToBack;
- end;
- FVerticalSplitter.OnMoved:=@VerticalSplitterMoved;
- end else
- FVerticalSplitter.Visible := false;
- end;
- procedure TMainFormLayout.ApplyTheme;
- var
- bevelOfs, newSpacing, i: Integer;
- begin
- FPanelToolBox.Color := DarkThemeInstance.GetColorButtonFace(DarkTheme);
- FStatusBar.Color:= DarkThemeInstance.GetColorButtonFace(DarkTheme);
- if DarkTheme then
- begin
- FDockedToolBoxToolBar.EdgeInner := esNone;
- FDockedToolBoxToolBar.EdgeOuter := esNone;
- FDockedToolBoxToolBar.OnPaint := @DarkThemeInstance.ToolBarPaintDark;
- FDockedToolBoxToolBar.OnPaintButton:= @DarkThemeInstance.ToolBarPaintButtonDark;
- end
- else
- begin
- FDockedToolBoxToolBar.EdgeInner := esRaised;
- FDockedToolBoxToolBar.EdgeOuter := esNone;
- if DarkThemeInstance.IsLclDarkTheme then
- begin
- FDockedToolBoxToolBar.OnPaint := @DarkThemeInstance.ToolBarPaintLight;
- FDockedToolBoxToolBar.OnPaintButton:= @DarkThemeInstance.ToolBarPaintButtonLight;
- end else
- begin
- FDockedToolBoxToolBar.OnPaint := nil;
- FDockedToolBoxToolBar.OnPaintButton:= nil;
- end;
- end;
- DarkThemeInstance.Apply(FDockedControlsPanel, DarkTheme, false);
- FVerticalSplitter.Color := DarkThemeInstance.GetColorButtonFace(DarkTheme);
- FDockedControlsPanel.Color := DarkThemeInstance.GetColorForm(DarkTheme);
- bevelOfs := integer(FDockedControlsPanel.BevelOuter <> bvNone)*FDockedControlsPanel.BevelWidth;
- newSpacing := DoScaleX(2, OriginalDPI) - bevelOfs;
- FDockedControlsPanel.ChildSizing.LeftRightSpacing:= newSpacing;
- FDockedControlsPanel.ChildSizing.TopBottomSpacing:= newSpacing;
- for i := 0 to High(FDockedToolboxGroup) do
- ApplyThemeToDockedToolboxGroup(i);
- end;
- function TMainFormLayout.DockedControlsPanelWidth: integer;
- var
- w, i: Integer;
- begin
- w := 0;
- if FDockedControlsPanel.ControlCount > 0 then
- begin
- w := LazPaintInstance.Config.DefaultDockLayersAndColorsWidth;
- if w = 0 then
- begin
- for i := 0 to FDockedControlsPanel.ControlCount-1 do
- w := max(w, FDockedControlsPanel.Controls[i].Tag);
- end;
- w := min(w, GetWorkAreaAt(lsAfterPaletteToolbar).Width * 3 div 4);
- inc(w, DockedControlsPanelInnerMargin);
- end;
- result := w;
- end;
- function TMainFormLayout.DockedControlsPanelInnerMargin: integer;
- var
- bevelOfs: Integer;
- begin
- bevelOfs := integer(FDockedControlsPanel.BevelOuter <> bvNone)*FDockedControlsPanel.BevelWidth;
- result := (FDockedControlsPanel.ChildSizing.LeftRightSpacing + bevelOfs)*2;
- end;
- procedure TMainFormLayout.ApplyThemeToDockedToolboxGroup(AGroupIndex: integer);
- var
- panel: TPanel;
- spacing: Integer;
- begin
- panel := FDockedToolboxGroup[AGroupIndex].panel;
- DarkThemeInstance.Apply(panel, DarkTheme);
- spacing := DoScaleX(2, OriginalDPI) - integer(panel.BevelOuter <> bvNone)*panel.BevelWidth;
- panel.ChildSizing.LeftRightSpacing:= spacing;
- panel.ChildSizing.TopBottomSpacing:= spacing;
- end;
- procedure TMainFormLayout.ShowToolboxGroup(AGroupIndex: integer);
- var
- panel: TPanel;
- button: TToolButton;
- tb: TToolBar;
- i: Integer;
- begin
- for i := 0 to high(FDockedToolboxGroup) do
- if i <> AGroupIndex then
- begin
- FDockedToolboxGroup[i].Panel.Visible:= false;
- FDockedToolboxGroup[i].Timer.Enabled:= false;
- end;
- button := FDockedToolboxGroup[AGroupIndex].Button;
- tb := FDockedToolboxGroup[AGroupIndex].Toolbar;
- panel := FDockedToolboxGroup[AGroupIndex].Panel;
- if ToolBoxDocking = twRight then
- begin
- if not panel.Visible then
- begin
- // show outside of window to measure the size of the panel
- panel.Left := panel.Parent.ClientWidth;
- panel.Visible := true;
- panel.Visible := false;
- end;
- panel.Left := button.Left + tb.Left + FPanelToolBox.Left - panel.Width
- - DoScaleX(2, OriginalDPI);
- end
- else
- panel.Left := button.Left + button.Width + tb.Left + FPanelToolBox.Left;
- panel.Top := button.Top + tb.Top + FPanelToolBox.Top - DoScaleX(4, OriginalDPI);
- panel.Visible := true;
- FDockedToolboxGroup[AGroupIndex].Timer.Enabled:= false;
- FDockedToolboxGroup[AGroupIndex].Timer.Enabled:= true;
- end;
- procedure TMainFormLayout.HideToolboxGroup(AGroupIndex: integer);
- begin
- FDockedToolboxGroup[AGroupIndex].Panel.Visible:= false;
- FDockedToolboxGroup[AGroupIndex].Timer.Enabled := false;
- end;
- procedure TMainFormLayout.HideToolboxGroups;
- var
- i: Integer;
- begin
- for i := 0 to High(FDockedToolboxGroup) do
- HideToolboxGroup(i);
- end;
- procedure TMainFormLayout.Arrange;
- begin
- if FArranging then exit;
- FArranging := true;
- try
- DoArrange;
- HideToolboxGroups;
- if Assigned(FMenu) then
- FMenu.RepaintToolbar;
- if Assigned(FPaletteToolbar) then
- FPaletteToolbar.Arrange;
- finally
- FArranging := false;
- end;
- end;
- procedure TMainFormLayout.FocusImage;
- begin
- if Assigned(FPaintBox) then SafeSetFocus(FPaintBox);
- end;
- procedure TMainFormLayout.CheckDelayedUpdate;
- begin
- if (LazPaintInstance = nil) or (FImageView = nil) then exit;
- if FImageView.CanCompressOrUpdateStack and LazPaintInstance.UpdateStackOnTimer then
- begin
- LazPaintInstance.NotifyStackChange;
- LazPaintInstance.UpdateStackOnTimer := false;
- end else
- begin
- if FImageView.CanCompressOrUpdateStack then LazPaintInstance.Image.CompressUndo;
- end;
- if DelayedPaintPicture or LazPaintInstance.ToolManager.ToolUpdateNeeded or
- (not FImageView.ShowSelection and
- (Now > FImageView.LastPaintDate+SelectionPaintDelay) ) then
- begin
- if LazPaintInstance.ToolManager.ToolUpdateNeeded then LazPaintInstance.ToolManager.ToolUpdate;
- if Assigned(FImageView) then FImageView.ShowSelection := true;
- PaintPictureNow;
- end;
- end;
- procedure TMainFormLayout.DockedToolBoxAddButton(AAction: TBasicAction);
- var button: TToolButton;
- begin
- button := TToolButton.Create(FDockedToolBoxToolBar);
- button.Parent := FDockedToolBoxToolBar;
- button.Action := AAction;
- button.Style := tbsButton;
- button.OnClick:=@ToolboxSimpleButton_Click;
- end;
- procedure TMainFormLayout.DockedToolBoxAddGroup(AActions: array of TBasicAction);
- var button: TToolButton;
- panel: TPanel;
- tb: TToolBar;
- i, groupIdx: Integer;
- timer: TTimer;
- begin
- if length(AActions) = 0 then exit else
- if length(AActions) = 1 then DockedToolBoxAddButton(AActions[0]) else
- begin
- groupIdx := Length(FDockedToolboxGroup);
- setlength(FDockedToolboxGroup, length(FDockedToolboxGroup)+1);
- button := TToolButton.Create(FDockedToolBoxToolBar);
- button.Parent := FDockedToolBoxToolBar;
- button.Action := AActions[0];
- button.Style := tbsButton;
- button.OnMouseMove:=@ToolboxGroupMainButton_MouseMove;
- button.Tag := groupIdx;
- FDockedToolboxGroup[groupIdx].Button := button;
- panel := TPanel.Create(FForm);
- panel.Visible:= false;
- panel.AutoSize:= true;
- panel.Parent := FForm;
- FDockedToolboxGroup[groupIdx].Panel := panel;
- tb := TToolBar.Create(panel);
- tb.Tag := groupIdx;
- tb.EdgeBorders:= [];
- tb.AutoSize:= true;
- tb.Parent := panel;
- tb.Images := FDockedToolBoxToolBar.Images;
- tb.ButtonWidth := FDockedToolBoxToolBar.ButtonWidth;
- tb.ButtonHeight := FDockedToolBoxToolBar.ButtonHeight;
- FDockedToolboxGroup[groupIdx].Toolbar := tb;
- ApplyThemeToDockedToolboxGroup(groupIdx);
- for i := 0 to high(AActions) do
- begin
- button := TToolButton.Create(tb);
- button.Parent := tb;
- button.Action := AActions[i];
- button.Style := tbsButton;
- button.OnClick:= @ToolboxGroupButton_Click;
- button.OnMouseEnter:=@ToolboxGroupToolbarButton_MouseEnter;
- button.OnMouseLeave:=@ToolboxGroupToolbarButton_MouseLeave;
- end;
- timer := TTimer.Create(FForm);
- timer.Tag := groupIdx;
- timer.Interval:= 2000;
- timer.Enabled:= false;
- timer.OnTimer:=@ToolboxGroupTimer_Timer;
- FDockedToolboxGroup[groupIdx].Timer := timer;
- end;
- end;
- procedure TMainFormLayout.DockedToolBoxSetImages(AImages: TImageList);
- var
- i: Integer;
- begin
- FDockedToolBoxToolBar.Images := AImages;
- FDockedToolBoxToolBar.ButtonWidth := Max(AImages.Width+4, 23);
- FDockedToolBoxToolBar.ButtonHeight := Max(AImages.Height+4, 22);
- for i := 0 to high(FDockedToolboxGroup) do
- begin
- FDockedToolboxGroup[i].Toolbar.Images := AImages;
- FDockedToolboxGroup[i].Toolbar.ButtonWidth := FDockedToolBoxToolBar.ButtonWidth;
- FDockedToolboxGroup[i].Toolbar.ButtonHeight := FDockedToolBoxToolBar.ButtonHeight;
- end;
- end;
- procedure TMainFormLayout.AddColorToPalette(AColor: TBGRAPixel);
- begin
- FPaletteToolbar.AddColor(AColor);
- end;
- procedure TMainFormLayout.RemoveColorFromPalette(AColor: TBGRAPixel);
- begin
- FPaletteToolbar.RemoveColor(AColor);
- end;
- procedure TMainFormLayout.AddDockedControl(AControl: TControl);
- begin
- if not FDockedControlsPanel.ContainsControl(AControl) then
- begin
- AControl.Tag := AControl.Width;
- if AControl.Name = 'ChooseColorControl' then
- AControl.Align:= alTop
- else
- AControl.Align:= alClient;
- FDockedControlsPanel.InsertControl(AControl);
- if (AControl.Name = 'ChooseColorControl') and not Assigned(FDockedChooseColorSplitter) then
- begin
- FDockedChooseColorSplitter := TSplitter.Create(FDockedControlsPanel);
- FDockedChooseColorSplitter.Align := alTop;
- FDockedChooseColorSplitter.Height := DoScaleY(8, OriginalDPI);
- FDockedChooseColorSplitter.MinSize:= DoScaleY(85, OriginalDPI);
- FDockedChooseColorSplitter.Top := AControl.Height;
- FDockedControlsPanel.InsertControl(FDockedChooseColorSplitter);
- end;
- end;
- end;
- procedure TMainFormLayout.RemoveDockedControl(AControl: TControl);
- begin
- if FDockedControlsPanel.ContainsControl(AControl) then
- begin
- if (AControl.Name = 'ChooseColorControl') and Assigned(FDockedChooseColorSplitter) then
- begin
- FDockedControlsPanel.RemoveControl(FDockedChooseColorSplitter);
- FreeAndNil(FDockedChooseColorSplitter);
- end;
- FDockedControlsPanel.RemoveControl(AControl);
- AControl.Align:= alNone;
- end;
- end;
- procedure TMainFormLayout.PaintPictureNow;
- begin
- if Assigned(FImageView) then
- FImageView.UpdatePicture;
- end;
- procedure TMainFormLayout.InvalidatePicture(AInvalidateAll: boolean);
- begin
- if Assigned(FImageView) then
- FImageView.InvalidatePicture(AInvalidateAll);
- end;
- procedure TMainFormLayout.ShowNoPicture;
- begin
- if Assigned(FImageView) then
- FImageView.ShowNoPicture;
- end;
- end.
|