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:
Marc Durdin 2018-12-10 14:23:53 +11:00 committed by GitHub
commit 43fbcd107d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 174 additions and 18 deletions

View file

@ -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;

View file

@ -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');

View file

@ -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.

View file

@ -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();
});