gegl_VElements.pas 33 KB

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