Serge! 127 Опубликовано 2 Октября 2015 Учим ТЧ русскому языку. Сложность: Легко Файлы: ui_save_dialog.script и ui_mm_save_dlg.xml Сначала проделаем маленькую, но необходимую работу. Нам надо в окне диалога определить индикатор текущего языка ввода. Для этого открываем файл ui_mm_save_dlg.xml и в конец тега form добавим строчки, чтобы получилось так: <st_lang x="280" y="400" width="30" height="20"> <text font="graffiti22" align="c" /> <text_color> <e r="227" g="199" b="178"/> <h r="255" g="0" b="0"/> </text_color> </st_lang> </form> Закрываем файл. Он нам больше не понадобится.В отдельном файле (например, ui_save_dlg_rus.script) создаем таблицу перекодировки. Это массив ключами которого являются коды печатных символов английского алфавита, а значениями - соответствующие им коды криллицы. Выглятит она следующим образом: local tbl_lang = { [034] = 221, -- " --> Э [039] = 253, -- ' --> э [044] = 225, -- , --> б ... -- и т.д. } local tbl_ansii = { [ 039 ] = 253, -- ' --> э [ 044 ] = 225, -- , --> б [ 046 ] = 254, -- . --> ю [ 047 ] = 046, -- / --> . [ 058 ] = 198, -- : --> Ж [ 059 ] = 230, -- ; --> ж [ 060 ] = 193, -- < --> Б [ 062 ] = 222, -- > --> Ю [ 065 ] = 212, -- A --> Ф [ 066 ] = 200, -- B --> И [ 067 ] = 209, -- C --> С [ 068 ] = 194, -- D --> В [ 069 ] = 211, -- E --> У [ 070 ] = 192, -- F --> А [ 071 ] = 207, -- G --> П [ 072 ] = 208, -- H --> Р [ 073 ] = 216, -- I --> Ш [ 074 ] = 206, -- J --> О [ 075 ] = 203, -- K --> Л [ 076 ] = 196, -- L --> Д [ 077 ] = 220, -- M --> Ь [ 078 ] = 210, -- N --> Т [ 079 ] = 217, -- O --> Щ [ 080 ] = 199, -- P --> З [ 081 ] = 201, -- Q --> Й [ 082 ] = 202, -- R --> К [ 083 ] = 219, -- S --> Ы [ 084 ] = 197, -- T --> Е [ 085 ] = 195, -- U --> Г [ 086 ] = 204, -- V --> М [ 087 ] = 214, -- W --> Ц [ 088 ] = 215, -- X --> Ч [ 089 ] = 205, -- Y --> Н [ 090 ] = 223, -- Z --> Я [ 091 ] = 245, -- [ --> х [ 093 ] = 250, -- ] --> ъ [ 097 ] = 244, -- a --> ф [ 098 ] = 232, -- b --> и [ 099 ] = 241, -- c --> с [ 100 ] = 226, -- d --> в [ 101 ] = 243, -- e --> у [ 102 ] = 224, -- f --> а [ 103 ] = 239, -- g --> п [ 104 ] = 240, -- h --> р [ 105 ] = 248, -- i --> ш [ 106 ] = 238, -- j --> о [ 107 ] = 235, -- k --> л [ 108 ] = 228, -- l --> д [ 109 ] = 252, -- m --> ь [ 110 ] = 242, -- n --> т [ 111 ] = 249, -- o --> щ [ 112 ] = 231, -- p --> з [ 113 ] = 233, -- q --> й [ 114 ] = 234, -- r --> к [ 115 ] = 251, -- s --> ы [ 116 ] = 229, -- t --> е [ 117 ] = 227, -- u --> г [ 118 ] = 236, -- v --> м [ 119 ] = 246, -- w --> ц [ 120 ] = 247, -- x --> ч [ 121 ] = 237, -- y --> н [ 122 ] = 255, -- z --> я [ 123 ] = 213, -- { --> Х [ 125 ] = 218, -- } --> Ъ } Теперь основное. Возможны два варианта решения задачи руссификации. Мы рассмотрим их оба. Первый. Это упрощённый вариант, который тем не менее вполне устроит подавляющее число пользователей. Преимущества: очень простая реализация с минимальными правками дистрибутивных скриптов. Решается стандартными средствами Lua и не требуется никаких дополнительный функций и внешних скриптов (кроме таблицы перекодировки) Недостатки: Ввод смешанного текста хоть и допускается, но при этом полностью теряется возможность корректировки введённого текста. При вводе однородного текста - корректировка корректна. Открываем в редакторе файл ui_save_dialog.script. 1. Вверху, сразу под комментариями описания, определяем переменную подключающую таблицу перекодировки: local t_lang = ui_save_dlg_rus.tbl_ansii 2. Создадим индикатор текущего языка ввода текста.Договоримся, что переключать раскладку будем щелчком левой кнопки мыши по индикатору или клавишей левый-Ctrl (причем она бутет работать как тригер), а перевключать режим временного изменения языка ввода будем при нажатой и удерживаемой клавише левый-Alt. Для этого в методе save_dialog:InitControls() в самом конце вставим: self.ind_lan = xml:Init3tButton("form:st_lang", self.form) self:Register(self.ind_lan, "button_lang") self.ind_lan:SetText("Рус") self.mode_lang = true Где: self.mode_lang - флаг текущего языка ввода (true - русский, false - английский) Таким образом индикатор режима ввода мы создали, теперь надо обеспечить его функционирование. Для этого в функцию InitCallBacks() вставим строку self:AddCallback("button_lang", ui_events.BUTTON_CLICKED, self.OnChg_lan, self) а под блоком вставляем функцию: function save_dialog:OnChg_lan() self.mode_lang = not self.mode_lang if self.mode_lang then self.ind_lang:SetText("Рус") else self.ind_lang:SetText("Eng") end end Здесь всё янсно - сначала инвертируем флаг текущего языка ввода и потом меняем текст индикатора. Далее функцию function save_dialog:OnKeyboard(dik, keyboard_action), в конец условного блока (перед end), добавляем строки: elseif keyboard_action == ui_events.WINDOW_KEY_PRESSED then -- вызываются на нажатие клавиши if dik == DIK_keys.DIK_LCONTROL or dik == DIK_keys.DIK_LMENU then self:OnChg_lan() end elseif keyboard_action == ui_events.WINDOW_KEY_RELEASED then -- вызываются на отпускание клавиши if dik == DIK_keys.DIK_LMENU then self:OnChg_lan() end 3. Чтобы отслеживать изменения в поле редактирования и проводить перекодировку введенного теста, в функцию InitCallBacks() дабавим строку: self:AddCallback("edit_filename", ui_events.EDIT_TEXT_CHANGED, self.OnEdit_CHANGED, self) Теперь надо, чтобы это отработало. Для этого под функцией save_dialog:OnChg_lan() вставляем еще одну свою ффункцию: function save_dialog:OnEdit_CHANGED() if self.mode_lang then -- /1 local str_edit = self:GetEditBox("edit_filename") -- /2 local txt, copy_txt, cls = str_edit:GetText(), "" -- /3 for n = 1, txt:len() do cls = txt:byte(n) -- /4 if t_lang[cls] ~= nil then copy_txt = copy_txt..string.char(t_lang[cls]) -- /5 else copy_txt = copy_txt..string.char(cls) end -- /6 end str_edit:SetText(copy_txt) -- /7 end end Рассмотрим построчно, что эта функция делает:- проверяем установлен ли флаг ввода кириллицы (1) - если установлен, то подключаем окно поля редактирования (2) - получаем строку введенного текста и инициализируем переменную для её копии (3) - в цикле получаем код каждого символа строки ввода (4) - ищем в таблице перекодировки соответствующий русский символ (стандартный ввод всегда английский) и если находим, то заменяем английский символ на русский (5) - если же не находим, то оставляем исходный (6) - возвращаем строку в поле редактирования (7) На этом всё. Данный алгоритм, с учетом отмеченных выше ограничений, вполне стабильно работает на всех модах платформы ТЧ, в которые я играл. Все необходимые откорректированные файлы этого урока будут доступны через сутки от даты публикации в течении месяца здесь: https://yadi.sk/d/UAn5jdKRjUmrz Второй вариант реализации этой же задачи мы рассмотрим в следующем уроке. 3 Поделиться этим сообщением Ссылка на сообщение
Serge! 127 Опубликовано 19 Октября 2015 Учим ТЧ русскому языку (продолжение).Сначала вернёмся к первому уроку. Charsi предложил свой, более компактный, вариант функции обработки добавления символа в строку ввода, который обрабатывает не всю строку, а только последний символ.Привожу его полностью: function save_dialog:OnEdit_CHANGED() local str_edit = self:GetEditBox("edit_filename") local txt = str_edit:GetText() txt = txt:gsub(".$", function(ch) local _ch = t_lang[ch:byte()] return _ch and string.char(_ch) or ch end) str_edit:SetText(txt) end Какой из вариантов Вас больше устраивает, определитесь самостоятельно, ну а мы идём дальше. Всё, что в первом уроке было написано до подзаголовка «Первый» остаётся в силе с одним замечанием.В таблице перекодировки, ссылка на которую дана в первом уроке, отсутствует пара символов. Добавьте их самостоятельно в самое начало таблицы. [034] = 221, -- " --> Э [035] = 185, -- # --> № Второй.На первом уроке мы научились вводить символы кириллицы в поле EditBox. Однако наш вариант имел существенный недостаток – в нём отсутствовала возможность корректного исправления текста вводимой строки. Давайте попробуем это исправить.Рассмотрим все возможные операции при корректировке:1 - добавление символа в конец строки;2 - удаление последнего введенного символа;3 – перемещение по строке влево/вправо;4 – вставка символа в позиции курсора в середине строки;5 – удаление символа в позиции курсора в середине строки;6 - удаление символа перед позицией курсора в середине строки. Большую часть этих операций движок замечательно проделывает сам и нам остаётся только отслеживать результат его работы и учитывать его. А вот две операции требуют нашего активного вмешательства: это 2 и 4, которые связаны с вводом новых символов. 1. Добавим две новых переменных к той, что была определена в п. 1 первого урока: local edb_Pos, edb_Str = 1, {} Где: edb_Pos – позиция курсора в поле EditBox (инициируется 1) и edb_Str – массив, в котором мы будем сохранять символы вводимого текста.2. В пункте 2 (урока 1) менять ничего не требуется, поэтому берем его, целиком как есть, а вот пункт 3 подлежит коренной реконструкции.3. Так как мы решили, что все события производимые пользователем в поле EditBox будем контролировать сами, то первым делом отключаем прерывание генерируемое движком при изменении поля. Для этого в функции save_dialog:InitCallBacks() удаляем добавленную нами в первом уроке строку: self:AddCallback("edit_filename", ui_events.EDIT_TEXT_CHANGED, self.OnEdit_CHANGED, self) Саму нашу функцию save_dialog:OnEdit_CHANGED() пока не трогаем.Далее пойдём от простого к более сложному. Простое - это отследить те моменты, которые мы договорились отдать на откуп самому движку, т.е. перемещение по строке и удаление. Делать это будем в функции save_dialog:OnKeyboard(dik, keyboard_action). Для этого добавляем в неё, после уже вставленных нами ранее (в 1 уроке) несколько дополнительных строк, чтобы в итоге получилось так: if keyboard_action == ui_events.WINDOW_KEY_PRESSED then if dik == DIK_keys.DIK_LCONTROL or dik == DIK_keys.DIK_LMENU then self: OnChg_lan() elseif dik == DIK_keys.DIK_LEFT then if edb_Pos > 1 then edb_Pos = edb_Pos - 1 end elseif dik == DIK_keys.DIK_RIGHT then if edb_Pos <= #edb_Str then edb_Pos = edb_Pos + 1 end elseif dik == DIK_keys.DIK_DELETE then if edb_Pos <= #edb_Str then table.remove(edb_Str,edb_Pos) end elseif dik == DIK_keys.DIK_BACK then if edb_Pos > 1 then edb_Pos = edb_Pos-1 end table.remove(edb_Str,edb_Pos) elseif (dik > 1 and dik <= 13) or (dik >= 16 and dik <= 27) or (dik >= 30 and dik <= 40) or (dik >= 44 and dik <= 53) or dik == 57 or (dik >= 71 and dik <= 83) then self:OnEdit_CHANGED() end Здесь всё достаточно просто. При перемещении стрелками проверяем новое положение курсора и, если оно в пределах строки, то запоминаем его позицию. При удалении символа из строки удаляем соответствующий элемент из массива копии строки и опять же запоминаем текущую позицию ввода.Теперь осталось только разобрать со вставкой символа. Для этого отлавливаются прерывания от всех клавиш с печатными символами и, если такое обнаружено, то вызывается функция обработчик, т.е. наша OnEdit_CHANGED(). Обратите внимание, что мы даже не пытаемся отловить ввод буквы ‘ё’, т.к. на этой же клавише размещена тильда ‘~’, которую движок обрабатывает специальным образом для вывода окна консоли.И так, если мы зафиксировали факт нажатия клавиши с печатным символом, то вызываем OnEdit_CHANGED(), которая теперь не привязана к сообщениям от движка и находится под полным нашим контролем. Вот этим контролем и займёмся.Убираем в ней все содержимое и вставляем новое. Должно получиться следующее: function save_dialog:OnEdit_CHANGED() local str_edit = self:GetEditBox("edit_filename") -- /1 local sim = str_edit:GetText():match ('.', edb_Pos) -- /2 local cls = self.mode_lang and t_lang[sim:byte()] -- /3 sim = cls and string.char(cls) or sim -- /4 table.insert(edb_Str, edb_Pos, sim) -- /5 edb_Pos = #edb_Str + 1 -- /6 str_edit:SetText(table.concat(edb_Str)) -- /7 end Здесь тоже нет особых сложностей, но, тем не менее, прокомментируем наши действия.Подключаемся к контролу EditBox (1) и получаем символ, находящийся в текущей позиции ввода (2). Если включен режим кириллицы, то ищем код переданного движком символа (он всегда английский) в таблице перекодировки и при его наличии получаем соответствующий код русского символа (3). Если код найден, то подменяем английский символ русским, а если нет, то оставляем всё как есть (4). Заносим полученный символ в массив копии строки ввода в соответствии со значение текущей позиции курсора (5). Устанавливаем новую текущую позиции ввода (6), преобразуем массив символов в строку и возвращаем её в поле ввода (7).Если Вы всё проделами правильно, то теперь можете вводить имя сохраняемого файла в английской, русской или смешанной кодировке, а также корректировать вводимый текст без искажения его синтаксиса.Послесловие:Этот алгоритм имеет отличие от стандартной обработки строки редактирования, которое выражается в том, что при вставке символа в середину строки, позиции ввода следующего символа всегда устанавливается в её конец, тогда как в “штатной” – текущей становится следующая позиция. В этой ситуации есть свой плюс и свой минус, однако в любом случае, как побороть это, я просто не знаю. 1 4 Поделиться этим сообщением Ссылка на сообщение