mirror of
https://github.com/ijprest/keyboard-layout-editor.git
synced 2026-04-08 01:00:48 -07:00
Implemented keyboard 'decals'
-- Intended to put decorative labels (logos, etc.) on keyboard layouts. -- They're basically just invisible keycaps; this works pretty well, since there are already so many formatting options for text on keycaps, and it saves us from having to manage a completely separate type of thing. -- Props to iandoug for the idea! Also: -- Disable x2,y2,width2,height2 on decals -- Increase max keycap size to 18x18 (allows for really large decals)
This commit is contained in:
parent
64e610327e
commit
ad24eadc87
5 changed files with 54 additions and 28 deletions
7
kb.css
7
kb.css
|
|
@ -67,9 +67,12 @@ html, body {
|
|||
box-sizing: border-box;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
#keyboard .hover .keyborder { border-color: green !important; border-style: solid; }
|
||||
#keyboard .selected .keyborder { border-color: red !important; border-style: solid; }
|
||||
#keyboard .hover .keyborder, #keyboard .hover .decal .keyborder { border-color: green !important; border-style: solid; }
|
||||
#keyboard .selected .keyborder, #keyboard .selected .decal .keyborder { border-color: red !important; border-style: solid; }
|
||||
#keyboard .ghosted { opacity: 0.5; }
|
||||
#keyboard .decal .keyborder { border-style: none !important; background: transparent !important; }
|
||||
#keyboard .hover .decal .keyborder,
|
||||
#keyboard .selected .decal .keyborder { border-style: dashed !important; border-width: 1px; }
|
||||
|
||||
/* Key labels */
|
||||
.keylabel>div { display: table-cell; position: static !important; }
|
||||
|
|
|
|||
37
kb.html
37
kb.html
|
|
@ -371,9 +371,9 @@ Nav Bar / Header
|
|||
<div class="col-md-9 col-lg-9">
|
||||
<div class="form-inline hint--top hint--rounded"
|
||||
data-hint="Specify the primary and secondary widths for the keycap. The secondary width is used to specify the size of non-rectangular or stepped keys.">
|
||||
<kbd-multi-numbox field="width" size="6" min="0.5" max="12" step='{{sizeStep}}'></kbd-multi-numbox>
|
||||
<kbd-multi-numbox field="width" size="6" min="0.5" max="18" step='{{sizeStep}}'></kbd-multi-numbox>
|
||||
<div class="form-group form-group-sm"> / </div>
|
||||
<kbd-multi-numbox field="width2" size="6" min="0.5" max="12" step='{{sizeStep}}'></kbd-multi-numbox>
|
||||
<kbd-multi-numbox field="width2" size="6" min="0.5" max="18" step='{{sizeStep}}' kbd-disable="multi.decal"></kbd-multi-numbox>
|
||||
</div>
|
||||
|
||||
<!-- Swap Colors Button -->
|
||||
|
|
@ -397,9 +397,9 @@ Nav Bar / Header
|
|||
<div class="col-md-9 col-lg-9">
|
||||
<div class="form-inline hint--top hint--rounded"
|
||||
data-hint="Specify the primary and secondary heights for the keycap. The secondary height is used to specify the size of non-rectangular or stepped keys.">
|
||||
<kbd-multi-numbox field="height" size="6" min="0.5" max="12" step='{{sizeStep}}'></kbd-multi-numbox>
|
||||
<kbd-multi-numbox field="height" size="6" min="0.5" max="18" step='{{sizeStep}}'></kbd-multi-numbox>
|
||||
<div class="form-group form-group-sm"> / </div>
|
||||
<kbd-multi-numbox field="height2" size="6" min="0.5" max="12" step='{{sizeStep}}'></kbd-multi-numbox>
|
||||
<kbd-multi-numbox field="height2" size="6" min="0.5" max="18" step='{{sizeStep}}' kbd-disable="multi.decal"></kbd-multi-numbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -412,7 +412,7 @@ Nav Bar / Header
|
|||
data-hint="Specify the X position of the keycap. An X-offset can also be specified to indicate how non-rectangular keys should be displayed.">
|
||||
<kbd-multi-numbox field="x" size="6" min="0" max="36" step='{{moveStep}}'></kbd-multi-numbox>
|
||||
<div class="form-group form-group-sm"> + </div>
|
||||
<kbd-multi-numbox field="x2" size="6" min="-6" max="6" step='{{moveStep}}'></kbd-multi-numbox>
|
||||
<kbd-multi-numbox field="x2" size="6" min="-6" max="6" step='{{moveStep}}' kbd-disable="multi.decal"></kbd-multi-numbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -425,7 +425,7 @@ Nav Bar / Header
|
|||
data-hint="Specify the Y position of the keycap. A Y-offset can also be specified to indicate how non-rectangular keys should be displayed.">
|
||||
<kbd-multi-numbox field="y" size="6" min="0" max="36" step='{{moveStep}}'></kbd-multi-numbox>
|
||||
<div class="form-group form-group-sm"> + </div>
|
||||
<kbd-multi-numbox field="y2" size="6" min="-6" max="6" step='{{moveStep}}'></kbd-multi-numbox>
|
||||
<kbd-multi-numbox field="y2" size="6" min="-6" max="6" step='{{moveStep}}' kbd-disable="multi.decal"></kbd-multi-numbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -470,6 +470,7 @@ Nav Bar / Header
|
|||
<kbd-multi-check field="ghost" hint-text="Specify whether the selected keys should be rendered slightly transparently; this is useful to draw attention to the other, non-ghosted keycaps.">Ghosted</kbd-multi-check>
|
||||
<kbd-multi-check field="stepped" hint-text="Specify whether the selected keys are 'stepped', i.e., part of the key is at a lower height than the rest. The secondary 'width' indicates the width of the stepped part.">Stepped</kbd-multi-check>
|
||||
<kbd-multi-check field="nub" hint-text="Specifies that the selected keys are 'homing' keys, which help the user find the home-row by touch alone.">Homing</kbd-multi-check>
|
||||
<kbd-multi-check field="decal" hint-text="Specifies that the selected keys are to be treated as 'decals', i.e., purely decorative additions to the layout.">Decal</kbd-multi-check>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -918,7 +919,7 @@ Angular Templates
|
|||
ng-model="$parent.multi[field]"
|
||||
ng-change="$parent.updateMulti(field)"
|
||||
ng-blur="$parent.validateMulti(field)"
|
||||
ng-disabled="$parent.selectedKeys.length<1"
|
||||
ng-disabled="$parent.selectedKeys.length<1 || kbdDisable"
|
||||
style="max-width:80px">
|
||||
</div>
|
||||
</script>
|
||||
|
|
@ -962,20 +963,20 @@ DOT.js Templates
|
|||
|
||||
<!-- Keycap Template -->
|
||||
<script type="text/ng-template" id="keycap_html">
|
||||
<div class='{{=key.ghost ? "ghosted keycap" : "keycap"}}'
|
||||
<div class='{{=key.ghost ? "ghosted" : ""}} {{=key.decal ? "decal" : ""}} keycap'
|
||||
{{? key.rotation_angle }}
|
||||
style='transform:rotate({{=key.rotation_angle}}deg); transform-origin:{{=parms.origin_x}}px {{=parms.origin_y}}px;'
|
||||
{{?}}>
|
||||
|
||||
<div style="left: {{=parms.capx}}px; top: {{=parms.capy}}px;
|
||||
width: {{=parms.capwidth}}px; height: {{=parms.capheight}}px;
|
||||
border: solid {{=sizes.strokeWidth}}px black; border-radius: {{=sizes.roundOuter}}px;
|
||||
border-style: solid; border-width: {{=sizes.strokeWidth}}px; border-color: black; border-radius: {{=sizes.roundOuter}}px;
|
||||
background-color: {{=parms.darkColor}};"
|
||||
class="keyborder"></div>
|
||||
{{? parms.jShaped }}
|
||||
{{? parms.jShaped}}
|
||||
<div style="left: {{=parms.capx2}}px; top: {{=parms.capy2}}px;
|
||||
width: {{=parms.capwidth2}}px; height: {{=parms.capheight2}}px;
|
||||
border: solid {{=sizes.strokeWidth}}px black; border-radius: {{=sizes.roundOuter}}px;
|
||||
border-style: solid; border-width: {{=sizes.strokeWidth}}px; border-color: black; border-radius: {{=sizes.roundOuter}}px;
|
||||
background-color: {{=parms.darkColor}};"
|
||||
class="keyborder"></div>
|
||||
<div style="left: {{=parms.capx + sizes.strokeWidth}}px; top: {{=parms.capy + sizes.strokeWidth}}px;
|
||||
|
|
@ -985,17 +986,18 @@ DOT.js Templates
|
|||
border-radius: {{=sizes.roundOuter}}px;"></div>
|
||||
{{?}}
|
||||
|
||||
{{? !key.ghost }}
|
||||
{{? !key.ghost }}
|
||||
{{? !key.decal}}
|
||||
<div style="left: {{=parms.innercapx}}px; top: {{=parms.innercapy}}px;
|
||||
width: {{=parms.innercapwidth}}px; height: {{=parms.innercapheight}}px;
|
||||
border: solid {{=sizes.strokeWidth}}px rgba(0,0,0,0.1);
|
||||
border-style: solid; border-width: {{=sizes.strokeWidth}}px; border-color: rgba(0,0,0,0.1);
|
||||
background-color: {{=parms.lightColor}};
|
||||
border-radius: {{=sizes.roundInner}}px;"
|
||||
class="keytop"></div>
|
||||
{{? parms.jShaped && !key.stepped }}
|
||||
<div style="left: {{=parms.innercapx2}}px; top: {{=parms.innercapy2}}px;
|
||||
width: {{=parms.innercapwidth2}}px; height: {{=parms.innercapheight2}}px;
|
||||
border: solid {{=sizes.strokeWidth}}px rgba(0,0,0,0.1); border-radius: {{=sizes.roundInner}}px;
|
||||
border-style: solid; border-width: {{=sizes.strokeWidth}}px; border-color: rgba(0,0,0,0.1); border-radius: {{=sizes.roundInner}}px;
|
||||
background-color: {{=parms.lightColor}};
|
||||
background-position: {{=Math.min(parms.innercapx-parms.innercapx2,0)}}px {{=Math.min(parms.innercapy-parms.innercapy2,0)}}px;
|
||||
background-size: {{=Math.max(parms.innercapwidth,parms.innercapwidth2)}}px {{=Math.max(parms.innercapheight,parms.innercapheight2)}}px;"
|
||||
|
|
@ -1008,6 +1010,7 @@ DOT.js Templates
|
|||
background-size: {{=Math.max(parms.innercapwidth,parms.innercapwidth2)}}px {{=Math.max(parms.innercapheight,parms.innercapheight2)}}px;"
|
||||
class="keytop"></div>
|
||||
{{?}}
|
||||
{{?}} <!--!key.decal-->
|
||||
|
||||
<div style='left: {{=parms.innercapx}}px; top: {{=parms.innercapy}}px; width: {{=parms.innercapwidth}}px; height: {{=parms.innercapheight}}px; padding: {{=sizes.padding}}px;' class='keylabels'>
|
||||
{{~key.labels :label:i}}
|
||||
|
|
@ -1062,7 +1065,7 @@ DOT.js Templates
|
|||
<rect x="{{=parms.innercapx+sizes.strokeWidth}}" y="{{=parms.innercapy+sizes.strokeWidth}}"
|
||||
width="{{=parms.innercapwidth-sizes.strokeWidth*2}}" height="{{=parms.innercapheight-sizes.strokeWidth*2}}"
|
||||
rx="{{=sizes.roundOuter}}" fill="{{=parms.lightColor}}" class="inner border"/>
|
||||
{{? parms.jShaped && !key.stepped }}
|
||||
{{? parms.jShaped && !key.stepped && !key.decal}}
|
||||
<rect x="{{=parms.innercapx2+sizes.strokeWidth}}" y="{{=parms.innercapy2+sizes.strokeWidth}}"
|
||||
width="{{=parms.innercapwidth2-sizes.strokeWidth*2}}" height="{{=parms.innercapheight2-sizes.strokeWidth*2}}"
|
||||
rx="{{=sizes.roundOuter}}" fill="{{=parms.lightColor}}" class="inner border"/>
|
||||
|
|
@ -1071,14 +1074,14 @@ DOT.js Templates
|
|||
<rect x="{{=parms.innercapx+sizes.strokeWidth}}" y="{{=parms.innercapy+sizes.strokeWidth}}"
|
||||
width="{{=parms.innercapwidth-sizes.strokeWidth*2}}" height="{{=parms.innercapheight-sizes.strokeWidth*2}}"
|
||||
rx="{{=sizes.roundOuter}}" fill="{{=parms.lightColor}}"/>
|
||||
{{? parms.jShaped && !key.stepped }}
|
||||
{{? parms.jShaped && !key.stepped && !key.decal}}
|
||||
<rect x="{{=parms.innercapx2+sizes.strokeWidth}}" y="{{=parms.innercapy2+sizes.strokeWidth}}"
|
||||
width="{{=parms.innercapwidth2-sizes.strokeWidth*2}}" height="{{=parms.innercapheight2-sizes.strokeWidth*2}}"
|
||||
rx="{{=sizes.roundOuter}}" fill="{{=parms.lightColor}}"/>
|
||||
{{?}}
|
||||
{{? sizes.profile !== "" }}
|
||||
{{var theProfile = sizes.profile; if(/\b(SPACE)\b/.exec(key.profile)) theProfile = "SPACE";}}
|
||||
{{? parms.jShaped && !key.stepped }}
|
||||
{{? parms.jShaped && !key.stepped && !key.decal}}
|
||||
{{
|
||||
/*much harder to do j-shaped keys in SVG*/
|
||||
theProfile = '_fill'+parms.index;
|
||||
|
|
|
|||
11
kb.js
11
kb.js
|
|
@ -531,10 +531,10 @@
|
|||
y : function() { return Math.max(0, Math.min(36, value)); },
|
||||
x2 : function() { return Math.max(-Math.abs(key.width-key.width2), Math.min(Math.abs(key.width-key.width2), value)); },
|
||||
y2 : function() { return Math.max(-Math.abs(key.height-key.height2), Math.min(Math.abs(key.height-key.height2), value)); },
|
||||
width : function() { return Math.max(0.5, Math.min(12, value)); },
|
||||
height : function() { return Math.max(0.5, Math.min(12, value)); },
|
||||
width2 : function() { return Math.max(0.5, Math.min(12, value)); },
|
||||
height2 : function() { return Math.max(0.5, Math.min(12, value)); },
|
||||
width : function() { return Math.max(0.5, Math.min(18, value)); },
|
||||
height : function() { return Math.max(0.5, Math.min(18, value)); },
|
||||
width2 : function() { return Math.max(0.5, Math.min(18, value)); },
|
||||
height2 : function() { return Math.max(0.5, Math.min(18, value)); },
|
||||
textSize : function() { return Math.max(1, Math.min(9, value)); },
|
||||
rotation_angle : function() { return Math.max(-180, Math.min(180, value)); },
|
||||
rotation_x : function() { return Math.max(0, Math.min(36, value)); },
|
||||
|
|
@ -562,6 +562,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
decal : function() { key[prop] = value; key.x2 = key.y2 = 0; key.width2 = key.width; key.height2 = key.height; },
|
||||
rotation_angle : function() { key.rotation_angle = value; key.rotation_x = $scope.multi.rotation_x; key.rotation_y = $scope.multi.rotation_y; },
|
||||
};
|
||||
return (u[prop] || u._)();
|
||||
|
|
@ -1418,7 +1419,7 @@
|
|||
return { templateUrl: "multiCheck.html", restrict: "E", scope: { hintText: "@", field: "@" }, transclude: true };
|
||||
});
|
||||
kbApp.directive('kbdMultiNumbox', function() {
|
||||
return { templateUrl: "multiNumbox.html", restrict: "E", scope: { field: "@", size:"@", min:"@", max:"@", step:"@" } };
|
||||
return { templateUrl: "multiNumbox.html", restrict: "E", scope: { field: "@", size:"@", min:"@", max:"@", step:"@", kbdDisable: "=" } };
|
||||
});
|
||||
|
||||
// Runs a confirmation dialog asynchronously, using promises.
|
||||
|
|
|
|||
|
|
@ -13,7 +13,14 @@
|
|||
},
|
||||
[
|
||||
{
|
||||
"y": 0.38,
|
||||
"x": 23,
|
||||
"d": true
|
||||
},
|
||||
""
|
||||
],
|
||||
[
|
||||
{
|
||||
"y": -0.62,
|
||||
"x": 1.25,
|
||||
"c": "#857eb1",
|
||||
"f": 6
|
||||
|
|
@ -208,10 +215,19 @@
|
|||
},
|
||||
"\n⌶ ▮"
|
||||
],
|
||||
[
|
||||
{
|
||||
"x": 9.5,
|
||||
"w": 5,
|
||||
"h": 0.5,
|
||||
"d": true
|
||||
},
|
||||
""
|
||||
],
|
||||
[
|
||||
{
|
||||
"r": 15,
|
||||
"y": -8.530000000000001,
|
||||
"y": -9.530000000000001,
|
||||
"x": 3,
|
||||
"c": "#c7c3b4",
|
||||
"f": 3,
|
||||
|
|
|
|||
|
|
@ -105,7 +105,8 @@ var $serial = (typeof(exports) !== 'undefined') ? exports : {};
|
|||
rotation_angle: 0, rotation_x: 0, rotation_y: 0, // rotation
|
||||
labels:[], textColor: [], textSize: [], // label properties
|
||||
default: { textColor: "#000000", textSize: 3 }, // label defaults
|
||||
color: "#cccccc", profile: "", nub: false, ghost: false, stepped: false // cap appearance
|
||||
color: "#cccccc", profile: "", nub: false, // cap appearance
|
||||
ghost: false, stepped: false, decal: false
|
||||
};
|
||||
|
||||
var _defaultMetaData = { backcolor: '#eeeeee', name: '', author: '', notes: '', background: undefined, radii: '' };
|
||||
|
|
@ -257,6 +258,7 @@ var $serial = (typeof(exports) !== 'undefined') ? exports : {};
|
|||
serializeProp(props, "y2", key.y2, 0);
|
||||
serializeProp(props, "n", key.nub || false, false);
|
||||
serializeProp(props, "l", key.stepped || false, false);
|
||||
serializeProp(props, "d", key.decal || false, false);
|
||||
if(!isEmptyObject(props)) { row.push(props); }
|
||||
current.labels = ordered.labels;
|
||||
row.push(ordered.labels.join("\n").trimEnd());
|
||||
|
|
@ -316,7 +318,7 @@ var $serial = (typeof(exports) !== 'undefined') ? exports : {};
|
|||
current.x += current.width;
|
||||
current.width = current.height = 1;
|
||||
current.x2 = current.y2 = current.width2 = current.height2 = 0;
|
||||
current.nub = current.stepped = false;
|
||||
current.nub = current.stepped = current.decal = false;
|
||||
|
||||
} else {
|
||||
if(key.r != null) { if(k!=0) {deserializeError("'r' can only be used on the first key in a row", key);} current.rotation_angle = key.r; }
|
||||
|
|
@ -343,6 +345,7 @@ var $serial = (typeof(exports) !== 'undefined') ? exports : {};
|
|||
if(key.h2) { current.height2 = key.h2; }
|
||||
if(key.n) { current.nub = key.n; }
|
||||
if(key.l) { current.stepped = key.l; }
|
||||
if(key.d) { current.decal = key.d; }
|
||||
if(key.g != null) { current.ghost = key.g; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue