gegl_VElements.pas 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972
  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. zgl_GetMem(Pointer(UseText^.Cursor), SizeOf(geglTCursor));
  240. _cursor := UseText^.Cursor;
  241. _cursor^.curRect.X := 0;
  242. _cursor^.curRect.Y := rs1_2 * Scale;
  243. _cursor^.curRect.H := 2;
  244. _cursor^.curRect.W := 6 * Scale / 10;
  245. _cursor^.NSleep := CUR_FLASH;
  246. _cursor^.Flags := False;
  247. _cursor^.position := 1;
  248. UseText^.translateX := 0;
  249. UseText^.RotatePoint := pointManager;
  250. UseText^.font := fnt;
  251. UseText^.procDraw := UserData1;
  252. UseText^.procLimit := UserData2;
  253. inc(managerSetOfTools.count);
  254. UseText := nil;
  255. end;
  256. procedure EventsEdit(numElement: LongWord);
  257. var
  258. symb, i, j, n: LongWord;
  259. _JcharSymb: zglPCharDesc;
  260. t: Double;
  261. _ShiftP: Single;
  262. mDX, mDY: Single;
  263. sinAngle, cosAngle: Single;
  264. label
  265. smallJmp, jmpMouse;
  266. // определяем позицию курсора и его ширину
  267. procedure SetCursorPosAndWidth;
  268. begin
  269. _cursor^.curRect.x := UseText^.EditString.posX[_cursor^.position - 1];
  270. if (_Cursor^.position <= UseText^.EditString.Len) and (_Cursor^.position <= UseText^.EditString.UseLen) then
  271. begin
  272. _JcharSymb := useFont^.CharDesc[UseText^.EditString.CharSymb[_Cursor^.position - 1]];
  273. if Assigned(_JcharSymb) then
  274. _Cursor^.curRect.W := _JcharSymb^.ShiftP * UseText^.Scale;
  275. end
  276. else
  277. _Cursor^.curRect.W := UseText^._ShiftP63 * UseText^.Scale;
  278. end;
  279. procedure RollEditLeft;
  280. begin
  281. SetCursorPosAndWidth;
  282. if UseText^.translateX > 0 then
  283. if (_Cursor^.curRect.X - 40) < UseText^.translateX then
  284. UseText^.translateX := _Cursor^.curRect.X - 40;
  285. if UseText^.translateX < 0 then
  286. UseText^.translateX := 0;
  287. end;
  288. procedure RollEditRight;
  289. begin
  290. SetCursorPosAndWidth;
  291. if UseText^.EditString.UseLen < _Cursor^.position then
  292. begin
  293. if (UseText^.Cursor^.curRect.x + _Cursor^.curRect.W - UseText^.translateX) > (UseText^.Rect.W) then
  294. begin
  295. UseText^.translateX := (_Cursor^.curRect.x + _Cursor^.curRect.W) - (UseText^.Rect.W );
  296. end;
  297. end
  298. else begin
  299. if ((_Cursor^.curRect.X - UseText^.translateX) > (UseText^.Rect.W - 60)) and
  300. ((UseText^.EditString.posX[UseText^.EditString.UseLen] - UseText^.translateX) > UseText^.Rect.W) then
  301. begin
  302. UseText^.translateX := (_Cursor^.curRect.x + 60) - (UseText^.Rect.W );
  303. if (UseText^.Rect.W + UseText^.translateX) > UseText^.EditString.posX[UseText^.EditString.UseLen] then
  304. UseText^.translateX := UseText^.EditString.posX[UseText^.EditString.UseLen] - UseText^.Rect.W;
  305. end;
  306. end;
  307. end;
  308. begin
  309. { AllEditElementsSost := True;
  310. if destroyElements then
  311. begin
  312. AllEditElementsSost := False;
  313. exit;
  314. end; }
  315. {$IfDef FULL_LOGGING}
  316. if (managerSetOfTools.count = 0) or (managerSetOfTools.SetOfTools[numElement] = nil) then
  317. BEGIN
  318. log_add('Error is EventsEdit!');
  319. exit;
  320. end;
  321. {$EndIf}
  322. if (managerSetOfTools.propElement[numElement].FlagsProp and el_Enable = 0) or (managerSetOfTools.propElement[numElement].FlagsProp and el_Visible = 0) then
  323. Exit;
  324. UseText := managerSetOfTools.SetOfTools[numElement];
  325. useFont := managerFont.Font[UseText^.font];
  326. _cursor := UseText^.Cursor;
  327. if managerSetOfTools.ActiveElement <> numElement then
  328. goto jmpMouse;
  329. if keysUp[K_INSERT] then
  330. if ((PkeybFlags^ and keyboardInsert) > 0) then
  331. _Cursor^.curRect.H := - UseText^.Scale * rs1_2
  332. else
  333. _Cursor^.curRect.H := 2;
  334. if keysLast[KA_DOWN] > 0 then
  335. begin
  336. t := timer_GetTicks;
  337. if keysLast[KA_DOWN] <> keysLast[KT_DOWN] then
  338. begin
  339. keysLast[KT_DOWN] := keysLast[KA_DOWN];
  340. keyDownRepeat := t;
  341. keyDelayWork := beginKeyDelay;
  342. end
  343. else
  344. if t - keyDownRepeat > keyDelayWork then
  345. begin
  346. keyDownRepeat := t;
  347. keyDelayWork := repeatKeyDelay;
  348. end
  349. else begin
  350. Exit;
  351. end;
  352. case keysLast[KA_DOWN] of
  353. K_ESCAPE: exit;
  354. K_UP: ;
  355. K_DOWN: ;
  356. K_LEFT:
  357. begin
  358. if _Cursor^.position = 1 then
  359. exit;
  360. if keysDown[K_CTRL] then
  361. begin
  362. i := _Cursor^.position;
  363. j := 0;
  364. if (UseText^.EditString.CharSymb[i - 2] = 32) or (UseText^.EditString.CharSymb[i - 2] = 9) then
  365. dec(i, 2);
  366. while i > 1 do
  367. begin
  368. if (j > 0) and ((UseText^.EditString.CharSymb[i - 1] = 32) or (UseText^.EditString.CharSymb[i - 1] = 9)) then
  369. begin
  370. if (UseText^.EditString.CharSymb[i] <> 32) and (UseText^.EditString.CharSymb[i] <> 9) then
  371. begin
  372. _Cursor^.position := i + 1;
  373. RollEditLeft;
  374. exit;
  375. end;
  376. end
  377. else
  378. inc(j);
  379. dec(i);
  380. end;
  381. _Cursor^.position := 1;
  382. end
  383. else begin
  384. dec(_Cursor^.position);
  385. end;
  386. RollEditLeft;
  387. end;
  388. K_RIGHT:
  389. Begin
  390. if _Cursor^.position > UseText^.EditString.UseLen then
  391. Exit;
  392. if keysDown[K_CTRL] then
  393. begin
  394. i := _Cursor^.position;
  395. j := 0;
  396. if (UseText^.EditString.CharSymb[i] = 32) or (UseText^.EditString.CharSymb[i] = 9) then
  397. inc(i, 2);
  398. while i < UseText^.EditString.UseLen + 1 do
  399. begin
  400. if (j > 0) and ((UseText^.EditString.CharSymb[i - 1] = 32) or (UseText^.EditString.CharSymb[i - 1] = 9)) then
  401. begin
  402. if (UseText^.EditString.CharSymb[i - 2] <> 32) and (UseText^.EditString.CharSymb[i - 2] <> 9) then
  403. begin
  404. _Cursor^.position := i - 1;
  405. RollEditRight;
  406. exit;
  407. end;
  408. end
  409. else
  410. inc(j);
  411. inc(i);
  412. end;
  413. _Cursor^.position := UseText^.EditString.UseLen + 1;
  414. end
  415. else begin
  416. inc(_Cursor^.position);
  417. end;
  418. RollEditRight;
  419. end;
  420. K_BACKSPACE:
  421. begin
  422. if (_Cursor^.position = 1) or (UseText^.EditString.UseLen = 0) then
  423. Exit;
  424. dec(_Cursor^.position);
  425. dec(UseText^.EditString.UseLen);
  426. if _Cursor^.position > UseText^.EditString.UseLen then
  427. UseText^.EditString.CharSymb[UseText^.EditString.UseLen] := 0
  428. else begin
  429. i := UseText^.EditString.UseLen - (_Cursor^.position - 1);
  430. j := _Cursor^.position;
  431. while i > 0 do
  432. begin
  433. UseText^.EditString.CharSymb[j - 1] := UseText^.EditString.CharSymb[j];
  434. UseText^.EditString.posX[j] := UseText^.EditString.posX[j - 1] +
  435. useFont^.CharDesc[UseText^.EditString.CharSymb[j - 1]]^.ShiftP * useFont^.Scale;
  436. inc(j);
  437. dec(i);
  438. end;
  439. UseText^.EditString.CharSymb[j - 1] := 0;
  440. end;
  441. RollEditLeft;
  442. end;
  443. K_DELETE:
  444. begin
  445. if (UseText^.EditString.UseLen = 0) or (UseText^.EditString.UseLen < _Cursor^.position) then
  446. Exit;
  447. dec(UseText^.EditString.UseLen);
  448. if _Cursor^.position > UseText^.EditString.UseLen then
  449. UseText^.EditString.CharSymb[_Cursor^.position - 1] := 0
  450. else begin
  451. j := _Cursor^.position;
  452. while j <= UseText^.EditString.UseLen do
  453. begin
  454. UseText^.EditString.CharSymb[j - 1] := UseText^.EditString.CharSymb[j];
  455. UseText^.EditString.posX[j] := UseText^.EditString.posX[j - 1] +
  456. useFont^.CharDesc[UseText^.EditString.CharSymb[j - 1]]^.ShiftP * useFont^.Scale;
  457. inc(j);
  458. end;
  459. UseText^.EditString.CharSymb[j - 1] := 0;
  460. end;
  461. RollEditLeft;
  462. end;
  463. K_HOME:
  464. begin
  465. if UseText^.EditString.UseLen = 0 then
  466. begin
  467. _Cursor^.position := 1;
  468. exit;
  469. end;
  470. _Cursor^.position := 1;
  471. RollEditLeft;
  472. end;
  473. K_END:
  474. begin
  475. if UseText^.EditString.UseLen = 0 then
  476. begin
  477. _Cursor^.position := 1;
  478. exit;
  479. end;
  480. _Cursor^.position := UseText^.EditString.UseLen + 1;
  481. RollEditRight;
  482. end;
  483. K_PAGEDOWN: ;
  484. K_PAGEUP: ;
  485. K_ENTER, K_KP_ENTER:
  486. begin
  487. {$IfDef MOBILE}
  488. VisibleMenuChange := False;
  489. {$EndIf}
  490. managerSetOfTools.ActiveElement := ELEMENT_NOT_ACTIVE;
  491. end;
  492. else
  493. begin
  494. if UseText^.EditString.UseLen >= UseText^.EditString.Len then
  495. Exit;
  496. if (UseText^.flags and (vc_NumOnly or vc_NumDelimeter or vc_SymbOnly)) > 0 then
  497. if (UseText^.flags and vc_NumOnly) > 0 then
  498. begin
  499. if not EditNumeric then
  500. exit;
  501. end
  502. else
  503. if (UseText^.flags and vc_NumDelimeter) > 0 then
  504. begin
  505. if not EditNumericAndDelimetr then
  506. Exit;
  507. end
  508. else
  509. if not EditNotSymbolic then
  510. exit;
  511. symb := scancode_to_utf8(keysLast[KA_DOWN]);
  512. if symb = 0 then
  513. Exit;
  514. {$IfDef USE_VKEYBOARD}
  515. if (keybFlags and keyboardSymbol) > 0 then
  516. begin
  517. if keysLast[KA_DOWN] = K_KP_1 then
  518. symb := 124;
  519. if keysLast[KA_DOWN] = K_KP_2 then
  520. symb := 63;
  521. if keysLast[KA_DOWN] = K_KP_3 then
  522. symb := 8470;
  523. goto smallJmp;
  524. end;
  525. {$EndIf}
  526. // эта часть должна быть другой, если используется не русский язык и не латиница
  527. if not (appFlags and APP_USE_ENGLISH_INPUT > 0) then
  528. if (PkeybFlags^ and keyboardLatinRus) > 0 then
  529. begin
  530. if symb = 47 then
  531. begin
  532. symb := 46;
  533. goto smallJmp;
  534. end;
  535. if symb = 63 then
  536. begin
  537. symb := 44;
  538. goto smallJmp;
  539. end;
  540. EngToRusUnicode(symb);
  541. end;
  542. if Assigned(UseText^.procLimit) then
  543. if not (UseText^.procLimit) then
  544. exit;
  545. smallJmp:
  546. _JcharSymb := useFont^.CharDesc[symb];
  547. if Assigned(_JcharSymb) then
  548. _ShiftP := _JcharSymb^.ShiftP * UseText^.Scale
  549. else
  550. _ShiftP := UseText^._ShiftP63;
  551. if _Cursor^.position > UseText^.EditString.UseLen then
  552. begin
  553. UseText^.EditString.CharSymb[_Cursor^.position - 1] := symb;
  554. UseText^.EditString.posX[_Cursor^.position] := UseText^.EditString.posX[_Cursor^.position - 1] + _ShiftP;
  555. inc(UseText^.EditString.UseLen);
  556. end
  557. else begin
  558. j := _Cursor^.position - 1;
  559. if (PkeybFlags^ and keyboardInsert) = 0 then
  560. begin
  561. i := UseText^.EditString.UseLen;
  562. while i >= (_Cursor^.position) do
  563. begin
  564. UseText^.EditString.CharSymb[i] := UseText^.EditString.CharSymb[i - 1];
  565. dec(i);
  566. end;
  567. end;
  568. UseText^.EditString.CharSymb[_Cursor^.position - 1] := symb;
  569. while j <= UseText^.EditString.UseLen do
  570. begin
  571. _JcharSymb := useFont^.CharDesc[UseText^.EditString.CharSymb[j]];
  572. if Assigned(_JcharSymb) then
  573. _ShiftP := _JcharSymb^.ShiftP * UseText^.Scale
  574. else
  575. _ShiftP := UseText^._ShiftP63;
  576. UseText^.EditString.posX[j + 1] := UseText^.EditString.posX[j] + _ShiftP;
  577. inc(j);
  578. end;
  579. if (PkeybFlags^ and keyboardInsert) = 0 then
  580. inc(UseText^.EditString.UseLen);
  581. end;
  582. inc(_Cursor^.position);
  583. RollEditRight;
  584. end;
  585. end;
  586. exit;
  587. end;
  588. jmpMouse:
  589. if (mouseAction[M_BLEFT].state and is_down) > 0 then
  590. begin
  591. sinAngle := sin(Pi * (360 - UseText^.Rotate) / 180);
  592. cosAngle := cos(Pi * (360 - UseText^.Rotate) / 180);
  593. mDX := UseText^.RotatePoint.X + (mouseX - UseText^.RotatePoint.x) * cosAngle - (mouseY - UseText^.RotatePoint.Y) * sinAngle;
  594. mDY := UseText^.RotatePoint.Y + (mouseY - UseText^.RotatePoint.Y) * cosAngle + (mouseX - UseText^.RotatePoint.x) * sinAngle;
  595. if col2d_PointInRect(mDX, mDY, UseText^.Rect) then
  596. begin
  597. {$IfDef ACTIVATE_MOUSE}
  598. if managerSetOfTools.ActiveElement <> numElement then
  599. begin
  600. managerSetOfTools.ActiveElement := numElement;
  601. {$IfDef MOBILE}
  602. VisibleMenuChange := True;
  603. {$EndIf}
  604. if ((PkeybFlags^ and keyboardInsert) > 0) then
  605. _Cursor^.curRect.H := - UseText^.Scale * 1.1
  606. else
  607. _Cursor^.curRect.H := 2;
  608. Exit;
  609. end;
  610. {$EndIf}
  611. if UseText^.EditString.UseLen > 0 then
  612. begin
  613. if (mDX - UseText^.Rect.X) < (UseText^.EditString.posX[UseText^.EditString.UseLen] - UseText^.translateX) then
  614. begin
  615. i := 0;
  616. while (UseText^.EditString.posX[i] + useFont^.CharDesc[UseText^.EditString.CharSymb[i]]^.xx2) < UseText^.translateX do
  617. inc(i);
  618. n := i;
  619. j := UseText^.EditString.UseLen;
  620. while (UseText^.EditString.posX[j - 1] + useFont^.CharDesc[UseText^.EditString.CharSymb[j - 1]]^.xx1) > (UseText^.translateX + UseText^.Rect.W) do
  621. dec(j);
  622. while i <= j do
  623. begin
  624. if (mDX - UseText^.Rect.X) < (UseText^.EditString.posX[i] - UseText^.translateX) then
  625. Break;
  626. inc(i);
  627. end;
  628. _Cursor^.position := i;
  629. SetCursorPosAndWidth;
  630. if i >= j then
  631. begin
  632. if (_Cursor^.curRect.X + _Cursor^.curRect.W - UseText^.translateX) > (UseText^.Rect.W) then
  633. UseText^.translateX := _Cursor^.curRect.X + _Cursor^.curRect.W - UseText^.Rect.w;
  634. Exit;
  635. end;
  636. if n = i - 1 then
  637. if (UseText^.EditString.posX[n] + useFont^.CharDesc[UseText^.EditString.CharSymb[n]]^.xx1) < UseText^.translateX then
  638. begin
  639. UseText^.translateX := _Cursor^.curRect.X;
  640. if UseText^.translateX < 0 then
  641. UseText^.translateX := 0;
  642. end;
  643. end
  644. else begin
  645. _Cursor^.position := UseText^.EditString.UseLen + 1;
  646. RollEditRight;
  647. end;
  648. end;
  649. end;
  650. end;
  651. end;
  652. procedure DeleteElementSOT(numElement: LongWord);
  653. begin
  654. { AllEditElementsSost := True;
  655. if destroyElements then
  656. begin
  657. AllEditElementsSost := False;
  658. exit;
  659. end; }
  660. {$IfDef FULL_LOGGING}
  661. if (managerSetOfTools.count = 0) or (managerSetOfTools.SetOfTools[numElement] = nil) then
  662. begin
  663. log_add('Error in DeleteElementSOT!');
  664. exit;
  665. end;
  666. {$EndIf}
  667. managerSetOfTools.propElement[numElement].FlagsProp := 0;
  668. // useFont[0] := nil;
  669. end;
  670. procedure SetDefColor(ColorText, ColorBackground: LongWord; ColorCursor: LongWord = cl_Black);
  671. begin
  672. geDefColor.Text := ColorText;
  673. geDefColor.Ground := ColorBackground;
  674. geDefColor.Cursor := ColorCursor;
  675. end;
  676. procedure DestroyManagerSOT();
  677. var
  678. i, j: LongWord;
  679. begin
  680. // destroyElements := True;
  681. // здесь может быть загвоздка. При многопроцессорности, может произойти ситуация, когда определённые процессы не завершены.
  682. // надо обязательно, чтоб они завершились!!! И только после этого уничтожать объекты.
  683. if managerSetOfTools.count = 0 then
  684. Exit;
  685. for i := 0 to managerSetOfTools.maxPossibleEl - 1 do
  686. begin
  687. if managerSetOfTools.propElement[i].Element = is_Edit then
  688. begin
  689. UseText := managerSetOfTools.SetOfTools[i];
  690. for j := 0 to 65535 do
  691. begin
  692. if Assigned(UseText^.CharDesc[j]) then
  693. Freemem(UseText^.CharDesc[j]);
  694. end;
  695. SetLength(UseText^.EditString.CharSymb, 0);
  696. SetLength(UseText^.EditString.posX, 0);
  697. Freemem(UseText^.Cursor);
  698. Freemem(UseText);
  699. managerSetOfTools.SetOfTools[i] := nil;
  700. end;
  701. // ...
  702. dec(managerSetOfTools.count);
  703. if managerSetOfTools.count = 0 then
  704. Break;
  705. end;
  706. UseText := nil;
  707. SetLength(managerSetOfTools.SetOfTools, 0);
  708. SetLength(managerSetOfTools.propElement, 0);
  709. _cursor := nil;
  710. useFont := nil;
  711. // destroyElements := False;
  712. end;
  713. procedure SetOfRotateAngleAndPoint(x, y: Single; angle: Single = 0);
  714. begin
  715. geAngle := angle;
  716. pointManager.X := x;
  717. pointManager.Y := y;
  718. end;
  719. function GetEditToText(num: LongWord): UTF8String;
  720. var
  721. i, j: Word;
  722. begin
  723. // AllEditElementsSost := True;
  724. Result := '';
  725. { if destroyElements then
  726. begin
  727. AllEditElementsSost := False;
  728. exit;
  729. end; }
  730. {$IfDef FULL_LOGGING}
  731. if (managerSetOfTools.count = 0) or (managerSetOfTools.SetOfTools[num] = nil) then
  732. begin
  733. log_Add('Error in GetEditToText!');
  734. exit;
  735. end;
  736. {$EndIf}
  737. UseText := managerSetOfTools.SetOfTools[num];
  738. j := UseText^.EditString.UseLen - 1;
  739. i := 0;
  740. while i <= j do
  741. begin
  742. Result := Result + ID_toUTF8(UseText^.EditString.CharSymb[i]);
  743. inc(i);
  744. end;
  745. end;
  746. procedure CorrectEditCursor(num: LongWord; y: Single);
  747. begin
  748. { AllEditElementsSost := True;
  749. if destroyElements then
  750. begin
  751. AllEditElementsSost := False;
  752. exit;
  753. end; }
  754. {$IfDef FULL_LOGGING}
  755. if (managerSetOfTools.count = 0) or (managerSetOfTools.SetOfTools[num] = nil) then
  756. begin
  757. log_Add('Error in CorrectEditCursor!');
  758. exit;
  759. end;
  760. {$EndIf}
  761. UseText := managerSetOfTools.SetOfTools[num];
  762. UseText^.Cursor^.curRect.Y := UseText^.Cursor^.curRect.Y + y;
  763. end;
  764. procedure ActivateEdit(num: LongWord);
  765. begin
  766. { AllEditElementsSost := True;
  767. if destroyElements then
  768. begin
  769. AllEditElementsSost := False;
  770. exit;
  771. end; }
  772. {$IfDef FULL_LOGGING}
  773. if (managerSetOfTools.count = 0) or (managerSetOfTools.SetOfTools[num] = nil) then
  774. begin
  775. log_Add('Error in ActivateEdit!');
  776. exit;
  777. end;
  778. {$EndIf}
  779. if not Assigned(managerSetOfTools.SetOfTools[num]) then
  780. exit;
  781. UseText := managerSetOfTools.SetOfTools[num];
  782. if ((PkeybFlags^ and keyboardInsert) > 0) then
  783. UseText^.Cursor^.curRect.H := - UseText^.Scale * 1.1
  784. else
  785. UseText^.Cursor^.curRect.H := 2;
  786. managerSetOfTools.ActiveElement := num;
  787. end;
  788. procedure SetFlagsEdit(num: LongWord; var newFlags: Byte);
  789. begin
  790. { AllEditElementsSost := True;
  791. if destroyElements then
  792. begin
  793. AllEditElementsSost := False;
  794. exit;
  795. end; }
  796. if ((newFlags and (vc_NumOnly or vc_NumDelimeter)) > 0) and ((newFlags and vc_SymbOnly) > 0) then
  797. begin
  798. newFlags := 0; // error;
  799. exit;
  800. end;
  801. UseText := managerSetOfTools.SetOfTools[num];
  802. UseText^.flags := UseText^.flags or newFlags;
  803. if (newFlags and (vc_NumOnly or vc_NumDelimeter or vc_SymbOnly)) > 0 then
  804. UseText^.procLimit := nil;
  805. end;
  806. function EditNumeric: Boolean;
  807. var
  808. n: LongWord;
  809. begin
  810. // AllEditElementsSost := True;
  811. Result := false;
  812. { if destroyElements then
  813. begin
  814. AllEditElementsSost := False;
  815. exit;
  816. end; }
  817. n := keysLast[KA_DOWN];
  818. UseText := managerSetOfTools.SetOfTools[managerSetOfTools.ActiveElement];
  819. if (UseText^.EditString.UseLen = 0) and ((n = K_0) or (n = K_KP_0)) then
  820. exit;
  821. case n of
  822. K_1..K_0, K_KP_7..K_KP_9, K_KP_4..K_KP_6, K_KP_1..K_KP_0:
  823. Result := true;
  824. end;
  825. end;
  826. function EditNumericAndDelimetr: Boolean;
  827. var
  828. n: LongWord;
  829. begin
  830. // AllEditElementsSost := True;
  831. Result := false;
  832. { if destroyElements then
  833. begin
  834. AllEditElementsSost := False;
  835. exit;
  836. end; }
  837. n := keysLast[KA_DOWN];
  838. UseText := managerSetOfTools.SetOfTools[managerSetOfTools.ActiveElement];
  839. if (UseText^.EditString.UseLen = 0) and ((n = K_0) or (n = K_KP_0)) then
  840. exit;
  841. case n of
  842. 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:
  843. Result := true;
  844. end;
  845. end;
  846. function EditNotSymbolic: Boolean;
  847. var
  848. m: LongWord;
  849. begin
  850. // AllEditElementsSost := True;
  851. Result := False;
  852. { if destroyElements then
  853. begin
  854. AllEditElementsSost := False;
  855. exit;
  856. end; }
  857. m := keysLast[KA_DOWN];
  858. // список кодов: $0C $0D $0F $1A $1B $27 $28 $29 $2B $33 $34 $35 $37 $39 $4A $4E $53 $B5 - которые не должны производить действие.
  859. // исключения есть, знак "-", при шифте - это подчёркивание. Так же, большинство цифровых клавиш.
  860. // исключение - русский алфавит.
  861. if keysDown[K_SHIFT] then
  862. begin
  863. if (m >= K_1) and (m <= K_0) then
  864. exit;
  865. end
  866. else
  867. if m = K_MINUS then
  868. exit;
  869. if (keybFlags and keyboardNumLock) > 0 then
  870. 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
  871. exit;
  872. if (PkeybFlags^ and keyboardLatinRus) = 0 then
  873. 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
  874. exit;
  875. 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
  876. exit;
  877. Result := True;
  878. end;
  879. procedure SetVisibleElement(numEl: LongWord; flag: Boolean);
  880. var
  881. prop: geglPPropertElement;
  882. begin
  883. { AllEditElementsSost := True;
  884. if destroyElements then
  885. begin
  886. AllEditElementsSost := False;
  887. exit;
  888. end; }
  889. prop := @managerSetOfTools.propElement[numEl];
  890. if flag then
  891. prop^.FlagsProp := prop^.FlagsProp or el_Visible
  892. else
  893. begin
  894. prop^.FlagsProp := prop^.FlagsProp and ($FFFFFFFF - el_Visible);
  895. if managerSetOfTools.ActiveElement = numEl then
  896. managerSetOfTools.ActiveElement := ELEMENT_NOT_ACTIVE;
  897. end;
  898. end;
  899. initialization
  900. SetDefColor(cl_Black, cl_White, cl_Black);
  901. end.