i am creating a MacOS application, i must capture the same three keys pressed like shift + A + exclamation key
I put this method in my AppDelegate.cs
NSEvent.AddLocalMonitorForEventsMatchingMask(NSEventMask.KeyUp | NSEventMask.FlagsChanged , FlagsChanged);
here i recebeive the keys
private static NSEvent FlagsChanged(NSEvent keyEvent)
{
var key = (NSKey)keyEvent.KeyCode;
if (!(keyEvent.Window?.Identifier is null))
{
if (key.Equals(NSKey.Escape))
return (keyEvent);
var especialKeysPressed = KeyConverterHelper.ConvertFlagsToString(keyEvent.ModifierFlags);
var keyPressed = KeyConverterHelper.ConvertVirtualKeyToKeyPressed(keyEvent.KeyCode);
if (key.Equals(NSKey.Command) ||
key.Equals(NSKey.Shift) ||
key.Equals(NSKey.Control) ||
key.Equals(NSKey.Return) ||
key.Equals(NSKey.Tab) ||
key.Equals(NSKey.Option) && keyPressed != KeyPressed.None)
{
return (keyEvent);
}
var chars = keyEvent.Characters;
if (keyPressed == KeyPressed.None)
return (keyEvent);
//todo: GET THE KEYS PRESSED WHERE (SHIFT + A + Exclamation ) for example
}
return (keyEvent);
}
Related
I wanted to execute the DeepLearning example by using H2O. But it went wrong when running "DeepLearningV3 dlBody = h2o.train_deeplearning(dlParams);"
The error message:
Illegal argument for field:
hidden of schema:
DeepLearningParametersV3:
cannot convert ""200"" to type int
This is my code, I used the default value of dlParam except "responseColumn". After it went wrong, I added one line to set value of "hidden", but the results didn't change.
private void DL() throws IOException {
//H2O start
String url = "http://localhost:54321/";
H2oApi h2o = new H2oApi(url);
//STEP 0: init a session
String sessionId = h2o.newSession().sessionKey;
//STEP 1: import raw file
String path = "hdfs://kbmst:9000/user/spark/datasets/iris.csv";
ImportFilesV3 importBody = h2o.importFiles(path, null);
System.out.println("import: " + importBody);
//STEP 2: parse setup
ParseSetupV3 parseSetupParams = new ParseSetupV3();
parseSetupParams.sourceFrames = H2oApi.stringArrayToKeyArray(importBody.destinationFrames, FrameKeyV3.class);
ParseSetupV3 parseSetupBody = h2o.guessParseSetup(parseSetupParams);
System.out.println("parseSetupBody: " + parseSetupBody);
//STEP 3: parse into columnar Frame
ParseV3 parseParams = new ParseV3();
H2oApi.copyFields(parseParams, parseSetupBody);
parseParams.destinationFrame = H2oApi.stringToFrameKey("iris.hex");
parseParams.blocking = true;
ParseV3 parseBody = h2o.parse(parseParams);
System.out.println("parseBody: " + parseBody);
//STEP 4: Split into test and train datasets
String tmpVec = "tmp_" + UUID.randomUUID().toString();
String splitExpr =
"(, " +
" (tmp= " + tmpVec + " (h2o.runif iris.hex 906317))" +
" (assign train " +
" (rows iris.hex (<= " + tmpVec + " 0.75)))" +
" (assign test " +
" (rows iris.hex (> " + tmpVec + " 0.75)))" +
" (rm " + tmpVec + "))";
RapidsSchemaV3 rapidsParams = new RapidsSchemaV3();
rapidsParams.sessionId = sessionId;
rapidsParams.ast = splitExpr;
h2o.rapidsExec(rapidsParams);
// STEP 5: Train the model
// (NOTE: step 4 is polling, which we don't require because we specified blocking for the parse above)
DeepLearningParametersV3 dlParams = new DeepLearningParametersV3();
dlParams.trainingFrame = H2oApi.stringToFrameKey("train");
dlParams.validationFrame = H2oApi.stringToFrameKey("test");
dlParams.hidden=new int[]{200,200};
ColSpecifierV3 responseColumn = new ColSpecifierV3();
responseColumn.columnName = "class";
dlParams.responseColumn = responseColumn;
System.out.println("About to train DL. . .");
DeepLearningV3 dlBody = h2o.train_deeplearning(dlParams);
System.out.println("dlBody: " + dlBody);
// STEP 6: poll for completion
JobV3 job = h2o.waitForJobCompletion(dlBody.job.key);
System.out.println("DL build done.");
// STEP 7: fetch the model
ModelKeyV3 model_key = (ModelKeyV3)job.dest;
ModelsV3 models = h2o.model(model_key);
System.out.println("models: " + models);
DeepLearningModelV3 model = (DeepLearningModelV3)models.models[0];
System.out.println("new DL model: " + model);
// STEP 8: predict!
ModelMetricsListSchemaV3 predict_params = new ModelMetricsListSchemaV3();
predict_params.model = model_key;
predict_params.frame = dlParams.trainingFrame;
predict_params.predictionsFrame = H2oApi.stringToFrameKey("predictions");
ModelMetricsListSchemaV3 predictions = h2o.predict(predict_params);
System.out.println("predictions: " + predictions);
// STEP 9: end the session
h2o.endSession();
}
I found the relative source code, but I can't understand why it goes wrong.
This is the definition of hidden.
public class DeepLearningParametersV3 extends ModelParametersSchemaV3 {{
/**
* Hidden layer sizes (e.g. [100, 100]).
*/
public int[] hidden;
//other params
}
And this is the code where the error message showed.It was the line String msg = "Illegal argument for field: " + field_name + " of schema: " + schemaClass.getSimpleName() + ": cannot convert \"" + s + "\" to type " + fclz.getSimpleName();
static <E> Object parse(String field_name, String s, Class fclz, boolean required, Class schemaClass) {
if (fclz.isPrimitive() || String.class.equals(fclz)) {
try {
return parsePrimitve(s, fclz);
} catch (NumberFormatException ne) {
String msg = "Illegal argument for field: " + field_name + " of schema: " + schemaClass.getSimpleName() + ": cannot convert \"" + s + "\" to type " + fclz.getSimpleName();
throw new H2OIllegalArgumentException(msg);
}
}
// An array?
if (fclz.isArray()) {
// Get component type
Class<E> afclz = (Class<E>) fclz.getComponentType();
// Result
E[] a = null;
// Handle simple case with null-array
if (s.equals("null") || s.length() == 0) return null;
// Handling of "auto-parseable" cases
if (AutoParseable.class.isAssignableFrom(afclz))
return gson.fromJson(s, fclz);
// Splitted values
String[] splits; // "".split(",") => {""} so handle the empty case explicitly
if (s.startsWith("[") && s.endsWith("]") ) { // It looks like an array
read(s, 0, '[', fclz);
read(s, s.length() - 1, ']', fclz);
String inside = s.substring(1, s.length() - 1).trim();
if (inside.length() == 0)
splits = new String[]{};
else
splits = splitArgs(inside);
} else { // Lets try to parse single value as an array!
// See PUBDEV-1955
splits = new String[] { s.trim() };
}
// Can't cast an int[] to an Object[]. Sigh.
if (afclz == int.class) { // TODO: other primitive types. . .
a = (E[]) Array.newInstance(Integer.class, splits.length);
} else if (afclz == double.class) {
a = (E[]) Array.newInstance(Double.class, splits.length);
} else if (afclz == float.class) {
a = (E[]) Array.newInstance(Float.class, splits.length);
} else {
// Fails with primitive classes; need the wrapper class. Thanks, Java.
a = (E[]) Array.newInstance(afclz, splits.length);
}
for (int i = 0; i < splits.length; i++) {
if (String.class == afclz || KeyV3.class.isAssignableFrom(afclz)) {
// strip quotes off string values inside array
String stripped = splits[i].trim();
if ("null".equals(stripped.toLowerCase()) || "na".equals(stripped.toLowerCase())) {
a[i] = null;
continue;
}
// Quotes are now optional because standard clients will send arrays of length one as just strings.
if (stripped.startsWith("\"") && stripped.endsWith("\"")) {
stripped = stripped.substring(1, stripped.length() - 1);
}
a[i] = (E) parse(field_name, stripped, afclz, required, schemaClass);
} else {
a[i] = (E) parse(field_name, splits[i].trim(), afclz, required, schemaClass);
}
}
return a;
}
// Are we parsing an object from a string? NOTE: we might want to make this check more restrictive.
if (! fclz.isAssignableFrom(Schema.class) && s != null && s.startsWith("{") && s.endsWith("}")) {
return gson.fromJson(s, fclz);
}
if (fclz.equals(Key.class))
if ((s == null || s.length() == 0) && required) throw new H2OKeyNotFoundArgumentException(field_name, s);
else if (!required && (s == null || s.length() == 0)) return null;
else
return Key.make(s.startsWith("\"") ? s.substring(1, s.length() - 1) : s); // If the key name is in an array we need to trim surrounding quotes.
if (KeyV3.class.isAssignableFrom(fclz)) {
if ((s == null || s.length() == 0) && required) throw new H2OKeyNotFoundArgumentException(field_name, s);
if (!required && (s == null || s.length() == 0)) return null;
return KeyV3.make(fclz, Key.make(s.startsWith("\"") ? s.substring(1, s.length() - 1) : s)); // If the key name is in an array we need to trim surrounding quotes.
}
if (Enum.class.isAssignableFrom(fclz)) {
return EnumUtils.valueOf(fclz, s);
}
// TODO: these can be refactored into a single case using the facilities in Schema:
if (FrameV3.class.isAssignableFrom(fclz)) {
if ((s == null || s.length() == 0) && required) throw new H2OKeyNotFoundArgumentException(field_name, s);
else if (!required && (s == null || s.length() == 0)) return null;
else {
Value v = DKV.get(s);
if (null == v) return null; // not required
if (!v.isFrame()) throw H2OIllegalArgumentException.wrongKeyType(field_name, s, "Frame", v.get().getClass());
return new FrameV3((Frame) v.get()); // TODO: version!
}
}
if (JobV3.class.isAssignableFrom(fclz)) {
if ((s == null || s.length() == 0) && required) throw new H2OKeyNotFoundArgumentException(s);
else if (!required && (s == null || s.length() == 0)) return null;
else {
Value v = DKV.get(s);
if (null == v) return null; // not required
if (!v.isJob()) throw H2OIllegalArgumentException.wrongKeyType(field_name, s, "Job", v.get().getClass());
return new JobV3().fillFromImpl((Job) v.get()); // TODO: version!
}
}
// TODO: for now handle the case where we're only passing the name through; later we need to handle the case
// where the frame name is also specified.
if (FrameV3.ColSpecifierV3.class.isAssignableFrom(fclz)) {
return new FrameV3.ColSpecifierV3(s);
}
if (ModelSchemaV3.class.isAssignableFrom(fclz))
throw H2O.fail("Can't yet take ModelSchemaV3 as input.");
/*
if( (s==null || s.length()==0) && required ) throw new IllegalArgumentException("Missing key");
else if (!required && (s == null || s.length() == 0)) return null;
else {
Value v = DKV.get(s);
if (null == v) return null; // not required
if (! v.isModel()) throw new IllegalArgumentException("Model argument points to a non-model object.");
return v.get();
}
*/
throw H2O.fail("Unimplemented schema fill from " + fclz.getSimpleName());
} // parse()
It looks like this could be a bug. A jira ticket has been created for this issue, you can track it here: https://0xdata.atlassian.net/browse/PUBDEV-5454?filter=-1.
I have defined a variable called fighter in my program. I have an if keyPressed function which selects a specific image based on key. The problem I am having is that that images are swapping but overlapping the original image. I also attempted to add an else statement with the fighter in the original position but still same response.
var fighter;
var stance;
var kick;
var jab;
var cross;
var mx; //Use to constrain fighter to center of circle
var my;
function preload(){
stance = loadImage("img/stance.svg");
kick = loadImage("img/kick.svg");
jab = loadImage("img/jab.svg");
cross = loadImage("img/cross.svg");
};
function setup(){
createCanvas(1280,720);
};
function draw(){
background(0, 246, 255);
fill("red");
ellipse(width/2,height/2,500,500);
mx = constrain(mouseX,width/2-250,width/2+250);
my = constrain(mouseY,height/2-250,height/2+250);
fighter = image(stance,mx,my);
if(keyIsPressed){
if((key == "a" || key == "A")){
fighter = "";
fighter = image(jab,mx,my);
}
else if ((key == "w" || key == "W")) {
fighter = image(cross,mx,my);
}
else if ((key == "s" || key == "S")) {
fighter = image(kick,mx,my);
}
};
};
You're setting fighter equal to the value returned by the image() function for some reason. This doesn't make a ton of sense.
Instead, I think you want to set fighter equal to one of the images, and then pass fighter into the image() function. Something like this:
fighter = stance;
if(keyIsPressed){
if((key == "a" || key == "A")){
fighter = jab;
}
else if ((key == "w" || key == "W")) {
fighter = cross
}
else if ((key == "s" || key == "S")) {
fighter = kick;
}
}
image(fighter, mx,my);
I'm trying to show alert message including click event on div element that are sought through a loop. The problem is that in any div I click, it is only displayed the alert of the last element. How can I solve? I do not understand the logic being performed.
for (var i = 0; i < this.legend.layerInfos.length; i++)
{
var sNomeDiv = "";
var sMensagem = "";
if (this.legend.layerInfos[i].layer.visible)
{
sNomeDiv = this.legend.id + "_" + this.legend.layerInfos[i].layer.id;
if (this.legend.layerInfos[i].layer.description == "" || this.legend.layerInfos[i].layer.description == "undefined" || this.legend.layerInfos[i].layer.description == "null")
{
sMensagem = "Nenhuma informação cadastrada para a camada " + this.legend.layerInfos[i].title;
}
else
{
sMensagem = this.legend.layerInfos[i].layer.description;
}
//Always display an alert with the text of the last element of the loop
dojo.connect
(
dojo.byId(sNomeDiv),
"onclick",
function()
{
alert(sMensagem + " --> " + sNomeDiv);
}
);
}
}
I am trying to use improve a GTK# application which runs on Mac OS by using the API that MonoMac exposes and build a native Mac menu using the NSMenuItem and NSMenu classes.
So far everything looks good and I was able to set some keyboard accelerators (KeyEquivalent) to the menu but the problem is that they don't react to the keyboard. The key combinations are displayed correctly in the menu but pressing the keys do not do anything. Selecting the menu items using the mouse works fine.
Here is some code that I used to initialize the the environment:
NSApplication.InitDrawingBridge ();
NSApplication.Init ();
NSMenuItem super = new NSMenuItem (DataHelper.ProductName);
super.Submenu = new NSMenu (DataHelper.ProductName);
NSMenu mainMenu = new NSMenu ();
mainMenu.AddItem (super);
NSApplication.SharedApplication.MainMenu = mainMenu;
< menu initialization comes here >
NSApplication.SharedApplication.Delegate = new AppDelegate ();
NSApplication.SharedApplication.ActivateIgnoringOtherApps (true);
Is there anything else I have to do in order to make the keyboard events pass to the menu?
I looked at MonoDevelop for code reference and could not find anything that could make that difference. I used some code from there for setting the KeyEquivalent values too.
It turns out that GTK does not automatically send the KeyPress events to the menu if they remain unhandled. What I did was to capture the event on the outermost container in GTK and manually send it to the Mac Menu like that:
Note: Most of the code bellow is borrowed from Monodevelop and is MIT/X11 licensed
private void frmMain_KeyPressEvent (object o, KeyPressEventArgs args)
{
Gdk.ModifierType state;
state = GtkWorkarounds.FixMacModifiers (args.Event.State, args.Event.Group);
string keyEquivalent;
NSEventModifierMask mask;
GetKeyEquivalentForGdkKey (args.Event.Key, state, out keyEquivalent, out mask);
if (keyEquivalent.Length == 0)
return false;
var nsEvent = NSEvent.KeyEvent (
NSEventType.KeyDown, PointF.Empty, mask, 0, 0,
NSGraphicsContext.CurrentContext, keyEquivalent, keyEquivalent, false, 0);
if (NSApplication.SharedApplication.MainMenu.PerformKeyEquivalent (nsEvent)) {
args.RetVal = true;
return true;
}
return false;
}
public static void GetKeyEquivalentForGdkKey (Gdk.Key key, ModifierType modifierType, out string keyEquivalent, out NSEventModifierMask mask)
{
keyEquivalent = GetKeyEquivalent (key);
mask = 0;
if (keyEquivalent.Length == 0)
return;
if ((modifierType & Gdk.ModifierType.Mod1Mask) != 0) {
mask |= NSEventModifierMask.AlternateKeyMask;
modifierType ^= Gdk.ModifierType.Mod1Mask;
}
if ((modifierType & Gdk.ModifierType.ShiftMask) != 0) {
mask |= NSEventModifierMask.ShiftKeyMask;
modifierType ^= Gdk.ModifierType.ShiftMask;
}
if ((modifierType & Gdk.ModifierType.ControlMask) != 0) {
mask |= NSEventModifierMask.ControlKeyMask;
modifierType ^= Gdk.ModifierType.ControlMask;
}
if ((modifierType & Gdk.ModifierType.MetaMask) != 0) {
mask |= NSEventModifierMask.CommandKeyMask;
modifierType ^= Gdk.ModifierType.MetaMask;
}
}
static string GetKeyEquivalent (Gdk.Key key)
{
char c = (char) Gdk.Keyval.ToUnicode ((uint) key);
if (c != 0)
return c.ToString ();
var fk = GetFunctionKey (key);
if (fk != 0)
return ((char) fk).ToString ();
return "";
}
static FunctionKey GetFunctionKey (Gdk.Key key)
{
switch (key) {
case Gdk.Key.Return:
return (FunctionKey) (uint) '\n';
case Gdk.Key.BackSpace:
return (FunctionKey) 0x08;
// NSBackspaceCharacter
case Gdk.Key.KP_Delete:
case Gdk.Key.Delete:
return (FunctionKey) 0x7F;
// NSDeleteCharacter
case Gdk.Key.KP_Up:
case Gdk.Key.Up:
return FunctionKey.UpArrow;
case Gdk.Key.KP_Down:
case Gdk.Key.Down:
return FunctionKey.DownArrow;
case Gdk.Key.KP_Left:
case Gdk.Key.Left:
return FunctionKey.LeftArrow;
case Gdk.Key.KP_Right:
case Gdk.Key.Right:
return FunctionKey.RightArrow;
case Gdk.Key.F1:
return FunctionKey.F1;
case Gdk.Key.F2:
return FunctionKey.F2;
case Gdk.Key.F3:
return FunctionKey.F3;
case Gdk.Key.F4:
return FunctionKey.F4;
case Gdk.Key.F5:
return FunctionKey.F5;
case Gdk.Key.F6:
return FunctionKey.F6;
case Gdk.Key.F7:
return FunctionKey.F7;
case Gdk.Key.F8:
return FunctionKey.F8;
case Gdk.Key.F9:
return FunctionKey.F9;
case Gdk.Key.F10:
return FunctionKey.F10;
case Gdk.Key.F11:
return FunctionKey.F11;
case Gdk.Key.F12:
return FunctionKey.F12;
case Gdk.Key.F13:
return FunctionKey.F13;
case Gdk.Key.F14:
return FunctionKey.F14;
case Gdk.Key.F15:
return FunctionKey.F15;
case Gdk.Key.F16:
return FunctionKey.F16;
case Gdk.Key.F17:
return FunctionKey.F17;
case Gdk.Key.F18:
return FunctionKey.F18;
case Gdk.Key.F19:
return FunctionKey.F19;
case Gdk.Key.F20:
return FunctionKey.F20;
case Gdk.Key.F21:
return FunctionKey.F21;
case Gdk.Key.F22:
return FunctionKey.F22;
case Gdk.Key.F23:
return FunctionKey.F23;
case Gdk.Key.F24:
return FunctionKey.F24;
case Gdk.Key.F25:
return FunctionKey.F25;
case Gdk.Key.F26:
return FunctionKey.F26;
case Gdk.Key.F27:
return FunctionKey.F27;
case Gdk.Key.F28:
return FunctionKey.F28;
case Gdk.Key.F29:
return FunctionKey.F29;
case Gdk.Key.F30:
return FunctionKey.F30;
case Gdk.Key.F31:
return FunctionKey.F31;
case Gdk.Key.F32:
return FunctionKey.F32;
case Gdk.Key.F33:
return FunctionKey.F33;
case Gdk.Key.F34:
return FunctionKey.F34;
case Gdk.Key.F35:
return FunctionKey.F35;
case Gdk.Key.KP_Insert:
case Gdk.Key.Insert:
return FunctionKey.Insert;
case Gdk.Key.KP_Home:
case Gdk.Key.Home:
return FunctionKey.Home;
case Gdk.Key.Begin:
return FunctionKey.Begin;
case Gdk.Key.KP_End:
case Gdk.Key.End:
return FunctionKey.End;
case Gdk.Key.KP_Page_Up:
case Gdk.Key.Page_Up:
return FunctionKey.PageUp;
case Gdk.Key.KP_Page_Down:
case Gdk.Key.Page_Down:
return FunctionKey.PageDown;
case Gdk.Key.Key_3270_PrintScreen:
return FunctionKey.PrintScreen;
case Gdk.Key.Scroll_Lock:
return FunctionKey.ScrollLock;
case Gdk.Key.Pause:
return FunctionKey.Pause;
case Gdk.Key.Sys_Req:
return FunctionKey.SysReq;
case Gdk.Key.Break:
return FunctionKey.Break;
case Gdk.Key.Key_3270_Reset:
return FunctionKey.Reset;
case Gdk.Key.Menu:
return FunctionKey.Menu;
case Gdk.Key.Print:
return FunctionKey.Print;
case Gdk.Key.Help:
return FunctionKey.Help;
case Gdk.Key.Find:
return FunctionKey.Find;
case Gdk.Key.Undo:
return FunctionKey.Undo;
case Gdk.Key.Redo:
return FunctionKey.Redo;
case Gdk.Key.Execute:
return FunctionKey.Execute;
/*
return FunctionKey.Stop;
return FunctionKey.User;
return FunctionKey.System;
return FunctionKey.ClearLine;
return FunctionKey.ClearDisplay;
return FunctionKey.InsertLine;
return FunctionKey.DeleteLine;
return FunctionKey.InsertChar;
return FunctionKey.DeleteChar;
return FunctionKey.Next;
return FunctionKey.Prev;
return FunctionKey.Select;
return FunctionKey.ModeSwitch;
*/
}
return 0;
}
// "Function-Key Unicodes" from NSEvent reference
enum FunctionKey : ushort
{
UpArrow = 0xF700,
DownArrow = 0xF701,
LeftArrow = 0xF702,
RightArrow = 0xF703,
F1 = 0xF704,
F2 = 0xF705,
F3 = 0xF706,
F4 = 0xF707,
F5 = 0xF708,
F6 = 0xF709,
F7 = 0xF70A,
F8 = 0xF70B,
F9 = 0xF70C,
F10 = 0xF70D,
F11 = 0xF70E,
F12 = 0xF70F,
F13 = 0xF710,
F14 = 0xF711,
F15 = 0xF712,
F16 = 0xF713,
F17 = 0xF714,
F18 = 0xF715,
F19 = 0xF716,
F20 = 0xF717,
F21 = 0xF718,
F22 = 0xF719,
F23 = 0xF71A,
F24 = 0xF71B,
F25 = 0xF71C,
F26 = 0xF71D,
F27 = 0xF71E,
F28 = 0xF71F,
F29 = 0xF720,
F30 = 0xF721,
F31 = 0xF722,
F32 = 0xF723,
F33 = 0xF724,
F34 = 0xF725,
F35 = 0xF726,
Insert = 0xF727,
Delete = 0xF728,
Home = 0xF729,
Begin = 0xF72A,
End = 0xF72B,
PageUp = 0xF72C,
PageDown = 0xF72D,
PrintScreen = 0xF72E,
ScrollLock = 0xF72F,
Pause = 0xF730,
SysReq = 0xF731,
Break = 0xF732,
Reset = 0xF733,
Stop = 0xF734,
Menu = 0xF735,
User = 0xF736,
System = 0xF737,
Print = 0xF738,
ClearLine = 0xF739,
ClearDisplay = 0xF73A,
InsertLine = 0xF73B,
DeleteLine = 0xF73C,
InsertChar = 0xF73D,
DeleteChar = 0xF73E,
Prev = 0xF73F,
Next = 0xF740,
Select = 0xF741,
Execute = 0xF742,
Undo = 0xF743,
Redo = 0xF744,
Find = 0xF745,
Help = 0xF746,
ModeSwitch = 0xF747
}
Using the Ace Code Editor can I lock or make readonly a segment of code but still allow other lines of code to be written or edited during a session?
Here is the start of a solution:
$(function() {
var editor = ace.edit("editor1")
, session = editor.getSession()
, Range = require("ace/range").Range
, range = new Range(1, 4, 1, 10)
, markerId = session.addMarker(range, "readonly-highlight");
session.setMode("ace/mode/javascript");
editor.keyBinding.addKeyboardHandler({
handleKeyboard : function(data, hash, keyString, keyCode, event) {
if (hash === -1 || (keyCode <= 40 && keyCode >= 37)) return false;
if (intersects(range)) {
return {command:"null", passEvent:false};
}
}
});
before(editor, 'onPaste', preventReadonly);
before(editor, 'onCut', preventReadonly);
range.start = session.doc.createAnchor(range.start);
range.end = session.doc.createAnchor(range.end);
range.end.$insertRight = true;
function before(obj, method, wrapper) {
var orig = obj[method];
obj[method] = function() {
var args = Array.prototype.slice.call(arguments);
return wrapper.call(this, function(){
return orig.apply(obj, args);
}, args);
}
return obj[method];
}
function intersects(range) {
return editor.getSelectionRange().intersects(range);
}
function preventReadonly(next, args) {
if (intersects(range)) return;
next();
}
});
see it working in this fiddle: http://jsfiddle.net/bzwheeler/btsxgena/
The major working pieces are:
create start and end ace anchors which track the location of a 'readonly' portion as the document around it changes.
create a range to encapsulate the anchors
add a custom keyhandler to check if the current impending keypress will affect the readonly range and cancel it if so.
add custom paste/cut handlers to protect against right-click menu and browser menu cut/paste actions
You can do it by listening to the exec events:
// Prevent editing first and last line of editor
editor.commands.on("exec", function(e) {
var rowCol = editor.selection.getCursor();
if ((rowCol.row === 0) || ((rowCol.row + 1) === editor.session.getLength())) {
e.preventDefault();
e.stopPropagation();
}
});
Source: https://jsfiddle.net/tripflex/y0huvc1b/
I suggest something else easier and more reliable to prevent range to be modified (check it!)
var old$tryReplace = editor.$tryReplace;
editor.$tryReplace = function(range, replacement) {
return intersects(range)?null:old$tryReplace.apply(this, arguments);
}
var session = editor.getSession();
var oldInsert = session.insert;
session.insert = function(position, text) {
return oldInsert.apply(this, [position, outsideRange(position)?text:""]);
}
var oldRemove = session.remove;
session.remove = function(range) {
return intersects(range)?false:oldRemove.apply(this, arguments);
}
var oldMoveText = session.moveText;
session.moveText = function(fromRange, toPosition, copy) {
if (intersects(fromRange) || !outsideRange(toPosition)) return fromRange;
return oldMoveText.apply(this, arguments)
}
outsideRange = function (position) {
var s0 = range.start;
if (position.row < s0.row || (position.row == s0.row && position.column <= s0.column)) return true; // position must be before range.start
var e0 = range.end;
if (position.row > e0.row || (position.row == e0.row && position.column >= e0.column)) return true; // or after range.end
return false;
}
intersects = function(withRange) {
var e = withRange.end, s0 = range.start, s = withRange.start, e0 = range.end;
if (e.row < s0.row || (e.row == s0.row && e.column <= s0.column)) return false; // withRange.end must be before range.start
if (s.row > e0.row || (s.row == e0.row && s.column >= e0.column)) return false; // or withRange.start must be after range.end
return true;
}