Skip to content

Commit dc24faa

Browse files
authored
Merge pull request espruino#4197 from RKBoss6/color-picker
Create colorpicker module
2 parents 7e6e0dc + 6be4013 commit dc24faa

2 files changed

Lines changed: 156 additions & 0 deletions

File tree

modules/colorpicker.js

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
exports.show = function(options) {
2+
var colors;
3+
var isPicking=true;
4+
var previewTimeout;
5+
if (!options.colors||options.colors.length==0) {
6+
colors = [
7+
"#000000", "#808080", "#AAAAAA", "#FFFFFF",
8+
"#FF9999", "#FFCC99", "#FFFF99", "#99FF99", "#99FFFF", "#9999FF", "#FF99FF",
9+
"#FF0000", "#FF8800", "#FFFF00", "#00FF00", "#00FFFF", "#0000FF", "#FF00FF",
10+
"#880000", "#884400", "#888800", "#008800", "#008888", "#000088", "#880088"
11+
];
12+
} else {
13+
colors = options.colors;
14+
}
15+
if(colors.length>36) throw new Error("More than 36 colors provided, cannot display");
16+
17+
if(!options.onSelect) throw new Error("No onSelect function provided");
18+
if(!options.back) throw new Error("No back function provided");
19+
20+
var rect = Bangle.appRect;
21+
var W = rect.w;
22+
var H = rect.h;
23+
var n = colors.length;
24+
var COLS = Math.round(Math.sqrt(n));
25+
var ROWS = Math.ceil(n / COLS);
26+
var CW = (W / COLS) | 0;
27+
var CH = (H / ROWS) | 0;
28+
var selectedColors=options.startingSelection?options.startingSelection:[];
29+
var insetX = (CW * 0.15) | 0;
30+
var insetY = (CH * 0.15) | 0;
31+
function draw() {
32+
g.clearRect(rect);
33+
for (var i = 0; i < n; i++) {
34+
var col = i % COLS;
35+
var row = (i / COLS) | 0;
36+
var x = rect.x + col * CW;
37+
var y = rect.y + row * CH;
38+
var oldCH=CH;
39+
var oldCW=CW;
40+
if(options.multiSelect){
41+
if(selectedColors.includes(colors[i])){
42+
x += insetX;
43+
y += insetY;
44+
CW -= insetX * 2;
45+
CH -= insetY * 2;
46+
}
47+
}
48+
g.setColor(colors[i])
49+
.fillRect(x + 1, y + 1, x + CW - 1, y + CH - 1)
50+
.setColor(g.theme.fg)
51+
.drawRect(x, y, x + CW, y + CH);
52+
CH=oldCH;
53+
CW=oldCW;
54+
}
55+
56+
}
57+
58+
function colorAt(x, y) {
59+
if(y<rect.y)return null;
60+
var col = ((x - rect.x) / CW) | 0;
61+
var row = ((y - rect.y) / CH) | 0;
62+
var i = row * COLS + col;
63+
if (i < 0 || i >= n) return null;
64+
return colors[i];
65+
}
66+
67+
function remove() {
68+
if(previewTimeout){
69+
clearTimeout(previewTimeout);
70+
previewTimeout=null;
71+
}
72+
options.back();
73+
}
74+
75+
function onTouch(btn, xy) {
76+
if(isPicking){
77+
var col = colorAt(xy.x, xy.y);
78+
if (!col) return;
79+
if(!options.multiSelect){
80+
isPicking=false;
81+
if(Bangle.haptic) Bangle.haptic();
82+
options.onSelect(col);
83+
if (options.showPreview === undefined || options.showPreview) {
84+
g.setColor(col)
85+
.fillRect(rect);
86+
if(previewTimeout){
87+
clearTimeout(previewTimeout);
88+
previewTimeout=null;
89+
}
90+
previewTimeout=setTimeout(remove, 0.7 * 1000);
91+
} else {
92+
remove();
93+
}
94+
}else{
95+
if(Bangle.haptic) Bangle.haptic();
96+
if(selectedColors.includes(col)){
97+
//unselect
98+
selectedColors=selectedColors.filter(color => color !== col);
99+
}else{
100+
selectedColors.push(col)
101+
}
102+
options.onSelect(selectedColors);
103+
draw()
104+
}
105+
}
106+
}
107+
108+
Bangle.setUI({
109+
mode: "custom",
110+
touch: function(n, e) { onTouch(n, e); },
111+
btn: function(n) { remove(); },
112+
back: remove,
113+
remove: remove,
114+
redraw: draw
115+
});
116+
117+
draw();
118+
};

modules/colorpicker.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Color Picker
2+
A module for showing a color picker for easy picking and setting of colors.
3+
4+
<img width="176" height="176" alt="d" src="https://github.com/user-attachments/assets/1fbde2f8-e25a-4a9b-9ce8-40803ae14adb" />
5+
6+
## Usage
7+
Example usage:
8+
```javascript
9+
var menu={
10+
"Color Picker" : function(){
11+
require("colorpicker").show({
12+
onSelect:function(color){
13+
print(color);
14+
},
15+
showPreview:true,
16+
back:function(){
17+
E.showMenu(menu);
18+
}
19+
20+
});
21+
}
22+
}
23+
E.showMenu(menu);
24+
25+
```
26+
<b>Options:</b>
27+
28+
`require("colorpicker").show(opts)` takes in an object of options, listed below:
29+
* `colors`: (Optional), specify a select list of colors to show instead of the default. Must not exceed 36 colors.
30+
* `showPreview`: (Optional), choose whether or not to show a full-screen preview of the color you selected.
31+
* `onSelect`: (Required), function that is called whenever the user changes the selection (selects or unselects a color). Saving logic goes here. In multi-select mode, this is called on every toggle and is passed the current list of selected colors.
32+
* `back`: (Required), function that is called to return to previous state. Color picker listeners are automatically removed.
33+
* `multiSelect` (Optional), if true, then the color picker allows the user to select multiple colors and returns a list of colors in `onSelect`
34+
* `startingSelection` (Optional, only for multi-select mode), array of colors selected at the start, for setting restoration.
35+
36+
## Author
37+
RKBoss6
38+

0 commit comments

Comments
 (0)