umainformlayout.pas 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056
  1. // SPDX-License-Identifier: GPL-3.0-only
  2. unit UMainFormLayout;
  3. {$mode objfpc}{$H+}
  4. interface
  5. uses
  6. Classes, LCLType, SysUtils, UMenu, Forms, LazPaintType, UZoom, ExtCtrls, ComCtrls,
  7. Menus, UPaletteToolbar, BGRABitmapTypes, Controls, UImageView;
  8. const SelectionPaintDelay = 100/(1000*60*60*24);
  9. VerticalSplitterWidth = 4;
  10. type
  11. TOnPictureAreaChange = procedure(ASender: TObject; ANewArea: TRect) of object;
  12. TToolWindowDocking = (twNone, twWindow, twLeft, twTop, twRight, twBottom);
  13. TLayoutStage = (lsAfterTopToolbar, lsAfterDockedToolBox, lsAfterPaletteToolbar,
  14. lsAfterDockedControlsPanel, lsAfterVerticalSplitter, lsAfterStatusBar);
  15. { TMainFormLayout }
  16. TMainFormLayout = class(TCustomMainFormLayout)
  17. private
  18. FForm: TForm;
  19. FOnPaintPicture: TNotifyEvent;
  20. FOnPictureMouseBefore: TPictureMouseBeforeEvent;
  21. FOnPictureMouseMove: TPictureMouseMoveEvent;
  22. FOnToolbarUpdate: TNotifyEvent;
  23. FZoom: TZoom;
  24. FMenu: TMainFormMenu;
  25. FLazPaintInstance: TLazPaintCustomInstance;
  26. FToolBoxDocking: TToolWindowDocking;
  27. FInSetToolBoxDocking: boolean;
  28. FPanelToolBox: TPanel;
  29. FDockedToolBoxToolBar: TToolBar;
  30. FPaletteToolbar: TPaletteToolbar;
  31. FStatusBarVisible: boolean;
  32. FStatusBar: TPanel;
  33. FStatusText: string;
  34. FStatusTextSplit: TStringList;
  35. FDarkTheme: boolean;
  36. FDockedControlsPanel: TPanel;
  37. FDockedChooseColorSplitter: TSplitter;
  38. FVerticalSplitter: TSplitter;
  39. FPaintBox: TOpaquePaintBox;
  40. FImageView: TImageView;
  41. FArranging: boolean;
  42. function GetFillSelectionHighlight: boolean;
  43. function GetMouseButtonState: TShiftState;
  44. function GetPaletteVisible: boolean;
  45. function GetPopupToolbox: TPopupMenu;
  46. function GetStatusBarVisible: boolean;
  47. function GetStatusText: string;
  48. function GetToolBoxVisible: boolean;
  49. function GetUpdatingPopup: boolean;
  50. procedure ImageToolbarUpdate(Sender: TObject);
  51. procedure ImageViewMouseBefore({%H-}ASender: TObject; AShift: TShiftState);
  52. procedure ImageViewMouseMove(Sender: TObject; APosition: TPointF);
  53. procedure ImageViewOnPaint(Sender: TObject);
  54. procedure SetFillSelectionHighlight(AValue: boolean);
  55. procedure SetOnPaintPicture(AValue: TNotifyEvent);
  56. procedure SetUpdatingPopup(AValue: boolean);
  57. procedure StatusBar_Paint(Sender: TObject);
  58. procedure ToolboxGroupMainButton_MouseMove(Sender: TObject; {%H-}Shift: TShiftState; {%H-}X,
  59. {%H-}Y: Integer);
  60. procedure SetDarkTheme(AValue: boolean);
  61. procedure SetLazPaintInstance(AValue: TLazPaintCustomInstance);
  62. procedure SetPaletteVisible(AValue: boolean);
  63. procedure SetPopupToolbox(AValue: TPopupMenu);
  64. procedure SetStatusBarVisible(AValue: boolean);
  65. procedure SetStatusText(AValue: string);
  66. procedure SetToolBoxDocking(AValue: TToolWindowDocking);
  67. procedure SetToolBoxVisible(AValue: boolean);
  68. function GetDefaultToolboxDocking: TToolWindowDocking;
  69. procedure ToolboxGroupButton_Click(Sender: TObject);
  70. procedure ToolboxGroupTimer_Timer(Sender: TObject);
  71. procedure ToolboxGroupToolbarButton_MouseEnter(Sender: TObject);
  72. procedure ToolboxGroupToolbarButton_MouseLeave(Sender: TObject);
  73. procedure ToolboxSimpleButton_Click(Sender: TObject);
  74. procedure PaletteVisibilityChangedByUser(Sender: TObject);
  75. procedure VerticalSplitterMoved(Sender: TObject);
  76. procedure ZoomChanged(sender: TZoom; ANewZoom: single);
  77. protected
  78. FDockedToolboxGroup: array of record
  79. Button: TToolButton;
  80. Panel: TPanel;
  81. Toolbar: TToolBar;
  82. Timer: TTimer;
  83. end;
  84. function GetWorkArea: TRect; override;
  85. function GetWorkAreaAt(AStage: TLayoutStage): TRect;
  86. function VerticalSplitterNeeded: boolean;
  87. procedure DoArrange;
  88. procedure ApplyTheme;
  89. function DockedControlsPanelWidth: integer;
  90. function DockedControlsPanelInnerMargin: integer;
  91. procedure ApplyThemeToDockedToolboxGroup(AGroupIndex: integer);
  92. procedure ShowToolboxGroup(AGroupIndex: integer);
  93. procedure HideToolboxGroup(AGroupIndex: integer);
  94. procedure HideToolboxGroups;
  95. public
  96. DelayedPaintPicture: boolean;
  97. constructor Create(AForm: TForm; AZoom: TZoom);
  98. destructor Destroy; override;
  99. function CatchToolKeyDown(var AKey: Word): boolean;
  100. function CatchToolKeyPress(var AKey: TUTF8Char): boolean;
  101. function CatchToolKeyUp(var AKey: Word): boolean;
  102. procedure Arrange;
  103. procedure FocusImage;
  104. procedure CheckDelayedUpdate;
  105. procedure DockedToolBoxAddButton(AAction: TBasicAction);
  106. procedure DockedToolBoxAddGroup(AActions: array of TBasicAction);
  107. procedure DockedToolBoxSetImages(AImages: TImageList);
  108. procedure AddColorToPalette(AColor : TBGRAPixel);
  109. procedure RemoveColorFromPalette(AColor : TBGRAPixel);
  110. procedure AddDockedControl(AControl: TControl);
  111. procedure RemoveDockedControl(AControl: TControl);
  112. procedure PaintPictureNow;
  113. procedure InvalidatePicture(AInvalidateAll: boolean);
  114. procedure ShowNoPicture;
  115. property Menu: TMainFormMenu read FMenu write FMenu;
  116. property Arranging: boolean read FArranging;
  117. property ToolBoxDocking: TToolWindowDocking read FToolBoxDocking write SetToolBoxDocking;
  118. property ToolBoxVisible: boolean read GetToolBoxVisible write SetToolBoxVisible;
  119. property LazPaintInstance: TLazPaintCustomInstance read FLazPaintInstance write SetLazPaintInstance;
  120. property ToolboxPopup: TPopupMenu read GetPopupToolbox write SetPopupToolbox;
  121. property PaletteVisible: boolean read GetPaletteVisible write SetPaletteVisible;
  122. property PaletteToolbar: TPaletteToolbar read FPaletteToolbar;
  123. property StatusBarVisible: boolean read GetStatusBarVisible write SetStatusBarVisible;
  124. property StatusText: string read GetStatusText write SetStatusText;
  125. property DefaultToolboxDocking: TToolWindowDocking read GetDefaultToolboxDocking;
  126. property DarkTheme: boolean read FDarkTheme write SetDarkTheme;
  127. property OnPaintPicture: TNotifyEvent read FOnPaintPicture write SetOnPaintPicture;
  128. property OnToolbarUpdate: TNotifyEvent read FOnToolbarUpdate write FOnToolbarUpdate;
  129. property OnPictureMouseMove: TPictureMouseMoveEvent read FOnPictureMouseMove write FOnPictureMouseMove;
  130. property OnPictureMouseBefore: TPictureMouseBeforeEvent read FOnPictureMouseBefore write FOnPictureMouseBefore;
  131. property FillSelectionHighlight: boolean read GetFillSelectionHighlight write SetFillSelectionHighlight;
  132. property UpdatingPopup: boolean read GetUpdatingPopup write SetUpdatingPopup;
  133. property MouseButtonState: TShiftState read GetMouseButtonState;
  134. end;
  135. function ToolWindowDockingToStr(AValue: TToolWindowDocking): string;
  136. function StrToToolWindowDocking(AValue: string): TToolWindowDocking;
  137. implementation
  138. uses Graphics, Toolwin, math, UDarkTheme, LCScaleDPI;
  139. function ToolWindowDockingToStr(AValue: TToolWindowDocking): string;
  140. begin
  141. case AValue of
  142. twNone: result := 'None';
  143. twWindow: result := 'Window';
  144. twLeft: result := 'Left';
  145. twRight: result := 'Right';
  146. twTop: result := 'Top';
  147. twBottom: result := 'Bottom';
  148. else
  149. result := 'Window';
  150. end;
  151. end;
  152. function StrToToolWindowDocking(AValue: string): TToolWindowDocking;
  153. begin
  154. if CompareText(AValue,'None') = 0 then
  155. result := twNone
  156. else if CompareText(AValue,'Window') = 0 then
  157. result := twWindow
  158. else if CompareText(AValue,'Left') = 0 then
  159. result := twLeft
  160. else if CompareText(AValue,'Top') = 0 then
  161. result := twTop
  162. else if CompareText(AValue,'Right') = 0 then
  163. result := twRight
  164. else if CompareText(AValue,'Bottom') = 0 then
  165. result := twBottom
  166. else
  167. result := twWindow;
  168. end;
  169. { TMainFormLayout }
  170. constructor TMainFormLayout.Create(AForm: TForm; AZoom: TZoom);
  171. begin
  172. FForm := AForm;
  173. FZoom := AZoom;
  174. FZoom.OnZoomChanged:=@ZoomChanged;
  175. FZoom.Layout := self;
  176. FPanelToolBox := TPanel.Create(nil);
  177. FPanelToolBox.BevelInner := bvNone;
  178. FPanelToolBox.BevelOuter := bvNone;
  179. FPanelToolBox.Width := 20;
  180. FPanelToolBox.Visible := false;
  181. FPanelToolBox.Cursor := crArrow;
  182. FDockedToolBoxToolBar := TToolBar.Create(FPanelToolBox);
  183. FDockedToolBoxToolBar.Align := alClient;
  184. FDockedToolBoxToolBar.EdgeBorders := [ebLeft,ebRight];
  185. FDockedToolBoxToolBar.Indent := 0;
  186. FDockedToolBoxToolBar.EdgeInner := esNone;
  187. FDockedToolBoxToolBar.EdgeOuter := esNone;
  188. FDockedToolBoxToolBar.ShowHint := true;
  189. FDockedToolBoxToolBar.Cursor := crArrow;
  190. FPanelToolBox.InsertControl(FDockedToolBoxToolBar);
  191. FForm.InsertControl(FPanelToolBox);
  192. FPaletteToolbar := TPaletteToolbar.Create;
  193. FPaletteToolbar.DarkTheme:= DarkTheme;
  194. FPaletteToolbar.OnVisibilityChangedByUser:= @PaletteVisibilityChangedByUser;
  195. FPaletteToolbar.Container := FForm;
  196. FVerticalSplitter := TSplitter.Create(nil);
  197. FVerticalSplitter.Visible := False;
  198. FVerticalSplitter.Align := alNone;
  199. FVerticalSplitter.Width := DoScaleX(VerticalSplitterWidth, OriginalDPI);
  200. FVerticalSplitter.Anchors := [akRight,akTop,akBottom];
  201. FForm.InsertControl(FVerticalSplitter);
  202. FDockedControlsPanel := TPanel.Create(nil);
  203. FDockedControlsPanel.Visible := false;
  204. FDockedControlsPanel.Anchors:= [akRight,akTop,akBottom];
  205. FForm.InsertControl(FDockedControlsPanel);
  206. FStatusBar := TPanel.Create(nil);
  207. FStatusBar.Align := alNone;
  208. FStatusBar.Visible := false;
  209. FStatusBar.Anchors := [akLeft,akRight,akBottom];
  210. FStatusBar.BevelOuter:= bvNone;
  211. FStatusBar.BevelInner:= bvNone;
  212. FStatusBar.Height := DoScaleY(15, OriginalDPI);
  213. FStatusBar.Font.Height := -DoScaleY(12, OriginalDPI);
  214. FStatusBar.OnPaint:=@StatusBar_Paint;
  215. FStatusTextSplit := TStringList.Create;
  216. FForm.InsertControl(FStatusBar);
  217. FPaintBox := TOpaquePaintBox.Create(nil);
  218. FForm.InsertControl(FPaintBox,0);
  219. FImageView := nil;
  220. FArranging := false;
  221. ApplyTheme;
  222. end;
  223. destructor TMainFormLayout.Destroy;
  224. begin
  225. FZoom.Layout := nil;
  226. if not FDockedControlsPanel.Visible then
  227. LazPaintInstance.Config.SetDefaultDockLayersAndColorsWidth(0);
  228. FreeAndNil(FImageView);
  229. FreeAndNil(FPaintBox);
  230. FreeAndNil(FDockedControlsPanel);
  231. FreeAndNil(FVerticalSplitter);
  232. FreeAndNil(FStatusBar);
  233. FreeAndNil(FStatusTextSplit);
  234. FreeAndNil(FPaletteToolbar);
  235. FreeAndNil(FPanelToolBox);
  236. FreeAndNil(FMenu);
  237. inherited Destroy;
  238. end;
  239. function TMainFormLayout.CatchToolKeyDown(var AKey: Word): boolean;
  240. begin
  241. if Assigned(FImageView) then
  242. begin
  243. result := FImageView.CatchToolKeyDown(AKey);
  244. if not result and Assigned(FPaletteToolbar) then
  245. result := FPaletteToolbar.CatchToolKeyDown(AKey);
  246. end else result := false;
  247. end;
  248. function TMainFormLayout.CatchToolKeyUp(var AKey: Word): boolean;
  249. begin
  250. if Assigned(FImageView) then
  251. begin
  252. result := FImageView.CatchToolKeyUp(AKey);
  253. if not result and Assigned(FPaletteToolbar) then
  254. result := FPaletteToolbar.CatchToolKeyUp(AKey);
  255. end else result := false;
  256. end;
  257. function TMainFormLayout.CatchToolKeyPress(var AKey: TUTF8Char): boolean;
  258. begin
  259. if Assigned(FImageView) then
  260. result := FImageView.CatchToolKeyPress(AKey)
  261. else result := false;
  262. end;
  263. procedure TMainFormLayout.SetToolBoxDocking(AValue: TToolWindowDocking);
  264. begin
  265. if FInSetToolBoxDocking or (FToolBoxDocking=AValue) then Exit;
  266. FInSetToolBoxDocking := true;
  267. FToolBoxDocking:=AValue;
  268. if Assigned(FLazPaintInstance) then
  269. begin
  270. FLazPaintInstance.ToolboxVisible := AValue <> twNone;
  271. if AValue <> twNone then
  272. FLazPaintInstance.Config.SetDefaultToolboxDocking(ToolWindowDockingToStr(AValue));
  273. end;
  274. DoArrange;
  275. FInSetToolBoxDocking := false;
  276. end;
  277. function TMainFormLayout.GetToolBoxVisible: boolean;
  278. begin
  279. result := LazPaintInstance.ToolboxVisible;
  280. end;
  281. function TMainFormLayout.GetUpdatingPopup: boolean;
  282. begin
  283. if Assigned(FImageView) then
  284. result := FImageView.UpdatingPopup
  285. else result := False;
  286. end;
  287. procedure TMainFormLayout.ImageToolbarUpdate(Sender: TObject);
  288. begin
  289. if Assigned(FOnToolbarUpdate) then
  290. FOnToolbarUpdate(self);
  291. end;
  292. procedure TMainFormLayout.ImageViewMouseBefore(ASender: TObject;
  293. AShift: TShiftState);
  294. begin
  295. if Assigned(FOnPictureMouseBefore) then
  296. FOnPictureMouseBefore(self, AShift);
  297. end;
  298. procedure TMainFormLayout.ImageViewMouseMove(Sender: TObject; APosition: TPointF);
  299. begin
  300. if Assigned(FOnPictureMouseMove) then
  301. FOnPictureMouseMove(self, APosition);
  302. end;
  303. procedure TMainFormLayout.ImageViewOnPaint(Sender: TObject);
  304. begin
  305. if Assigned(FOnPaintPicture) then
  306. FOnPaintPicture(self);
  307. end;
  308. procedure TMainFormLayout.SetFillSelectionHighlight(AValue: boolean);
  309. begin
  310. if Assigned(FImageView) then
  311. FImageView.FillSelectionHighlight := AValue;
  312. end;
  313. procedure TMainFormLayout.SetOnPaintPicture(AValue: TNotifyEvent);
  314. begin
  315. if FOnPaintPicture=AValue then Exit;
  316. FOnPaintPicture:=AValue;
  317. end;
  318. procedure TMainFormLayout.SetUpdatingPopup(AValue: boolean);
  319. begin
  320. if Assigned(FImageView) then
  321. FImageView.UpdatingPopup := AValue;
  322. end;
  323. procedure TMainFormLayout.StatusBar_Paint(Sender: TObject);
  324. var
  325. colWidth, spacing, i, x: Integer;
  326. begin
  327. if FStatusTextSplit.Count > 0 then
  328. begin
  329. FStatusBar.Canvas.Brush.Style := bsClear;
  330. spacing := DoScaleX(6, OriginalDPI);
  331. colWidth := (FStatusBar.ClientWidth - spacing*2) div FStatusTextSplit.Count;
  332. if colWidth > spacing*2 then
  333. begin
  334. FStatusBar.Canvas.Pen.Color := DarkThemeInstance.GetColorPanelHighlight(DarkTheme);
  335. FStatusBar.Canvas.Line(0,0, FStatusBar.Width,0);
  336. x := 0;
  337. for i := 0 to FStatusTextSplit.Count-1 do
  338. begin
  339. FStatusBar.Canvas.Font := FStatusBar.Font;
  340. FStatusBar.Canvas.Font.Color := DarkThemeInstance.GetColorButtonText(DarkTheme);
  341. FStatusBar.Canvas.TextOut(x + spacing,
  342. (FStatusBar.ClientHeight - FStatusBar.Canvas.TextHeight('Hg')) div 2,
  343. FStatusTextSplit[i]);
  344. if i > 0 then
  345. begin
  346. FStatusBar.Canvas.Pen.Color := DarkThemeInstance.GetColorPanelShadow(DarkTheme);
  347. FStatusBar.Canvas.Line(x-1,0, x-1,FStatusBar.Height);
  348. FStatusBar.Canvas.Pen.Color := DarkThemeInstance.GetColorPanelHighlight(DarkTheme);
  349. FStatusBar.Canvas.Line(x,0, x,FStatusBar.Height);
  350. end;
  351. inc(x, max(colWidth, FStatusBar.Canvas.TextWidth(FStatusTextSplit[i]) + 2*spacing));
  352. end;
  353. end;
  354. end;
  355. end;
  356. procedure TMainFormLayout.ToolboxGroupMainButton_MouseMove(Sender: TObject;
  357. Shift: TShiftState; X, Y: Integer);
  358. var
  359. button: TToolButton;
  360. begin
  361. button := Sender as TToolButton;
  362. ShowToolboxGroup(button.Tag);
  363. end;
  364. procedure TMainFormLayout.SetDarkTheme(AValue: boolean);
  365. begin
  366. if FDarkTheme=AValue then Exit;
  367. FDarkTheme:=AValue;
  368. ApplyTheme;
  369. if Assigned(FPaletteToolbar) then
  370. FPaletteToolbar.DarkTheme:= AValue;
  371. if Assigned(FMenu) then
  372. FMenu.DarkTheme:= AValue;
  373. InvalidatePicture(true);
  374. end;
  375. procedure TMainFormLayout.SetLazPaintInstance(AValue: TLazPaintCustomInstance);
  376. begin
  377. if FLazPaintInstance=AValue then Exit;
  378. FLazPaintInstance:=AValue;
  379. FPaletteToolbar.LazPaintInstance:= AValue;
  380. FStatusBarVisible := LazPaintInstance.Config.GetStatusBarVisible;
  381. if Assigned(FImageView) then FreeAndNil(FImageView);
  382. FImageView := TImageView.Create(FLazPaintInstance, FZoom, FPaintBox);
  383. FImageView.OnPaint:=@ImageViewOnPaint;
  384. FImageView.OnToolbarUpdate:=@ImageToolbarUpdate;
  385. FImageView.OnMouseMove:=@ImageViewMouseMove;
  386. FImageView.OnMouseBefore:=@ImageViewMouseBefore;
  387. end;
  388. procedure TMainFormLayout.SetPaletteVisible(AValue: boolean);
  389. begin
  390. if FPaletteToolbar.Visible=AValue then Exit;
  391. FPaletteToolbar.Visible:=AValue;
  392. Arrange;
  393. end;
  394. function TMainFormLayout.GetPopupToolbox: TPopupMenu;
  395. begin
  396. result := FPanelToolBox.PopupMenu;
  397. end;
  398. function TMainFormLayout.GetStatusBarVisible: boolean;
  399. begin
  400. result := FStatusBarVisible;
  401. end;
  402. function TMainFormLayout.GetStatusText: string;
  403. begin
  404. result := FStatusText;
  405. end;
  406. procedure TMainFormLayout.PaletteVisibilityChangedByUser(Sender: TObject);
  407. begin
  408. Arrange;
  409. end;
  410. procedure TMainFormLayout.VerticalSplitterMoved(Sender: TObject);
  411. begin
  412. LazPaintInstance.Config.SetDefaultDockLayersAndColorsWidth(
  413. FDockedControlsPanel.Width - DockedControlsPanelInnerMargin);
  414. if Assigned(FImageView) then
  415. FImageView.InvalidatePicture(true);
  416. end;
  417. procedure TMainFormLayout.ZoomChanged(sender: TZoom; ANewZoom: single);
  418. begin
  419. if Assigned(FImageView) then
  420. begin
  421. if not LazPaintInstance.Image.SelectionMaskEmpty then
  422. FImageView.ShowSelection := false;
  423. FImageView.OnZoomChanged(sender, ANewZoom);
  424. end;
  425. PaintPictureNow;
  426. end;
  427. function TMainFormLayout.GetPaletteVisible: boolean;
  428. begin
  429. result := FPaletteToolbar.Visible;
  430. end;
  431. function TMainFormLayout.GetFillSelectionHighlight: boolean;
  432. begin
  433. if Assigned(FImageView) then
  434. result := FillSelectionHighlight
  435. else result := false;
  436. end;
  437. function TMainFormLayout.GetMouseButtonState: TShiftState;
  438. begin
  439. if Assigned(FImageView) then
  440. result := FImageView.MouseButtonState
  441. else result := [];
  442. end;
  443. procedure TMainFormLayout.SetPopupToolbox(AValue: TPopupMenu);
  444. begin
  445. FPanelToolBox.PopupMenu := AValue;
  446. if LazPaintInstance <> nil then
  447. LazPaintInstance.ToolboxWindowPopup := AValue;
  448. end;
  449. procedure TMainFormLayout.SetStatusBarVisible(AValue: boolean);
  450. begin
  451. FStatusBarVisible := AValue;
  452. LazPaintInstance.Config.SetStatusBarVisible(AValue);
  453. Arrange;
  454. end;
  455. procedure TMainFormLayout.SetStatusText(AValue: string);
  456. begin
  457. if AValue = FStatusText then exit;
  458. FStatusText := AValue;
  459. FStatusTextSplit.Delimiter:= '|';
  460. FStatusTextSplit.StrictDelimiter:= true;
  461. FStatusTextSplit.DelimitedText := FStatusText;
  462. FStatusBar.Invalidate;
  463. end;
  464. procedure TMainFormLayout.SetToolBoxVisible(AValue: boolean);
  465. begin
  466. if AValue then
  467. ToolBoxDocking:= DefaultToolBoxDocking
  468. else
  469. ToolBoxDocking := twNone;
  470. end;
  471. function TMainFormLayout.GetDefaultToolboxDocking: TToolWindowDocking;
  472. begin
  473. result := StrToToolWindowDocking(FLazPaintInstance.Config.DefaultToolboxDocking);
  474. end;
  475. procedure TMainFormLayout.ToolboxGroupButton_Click(Sender: TObject);
  476. var
  477. button: TToolButton;
  478. tb: TToolBar;
  479. groupIndex: integer;
  480. begin
  481. button := Sender as TToolButton;
  482. tb := button.Parent as TToolBar;
  483. groupIndex := tb.Tag;
  484. FDockedToolboxGroup[groupIndex].Button.Action := button.Action;
  485. end;
  486. procedure TMainFormLayout.ToolboxGroupTimer_Timer(Sender: TObject);
  487. var
  488. groupIdx: integer;
  489. begin
  490. groupIdx := (Sender as TTimer).Tag;
  491. HideToolboxGroup(groupIdx);
  492. end;
  493. procedure TMainFormLayout.ToolboxGroupToolbarButton_MouseEnter(Sender: TObject);
  494. var
  495. button: TToolButton;
  496. groupIndex: integer;
  497. tb: TToolBar;
  498. begin
  499. button := Sender as TToolButton;
  500. tb := button.Parent as TToolbar;
  501. groupIndex := tb.Tag;
  502. FDockedToolboxGroup[groupIndex].Timer.Enabled := false;
  503. end;
  504. procedure TMainFormLayout.ToolboxGroupToolbarButton_MouseLeave(Sender: TObject);
  505. var
  506. button: TToolButton;
  507. groupIndex: integer;
  508. tb: TToolBar;
  509. begin
  510. button := Sender as TToolButton;
  511. tb := button.Parent as TToolbar;
  512. groupIndex := tb.Tag;
  513. FDockedToolboxGroup[groupIndex].Timer.Enabled := true;
  514. end;
  515. procedure TMainFormLayout.ToolboxSimpleButton_Click(Sender: TObject);
  516. var
  517. i: Integer;
  518. begin
  519. for i := 0 to high(FDockedToolboxGroup) do
  520. begin
  521. FDockedToolboxGroup[i].Panel.Visible:= false;
  522. FDockedToolboxGroup[i].Timer.Enabled:= false;
  523. end;
  524. end;
  525. function TMainFormLayout.GetWorkArea: TRect;
  526. begin
  527. result := GetWorkAreaAt(high(TLayoutStage));
  528. end;
  529. function TMainFormLayout.GetWorkAreaAt(AStage: TLayoutStage): TRect;
  530. begin
  531. result := Rect(0,0,FForm.ClientWidth,FForm.ClientHeight);
  532. if Assigned(FMenu) then
  533. result.top += FMenu.ToolbarsHeight;
  534. if AStage = lsAfterTopToolbar then exit;
  535. if FToolBoxDocking = twLeft then result.Left += FPanelToolBox.Width else
  536. if FToolBoxDocking = twRight then result.Right -= FPanelToolBox.Width;
  537. if AStage = lsAfterDockedToolBox then exit;
  538. if PaletteVisible then result.Right -= FPaletteToolbar.Width;
  539. if AStage = lsAfterPaletteToolbar then exit;
  540. if VerticalSplitterNeeded then result.Right -= DockedControlsPanelWidth;
  541. if AStage = lsAfterDockedControlsPanel then exit;
  542. if (AStage = lsAfterVerticalSplitter) and VerticalSplitterNeeded then
  543. result.Right -= DoScaleX(VerticalSplitterWidth, OriginalDPI);
  544. if AStage = lsAfterVerticalSplitter then exit;
  545. if StatusBarVisible then result.Bottom -= FStatusBar.Height;
  546. if AStage = lsAfterStatusBar then exit;
  547. end;
  548. function TMainFormLayout.VerticalSplitterNeeded: boolean;
  549. begin
  550. result := FDockedControlsPanel.ControlCount > 0;
  551. end;
  552. procedure TMainFormLayout.DoArrange;
  553. var nbY,nbX,w,i: integer;
  554. updateChooseColorHeight: Boolean;
  555. begin
  556. if Assigned(FMenu) then
  557. FMenu.ArrangeToolbars(FForm.ClientWidth);
  558. if FToolBoxDocking in [twLeft,twRight] then
  559. begin
  560. with GetWorkAreaAt(lsAfterTopToolbar) do
  561. begin
  562. if FToolBoxDocking = twLeft then FDockedToolBoxToolBar.Align:= alLeft
  563. else FDockedToolBoxToolBar.Align:= alRight;
  564. FPanelToolBox.Top := top;
  565. FPanelToolBox.Height:= bottom-top;
  566. nbY := FPanelToolBox.ClientHeight div FDockedToolBoxToolBar.ButtonHeight;
  567. if nbY = 0 then nbY := 1;
  568. nbX := (FDockedToolBoxToolBar.ButtonCount+nbY-1) div nbY;
  569. if nbX> 5 then nbX := 5;
  570. w := FDockedToolBoxToolBar.ButtonWidth * nbX+2;
  571. FDockedToolBoxToolBar.Width := w;
  572. FPanelToolBox.Width := w;
  573. if FToolBoxDocking = twLeft then
  574. begin
  575. FPanelToolBox.Left:= Left;
  576. FPanelToolBox.Anchors:= [akLeft,akTop,akBottom];
  577. end else
  578. begin
  579. FPanelToolBox.Left:= Right-FPanelToolBox.Width;
  580. FPanelToolBox.Anchors:= [akRight,akTop,akBottom];
  581. end;
  582. for i := 0 to FDockedToolBoxToolBar.ButtonCount-1 do
  583. FDockedToolBoxToolBar.Buttons[i].Top := i*FDockedToolBoxToolBar.ButtonHeight;
  584. end;
  585. if not FPanelToolBox.Visible then
  586. begin
  587. FPanelToolBox.Visible := true;
  588. FPanelToolBox.SendToBack;
  589. end;
  590. end else
  591. FPanelToolBox.Visible := false;
  592. if PaletteVisible then
  593. with GetWorkAreaAt(lsAfterDockedToolBox) do
  594. FPaletteToolbar.SetBounds(Right - FPaletteToolbar.Width,Top,FPaletteToolbar.Width,Bottom-Top);
  595. //temporarily disable controlside anchors
  596. FVerticalSplitter.OnMoved:= nil;
  597. FDockedControlsPanel.AnchorSideLeft.Control := nil;
  598. FDockedControlsPanel.Anchors := FDockedControlsPanel.Anchors - [akLeft];
  599. FPaintBox.AnchorSideRight.Control := nil;
  600. FPaintBox.Anchors := FPaintBox.Anchors - [akRight];
  601. FStatusBar.AnchorSideRight.Control := nil;
  602. if FDockedControlsPanel.ControlCount > 0 then
  603. begin
  604. with GetWorkAreaAt(lsAfterPaletteToolbar) do
  605. begin
  606. w := DockedControlsPanelWidth;
  607. updateChooseColorHeight := (FDockedControlsPanel.Width <> w) or not FDockedControlsPanel.Visible;
  608. FDockedControlsPanel.SetBounds(Right - w, Top, w, Bottom - Top);
  609. for i := 0 to FDockedControlsPanel.ControlCount-1 do
  610. if FDockedControlsPanel.Controls[i].Name = 'ChooseColorControl' then
  611. begin
  612. FDockedControlsPanel.Controls[i].Width := w - DockedControlsPanelInnerMargin;
  613. if updateChooseColorHeight then
  614. LazPaintInstance.AdjustChooseColorHeight;
  615. end;
  616. end;
  617. if not FDockedControlsPanel.Visible then
  618. begin
  619. FDockedControlsPanel.Visible:= true;
  620. FDockedControlsPanel.SendToBack;
  621. end;
  622. end else
  623. FDockedControlsPanel.Visible:= false;
  624. if StatusBarVisible then
  625. begin
  626. with GetWorkAreaAt(lsAfterVerticalSplitter) do
  627. FStatusBar.SetBounds(Left,Bottom-FStatusBar.Height,Right-Left,FStatusBar.Height);
  628. if not FStatusBar.Visible then
  629. begin
  630. FStatusBar.Visible := true;
  631. FStatusBar.SendToBack;
  632. end;
  633. end
  634. else FStatusBar.Visible := false;
  635. if Assigned(FImageView) then
  636. with WorkArea do
  637. FImageView.SetBounds(Left, Top, Width, Height);
  638. // enable controlside anchors
  639. if VerticalSplitterNeeded then
  640. begin
  641. FVerticalSplitter.Left := FDockedControlsPanel.Left - FVerticalSplitter.Width;
  642. FVerticalSplitter.Top := FDockedControlsPanel.Top;
  643. FVerticalSplitter.Height := FDockedControlsPanel.Height;
  644. FDockedControlsPanel.AnchorSideLeft.Side := asrRight;
  645. FDockedControlsPanel.AnchorSideLeft.Control := FVerticalSplitter;
  646. FDockedControlsPanel.Anchors := FDockedControlsPanel.Anchors + [akLeft];
  647. FPaintBox.AnchorSideRight.Side := asrLeft;
  648. FPaintBox.AnchorSideRight.Control := FVerticalSplitter;
  649. FPaintBox.Anchors := FPaintBox.Anchors + [akRight];
  650. FStatusBar.AnchorSideRight.Side := asrLeft;
  651. FStatusBar.AnchorSideRight.Control := FVerticalSplitter;
  652. if not FVerticalSplitter.Visible then
  653. begin
  654. FVerticalSplitter.Visible := true;
  655. FVerticalSplitter.SendToBack;
  656. end;
  657. FVerticalSplitter.OnMoved:=@VerticalSplitterMoved;
  658. end else
  659. FVerticalSplitter.Visible := false;
  660. end;
  661. procedure TMainFormLayout.ApplyTheme;
  662. var
  663. bevelOfs, newSpacing, i: Integer;
  664. begin
  665. FPanelToolBox.Color := DarkThemeInstance.GetColorButtonFace(DarkTheme);
  666. FStatusBar.Color:= DarkThemeInstance.GetColorButtonFace(DarkTheme);
  667. if DarkTheme then
  668. begin
  669. FDockedToolBoxToolBar.EdgeInner := esNone;
  670. FDockedToolBoxToolBar.EdgeOuter := esNone;
  671. FDockedToolBoxToolBar.OnPaint := @DarkThemeInstance.ToolBarPaintDark;
  672. FDockedToolBoxToolBar.OnPaintButton:= @DarkThemeInstance.ToolBarPaintButtonDark;
  673. end
  674. else
  675. begin
  676. FDockedToolBoxToolBar.EdgeInner := esRaised;
  677. FDockedToolBoxToolBar.EdgeOuter := esNone;
  678. if DarkThemeInstance.IsLclDarkTheme then
  679. begin
  680. FDockedToolBoxToolBar.OnPaint := @DarkThemeInstance.ToolBarPaintLight;
  681. FDockedToolBoxToolBar.OnPaintButton:= @DarkThemeInstance.ToolBarPaintButtonLight;
  682. end else
  683. begin
  684. FDockedToolBoxToolBar.OnPaint := nil;
  685. FDockedToolBoxToolBar.OnPaintButton:= nil;
  686. end;
  687. end;
  688. DarkThemeInstance.Apply(FDockedControlsPanel, DarkTheme, false);
  689. FVerticalSplitter.Color := DarkThemeInstance.GetColorButtonFace(DarkTheme);
  690. FDockedControlsPanel.Color := DarkThemeInstance.GetColorForm(DarkTheme);
  691. bevelOfs := integer(FDockedControlsPanel.BevelOuter <> bvNone)*FDockedControlsPanel.BevelWidth;
  692. newSpacing := DoScaleX(2, OriginalDPI) - bevelOfs;
  693. FDockedControlsPanel.ChildSizing.LeftRightSpacing:= newSpacing;
  694. FDockedControlsPanel.ChildSizing.TopBottomSpacing:= newSpacing;
  695. for i := 0 to High(FDockedToolboxGroup) do
  696. ApplyThemeToDockedToolboxGroup(i);
  697. end;
  698. function TMainFormLayout.DockedControlsPanelWidth: integer;
  699. var
  700. w, i: Integer;
  701. begin
  702. w := 0;
  703. if FDockedControlsPanel.ControlCount > 0 then
  704. begin
  705. w := LazPaintInstance.Config.DefaultDockLayersAndColorsWidth;
  706. if w = 0 then
  707. begin
  708. for i := 0 to FDockedControlsPanel.ControlCount-1 do
  709. w := max(w, FDockedControlsPanel.Controls[i].Tag);
  710. end;
  711. w := min(w, GetWorkAreaAt(lsAfterPaletteToolbar).Width * 3 div 4);
  712. inc(w, DockedControlsPanelInnerMargin);
  713. end;
  714. result := w;
  715. end;
  716. function TMainFormLayout.DockedControlsPanelInnerMargin: integer;
  717. var
  718. bevelOfs: Integer;
  719. begin
  720. bevelOfs := integer(FDockedControlsPanel.BevelOuter <> bvNone)*FDockedControlsPanel.BevelWidth;
  721. result := (FDockedControlsPanel.ChildSizing.LeftRightSpacing + bevelOfs)*2;
  722. end;
  723. procedure TMainFormLayout.ApplyThemeToDockedToolboxGroup(AGroupIndex: integer);
  724. var
  725. panel: TPanel;
  726. spacing: Integer;
  727. begin
  728. panel := FDockedToolboxGroup[AGroupIndex].panel;
  729. DarkThemeInstance.Apply(panel, DarkTheme);
  730. spacing := DoScaleX(2, OriginalDPI) - integer(panel.BevelOuter <> bvNone)*panel.BevelWidth;
  731. panel.ChildSizing.LeftRightSpacing:= spacing;
  732. panel.ChildSizing.TopBottomSpacing:= spacing;
  733. end;
  734. procedure TMainFormLayout.ShowToolboxGroup(AGroupIndex: integer);
  735. var
  736. panel: TPanel;
  737. button: TToolButton;
  738. tb: TToolBar;
  739. i: Integer;
  740. begin
  741. for i := 0 to high(FDockedToolboxGroup) do
  742. if i <> AGroupIndex then
  743. begin
  744. FDockedToolboxGroup[i].Panel.Visible:= false;
  745. FDockedToolboxGroup[i].Timer.Enabled:= false;
  746. end;
  747. button := FDockedToolboxGroup[AGroupIndex].Button;
  748. tb := FDockedToolboxGroup[AGroupIndex].Toolbar;
  749. panel := FDockedToolboxGroup[AGroupIndex].Panel;
  750. if ToolBoxDocking = twRight then
  751. begin
  752. if not panel.Visible then
  753. begin
  754. // show outside of window to measure the size of the panel
  755. panel.Left := panel.Parent.ClientWidth;
  756. panel.Visible := true;
  757. panel.Visible := false;
  758. end;
  759. panel.Left := button.Left + tb.Left + FPanelToolBox.Left - panel.Width
  760. - DoScaleX(2, OriginalDPI);
  761. end
  762. else
  763. panel.Left := button.Left + button.Width + tb.Left + FPanelToolBox.Left;
  764. panel.Top := button.Top + tb.Top + FPanelToolBox.Top - DoScaleX(4, OriginalDPI);
  765. panel.Visible := true;
  766. FDockedToolboxGroup[AGroupIndex].Timer.Enabled:= false;
  767. FDockedToolboxGroup[AGroupIndex].Timer.Enabled:= true;
  768. end;
  769. procedure TMainFormLayout.HideToolboxGroup(AGroupIndex: integer);
  770. begin
  771. FDockedToolboxGroup[AGroupIndex].Panel.Visible:= false;
  772. FDockedToolboxGroup[AGroupIndex].Timer.Enabled := false;
  773. end;
  774. procedure TMainFormLayout.HideToolboxGroups;
  775. var
  776. i: Integer;
  777. begin
  778. for i := 0 to High(FDockedToolboxGroup) do
  779. HideToolboxGroup(i);
  780. end;
  781. procedure TMainFormLayout.Arrange;
  782. begin
  783. if FArranging then exit;
  784. FArranging := true;
  785. try
  786. DoArrange;
  787. HideToolboxGroups;
  788. if Assigned(FMenu) then
  789. FMenu.RepaintToolbar;
  790. if Assigned(FPaletteToolbar) then
  791. FPaletteToolbar.Arrange;
  792. finally
  793. FArranging := false;
  794. end;
  795. end;
  796. procedure TMainFormLayout.FocusImage;
  797. begin
  798. if Assigned(FPaintBox) then SafeSetFocus(FPaintBox);
  799. end;
  800. procedure TMainFormLayout.CheckDelayedUpdate;
  801. begin
  802. if (LazPaintInstance = nil) or (FImageView = nil) then exit;
  803. if FImageView.CanCompressOrUpdateStack and LazPaintInstance.UpdateStackOnTimer then
  804. begin
  805. LazPaintInstance.NotifyStackChange;
  806. LazPaintInstance.UpdateStackOnTimer := false;
  807. end else
  808. begin
  809. if FImageView.CanCompressOrUpdateStack then LazPaintInstance.Image.CompressUndo;
  810. end;
  811. if DelayedPaintPicture or LazPaintInstance.ToolManager.ToolUpdateNeeded or
  812. (not FImageView.ShowSelection and
  813. (Now > FImageView.LastPaintDate+SelectionPaintDelay) ) then
  814. begin
  815. if LazPaintInstance.ToolManager.ToolUpdateNeeded then LazPaintInstance.ToolManager.ToolUpdate;
  816. if Assigned(FImageView) then FImageView.ShowSelection := true;
  817. PaintPictureNow;
  818. end;
  819. end;
  820. procedure TMainFormLayout.DockedToolBoxAddButton(AAction: TBasicAction);
  821. var button: TToolButton;
  822. begin
  823. button := TToolButton.Create(FDockedToolBoxToolBar);
  824. button.Parent := FDockedToolBoxToolBar;
  825. button.Action := AAction;
  826. button.Style := tbsButton;
  827. button.OnClick:=@ToolboxSimpleButton_Click;
  828. end;
  829. procedure TMainFormLayout.DockedToolBoxAddGroup(AActions: array of TBasicAction);
  830. var button: TToolButton;
  831. panel: TPanel;
  832. tb: TToolBar;
  833. i, groupIdx: Integer;
  834. timer: TTimer;
  835. begin
  836. if length(AActions) = 0 then exit else
  837. if length(AActions) = 1 then DockedToolBoxAddButton(AActions[0]) else
  838. begin
  839. groupIdx := Length(FDockedToolboxGroup);
  840. setlength(FDockedToolboxGroup, length(FDockedToolboxGroup)+1);
  841. button := TToolButton.Create(FDockedToolBoxToolBar);
  842. button.Parent := FDockedToolBoxToolBar;
  843. button.Action := AActions[0];
  844. button.Style := tbsButton;
  845. button.OnMouseMove:=@ToolboxGroupMainButton_MouseMove;
  846. button.Tag := groupIdx;
  847. FDockedToolboxGroup[groupIdx].Button := button;
  848. panel := TPanel.Create(FForm);
  849. panel.Visible:= false;
  850. panel.AutoSize:= true;
  851. panel.Parent := FForm;
  852. FDockedToolboxGroup[groupIdx].Panel := panel;
  853. tb := TToolBar.Create(panel);
  854. tb.Tag := groupIdx;
  855. tb.EdgeBorders:= [];
  856. tb.AutoSize:= true;
  857. tb.Parent := panel;
  858. tb.Images := FDockedToolBoxToolBar.Images;
  859. tb.ButtonWidth := FDockedToolBoxToolBar.ButtonWidth;
  860. tb.ButtonHeight := FDockedToolBoxToolBar.ButtonHeight;
  861. FDockedToolboxGroup[groupIdx].Toolbar := tb;
  862. ApplyThemeToDockedToolboxGroup(groupIdx);
  863. for i := 0 to high(AActions) do
  864. begin
  865. button := TToolButton.Create(tb);
  866. button.Parent := tb;
  867. button.Action := AActions[i];
  868. button.Style := tbsButton;
  869. button.OnClick:= @ToolboxGroupButton_Click;
  870. button.OnMouseEnter:=@ToolboxGroupToolbarButton_MouseEnter;
  871. button.OnMouseLeave:=@ToolboxGroupToolbarButton_MouseLeave;
  872. end;
  873. timer := TTimer.Create(FForm);
  874. timer.Tag := groupIdx;
  875. timer.Interval:= 2000;
  876. timer.Enabled:= false;
  877. timer.OnTimer:=@ToolboxGroupTimer_Timer;
  878. FDockedToolboxGroup[groupIdx].Timer := timer;
  879. end;
  880. end;
  881. procedure TMainFormLayout.DockedToolBoxSetImages(AImages: TImageList);
  882. var
  883. i: Integer;
  884. begin
  885. FDockedToolBoxToolBar.Images := AImages;
  886. FDockedToolBoxToolBar.ButtonWidth := Max(AImages.Width+4, 23);
  887. FDockedToolBoxToolBar.ButtonHeight := Max(AImages.Height+4, 22);
  888. for i := 0 to high(FDockedToolboxGroup) do
  889. begin
  890. FDockedToolboxGroup[i].Toolbar.Images := AImages;
  891. FDockedToolboxGroup[i].Toolbar.ButtonWidth := FDockedToolBoxToolBar.ButtonWidth;
  892. FDockedToolboxGroup[i].Toolbar.ButtonHeight := FDockedToolBoxToolBar.ButtonHeight;
  893. end;
  894. end;
  895. procedure TMainFormLayout.AddColorToPalette(AColor: TBGRAPixel);
  896. begin
  897. FPaletteToolbar.AddColor(AColor);
  898. end;
  899. procedure TMainFormLayout.RemoveColorFromPalette(AColor: TBGRAPixel);
  900. begin
  901. FPaletteToolbar.RemoveColor(AColor);
  902. end;
  903. procedure TMainFormLayout.AddDockedControl(AControl: TControl);
  904. begin
  905. if not FDockedControlsPanel.ContainsControl(AControl) then
  906. begin
  907. AControl.Tag := AControl.Width;
  908. if AControl.Name = 'ChooseColorControl' then
  909. AControl.Align:= alTop
  910. else
  911. AControl.Align:= alClient;
  912. FDockedControlsPanel.InsertControl(AControl);
  913. if (AControl.Name = 'ChooseColorControl') and not Assigned(FDockedChooseColorSplitter) then
  914. begin
  915. FDockedChooseColorSplitter := TSplitter.Create(FDockedControlsPanel);
  916. FDockedChooseColorSplitter.Align := alTop;
  917. FDockedChooseColorSplitter.Height := DoScaleY(8, OriginalDPI);
  918. FDockedChooseColorSplitter.MinSize:= DoScaleY(85, OriginalDPI);
  919. FDockedChooseColorSplitter.Top := AControl.Height;
  920. FDockedControlsPanel.InsertControl(FDockedChooseColorSplitter);
  921. end;
  922. end;
  923. end;
  924. procedure TMainFormLayout.RemoveDockedControl(AControl: TControl);
  925. begin
  926. if FDockedControlsPanel.ContainsControl(AControl) then
  927. begin
  928. if (AControl.Name = 'ChooseColorControl') and Assigned(FDockedChooseColorSplitter) then
  929. begin
  930. FDockedControlsPanel.RemoveControl(FDockedChooseColorSplitter);
  931. FreeAndNil(FDockedChooseColorSplitter);
  932. end;
  933. FDockedControlsPanel.RemoveControl(AControl);
  934. AControl.Align:= alNone;
  935. end;
  936. end;
  937. procedure TMainFormLayout.PaintPictureNow;
  938. begin
  939. if Assigned(FImageView) then
  940. FImageView.UpdatePicture;
  941. end;
  942. procedure TMainFormLayout.InvalidatePicture(AInvalidateAll: boolean);
  943. begin
  944. if Assigned(FImageView) then
  945. FImageView.InvalidatePicture(AInvalidateAll);
  946. end;
  947. procedure TMainFormLayout.ShowNoPicture;
  948. begin
  949. if Assigned(FImageView) then
  950. FImageView.ShowNoPicture;
  951. end;
  952. end.