mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-13 12:19:25 +00:00
Merge pull request #1405 from keymanapp/developer-touch-layout-bug-fixes
[Developer] Various small bug fixes for Keyman Developer Touch Layout Editor
This commit is contained in:
commit
43fbcd107d
4 changed files with 174 additions and 18 deletions
|
|
@ -653,6 +653,8 @@ begin
|
|||
GetCharMapDropTool.Handle(Self, cmimText);
|
||||
GetCharMapDropTool.Handle(editKeyOutputCode, cmimCode);
|
||||
frameSource.SetupCharMapDrop;
|
||||
frameTouchLayout.SetupCharMapDrop;
|
||||
frameTouchLayoutSource.SetupCharMapDrop;
|
||||
|
||||
FillFeatureGrid;
|
||||
|
||||
|
|
@ -3144,7 +3146,7 @@ begin
|
|||
if pagesTouchLayout.ActivePage = pageTouchLayoutCode then
|
||||
begin
|
||||
frameTouchLayoutSource.EditorText := frameTouchLayout.SaveToString;
|
||||
DoFocus(frameTouchLayout);
|
||||
DoFocus(frameTouchLayoutSource);
|
||||
end;
|
||||
FLoading := False;
|
||||
end;
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ type
|
|||
cef: TframeCEFHost;
|
||||
FFilename: string;
|
||||
FOnBreakpointClicked: TEditorBreakpointClickedEvent;
|
||||
FErrorLine: Integer;
|
||||
|
||||
procedure RefreshOptions;
|
||||
function GetText: WideString;
|
||||
|
|
@ -288,7 +289,10 @@ procedure TframeTextEditor.cefPreKeySyncEvent(Sender: TObject;
|
|||
e: TCEFHostKeyEventData; out isShortcut, Handled: Boolean);
|
||||
begin
|
||||
AssertCefThread;
|
||||
if e.event.windows_key_code = VK_ESCAPE then
|
||||
Handled := False;
|
||||
// While FErrorLine is from main thread, this is unlikely to cause trouble so
|
||||
// will not worry about synchronisation
|
||||
if (e.event.windows_key_code = VK_ESCAPE) and (FErrorLine > 0) then
|
||||
Handled := True;
|
||||
end;
|
||||
|
||||
|
|
@ -926,6 +930,9 @@ end;
|
|||
procedure TframeTextEditor.FindError(ln: Integer);
|
||||
begin
|
||||
ClearError;
|
||||
|
||||
FErrorLine := ln;
|
||||
|
||||
if (ln <= 0) then Exit;
|
||||
|
||||
ExecuteLineCommand(ln, 'highlightError');
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
(*
|
||||
Name: UframeTouchLayoutBuilder
|
||||
Copyright: Copyright (C) SIL International.
|
||||
Documentation:
|
||||
Description:
|
||||
Documentation:
|
||||
Description:
|
||||
Create Date: 21 Aug 2013
|
||||
|
||||
Modified Date: 3 Aug 2015
|
||||
Authors: mcdurdin
|
||||
Related Files:
|
||||
Dependencies:
|
||||
Related Files:
|
||||
Dependencies:
|
||||
|
||||
Bugs:
|
||||
Todo:
|
||||
Notes:
|
||||
Bugs:
|
||||
Todo:
|
||||
Notes:
|
||||
History: 21 Aug 2013 - mcdurdin - I3894 - V9.0 - Support modified state for touch layout builder
|
||||
21 Aug 2013 - mcdurdin - I3895 - V9.0 - App hotkeys don't work within layout builder
|
||||
07 Nov 2013 - mcdurdin - I3945 - V9.0 - Touch Layout Editor should allow import from existing On Screen Keyboard
|
||||
|
|
@ -36,9 +36,24 @@ unit UframeTouchLayoutBuilder;
|
|||
interface
|
||||
|
||||
uses
|
||||
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
|
||||
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, UfrmTike, UserMessages, KMDActionInterfaces,
|
||||
KeyboardFonts, TempFileManager, Keyman.Developer.UI.UframeCEFHost;
|
||||
System.Classes,
|
||||
System.JSON,
|
||||
System.SysUtils,
|
||||
System.Variants,
|
||||
Winapi.Messages,
|
||||
Winapi.Windows,
|
||||
Vcl.Controls,
|
||||
Vcl.Dialogs,
|
||||
Vcl.Forms,
|
||||
Vcl.Graphics,
|
||||
|
||||
Keyman.Developer.UI.UframeCEFHost,
|
||||
|
||||
KeyboardFonts,
|
||||
KMDActionInterfaces,
|
||||
TempFileManager,
|
||||
UfrmTike,
|
||||
UserMessages;
|
||||
|
||||
type
|
||||
TframeTouchLayoutBuilder = class(TTikeForm, IKMDEditActions)
|
||||
|
|
@ -62,19 +77,25 @@ type
|
|||
FLastError: string; // I4083
|
||||
FLastErrorOffset: Integer; // I4083
|
||||
FFilename: string;
|
||||
FSourceWasRegistered: Boolean;
|
||||
function GetLayoutJS: string;
|
||||
procedure DoModified;
|
||||
procedure DoLoad;
|
||||
procedure FireCommand(const commands: TStringList); virtual;
|
||||
procedure DoSelectTemplate;
|
||||
procedure DoImportFromOSK;
|
||||
function BuilderCommand(const cmd: string): Boolean;
|
||||
function BuilderCommand(const cmd: string; const parameters: TJSONValue = nil): Boolean;
|
||||
procedure UpdateCharacterMap(code: string); // I4046
|
||||
function GetFontInfo(Index: TKeyboardFont): TKeyboardFontInfo; // I4057
|
||||
procedure SetFontInfo(Index: TKeyboardFont; const Value: TKeyboardFontInfo); // I4057
|
||||
|
||||
procedure cefBeforeBrowse(Sender: TObject; const Url: string; params: TStringList; wasHandled: Boolean);
|
||||
procedure cefLoadEnd(Sender: TObject);
|
||||
procedure RegisterSource;
|
||||
procedure UnregisterSource;
|
||||
procedure CharMapDragDrop(Sender, Source: TObject; X, Y: Integer);
|
||||
procedure CharMapDragOver(Sender, Source: TObject; X, Y: Integer;
|
||||
State: TDragState; var Accept: Boolean);
|
||||
protected
|
||||
function GetHelpTopic: string; override;
|
||||
|
||||
|
|
@ -95,6 +116,7 @@ type
|
|||
|
||||
public
|
||||
{ Public declarations }
|
||||
procedure SetupCharMapDrop;
|
||||
function Load(const AFilename: string; ALoadFromTemplate, ALoadFromString: Boolean): Boolean;
|
||||
procedure Save(const AFilename: string);
|
||||
function SaveToString: string;
|
||||
|
|
@ -112,7 +134,7 @@ type
|
|||
implementation
|
||||
|
||||
uses
|
||||
System.JSON,
|
||||
System.TypInfo,
|
||||
|
||||
xmlintf,
|
||||
xmldoc,
|
||||
|
|
@ -120,6 +142,9 @@ uses
|
|||
Keyman.Developer.System.HelpTopics,
|
||||
Keyman.Developer.System.TouchLayoutToVisualKeyboardConverter,
|
||||
|
||||
CharacterDragObject,
|
||||
CharMapDropTool,
|
||||
CharMapInsertMode,
|
||||
KeymanDeveloperOptions,
|
||||
VKeys,
|
||||
OnScreenKeyboardData,
|
||||
|
|
@ -196,13 +221,29 @@ begin
|
|||
cef.Visible := True;
|
||||
cef.OnBeforeBrowse := cefBeforeBrowse;
|
||||
cef.OnLoadEnd := cefLoadEnd;
|
||||
SetupCharMapDrop;
|
||||
end;
|
||||
|
||||
procedure TframeTouchLayoutBuilder.FormDestroy(Sender: TObject);
|
||||
begin
|
||||
inherited;
|
||||
UnregisterSource;
|
||||
end;
|
||||
|
||||
procedure TframeTouchLayoutBuilder.RegisterSource;
|
||||
begin
|
||||
if FFilename <> '' then
|
||||
modWebHttpServer.AppSource.RegisterSource(FFilename, FSavedLayoutJS);
|
||||
|
||||
FSourceWasRegistered := True;
|
||||
end;
|
||||
|
||||
procedure TframeTouchLayoutBuilder.UnregisterSource;
|
||||
begin
|
||||
if (FFilename <> '') and FSourceWasRegistered then
|
||||
modWebHttpServer.AppSource.UnregisterSource(FFilename);
|
||||
|
||||
FSourceWasRegistered := False;
|
||||
end;
|
||||
|
||||
procedure TframeTouchLayoutBuilder.ImportFromKVK(const KVKFileName: string); // I3945
|
||||
|
|
@ -288,6 +329,8 @@ begin
|
|||
// FreeAndNil(FHTMLTempFilename); // I4195
|
||||
// FHTMLTempFilename := TTempFileManager.Get('.html'); // I4195
|
||||
|
||||
UnregisterSource;
|
||||
|
||||
if ALoadFromString then
|
||||
begin
|
||||
FNewLayoutJS := AFilename;
|
||||
|
|
@ -344,7 +387,7 @@ begin
|
|||
FTouchLayout.Free;
|
||||
end;
|
||||
|
||||
modWebHttpServer.AppSource.RegisterSource(FFilename, FSavedLayoutJS);
|
||||
RegisterSource;
|
||||
|
||||
try
|
||||
DoLoad;
|
||||
|
|
@ -474,14 +517,21 @@ begin
|
|||
FLoading := False;
|
||||
end;
|
||||
|
||||
function TframeTouchLayoutBuilder.BuilderCommand(const cmd: string): Boolean;
|
||||
function TframeTouchLayoutBuilder.BuilderCommand(const cmd: string; const parameters: TJSONValue): Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
if FLoading then Exit; // I4057
|
||||
FDisplayScriptErrors := False; // I4047
|
||||
try
|
||||
try
|
||||
cef.cef.ExecuteJavaScript('builder.'+cmd+'();', '');
|
||||
if Assigned(parameters) then
|
||||
begin
|
||||
cef.cef.ExecuteJavaScript('builder.'+cmd+'('+parameters.ToJSON+')', '');
|
||||
end
|
||||
else
|
||||
begin
|
||||
cef.cef.ExecuteJavaScript('builder.'+cmd+'();', '');
|
||||
end;
|
||||
except
|
||||
// Ignore errors
|
||||
end;
|
||||
|
|
@ -588,4 +638,50 @@ begin
|
|||
BuilderCommand('redo');
|
||||
end;
|
||||
|
||||
|
||||
procedure TframeTouchLayoutBuilder.CharMapDragOver(Sender, Source: TObject; X, Y: Integer;
|
||||
State: TDragState; var Accept: Boolean);
|
||||
var
|
||||
j: TJSONObject;
|
||||
begin
|
||||
cef.cefwp.SetFocus;
|
||||
j := TJSONObject.Create;
|
||||
try
|
||||
j.AddPair('x', TJSONNumber.Create(X));
|
||||
j.AddPair('y', TJSONNumber.Create(Y));
|
||||
j.AddPair('state', GetEnumName(TypeInfo(TDragState), Ord(State)));
|
||||
BuilderCommand('charmapDragOver', j);
|
||||
finally
|
||||
j.Free;
|
||||
end;
|
||||
|
||||
// We cannot test acceptance via event because it is asynchronous
|
||||
// So we will just assume we can accept and throw it away if it is outside bounds
|
||||
// during drop.
|
||||
Accept := True;
|
||||
end;
|
||||
|
||||
procedure TframeTouchLayoutBuilder.CharMapDragDrop(Sender, Source: TObject; X, Y: Integer);
|
||||
var
|
||||
j: TJSONObject;
|
||||
cdo: TCharacterDragObject;
|
||||
begin
|
||||
cef.cefwp.SetFocus;
|
||||
cdo := Source as TCharacterDragObject;
|
||||
j := TJSONObject.Create;
|
||||
try
|
||||
j.AddPair('x', TJSONNumber.Create(X));
|
||||
j.AddPair('y', TJSONNumber.Create(Y));
|
||||
j.AddPair('text', cdo.Text[cdo.InsertType]);
|
||||
BuilderCommand('charmapDragDrop', j);
|
||||
finally
|
||||
j.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TframeTouchLayoutBuilder.SetupCharMapDrop;
|
||||
begin
|
||||
GetCharMapDropTool.Handle(cef.cefwp, cmimDefault, CharMapDragOver, CharMapDragDrop);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
|
|
|||
|
|
@ -1368,7 +1368,9 @@ $(function () {
|
|||
builder.generateSubKeys();
|
||||
}));
|
||||
|
||||
builder.updateSubKeyCap = builder.wrapChange(function (val) {
|
||||
builder.updateSubKeyCap = builder.wrapChange(function () {
|
||||
var val = $(this).val();
|
||||
|
||||
var k = builder.selectedSubKey();
|
||||
if (k.length == 0) return;
|
||||
$('.text', k).text(builder.renameSpecialKey(val));
|
||||
|
|
@ -1794,6 +1796,55 @@ $(function () {
|
|||
builder.ctrlDown = false;
|
||||
});
|
||||
|
||||
//
|
||||
// Character map drag+drop and double-click insertion
|
||||
//
|
||||
|
||||
builder.charmapDragOver = function(o) {
|
||||
|
||||
// Convert X, Y to document coordinates
|
||||
|
||||
let target = document.elementFromPoint(o.x, o.y);
|
||||
if(target === null || (target.nodeName != 'INPUT' && target.className != 'text')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
builder.charmapDragDrop = function(o) {
|
||||
|
||||
// Convert X, Y to document coordinates
|
||||
|
||||
if(o.x >= 0 && o.y >= 0) {
|
||||
var target = document.elementFromPoint(o.x, o.y);
|
||||
if(target === null) {
|
||||
return false;
|
||||
}
|
||||
if(target.nodeName == 'INPUT') {
|
||||
target = $(target);
|
||||
} else if(target.className == 'text') {
|
||||
if(target.parentElement.parentElement.id == 'sk') {
|
||||
builder.selectSubKey(target.parentElement);
|
||||
target = document.lastFocus;
|
||||
} else {
|
||||
builder.selectKey(target.parentElement);
|
||||
target = document.lastFocus;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// Double-click insertion, so use last focused control
|
||||
var target = $(document.lastFocus);
|
||||
}
|
||||
|
||||
// Focus the control and add the text
|
||||
|
||||
target.focus();
|
||||
target.val(target.val() + o.text);
|
||||
};
|
||||
|
||||
builder.preparePlatforms();
|
||||
builder.enableUndoControls();
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue