gegl_VElements.pas 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977
  1. {
  2. * Copyright (c) 2021 SSW
  3. *
  4. * This software is provided 'as-is', without any express or
  5. * implied warranty. In no event will the authors be held
  6. * liable for any damages arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute
  10. * it freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented;
  13. * you must not claim that you wrote the original software.
  14. * If you use this software in a product, an acknowledgment
  15. * in the product documentation would be appreciated but
  16. * is not required.
  17. *
  18. * 2. Altered source versions must be plainly marked as such,
  19. * and must not be misrepresented as being the original software.
  20. *
  21. * 3. This notice may not be removed or altered from any
  22. * source distribution.
  23. }
  24. unit gegl_VElements;
  25. {$I zgl_config.cfg}
  26. interface
  27. uses
  28. gegl_Types,
  29. zgl_application,
  30. zgl_types,
  31. zgl_utils,
  32. zgl_font,
  33. zgl_keyboard,
  34. zgl_timers,
  35. gegl_utils,
  36. zgl_mouse,
  37. {$IfDef MOBILE}
  38. zgl_touch,
  39. {$EndIf}
  40. zgl_collision_2d,
  41. gegl_color,
  42. zgl_window;
  43. var
  44. managerSetOfTools: geglTSetOfToolsManager;
  45. propEl: geglPPropertElement;
  46. // Rus: создание поля ввода. Заданный прямоугольник; шрифт; размер шрифта;
  47. // заданные процедуры: вывода поля ввода и ограничению вводимых символов;
  48. // длина строки. По умолчанию, заданных процедур нет, длина строки = 80.
  49. //
  50. // Eng: creating an input field. The specified rectangle; font; font size; the
  51. // specified procedures: output of the input field and the limitation of the
  52. // entered characters; the length of the string. By default, there are no
  53. // specified procedures, line length = 80.
  54. function CreateEdit(Rect: zglTRect2D; fnt, Scale: LongWord; UserData1: Pointer = nil; UserData2: Pointer = nil; Len: Word = MAX_SYMBOL_LINE): LongWord; // функция с запасом на будущее
  55. // Rus: обработка событий поля ввода, вызывать не надо. Менеджер всё сделает
  56. // за вас.
  57. // Eng: event handling of the input field, no need to call. The manager will do
  58. // everything for you.
  59. procedure EventsEdit(numElement: LongWord);
  60. // Rus: удаление определённого элемента API, по его номеру. И без разницы какой
  61. // это элемент, он будет удалён, не выключен.
  62. // Eng: deleting a specific API element by its number. And no matter what element
  63. // it is, it will be deleted, not turned off.
  64. procedure DeleteElementSOT(numElement: LongWord);
  65. // Rus: Установка цвета в уже созданном поле ввода (а точнее указание номеров
  66. // использыемых цветов). Вы можете использовать эту функцию для настройки
  67. // как после создания поля ввода, так и во время работы программы (в меню
  68. // настроек).
  69. // Eng: Setting a color in an already created input field (or rather, specifying
  70. // the numbers of used colors). You can use this function to configure both
  71. // after creating the input field and while the program is running (in the
  72. // settings menu).
  73. procedure SetDefColor(ColorText, ColorBackground: LongWord; ColorCursor: LongWord = cl_Black);
  74. // Rus: уничтожение всех элементов API. Вызывать не нужно!!! Производится по
  75. // закрытию программы!!!
  76. // Eng: destruction of all API elements. Don't Run !!! It is performed when the
  77. // program is closed !!!
  78. procedure DestroyManagerSOT();
  79. // Rus: Установка точки вращения и угла вращения (если это необходимо).
  80. // Обратить внимание! Заданная точка, будет работать для всех элементов!!!
  81. // Потому, для создания нового элемента, её надо пересчитать или обнулить.
  82. // Запускать до создания элемента API!!!
  83. // Engv: Set pivot point and pivot angle (if necessary).
  84. // Note! The set point will work for all elements !!! Therefore, to create
  85. // a new element, it must be recalculated or reset to zero.
  86. // Run before API element is created !!!
  87. procedure SetOfRotateAngleAndPoint(x, y: Single; angle: Single = 0); {$IfDef USE_INLINE} inline; {$EndIf}
  88. // Rus: возвращаем текст из строки
  89. // Eng: return text from string
  90. function GetEditToText(num: LongWord): UTF8String;
  91. // Rus: корректировка курсора, + - вниз. Курсор может быть не правильно
  92. // скорректирован, это зависит от используемого шрифта. Надо настраивать
  93. // вручную для разных шрифтов.
  94. // Eng: cursor adjustment, + - down. The cursor may not be adjusted correctly,
  95. // depending on the font used. Must be manually configured for
  96. // different fonts.
  97. procedure CorrectEditCursor(num: LongWord; y: Single);
  98. // Rus: активация поля ввода. Сделано автоматическое, при нажатии мыши на поле
  99. // ввода. Но это можно отключить и по своему событию произвести активацию.
  100. // Eng: activation of the input field. Made automatic when clicking on the input
  101. // field. But this can be turned off and activated according to your event.
  102. procedure ActivateEdit(num: LongWord);
  103. // Rus: Установить флаги поля ввода.
  104. // NumOnly - только цифры
  105. // NumDelimeter - цифры и разделитель - точка и запятая
  106. // CurEndSymb - курсор не дальше последнего символа (смещается всё влево)
  107. // RightToLeft - обратное направление?
  108. // OnTRightSide - прижато к правой стороне
  109. // SymbOnly - только символы и цифры, ни каких пробелов и знаков препинания.
  110. // DelimetrTrue - разделитель уже существует.
  111. // Eng:
  112. procedure SetFlagsEdit(num: LongWord; var newFlags: Byte);
  113. // Rus: функции обработки (ограничения) поля ввода. Вызывать не надо,
  114. // устанавливаются по функции устновки флагов - SetFlagsEdit.
  115. // Eng:
  116. // Rus: только числа
  117. // Eng:
  118. function EditNumeric: Boolean;
  119. // Rus: только числа и разделитель
  120. // Eng:
  121. function EditNumericAndDelimetr: Boolean;
  122. // Rus: символы кроме не учавствующих в именах (буквы, цифры) и исключая пробел
  123. // - в общем всё для создания имени.
  124. // Eng:
  125. function EditNotSymbolic: Boolean;
  126. // Rus: установка флага видимости данного элемента.
  127. // Eng:
  128. procedure SetVisibleElement(numEl: LongWord; flag: Boolean);
  129. var
  130. // угол поворота
  131. geAngle: Single = 0;
  132. // точка поворота
  133. pointManager: zglTPoint2D = (x: 0; y: 0);
  134. implementation
  135. {$IfDef FULL_LOGGING}
  136. uses
  137. zgl_log;
  138. {$EndIf}
  139. var
  140. // RU: поле ввода (пока просто вывода текста)
  141. UseText: geglPEdit;
  142. // цвет по умолчанию.
  143. geDefColor: geglDefColor;
  144. useFont: zglPFont; // защита от многопроцессорного исполнения
  145. rs1_2: Single = 1.2;
  146. _cursor: geglPCursor;
  147. { эта часть может понадобиться только если мы будем использовать код в многопоточности. Остальное - это заморочки.
  148. // момент, когда уничтожаются все элементы (на данное время, все поля ввода).
  149. destroyElements: Boolean = False;
  150. // момент, когда происходит действие с определённым элементом, а его надо уничтожить. Состояние элемента, True - занят.
  151. AllEditElementsSost: Boolean = False; }
  152. function CreateEdit(Rect: zglTRect2D; fnt, Scale: LongWord; UserData1: Pointer = nil; UserData2: Pointer = nil; Len: Word = MAX_SYMBOL_LINE): LongWord;
  153. var
  154. i: LongWord;
  155. pFlags: PLongWord;
  156. charDesc: zglPCharDescSmall;
  157. charDesc1: zglPCharDesc;
  158. begin
  159. // AllEditElementsSost := True;
  160. Result := 65536;
  161. { if destroyElements then
  162. begin
  163. AllEditElementsSost := False;
  164. exit;
  165. end;}
  166. if managerSetOfTools.count = 65535 then
  167. begin
  168. Result := 65536;
  169. log_Add('Too many visuals already created!!');
  170. exit;
  171. end;
  172. if managerSetOfTools.count >= managerSetOfTools.maxPossibleEl then
  173. begin
  174. managerSetOfTools.maxPossibleEl := managerSetOfTools.maxPossibleEl + 5;
  175. SetLength(managerSetOfTools.SetOfTools, managerSetOfTools.maxPossibleEl);
  176. SetLength(managerSetOfTools.propElement, managerSetOfTools.maxPossibleEl);
  177. for i := managerSetOfTools.count to managerSetOfTools.maxPossibleEl - 1 do
  178. managerSetOfTools.propElement[i].FlagsProp := 0;
  179. end;
  180. for i := 0 to managerSetOfTools.maxPossibleEl - 1 do
  181. begin
  182. UseText := managerSetOfTools.SetOfTools[i];
  183. pFlags := @managerSetOfTools.propElement[i].FlagsProp;
  184. if not Assigned(UseText) then
  185. Break;
  186. if (pFlags^ and el_Enable) = 0 then
  187. Break;
  188. end;
  189. if not Assigned(UseText) then
  190. begin
  191. zgl_GetMem(Pointer(UseText), SizeOf(geglTEdit));
  192. managerSetOfTools.SetOfTools[managerSetOfTools.count] := UseText;
  193. end;
  194. managerSetOfTools.propElement[i].Element := is_Edit;
  195. pFlags^ := pFlags^ or el_Enable_or_Visible;
  196. pFlags := nil;
  197. Result := i;
  198. useFont := managerFont.Font[fnt];
  199. UseText^.Rect.X := Rect.X;
  200. UseText^.Rect.Y := Rect.Y;
  201. UseText^.Rect.W := Rect.W;
  202. UseText^.Rect.H := Rect.H;
  203. UseText^.ColorText := geDefColor.Text;
  204. UseText^.ColorGround := geDefColor.Ground;
  205. UseText^.ColorCursor := geDefColor.Cursor;
  206. UseText^.Scale := useFont^.ScaleNorm * Scale / 10;
  207. UseText^._ShiftP63 := useFont^.CharDesc[63]^.ShiftP * useFont^.Scale * 1.5;
  208. UseText^.Rotate := geAngle;
  209. UseText^.EditString.Len := Len;
  210. SetLength(UseText^.EditString.CharSymb, Len + 1);
  211. SetLength(UseText^.EditString.posX, len + 1);
  212. UseText^.EditString.UseLen := 0;
  213. for i := 0 to 65535 do
  214. begin
  215. if Assigned(useFont.CharDesc[i]) then
  216. begin
  217. zgl_GetMem(Pointer(UseText.CharDesc[i]), SizeOf(zglTCharDesc));
  218. charDesc := UseText^.CharDesc[i];
  219. charDesc1 := useFont^.CharDesc[i];
  220. end
  221. else
  222. Continue;
  223. charDesc^.TexCoords[0] := charDesc1^.TexCoords[0];
  224. charDesc^.TexCoords[1] := charDesc1^.TexCoords[1];
  225. charDesc^.TexCoords[2] := charDesc1^.TexCoords[2];
  226. charDesc^.TexCoords[3] := charDesc1^.TexCoords[3];
  227. charDesc^.Page := charDesc1^.Page;
  228. charDesc^.xx1 := charDesc1^._x1 * UseText.Scale;
  229. charDesc^.yy1 := charDesc1^._y1 * UseText.Scale;
  230. charDesc^.xx2 := charDesc1^._x2 * UseText.Scale;
  231. charDesc^.yy2 := charDesc1^._y2 * UseText.Scale;
  232. end;
  233. i := 0;
  234. while i <= Len do
  235. begin
  236. UseText^.EditString.posX[i] := 0;
  237. inc(i);
  238. end;
  239. {$IFDEF DELPHI7_AND_DOWN}
  240. zgl_GetMem(z, SizeOf(geglTCursor));
  241. UseText^.Cursor := z;
  242. {$ELSE}
  243. zgl_GetMem(UseText^.Cursor, SizeOf(geglTCursor));
  244. {$EndIf}
  245. _cursor := UseText^.Cursor;
  246. _cursor^.curRect.X := 0;
  247. _cursor^.curRect.Y := rs1_2 * Scale;
  248. _cursor^.curRect.H := 2;
  249. _cursor^.curRect.W := 6 * Scale / 10;
  250. _cursor^.NSleep := CUR_FLASH;
  251. _cursor^.Flags := False;
  252. _cursor^.position := 1;
  253. UseText^.translateX := 0;
  254. UseText^.RotatePoint := pointManager;
  255. UseText^.font := fnt;
  256. UseText^.procDraw := UserData1;
  257. UseText^.procLimit := UserData2;
  258. inc(managerSetOfTools.count);
  259. UseText := nil;
  260. end;
  261. procedure EventsEdit(numElement: LongWord);
  262. var
  263. symb, i, j, n: LongWord;
  264. _JcharSymb: zglPCharDesc;
  265. t: Double;
  266. _ShiftP: Single;
  267. mDX, mDY: Single;
  268. sinAngle, cosAngle: Single;
  269. label
  270. smallJmp, jmpMouse;
  271. // определяем позицию курсора и его ширину
  272. procedure SetCursorPosAndWidth;
  273. begin
  274. _cursor^.curRect.x := UseText^.EditString.posX[_cursor^.position - 1];
  275. if (_Cursor^.position <= UseText^.EditString.Len) and (_Cursor^.position <= UseText^.EditString.UseLen) then
  276. begin
  277. _JcharSymb := useFont^.CharDesc[UseText^.EditString.CharSymb[_Cursor^.position - 1]];
  278. if Assigned(_JcharSymb) then
  279. _Cursor^.curRect.W := _JcharSymb^.ShiftP * UseText^.Scale;
  280. end
  281. else
  282. _Cursor^.curRect.W := UseText^._ShiftP63 * UseText^.Scale;
  283. end;
  284. procedure RollEditLeft;
  285. begin
  286. SetCursorPosAndWidth;
  287. if UseText^.translateX > 0 then
  288. if (_Cursor^.curRect.X - 40) < UseText^.translateX then
  289. UseText^.translateX := _Cursor^.curRect.X - 40;
  290. if UseText^.translateX < 0 then
  291. UseText^.translateX := 0;
  292. end;
  293. procedure RollEditRight;
  294. begin
  295. SetCursorPosAndWidth;
  296. if UseText^.EditString.UseLen < _Cursor^.position then
  297. begin
  298. if (UseText^.Cursor^.curRect.x + _Cursor^.curRect.W - UseText^.translateX) > (UseText^.Rect.W) then
  299. begin
  300. UseText^.translateX := (_Cursor^.curRect.x + _Cursor^.curRect.W) - (UseText^.Rect.W );
  301. end;
  302. end
  303. else begin
  304. if ((_Cursor^.curRect.X - UseText^.translateX) > (UseText^.Rect.W - 60)) and
  305. ((UseText^.EditString.posX[UseText^.EditString.UseLen] - UseText^.translateX) > UseText^.Rect.W) then
  306. begin
  307. UseText^.translateX := (_Cursor^.curRect.x + 60) - (UseText^.Rect.W );
  308. if (UseText^.Rect.W + UseText^.translateX) > UseText^.EditString.posX[UseText^.EditString.UseLen] then
  309. UseText^.translateX := UseText^.EditString.posX[UseText^.EditString.UseLen] - UseText^.Rect.W;
  310. end;
  311. end;
  312. end;
  313. begin
  314. { AllEditElementsSost := True;
  315. if destroyElements then
  316. begin
  317. AllEditElementsSost := False;
  318. exit;
  319. end; }
  320. {$IfDef FULL_LOGGING}
  321. if (managerSetOfTools.count = 0) or (managerSetOfTools.SetOfTools[numElement] = nil) then
  322. BEGIN
  323. log_add('Error is EventsEdit!');
  324. exit;
  325. end;
  326. {$EndIf}
  327. if (managerSetOfTools.propElement[numElement].FlagsProp and el_Enable = 0) or (managerSetOfTools.propElement[numElement].FlagsProp and el_Visible = 0) then
  328. Exit;
  329. UseText := managerSetOfTools.SetOfTools[numElement];
  330. useFont := managerFont.Font[UseText^.font];
  331. _cursor := UseText^.Cursor;
  332. if managerSetOfTools.ActiveElement <> numElement then
  333. goto jmpMouse;
  334. if keysUp[K_INSERT] then
  335. if ((PkeybFlags^ and keyboardInsert) > 0) then
  336. _Cursor^.curRect.H := - UseText^.Scale * rs1_2
  337. else
  338. _Cursor^.curRect.H := 2;
  339. if keysLast[KA_DOWN] > 0 then
  340. begin
  341. t := timer_GetTicks;
  342. if keysLast[KA_DOWN] <> keysLast[KT_DOWN] then
  343. begin
  344. keysLast[KT_DOWN] := keysLast[KA_DOWN];
  345. keyDownRepeat := t;
  346. keyDelayWork := beginKeyDelay;
  347. end
  348. else
  349. if t - keyDownRepeat > keyDelayWork then
  350. begin
  351. keyDownRepeat := t;
  352. keyDelayWork := repeatKeyDelay;
  353. end
  354. else begin
  355. Exit;
  356. end;
  357. case keysLast[KA_DOWN] of
  358. K_ESCAPE: exit;
  359. K_UP: ;
  360. K_DOWN: ;
  361. K_LEFT:
  362. begin
  363. if _Cursor^.position = 1 then
  364. exit;
  365. if keysDown[K_CTRL] then
  366. begin
  367. i := _Cursor^.position;
  368. j := 0;
  369. if (UseText^.EditString.CharSymb[i - 2] = 32) or (UseText^.EditString.CharSymb[i - 2] = 9) then
  370. dec(i, 2);
  371. while i > 1 do
  372. begin
  373. if (j > 0) and ((UseText^.EditString.CharSymb[i - 1] = 32) or (UseText^.EditString.CharSymb[i - 1] = 9)) then
  374. begin
  375. if (UseText^.EditString.CharSymb[i] <> 32) and (UseText^.EditString.CharSymb[i] <> 9) then
  376. begin
  377. _Cursor^.position := i + 1;
  378. RollEditLeft;
  379. exit;
  380. end;
  381. end
  382. else
  383. inc(j);
  384. dec(i);
  385. end;
  386. _Cursor^.position := 1;
  387. end
  388. else begin
  389. dec(_Cursor^.position);
  390. end;
  391. RollEditLeft;
  392. end;
  393. K_RIGHT:
  394. Begin
  395. if _Cursor^.position > UseText^.EditString.UseLen then
  396. Exit;
  397. if keysDown[K_CTRL] then
  398. begin
  399. i := _Cursor^.position;
  400. j := 0;
  401. if (UseText^.EditString.CharSymb[i] = 32) or (UseText^.EditString.CharSymb[i] = 9) then
  402. inc(i, 2);
  403. while i < UseText^.EditString.UseLen + 1 do
  404. begin
  405. if (j > 0) and ((UseText^.EditString.CharSymb[i - 1] = 32) or (UseText^.EditString.CharSymb[i - 1] = 9)) then
  406. begin
  407. if (UseText^.EditString.CharSymb[i - 2] <> 32) and (UseText^.EditString.CharSymb[i - 2] <> 9) then
  408. begin
  409. _Cursor^.position := i - 1;
  410. RollEditRight;
  411. exit;
  412. end;
  413. end
  414. else
  415. inc(j);
  416. inc(i);
  417. end;
  418. _Cursor^.position := UseText^.EditString.UseLen + 1;
  419. end
  420. else begin
  421. inc(_Cursor^.position);
  422. end;
  423. RollEditRight;
  424. end;
  425. K_BACKSPACE:
  426. begin
  427. if (_Cursor^.position = 1) or (UseText^.EditString.UseLen = 0) then
  428. Exit;
  429. dec(_Cursor^.position);
  430. dec(UseText^.EditString.UseLen);
  431. if _Cursor^.position > UseText^.EditString.UseLen then
  432. UseText^.EditString.CharSymb[UseText^.EditString.UseLen] := 0
  433. else begin
  434. i := UseText^.EditString.UseLen - (_Cursor^.position - 1);
  435. j := _Cursor^.position;
  436. while i > 0 do
  437. begin
  438. UseText^.EditString.CharSymb[j - 1] := UseText^.EditString.CharSymb[j];
  439. UseText^.EditString.posX[j] := UseText^.EditString.posX[j - 1] +
  440. useFont^.CharDesc[UseText^.EditString.CharSymb[j - 1]]^.ShiftP * useFont^.Scale;
  441. inc(j);
  442. dec(i);
  443. end;
  444. UseText^.EditString.CharSymb[j - 1] := 0;
  445. end;
  446. RollEditLeft;
  447. end;
  448. K_DELETE:
  449. begin
  450. if (UseText^.EditString.UseLen = 0) or (UseText^.EditString.UseLen < _Cursor^.position) then
  451. Exit;
  452. dec(UseText^.EditString.UseLen);
  453. if _Cursor^.position > UseText^.EditString.UseLen then
  454. UseText^.EditString.CharSymb[_Cursor^.position - 1] := 0
  455. else begin
  456. j := _Cursor^.position;
  457. while j <= UseText^.EditString.UseLen do
  458. begin
  459. UseText^.EditString.CharSymb[j - 1] := UseText^.EditString.CharSymb[j];
  460. UseText^.EditString.posX[j] := UseText^.EditString.posX[j - 1] +
  461. useFont^.CharDesc[UseText^.EditString.CharSymb[j - 1]]^.ShiftP * useFont^.Scale;
  462. inc(j);
  463. end;
  464. UseText^.EditString.CharSymb[j - 1] := 0;
  465. end;
  466. RollEditLeft;
  467. end;
  468. K_HOME:
  469. begin
  470. if UseText^.EditString.UseLen = 0 then
  471. begin
  472. _Cursor^.position := 1;
  473. exit;
  474. end;
  475. _Cursor^.position := 1;
  476. RollEditLeft;
  477. end;
  478. K_END:
  479. begin
  480. if UseText^.EditString.UseLen = 0 then
  481. begin
  482. _Cursor^.position := 1;
  483. exit;
  484. end;
  485. _Cursor^.position := UseText^.EditString.UseLen + 1;
  486. RollEditRight;
  487. end;
  488. K_PAGEDOWN: ;
  489. K_PAGEUP: ;
  490. K_ENTER, K_KP_ENTER:
  491. begin
  492. {$IfDef MOBILE}
  493. VisibleMenuChange := False;
  494. {$EndIf}
  495. managerSetOfTools.ActiveElement := ELEMENT_NOT_ACTIVE;
  496. end;
  497. else
  498. begin
  499. if UseText^.EditString.UseLen >= UseText^.EditString.Len then
  500. Exit;
  501. if (UseText^.flags and (vc_NumOnly or vc_NumDelimeter or vc_SymbOnly)) > 0 then
  502. if (UseText^.flags and vc_NumOnly) > 0 then
  503. begin
  504. if not EditNumeric then
  505. exit;
  506. end
  507. else
  508. if (UseText^.flags and vc_NumDelimeter) > 0 then
  509. begin
  510. if not EditNumericAndDelimetr then
  511. Exit;
  512. end
  513. else
  514. if not EditNotSymbolic then
  515. exit;
  516. symb := scancode_to_utf8(keysLast[KA_DOWN]);
  517. if symb = 0 then
  518. Exit;
  519. {$IfDef USE_VKEYBOARD}
  520. if (keybFlags and keyboardSymbol) > 0 then
  521. begin
  522. if keysLast[KA_DOWN] = K_KP_1 then
  523. symb := 124;
  524. if keysLast[KA_DOWN] = K_KP_2 then
  525. symb := 63;
  526. if keysLast[KA_DOWN] = K_KP_3 then
  527. symb := 8470;
  528. goto smallJmp;
  529. end;
  530. {$EndIf}
  531. // эта часть должна быть другой, если используется не русский язык и не латиница
  532. if not (appFlags and APP_USE_ENGLISH_INPUT > 0) then
  533. if (PkeybFlags^ and keyboardLatinRus) > 0 then
  534. begin
  535. if symb = 47 then
  536. begin
  537. symb := 46;
  538. goto smallJmp;
  539. end;
  540. if symb = 63 then
  541. begin
  542. symb := 44;
  543. goto smallJmp;
  544. end;
  545. EngToRusUnicode(symb);
  546. end;
  547. if Assigned(UseText^.procLimit) then
  548. if not (UseText^.procLimit) then
  549. exit;
  550. smallJmp:
  551. _JcharSymb := useFont^.CharDesc[symb];
  552. if Assigned(_JcharSymb) then
  553. _ShiftP := _JcharSymb^.ShiftP * UseText^.Scale
  554. else
  555. _ShiftP := UseText^._ShiftP63;
  556. if _Cursor^.position > UseText^.EditString.UseLen then
  557. begin
  558. UseText^.EditString.CharSymb[_Cursor^.position - 1] := symb;
  559. UseText^.EditString.posX[_Cursor^.position] := UseText^.EditString.posX[_Cursor^.position - 1] + _ShiftP;
  560. inc(UseText^.EditString.UseLen);
  561. end
  562. else begin
  563. j := _Cursor^.position - 1;
  564. if (PkeybFlags^ and keyboardInsert) = 0 then
  565. begin
  566. i := UseText^.EditString.UseLen;
  567. while i >= (_Cursor^.position) do
  568. begin
  569. UseText^.EditString.CharSymb[i] := UseText^.EditString.CharSymb[i - 1];
  570. dec(i);
  571. end;
  572. end;
  573. UseText^.EditString.CharSymb[_Cursor^.position - 1] := symb;
  574. while j <= UseText^.EditString.UseLen do
  575. begin
  576. _JcharSymb := useFont^.CharDesc[UseText^.EditString.CharSymb[j]];
  577. if Assigned(_JcharSymb) then
  578. _ShiftP := _JcharSymb^.ShiftP * UseText^.Scale
  579. else
  580. _ShiftP := UseText^._ShiftP63;
  581. UseText^.EditString.posX[j + 1] := UseText^.EditString.posX[j] + _ShiftP;
  582. inc(j);
  583. end;
  584. if (PkeybFlags^ and keyboardInsert) = 0 then
  585. inc(UseText^.EditString.UseLen);
  586. end;
  587. inc(_Cursor^.position);
  588. RollEditRight;
  589. end;
  590. end;
  591. exit;
  592. end;
  593. jmpMouse:
  594. if (mouseAction[M_BLEFT].state and is_down) > 0 then
  595. begin
  596. sinAngle := sin(Pi * (360 - UseText^.Rotate) / 180);
  597. cosAngle := cos(Pi * (360 - UseText^.Rotate) / 180);
  598. mDX := UseText^.RotatePoint.X + (mouseX - UseText^.RotatePoint.x) * cosAngle - (mouseY - UseText^.RotatePoint.Y) * sinAngle;
  599. mDY := UseText^.RotatePoint.Y + (mouseY - UseText^.RotatePoint.Y) * cosAngle + (mouseX - UseText^.RotatePoint.x) * sinAngle;
  600. if col2d_PointInRect(mDX, mDY, UseText^.Rect) then
  601. begin
  602. {$IfDef ACTIVATE_MOUSE}
  603. if managerSetOfTools.ActiveElement <> numElement then
  604. begin
  605. managerSetOfTools.ActiveElement := numElement;
  606. {$IfDef MOBILE}
  607. VisibleMenuChange := True;
  608. {$EndIf}
  609. if ((PkeybFlags^ and keyboardInsert) > 0) then
  610. _Cursor^.curRect.H := - UseText^.Scale * 1.1
  611. else
  612. _Cursor^.curRect.H := 2;
  613. Exit;
  614. end;
  615. {$EndIf}
  616. if UseText^.EditString.UseLen > 0 then
  617. begin
  618. if (mDX - UseText^.Rect.X) < (UseText^.EditString.posX[UseText^.EditString.UseLen] - UseText^.translateX) then
  619. begin
  620. i := 0;
  621. while (UseText^.EditString.posX[i] + useFont^.CharDesc[UseText^.EditString.CharSymb[i]]^.xx2) < UseText^.translateX do
  622. inc(i);
  623. n := i;
  624. j := UseText^.EditString.UseLen;
  625. while (UseText^.EditString.posX[j - 1] + useFont^.CharDesc[UseText^.EditString.CharSymb[j - 1]]^.xx1) > (UseText^.translateX + UseText^.Rect.W) do
  626. dec(j);
  627. while i <= j do
  628. begin
  629. if (mDX - UseText^.Rect.X) < (UseText^.EditString.posX[i] - UseText^.translateX) then
  630. Break;
  631. inc(i);
  632. end;
  633. _Cursor^.position := i;
  634. SetCursorPosAndWidth;
  635. if i >= j then
  636. begin
  637. if (_Cursor^.curRect.X + _Cursor^.curRect.W - UseText^.translateX) > (UseText^.Rect.W) then
  638. UseText^.translateX := _Cursor^.curRect.X + _Cursor^.curRect.W - UseText^.Rect.w;
  639. Exit;
  640. end;
  641. if n = i - 1 then
  642. if (UseText^.EditString.posX[n] + useFont^.CharDesc[UseText^.EditString.CharSymb[n]]^.xx1) < UseText^.translateX then
  643. begin
  644. UseText^.translateX := _Cursor^.curRect.X;
  645. if UseText^.translateX < 0 then
  646. UseText^.translateX := 0;
  647. end;
  648. end
  649. else begin
  650. _Cursor^.position := UseText^.EditString.UseLen + 1;
  651. RollEditRight;
  652. end;
  653. end;
  654. end;
  655. end;
  656. end;
  657. procedure DeleteElementSOT(numElement: LongWord);
  658. begin
  659. { AllEditElementsSost := True;
  660. if destroyElements then
  661. begin
  662. AllEditElementsSost := False;
  663. exit;
  664. end; }
  665. {$IfDef FULL_LOGGING}
  666. if (managerSetOfTools.count = 0) or (managerSetOfTools.SetOfTools[numElement] = nil) then
  667. begin
  668. log_add('Error in DeleteElementSOT!');
  669. exit;
  670. end;
  671. {$EndIf}
  672. managerSetOfTools.propElement[numElement].FlagsProp := 0;
  673. // useFont[0] := nil;
  674. end;
  675. procedure SetDefColor(ColorText, ColorBackground: LongWord; ColorCursor: LongWord = cl_Black);
  676. begin
  677. geDefColor.Text := ColorText;
  678. geDefColor.Ground := ColorBackground;
  679. geDefColor.Cursor := ColorCursor;
  680. end;
  681. procedure DestroyManagerSOT();
  682. var
  683. i, j: LongWord;
  684. begin
  685. // destroyElements := True;
  686. // здесь может быть загвоздка. При многопроцессорности, может произойти ситуация, когда определённые процессы не завершены.
  687. // надо обязательно, чтоб они завершились!!! И только после этого уничтожать объекты.
  688. if managerSetOfTools.count = 0 then
  689. Exit;
  690. for i := 0 to managerSetOfTools.maxPossibleEl - 1 do
  691. begin
  692. if managerSetOfTools.propElement[i].Element = is_Edit then
  693. begin
  694. UseText := managerSetOfTools.SetOfTools[i];
  695. for j := 0 to 65535 do
  696. begin
  697. if Assigned(UseText^.CharDesc[j]) then
  698. Freemem(UseText^.CharDesc[j]);
  699. end;
  700. SetLength(UseText^.EditString.CharSymb, 0);
  701. SetLength(UseText^.EditString.posX, 0);
  702. Freemem(UseText^.Cursor);
  703. Freemem(UseText);
  704. managerSetOfTools.SetOfTools[i] := nil;
  705. end;
  706. // ...
  707. dec(managerSetOfTools.count);
  708. if managerSetOfTools.count = 0 then
  709. Break;
  710. end;
  711. UseText := nil;
  712. SetLength(managerSetOfTools.SetOfTools, 0);
  713. SetLength(managerSetOfTools.propElement, 0);
  714. _cursor := nil;
  715. useFont := nil;
  716. // destroyElements := False;
  717. end;
  718. procedure SetOfRotateAngleAndPoint(x, y: Single; angle: Single = 0);
  719. begin
  720. geAngle := angle;
  721. pointManager.X := x;
  722. pointManager.Y := y;
  723. end;
  724. function GetEditToText(num: LongWord): UTF8String;
  725. var
  726. i, j: Word;
  727. begin
  728. // AllEditElementsSost := True;
  729. Result := '';
  730. { if destroyElements then
  731. begin
  732. AllEditElementsSost := False;
  733. exit;
  734. end; }
  735. {$IfDef FULL_LOGGING}
  736. if (managerSetOfTools.count = 0) or (managerSetOfTools.SetOfTools[num] = nil) then
  737. begin
  738. log_Add('Error in GetEditToText!');
  739. exit;
  740. end;
  741. {$EndIf}
  742. UseText := managerSetOfTools.SetOfTools[num];
  743. j := UseText^.EditString.UseLen - 1;
  744. i := 0;
  745. while i <= j do
  746. begin
  747. Result := Result + ID_toUTF8(UseText^.EditString.CharSymb[i]);
  748. inc(i);
  749. end;
  750. end;
  751. procedure CorrectEditCursor(num: LongWord; y: Single);
  752. begin
  753. { AllEditElementsSost := True;
  754. if destroyElements then
  755. begin
  756. AllEditElementsSost := False;
  757. exit;
  758. end; }
  759. {$IfDef FULL_LOGGING}
  760. if (managerSetOfTools.count = 0) or (managerSetOfTools.SetOfTools[num] = nil) then
  761. begin
  762. log_Add('Error in CorrectEditCursor!');
  763. exit;
  764. end;
  765. {$EndIf}
  766. UseText := managerSetOfTools.SetOfTools[num];
  767. UseText^.Cursor^.curRect.Y := UseText^.Cursor^.curRect.Y + y;
  768. end;
  769. procedure ActivateEdit(num: LongWord);
  770. begin
  771. { AllEditElementsSost := True;
  772. if destroyElements then
  773. begin
  774. AllEditElementsSost := False;
  775. exit;
  776. end; }
  777. {$IfDef FULL_LOGGING}
  778. if (managerSetOfTools.count = 0) or (managerSetOfTools.SetOfTools[num] = nil) then
  779. begin
  780. log_Add('Error in ActivateEdit!');
  781. exit;
  782. end;
  783. {$EndIf}
  784. if not Assigned(managerSetOfTools.SetOfTools[num]) then
  785. exit;
  786. UseText := managerSetOfTools.SetOfTools[num];
  787. if ((PkeybFlags^ and keyboardInsert) > 0) then
  788. UseText^.Cursor^.curRect.H := - UseText^.Scale * 1.1
  789. else
  790. UseText^.Cursor^.curRect.H := 2;
  791. managerSetOfTools.ActiveElement := num;
  792. end;
  793. procedure SetFlagsEdit(num: LongWord; var newFlags: Byte);
  794. begin
  795. { AllEditElementsSost := True;
  796. if destroyElements then
  797. begin
  798. AllEditElementsSost := False;
  799. exit;
  800. end; }
  801. if ((newFlags and (vc_NumOnly or vc_NumDelimeter)) > 0) and ((newFlags and vc_SymbOnly) > 0) then
  802. begin
  803. newFlags := 0; // error;
  804. exit;
  805. end;
  806. UseText := managerSetOfTools.SetOfTools[num];
  807. UseText^.flags := UseText^.flags or newFlags;
  808. if (newFlags and (vc_NumOnly or vc_NumDelimeter or vc_SymbOnly)) > 0 then
  809. UseText^.procLimit := nil;
  810. end;
  811. function EditNumeric: Boolean;
  812. var
  813. n: LongWord;
  814. begin
  815. // AllEditElementsSost := True;
  816. Result := false;
  817. { if destroyElements then
  818. begin
  819. AllEditElementsSost := False;
  820. exit;
  821. end; }
  822. n := keysLast[KA_DOWN];
  823. UseText := managerSetOfTools.SetOfTools[managerSetOfTools.ActiveElement];
  824. if (UseText^.EditString.UseLen = 0) and ((n = K_0) or (n = K_KP_0)) then
  825. exit;
  826. case n of
  827. K_1..K_0, K_KP_7..K_KP_9, K_KP_4..K_KP_6, K_KP_1..K_KP_0:
  828. Result := true;
  829. end;
  830. end;
  831. function EditNumericAndDelimetr: Boolean;
  832. var
  833. n: LongWord;
  834. begin
  835. // AllEditElementsSost := True;
  836. Result := false;
  837. { if destroyElements then
  838. begin
  839. AllEditElementsSost := False;
  840. exit;
  841. end; }
  842. n := keysLast[KA_DOWN];
  843. UseText := managerSetOfTools.SetOfTools[managerSetOfTools.ActiveElement];
  844. if (UseText^.EditString.UseLen = 0) and ((n = K_0) or (n = K_KP_0)) then
  845. exit;
  846. case n of
  847. K_1..K_0, K_KP_7..K_KP_9, K_KP_4..K_KP_6, K_KP_1..k_kp_0, K_DECIMAL, K_SEMICOLON:
  848. Result := true;
  849. end;
  850. end;
  851. function EditNotSymbolic: Boolean;
  852. var
  853. m: LongWord;
  854. begin
  855. // AllEditElementsSost := True;
  856. Result := False;
  857. { if destroyElements then
  858. begin
  859. AllEditElementsSost := False;
  860. exit;
  861. end; }
  862. m := keysLast[KA_DOWN];
  863. // список кодов: $0C $0D $0F $1A $1B $27 $28 $29 $2B $33 $34 $35 $37 $39 $4A $4E $53 $B5 - которые не должны производить действие.
  864. // исключения есть, знак "-", при шифте - это подчёркивание. Так же, большинство цифровых клавиш.
  865. // исключение - русский алфавит.
  866. if keysDown[K_SHIFT] then
  867. begin
  868. if (m >= K_1) and (m <= K_0) then
  869. exit;
  870. end
  871. else
  872. if m = K_MINUS then
  873. exit;
  874. if (keybFlags and keyboardNumLock) > 0 then
  875. if (m = K_KP_MUL) or (m = K_KP_SUB) or (m = K_KP_ADD) or (m = K_KP_DECIMAL) or (m = K_KP_DIV) then
  876. exit;
  877. if (PkeybFlags^ and keyboardLatinRus) = 0 then
  878. if (m = K_BRACKET_L) or (m = K_BRACKET_R) or ((m >= K_SEMICOLON) and (m <= K_TILDE)) or (m = K_SEPARATOR) or (m = K_DECIMAL) then
  879. exit;
  880. if (m = K_SLASH) or (m = K_EQUALS) or (m = K_BACKSPACE) or (m = K_BACKSLASH) or (m = K_SPACE) or (m = K_TAB) then
  881. exit;
  882. Result := True;
  883. end;
  884. procedure SetVisibleElement(numEl: LongWord; flag: Boolean);
  885. var
  886. prop: geglPPropertElement;
  887. begin
  888. { AllEditElementsSost := True;
  889. if destroyElements then
  890. begin
  891. AllEditElementsSost := False;
  892. exit;
  893. end; }
  894. prop := @managerSetOfTools.propElement[numEl];
  895. if flag then
  896. prop^.FlagsProp := prop^.FlagsProp or el_Visible
  897. else
  898. begin
  899. prop^.FlagsProp := prop^.FlagsProp and ($FFFFFFFF - el_Visible);
  900. if managerSetOfTools.ActiveElement = numEl then
  901. managerSetOfTools.ActiveElement := ELEMENT_NOT_ACTIVE;
  902. end;
  903. end;
  904. initialization
  905. SetDefColor(cl_Black, cl_White, cl_Black);
  906. end.