1 module scone.input.os.posix.keyboard_event_tree; 2 3 version (Posix) 4 { 5 import scone.input.scone_control_key : SCK; 6 import scone.input.scone_key : SK; 7 import scone.input.keyboard_event : KeyboardEvent; 8 import std.typecons : Nullable; 9 10 // todo this logic for inserting values has some problems 11 // i believe it does not safeguard a node from having both children and a value 12 // also, getting multiple inputs from a sequence is not 100% reliable. it should work for known sequences, but i would not consider this reliable yet. 13 class KeyboardEventTree 14 { 15 public KeyboardEvent[] find(uint[] sequence) 16 { 17 assert(sequence.length); 18 19 // special case for escape key until i figure out this logic 20 if (sequence == [27]) 21 { 22 return [KeyboardEvent(SK.escape, SCK.none)]; 23 } 24 25 KeyboardEvent[] keypresses = []; 26 auto node = this.root; 27 28 foreach (n, number; sequence) 29 { 30 const bool hasNodeChild = (number in node.children) !is null; 31 32 if (node.value.isNull() && !hasNodeChild) 33 { 34 if (!(keypresses.length && keypresses[$ - 1].key == SK.unknown)) 35 { 36 keypresses ~= KeyboardEvent(SK.unknown, SCK.none); 37 } 38 39 node = this.root; 40 continue; 41 } 42 43 if (hasNodeChild) 44 { 45 node = node.children[number]; 46 } 47 48 if (!node.value.isNull()) 49 { 50 keypresses ~= node.value.get(); 51 node = this.root; 52 continue; 53 } 54 } 55 56 return keypresses; 57 } 58 59 public bool insert(in uint[] sequence, KeyboardEvent data) 60 { 61 // special case for escape key until i figure out this logic 62 if (sequence == [27]) 63 { 64 return true; 65 } 66 67 auto node = this.root; 68 69 foreach (number; sequence) 70 { 71 if ((number in node.children) is null) 72 { 73 if (!node.value.isNull()) 74 { 75 return false; 76 } 77 78 node.children[number] = new KeyboardEventNode(); 79 } 80 81 node = node.children[number]; 82 } 83 84 node.value = data; 85 86 return true; 87 } 88 89 private KeyboardEventNode root = new KeyboardEventNode(); 90 } 91 92 unittest 93 { 94 auto tree = new KeyboardEventTree(); 95 tree.insert([27], KeyboardEvent(SK.escape, SCK.none)); 96 tree.insert([27, 91, 67], KeyboardEvent(SK.right, SCK.none)); 97 tree.insert([27, 91, 66], KeyboardEvent(SK.down, SCK.none)); 98 tree.insert([48], KeyboardEvent(SK.key_0, SCK.none)); 99 tree.insert([49], KeyboardEvent(SK.key_1, SCK.none)); 100 101 KeyboardEvent[] find; 102 103 find = tree.find([1]); 104 assert(find.length == 1); 105 assert(SK.unknown == find[0].key); 106 107 find = tree.find([48]); 108 assert(find.length == 1); 109 assert(SK.key_0 == find[0].key); 110 111 find = tree.find([27]); 112 assert(find.length == 1); 113 assert(SK.escape == find[0].key); 114 115 find = tree.find([27, 91, 67]); 116 assert(find.length == 1); 117 assert(SK.right == find[0].key); 118 119 find = tree.find([27, 91, 66]); 120 assert(find.length == 1); 121 assert(SK.down == find[0].key); 122 123 find = tree.find([48, 49]); 124 assert(find.length == 2); 125 assert(SK.key_0 == find[0].key); 126 assert(SK.key_1 == find[1].key); 127 128 find = tree.find([27, 91, 67, 27, 91, 66]); 129 assert(find.length == 2); 130 assert(SK.right == find[0].key); 131 assert(SK.down == find[1].key); 132 133 find = tree.find([27, 6, 67, 27, 91, 66]); 134 assert(find.length == 2); 135 assert(SK.unknown == find[0].key); 136 assert(SK.down == find[1].key); 137 } 138 139 private class KeyboardEventNode 140 { 141 KeyboardEventNode[uint] children; 142 Nullable!KeyboardEvent value; 143 } 144 }