umenu.pas 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. // SPDX-License-Identifier: GPL-3.0-only
  2. unit UMenu;
  3. {$mode objfpc}{$H+}
  4. interface
  5. uses
  6. Classes, SysUtils, ActnList, Forms, Menus, UTool, LCLType, ExtCtrls, UConfig,
  7. Controls, LazPaintType;
  8. type
  9. { TMainFormMenu }
  10. TMainFormMenu = class
  11. private
  12. FActionList: TActionList;
  13. FDarkTheme: boolean;
  14. FMainMenus: array of record
  15. menu: TMenuItem;
  16. used: boolean;
  17. end;
  18. FToolsShortcuts: array[TPaintToolType] of TUTF8Char;
  19. FToolbars: array of record
  20. tb: TPanel;
  21. fixed: boolean;
  22. end;
  23. FToolbarsHeight : integer;
  24. FToolbarBackground: TPanel;
  25. FImageList: TImageList;
  26. procedure IconSizeItemClick(Sender: TObject);
  27. procedure IconSizeMenuClick(Sender: TObject);
  28. procedure Script_Click(Sender: TObject);
  29. procedure SetDarkTheme(AValue: boolean);
  30. protected
  31. FInstance: TLazPaintCustomInstance;
  32. FInstalledScripts: TStringList;
  33. FTargetDPI: integer;
  34. procedure AddMenus(AMenu: TMenuItem; AActionList: TActionList; AActionsCommaText: string; AIndex: integer = -1); overload;
  35. procedure AddMenus(AMenuName: string; AActionsCommaText: string); overload;
  36. procedure AddInstalledScripts(AMenu: TMenuItem; AIndex: integer = -1);
  37. procedure ApplyShortcuts;
  38. procedure ActionShortcut(AName: string; AShortcut: TUTF8Char);
  39. procedure ApplyTheme;
  40. function GetIndividualToolbarHeight: integer;
  41. public
  42. constructor Create(AInstance: TLazPaintCustomInstance; AActionList: TActionList);
  43. destructor Destroy; override;
  44. procedure PredefinedMainMenus(const AMainMenus: array of TMenuItem);
  45. procedure Toolbars(const AToolbars: array of TPanel; AToolbarBackground: TPanel);
  46. procedure ScaleToolbars(ATargetDPI: integer);
  47. procedure CycleTool(var ATool: TPaintToolType; var AShortCut: TUTF8Char);
  48. procedure Apply;
  49. procedure ArrangeToolbars(ClientWidth: integer);
  50. procedure RepaintToolbar;
  51. property ToolbarsHeight: integer read FToolbarsHeight;
  52. property ImageList: TImageList read FImageList write FImageList;
  53. property DarkTheme: boolean read FDarkTheme write SetDarkTheme;
  54. end;
  55. implementation
  56. uses UResourceStrings, BGRAUTF8, LCScaleDPI, ComCtrls, Graphics,
  57. StdCtrls, BGRAText, math, udarktheme,
  58. ugraph, BGRABitmapTypes, LCVectorialFillControl,
  59. UPython, UTranslation;
  60. { TMainFormMenu }
  61. procedure TMainFormMenu.IconSizeMenuClick(Sender: TObject);
  62. var
  63. menu: TMenuItem;
  64. i, iconSize: Integer;
  65. begin
  66. menu := Sender as TMenuItem;
  67. iconSize := FInstance.Config.DefaultIconSize(0);
  68. for i := 0 to menu.Count-1 do
  69. menu.Items[i].Checked := (menu.Items[i].Tag = iconSize);
  70. end;
  71. procedure TMainFormMenu.Script_Click(Sender: TObject);
  72. var
  73. item: TMenuItem;
  74. scriptIndex: integer;
  75. begin
  76. if Assigned(FInstalledScripts) then
  77. begin
  78. item := Sender as TMenuItem;
  79. scriptIndex := item.Tag;
  80. FInstance.RunScript(FInstalledScripts[scriptIndex], item.Caption);
  81. end;
  82. end;
  83. procedure TMainFormMenu.SetDarkTheme(AValue: boolean);
  84. begin
  85. if FDarkTheme=AValue then Exit;
  86. FDarkTheme:=AValue;
  87. ApplyTheme;
  88. end;
  89. procedure TMainFormMenu.IconSizeItemClick(Sender: TObject);
  90. var
  91. item: TMenuItem;
  92. begin
  93. item:= Sender as TMenuItem;
  94. FInstance.ChangeIconSize(item.Tag);
  95. end;
  96. procedure TMainFormMenu.AddMenus(AMenu: TMenuItem; AActionList: TActionList;
  97. AActionsCommaText: string; AIndex: integer);
  98. var actions: TStringList;
  99. foundAction: TBasicAction;
  100. item: TMenuItem;
  101. i,j: NativeInt;
  102. procedure AddSubItem(ACaption: string; AOnClick: TNotifyEvent; ATag: integer);
  103. var
  104. subItem: TMenuItem;
  105. begin
  106. subItem := TMenuItem.Create(item);
  107. subItem.Caption := ACaption;
  108. subItem.Tag := ATag;
  109. subItem.OnClick := AOnClick;
  110. item.Add(subItem);
  111. end;
  112. procedure AddSubItem(AAction: TBasicAction; ATag: integer = 0);
  113. var
  114. subItem: TMenuItem;
  115. begin
  116. subItem := TMenuItem.Create(item);
  117. subItem.Action := AAction;
  118. subItem.Tag := ATag;
  119. item.Add(subItem);
  120. end;
  121. begin
  122. actions := TStringList.Create;
  123. actions.CommaText := AActionsCommaText;
  124. for i := 0 to actions.Count-1 do
  125. if (actions[i]='*') and (AIndex = -1) then
  126. AIndex := 0;
  127. for i := 0 to actions.Count-1 do
  128. begin
  129. if actions[i]='*' then
  130. begin
  131. AIndex := -1;
  132. Continue;
  133. end;
  134. if actions[i]='InstalledScripts' then
  135. begin
  136. AddInstalledScripts(AMenu, AIndex);
  137. continue;
  138. end;
  139. item := TMenuItem.Create(nil);
  140. if trim(actions[i]) = '-' then
  141. item.Caption := cLineCaption
  142. else
  143. begin
  144. foundAction := AActionList.ActionByName(actions[i]);
  145. if foundAction <> nil then
  146. item.Action := foundAction
  147. else
  148. begin
  149. for j := 0 to AMenu.Count-1 do
  150. if UTF8CompareText(AMenu.Items[j].Name,actions[i])=0 then
  151. begin
  152. FreeAndNil(item);
  153. AMenu.Items[j].Visible := true;
  154. if (AIndex <> -1) and (AIndex < j) then
  155. begin
  156. item := AMenu.Items[j];
  157. AMenu.Remove(item);
  158. AMenu.Insert(AIndex,item);
  159. item := nil;
  160. inc(AIndex);
  161. end else
  162. if AIndex = -1 then
  163. begin
  164. item := AMenu.Items[j];
  165. AMenu.Remove(item);
  166. AMenu.Add(item);
  167. item := nil;
  168. end;
  169. break;
  170. end;
  171. if Assigned(item) and (actions[i] = 'MenuIconSize') then
  172. begin
  173. item.Caption := rsIconSize;
  174. item.OnClick:=@IconSizeMenuClick;
  175. AddSubItem('16px', @IconSizeItemClick, 16);
  176. AddSubItem('20px', @IconSizeItemClick, 20);
  177. AddSubItem('24px', @IconSizeItemClick, 24);
  178. AddSubItem('32px', @IconSizeItemClick, 32);
  179. AddSubItem('40px', @IconSizeItemClick, 40);
  180. AddSubItem('48px', @IconSizeItemClick, 48);
  181. AddSubItem(rsAutodetect, @IconSizeItemClick, 0);
  182. AMenu.Add(item);
  183. item := nil;
  184. end else
  185. if Assigned(item) and (actions[i] = 'EditShapeAlign') then
  186. begin
  187. item.Caption := rsAlignShape;
  188. AddSubItem(AActionList.ActionByName('EditShapeAlignLeft'));
  189. AddSubItem(AActionList.ActionByName('EditShapeCenterHorizontally'));
  190. AddSubItem(AActionList.ActionByName('EditShapeAlignRight'));
  191. AddSubItem('-',nil,0);
  192. AddSubItem(AActionList.ActionByName('EditShapeAlignTop'));
  193. AddSubItem(AActionList.ActionByName('EditShapeCenterVertically'));
  194. AddSubItem(AActionList.ActionByName('EditShapeAlignBottom'));
  195. AMenu.Add(item);
  196. item := nil;
  197. end;
  198. if Assigned(item) then item.Caption := trim(actions[i])+'?';
  199. end;
  200. end;
  201. if Assigned(item) then
  202. begin
  203. if AIndex = -1 then
  204. AMenu.Add(item)
  205. else
  206. begin
  207. AMenu.Insert(AIndex,item);
  208. inc(AIndex);
  209. end;
  210. end;
  211. end;
  212. actions.Free;
  213. end;
  214. procedure TMainFormMenu.AddMenus(AMenuName: string; AActionsCommaText: string);
  215. var i: NativeInt;
  216. begin
  217. for i := 0 to MenuDefinitionKeys.count-1 do
  218. if UTF8CompareText(MenuDefinitionKeys[i],AMenuName)=0 then
  219. begin
  220. AActionsCommaText:= MenuDefinitionValues[i];
  221. if AActionsCommaText = '' then exit;
  222. break;
  223. end;
  224. for i := 0 to high(FMainMenus) do
  225. if FMainMenus[i].menu.Name = AMenuName then
  226. begin
  227. AddMenus(FMainMenus[i].menu, FActionList, AActionsCommaText);
  228. FMainMenus[i].used := true;
  229. end;
  230. end;
  231. procedure TMainFormMenu.AddInstalledScripts(AMenu: TMenuItem; AIndex: integer);
  232. procedure AddScriptRec(AMenu: TMenuItem; var AIndex: integer; AItem: TMenuItem);
  233. var
  234. posSub, j, subIndex: integer;
  235. sectionName: String;
  236. sectionItem: TMenuItem;
  237. begin
  238. posSub := pos('>', AItem.Caption);
  239. if posSub > 0 then
  240. begin
  241. sectionName := copy(AItem.Caption, 1, posSub-1);
  242. AItem.Caption := copy(AItem.Caption, posSub+1, length(AItem.Caption) - posSub);
  243. subIndex := -1;
  244. for j := 0 to AMenu.Count-1 do
  245. if AMenu.Items[j].Caption = sectionName then
  246. begin
  247. AddScriptRec(AMenu.Items[j], subIndex, AItem);
  248. exit;
  249. end;
  250. sectionItem := TMenuItem.Create(AMenu);
  251. sectionItem.Caption := sectionName;
  252. if AIndex = -1 then
  253. AMenu.Add(sectionItem)
  254. else
  255. begin
  256. AMenu.Insert(AIndex, sectionItem);
  257. inc(AIndex);
  258. end;
  259. AddScriptRec(sectionItem, subIndex, AItem);
  260. exit;
  261. end;
  262. if AIndex = -1 then
  263. AMenu.Add(AItem)
  264. else
  265. begin
  266. AMenu.Insert(AIndex, AItem);
  267. inc(AIndex);
  268. end;
  269. end;
  270. var
  271. path, fullname, title: String;
  272. searchRec: TSearchRec;
  273. item: TMenuItem;
  274. items: TStringList;
  275. i: Integer;
  276. begin
  277. if FInstalledScripts = nil then FInstalledScripts := TStringList.Create;
  278. path := TPythonScript.DefaultScriptDirectory;
  279. if FindFirstUTF8(path+PathDelim+'*.py', faAnyFile, searchRec)=0 then
  280. begin
  281. items := TStringList.Create;
  282. items.Sorted := true;
  283. try
  284. repeat
  285. fullname := ConcatPaths([path, searchRec.Name]);
  286. if FileExistsUTF8(fullname) then
  287. begin
  288. title := GetScriptTitle(fullname);
  289. if title <> '' then
  290. begin
  291. item := TMenuItem.Create(AMenu);
  292. item.Caption := title;
  293. item.Tag := FInstalledScripts.Add(fullname);
  294. item.OnClick:=@Script_Click;
  295. items.AddObject(title, item);
  296. end;
  297. end;
  298. until FindNextUTF8(searchRec)<>0;
  299. finally
  300. FindCloseUTF8(searchRec);
  301. for i := 0 to items.Count-1 do
  302. AddScriptRec(AMenu, AIndex, TMenuItem(items.Objects[i]));
  303. items.Free;
  304. end;
  305. end;
  306. end;
  307. procedure TMainFormMenu.ActionShortcut(AName: string; AShortcut: TUTF8Char);
  308. var foundAction: TBasicAction;
  309. ShortcutStr: string;
  310. begin
  311. foundAction := FActionList.ActionByName(AName);
  312. if foundAction <> nil then
  313. begin
  314. ShortcutStr := AShortcut;
  315. if (length(AName) >= 5) and (copy(AName,1,4) = 'Tool') and
  316. (AName[5] = upcase(AName[5])) then
  317. FToolsShortcuts[StrToPaintToolType(copy(AName,5,length(AName)-4))] := AShortcut;
  318. AppendShortcut(foundAction as TAction, ShortcutStr);
  319. end;
  320. end;
  321. procedure TMainFormMenu.ApplyTheme;
  322. var
  323. i, j: Integer;
  324. begin
  325. for i := 0 to high(FToolbars) do
  326. begin
  327. with FToolbars[i].tb do
  328. begin
  329. DarkThemeInstance.Apply(FToolbars[i].tb, DarkTheme);
  330. for j := 0 to ControlCount-1 do
  331. if Controls[j] is TLabel then
  332. begin
  333. if (Controls[j].Name = 'Label_CurrentZoom') then
  334. begin
  335. Controls[j].Color := DarkThemeInstance.GetColorEditableFace(FDarkTheme);
  336. Controls[j].Font.Color := DarkThemeInstance.GetColorEditableText(FDarkTheme);
  337. end;
  338. end;
  339. end;
  340. end;
  341. if Assigned(FToolbarBackground) then
  342. FToolbarBackground.Color := DarkThemeInstance.GetColorButtonFace(FDarkTheme);
  343. end;
  344. function TMainFormMenu.GetIndividualToolbarHeight: integer;
  345. begin
  346. result := DoScaleY(24,OriginalDPI,FTargetDPI);
  347. end;
  348. constructor TMainFormMenu.Create(AInstance: TLazPaintCustomInstance; AActionList: TActionList);
  349. begin
  350. FInstance := AInstance;
  351. FActionList := AActionList;
  352. FToolbarsHeight := 0;
  353. FTargetDPI := OriginalDPI;
  354. end;
  355. destructor TMainFormMenu.Destroy;
  356. begin
  357. FInstalledScripts.Free;
  358. inherited Destroy;
  359. end;
  360. procedure TMainFormMenu.PredefinedMainMenus(const AMainMenus: array of TMenuItem);
  361. var i: NativeInt;
  362. begin
  363. setlength(FMainMenus, length(AMainMenus));
  364. for i := 0 to high(AMainMenus) do
  365. begin
  366. FMainMenus[i].menu := AMainMenus[i];
  367. FMainMenus[i].used := false;
  368. end;
  369. end;
  370. procedure TMainFormMenu.Toolbars(const AToolbars: array of TPanel; AToolbarBackground: TPanel);
  371. var i,j: NativeInt;
  372. begin
  373. setlength(FToolbars, length(AToolbars));
  374. for i := 0 to high(FToolbars) do
  375. begin
  376. FToolbars[i].tb := AToolbars[i];
  377. FToolbars[i].tb.Cursor := crArrow;
  378. with FToolbars[i].tb do
  379. for j := 0 to ControlCount-1 do
  380. begin
  381. Controls[j].Cursor := crArrow;
  382. if Controls[j] is TLabel then
  383. begin
  384. if (Controls[j].Name = 'Label_Coordinates') or
  385. (Controls[j].Name = 'Label_CurrentZoom') or
  386. (Controls[j].Name = 'Label_CurrentDiff') then
  387. Controls[j].Font.Height := -DoScaleY(12, OriginalDPI, FTargetDPI);
  388. end;
  389. end;
  390. end;
  391. FToolbarBackground := AToolbarBackground;
  392. end;
  393. procedure TMainFormMenu.ScaleToolbars(ATargetDPI: integer);
  394. var
  395. i: Integer;
  396. begin
  397. FTargetDPI := ATargetDPI;
  398. for i := 0 to high(FToolbars) do
  399. ScaleControl(FToolbars[i].tb, OriginalDPI, ATargetDPI, ATargetDPI, true);
  400. end;
  401. procedure TMainFormMenu.CycleTool(var ATool: TPaintToolType;
  402. var AShortCut: TUTF8Char);
  403. const cyrillicMap = 'ФИСВУАПРШОЛДЬТЩЗЙКЫЕГМЦЧНЯ';
  404. var
  405. curTool: TPaintToolType;
  406. latinShortCut: TUTF8Char;
  407. idx: integer;
  408. begin
  409. latinShortCut := UTF8UpperCase(AShortCut);
  410. curTool := ATool;
  411. if (length(latinShortCut) <> 1) or
  412. ((length(latinShortCut) = 1) and not (latinShortCut[1] in ['A'..'Z'])) then
  413. begin
  414. idx := pos(latinShortCut, cyrillicMap);
  415. if idx <> 0 then
  416. begin
  417. idx := UTF8Length(copy(cyrillicMap, 1, idx));
  418. latinShortCut := chr(idx+64);
  419. end;
  420. end;
  421. repeat
  422. if curTool = high(TPaintToolType) then
  423. curTool := low(TPaintToolType)
  424. else
  425. curTool := succ(curTool);
  426. if (FToolsShortcuts[curTool] = latinShortCut) and not
  427. ((curTool = ptHotSpot) and not FInstance.Image.IsCursor) then
  428. begin
  429. ATool := curTool;
  430. AShortCut:= '';
  431. exit;
  432. end;
  433. until curTool = ATool;
  434. end;
  435. procedure TMainFormMenu.Apply;
  436. const ImageBrowser = 'FileUseImageBrowser,';
  437. var i,j,tbHeight,tbHeightOrig: NativeInt;
  438. begin
  439. for i := 0 to FActionList.ActionCount-1 do
  440. with FActionList.Actions[i] as TAction do
  441. if (Caption = '') and (Hint <> '') then Caption := Hint;
  442. AddMenus('MenuFile', 'FileNew,FileOpen,LayerFromFile,FileChooseEntry,FileReload,MenuRecentFiles,-,FileSave,FileSaveAsInSameFolder,FileSaveAs,FileExport,-,FileImport3D,-,FilePrint,-,'+ImageBrowser+'FileRememberSaveFormat,ForgetDialogAnswers,MenuLanguage,*');
  443. AddMenus('MenuEdit', 'EditUndo,EditRedo,-,EditCut,EditCopy,EditPaste,EditPasteAsNew,EditPasteAsNewLayer,EditDeleteSelection,-,EditMoveUp,EditMoveToFront,EditMoveDown,EditMoveToBack,EditShapeAlign,EditShapeToCurve');
  444. AddMenus('MenuSelect', 'EditSelection,FileLoadSelection,FileSaveSelectionAs,-,EditSelectAll,EditInvertSelection,EditSelectionFit,EditDeselect,-,ToolSelectRect,ToolSelectEllipse,ToolSelectPoly,ToolSelectSpline,-,ToolMoveSelection,ToolRotateSelection,SelectionHorizontalFlip,SelectionVerticalFlip,-,ToolSelectPen,ToolMagicWand');
  445. AddMenus('MenuView', 'ViewGrid,ViewZoomOriginal,ViewZoomIn,ViewZoomOut,ViewZoomFit,-,ViewToolBox,ViewColors,ViewPalette,ViewLayerStack,ViewImageList,ViewStatusBar,-,*,-,ViewDarkTheme,ViewWorkspaceColor,MenuIconSize');
  446. AddMenus('MenuImage', 'ImageCrop,ImageCropLayer,ImageFlatten,MenuRemoveTransparency,-,ImageNegative,ImageLinearNegative,ImageSwapRedBlue,-,ImageChangeCanvasSize,ImageRepeat,-,ImageResample,ImageSmartZoom3,-,ImageRotateCW,ImageRotateCCW,ImageRotate180,ImageHorizontalFlip,ImageVerticalFlip');
  447. AddMenus('MenuRemoveTransparency', 'ImageClearAlpha,ImageFillBackground');
  448. AddMenus('MenuFilter', 'MenuRadialBlur,FilterBlurMotion,FilterBlurCustom,FilterPixelate,-,FilterSharpen,FilterSmooth,FilterNoise,FilterMedian,FilterClearType,FilterClearTypeInverse,FilterFunction,-,FilterContour,FilterEmboss,FilterPhong,-,FilterSphere,FilterTwirl,FilterWaveDisplacement,FilterCylinder');
  449. AddMenus('MenuRadialBlur', 'FilterBlurBox,FilterBlurFast,FilterBlurRadial,FilterBlurCorona,FilterBlurDisk');
  450. AddMenus('MenuColors', 'ColorCurves,ColorPosterize,ColorColorize,ColorShiftColors,FilterComplementaryColor,ColorIntensity,-,ColorLightness,FilterNegative,FilterLinearNegative,FilterNormalize,FilterGrayscale');
  451. AddMenus('MenuTool', 'ToolHand,ToolHotSpot,ToolColorPicker,-,ToolPen,ToolBrush,ToolEraser,ToolFloodFill,ToolClone,-,ToolEditShape,ToolRect,ToolEllipse,ToolPolyline,ToolOpenedCurve,ToolPolygon,ToolSpline,ToolGradient,ToolPhong,ToolText,-,ToolDeformation,ToolTextureMapping');
  452. AddMenus('MenuRender', 'RenderPerlinNoise,RenderCyclicPerlinNoise,-,RenderWater,RenderCustomWater,RenderSnowPrint,RenderWood,RenderWoodVertical,RenderMetalFloor,RenderPlastik,RenderStone,RenderRoundStone,RenderMarble,RenderCamouflage,-,RenderClouds,FilterRain,RenderHypocycloid,RenderSuperformula');
  453. AddMenus('MenuScript', 'FileRunScript,FileCheckScriptsSecure,-,InstalledScripts');
  454. AddMenus('MenuHelp', 'HelpIndex,-,HelpAbout');
  455. for i := 0 to high(FMainMenus) do
  456. if not FMainMenus[i].used then
  457. FMainMenus[i].menu.Visible := false;
  458. ApplyShortcuts;
  459. if Assigned(FImageList) then
  460. FActionList.Images := FImageList;
  461. tbHeightOrig := GetIndividualToolbarHeight;
  462. tbHeight := tbHeightOrig;
  463. for i := 0 to high(FToolbars) do
  464. with FToolbars[i].tb do
  465. begin
  466. Top := 0;
  467. Left := -Width;
  468. Color := clBtnFace;
  469. for j := 0 to ControlCount-1 do
  470. begin
  471. if Controls[j] is TToolBar then
  472. begin
  473. if assigned(FImageList) then TToolbar(Controls[j]).Images := FImageList;
  474. TToolbar(Controls[j]).ButtonWidth := TToolbar(Controls[j]).Images.Width+ScaleX(6, 96);
  475. TToolbar(Controls[j]).ButtonHeight := TToolbar(Controls[j]).Images.Height+ScaleY(5, 96);
  476. end else
  477. if Controls[j] is TLCVectorialFillControl then
  478. begin
  479. if assigned(FImageList) then
  480. TLCVectorialFillControl(Controls[j]).ToolIconSize:= FImageList.Height;
  481. end;
  482. end;
  483. end;
  484. for i := 0 to high(FToolbars) do
  485. with FToolbars[i].tb do
  486. begin
  487. Height := tbHeight;
  488. for j := 0 to ControlCount-1 do
  489. Controls[j].Top := Controls[j].Top + (tbHeight-tbHeightOrig) div 2;
  490. end;
  491. ApplyTheme;
  492. end;
  493. procedure TMainFormMenu.ArrangeToolbars(ClientWidth: integer);
  494. var i,j,k,curx,cury,maxh, w, minNextX, delta,
  495. tbNormalHeight: integer;
  496. tb: TPanel;
  497. vfc: TLCVectorialFillControl;
  498. begin
  499. tbNormalHeight := GetIndividualToolbarHeight;
  500. curx := 0;
  501. cury := 0;
  502. maxh := 0;
  503. for i := 0 to high(FToolbars) do
  504. begin
  505. tb := FToolbars[i].tb;
  506. if not FToolbars[i].fixed then
  507. begin
  508. for j := 0 to tb.ControlCount-1 do
  509. begin
  510. tb.Controls[j].Top := DoScaleY(1, OriginalDPI, FTargetDPI);
  511. if tb.Controls[j] is TLCVectorialFillControl then
  512. begin
  513. vfc := TLCVectorialFillControl(tb.Controls[j]);
  514. if tb.Height < vfc.PreferredSize.cy then
  515. vfc.Height := min(vfc.ToolIconSize + vfc.VerticalPadding,
  516. tb.Height - tb.Controls[j].Top - 1)
  517. else
  518. vfc.Height := vfc.PreferredSize.cy;
  519. end else
  520. if tb.Controls[j] is TLabel then
  521. tb.Controls[j].Height := tbNormalHeight - DoScaleY(3, OriginalDPI, FTargetDPI)
  522. else
  523. tb.Controls[j].Height := tbNormalHeight - DoScaleY(2, OriginalDPI, FTargetDPI);
  524. if tb.Controls[j] is TToolBar then
  525. begin
  526. minNextX := MaxLongInt;
  527. for k := 0 to tb.ControlCount-1 do
  528. if tb.Controls[k].Left > tb.Controls[j].Left then
  529. minNextX := min(minNextX, tb.Controls[k].Left);
  530. delta := tb.Controls[j].Left+tb.Controls[j].Width+2-minNextX;
  531. for k := 0 to tb.ControlCount-1 do
  532. if tb.Controls[k].Left > tb.Controls[j].Left then
  533. tb.Controls[k].Left := tb.Controls[k].Left+delta;
  534. end;
  535. end;
  536. end;
  537. w := DoScaleX(4, OriginalDPI);
  538. for j := 0 to tb.ControlCount-1 do
  539. if tb.Controls[j].Visible then
  540. w := max(w, tb.Controls[j].Left + tb.Controls[j].Width);
  541. w += DoScaleX(4, OriginalDPI);
  542. tb.Width := w;
  543. if tb.Visible then
  544. begin
  545. if curx+tb.Width > ClientWidth then
  546. begin
  547. curx := 0;
  548. cury += maxh;
  549. maxh := 0;
  550. end;
  551. tb.Left := curx;
  552. tb.Top := cury;
  553. inc(curx, tb.Width);
  554. if tb.Height > maxh then maxh := tb.Height;
  555. maxh := min(maxh, tbNormalHeight);
  556. end else
  557. begin
  558. //hide fix for Gtk
  559. tb.Top := -tb.Height;
  560. end;
  561. end;
  562. if curx <> 0 then FToolbarsHeight := cury+maxh else FToolbarsHeight := cury;
  563. if FToolbarsHeight = 0 then
  564. begin
  565. FToolbarBackground.Visible := false;
  566. end else
  567. begin
  568. FToolbarBackground.Top := 0;
  569. FToolbarBackground.Left := 0;
  570. FToolbarBackground.width := ClientWidth;
  571. FToolbarBackground.Height := FToolbarsHeight;
  572. FToolbarBackground.Anchors:= [akLeft,akTop,akRight];
  573. FToolbarBackground.Visible := true;
  574. end;
  575. end;
  576. procedure TMainFormMenu.RepaintToolbar;
  577. var i: NativeInt;
  578. begin
  579. FToolbarBackground.Invalidate;
  580. for i := 0 to high(FToolbars) do FToolbars[i].tb.Invalidate;
  581. FToolbarBackground.Update;
  582. for i := 0 to high(FToolbars) do FToolbars[i].tb.Update;
  583. end;
  584. procedure TMainFormMenu.ApplyShortcuts;
  585. begin
  586. ActionShortcut('ToolHand','H');
  587. ActionShortcut('ToolHotSpot','H');
  588. ActionShortcut('ToolPen','P');
  589. ActionShortcut('ToolBrush','B');
  590. ActionShortcut('ToolClone','K');
  591. ActionShortcut('ToolColorPicker','C');
  592. ActionShortcut('ToolEraser','E');
  593. ActionShortcut('ToolEditShape','J');
  594. ActionShortcut('ToolRect','U');
  595. ActionShortcut('ToolEllipse','U');
  596. ActionShortcut('ToolPolyline','L');
  597. ActionShortcut('ToolOpenedCurve','N');
  598. ActionShortcut('ToolPolygon','D');
  599. ActionShortcut('ToolSpline','D');
  600. ActionShortcut('ToolFloodfill','G');
  601. ActionShortcut('ToolGradient','G');
  602. ActionShortcut('ToolPhong','Y');
  603. ActionShortcut('ToolText','T');
  604. ActionShortcut('ToolSelectRect','M');
  605. ActionShortcut('ToolSelectEllipse','M');
  606. ActionShortcut('ToolSelectPoly','F');
  607. ActionShortcut('ToolSelectSpline','F');
  608. ActionShortcut('ToolMoveSelection','V');
  609. ActionShortcut('ToolRotateSelection','V');
  610. ActionShortcut('ToolSelectPen','O');
  611. ActionShortcut('ToolMagicWand','W');
  612. ActionShortcut('ViewZoomIn','+');
  613. ActionShortcut('ViewZoomOut','-');
  614. end;
  615. end.