1
|
package org.distorted.sokoban;
|
2
|
|
3
|
import android.content.Context;
|
4
|
import android.content.res.Resources;
|
5
|
import android.graphics.Bitmap;
|
6
|
import android.graphics.BitmapFactory;
|
7
|
import android.graphics.Canvas;
|
8
|
import android.graphics.Paint;
|
9
|
import android.graphics.Paint.Align;
|
10
|
import android.graphics.Paint.Style;
|
11
|
import android.graphics.drawable.NinePatchDrawable;
|
12
|
|
13
|
import android.view.KeyEvent;
|
14
|
import android.view.MotionEvent;
|
15
|
import android.view.View;
|
16
|
|
17
|
//import android.util.Log;
|
18
|
|
19
|
////////////////////////////////////////////////////////////////////////////////
|
20
|
|
21
|
public class TouchKeyboard extends View
|
22
|
{
|
23
|
//private static final String TAG_KEYBOARD = "RubikKeyboard";
|
24
|
|
25
|
private static final int MARGIN = 2;
|
26
|
private static final int WMARGIN = 8;
|
27
|
private static final int BUTTON_NONE = -4;
|
28
|
private static final int BUTTON_OK = -3;
|
29
|
private static final int BUTTON_BKSP = -2;
|
30
|
private static final int BUTTON_CAPS = -1;
|
31
|
|
32
|
private int currPressed;
|
33
|
|
34
|
private TextFieldArea textField;
|
35
|
private Paint mPaint;
|
36
|
private NinePatchDrawable keyBlue, keyRed, keyWhite;
|
37
|
private Bitmap ok, bksp, caps;
|
38
|
|
39
|
private int bmpSize;
|
40
|
|
41
|
char[][] lowerCaseL =
|
42
|
{ {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'},
|
43
|
{'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r'},
|
44
|
{'s', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0'},
|
45
|
{'1', '2', '3', '4', '5', '6', '7', '8', '9'}
|
46
|
};
|
47
|
|
48
|
char[][] upperCaseL =
|
49
|
{ {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'},
|
50
|
{'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R'},
|
51
|
{'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0'},
|
52
|
{'1', '2', '3', '4', '5', '6', '7', '8', '9'}
|
53
|
};
|
54
|
|
55
|
char[][] lowerCaseP =
|
56
|
{ {'a', 'b', 'c', 'd', 'e', 'f'},
|
57
|
{'g', 'h', 'i', 'j', 'k', 'l'},
|
58
|
{'m', 'n', 'o', 'p', 'q', 'r'},
|
59
|
{'s', 't', 'u', 'v', 'w', 'x'},
|
60
|
{'y', 'z', '0', '1', '2', '3'},
|
61
|
{'4', '5', '6', '7', '8', '9'}
|
62
|
};
|
63
|
|
64
|
char[][] upperCaseP =
|
65
|
{ {'A', 'B', 'C', 'D', 'E', 'F'},
|
66
|
{'G', 'H', 'I', 'J', 'K', 'L'},
|
67
|
{'M', 'N', 'O', 'P', 'Q', 'R'},
|
68
|
{'S', 'T', 'U', 'V', 'W', 'X'},
|
69
|
{'Y', 'Z', '0', '1', '2', '3'},
|
70
|
{'4', '5', '6', '7', '8', '9'}
|
71
|
};
|
72
|
|
73
|
private int width, height;
|
74
|
|
75
|
private int textFieldWidth;
|
76
|
private int textFieldHeight;
|
77
|
private int textTopLeftX;
|
78
|
private int textTopLeftY;
|
79
|
private int keyWidth, keyHeight;
|
80
|
private int sKeyWidth, sKeyHeight;
|
81
|
|
82
|
private VirtualKeyboardListener invoker;
|
83
|
|
84
|
private int charH;
|
85
|
|
86
|
private int backgroundColor = 0xffffffff;
|
87
|
private int buttonsColor = 0xff000000;
|
88
|
|
89
|
private boolean uppercase;
|
90
|
private int minSize=0;
|
91
|
|
92
|
public interface VirtualKeyboardListener
|
93
|
{
|
94
|
void okPressed(String string);
|
95
|
}
|
96
|
|
97
|
////////////////////////////////////////////////////////////////////////////////
|
98
|
|
99
|
public TouchKeyboard(Context context, int scrWid, int scrHei)
|
100
|
{
|
101
|
super(context);
|
102
|
mPaint = new Paint();
|
103
|
mPaint.setAntiAlias(true);
|
104
|
|
105
|
currPressed = BUTTON_NONE;
|
106
|
width = scrWid;
|
107
|
height= scrHei;
|
108
|
|
109
|
Resources res = context.getResources();
|
110
|
|
111
|
keyBlue = (NinePatchDrawable)res.getDrawable(R.drawable.keys_blue);
|
112
|
keyRed = (NinePatchDrawable)res.getDrawable(R.drawable.keys_red);
|
113
|
keyWhite= (NinePatchDrawable)res.getDrawable(R.drawable.keys_white);
|
114
|
|
115
|
ok = BitmapFactory.decodeResource(res, R.drawable.ok );
|
116
|
bksp= BitmapFactory.decodeResource(res, R.drawable.bksp);
|
117
|
caps= BitmapFactory.decodeResource(res, R.drawable.caps);
|
118
|
|
119
|
if( width<=height )
|
120
|
{
|
121
|
sKeyWidth = width/3;
|
122
|
sKeyHeight= width/5;
|
123
|
keyWidth = width/6;
|
124
|
keyHeight = (height-2*sKeyHeight)/6;
|
125
|
|
126
|
textFieldHeight = height-sKeyHeight-6*keyHeight;
|
127
|
textFieldWidth = width;
|
128
|
textTopLeftX = 0;
|
129
|
textTopLeftY = sKeyHeight;
|
130
|
}
|
131
|
else
|
132
|
{
|
133
|
sKeyWidth = sKeyHeight = keyHeight = height/5;
|
134
|
keyWidth = (width+1)/9;
|
135
|
|
136
|
textFieldHeight= sKeyHeight;
|
137
|
textFieldWidth = width-3*sKeyWidth;
|
138
|
textTopLeftX = sKeyWidth;
|
139
|
textTopLeftY = 0;
|
140
|
}
|
141
|
|
142
|
bmpSize = ok.getHeight();
|
143
|
|
144
|
if( bmpSize> 0.8*sKeyHeight )
|
145
|
{
|
146
|
bmpSize = (int)(0.8*sKeyHeight);
|
147
|
ok = Bitmap.createScaledBitmap(ok , bmpSize, bmpSize, true);
|
148
|
bksp = Bitmap.createScaledBitmap(bksp, bmpSize, bmpSize, true);
|
149
|
caps = Bitmap.createScaledBitmap(caps, bmpSize, bmpSize, true);
|
150
|
}
|
151
|
|
152
|
textField = new TextFieldArea();
|
153
|
charH= (int)(keyHeight*0.7);
|
154
|
uppercase = true;
|
155
|
}
|
156
|
|
157
|
////////////////////////////////////////////////////////////////////////////////
|
158
|
|
159
|
public void resetKeyBoard()
|
160
|
{
|
161
|
textField.clearTextField();
|
162
|
invalidate();
|
163
|
}
|
164
|
|
165
|
////////////////////////////////////////////////////////////////////////////////
|
166
|
|
167
|
protected void onDraw(Canvas c)
|
168
|
{
|
169
|
mPaint.setColor(backgroundColor);
|
170
|
mPaint.setStyle(Style.FILL);
|
171
|
mPaint.setTextSize(charH);
|
172
|
mPaint.setTextAlign(Align.CENTER);
|
173
|
|
174
|
c.drawRect(0, 0, width, height, mPaint);
|
175
|
|
176
|
mPaint.setColor(buttonsColor);
|
177
|
|
178
|
textField.paint( c, textTopLeftX+1, textTopLeftY+MARGIN/2+1, textTopLeftX+textFieldWidth-1, textTopLeftY+textFieldHeight-MARGIN/2-1);
|
179
|
|
180
|
if( currPressed==BUTTON_OK )
|
181
|
{
|
182
|
keyRed.setBounds( MARGIN/2, MARGIN/2, sKeyWidth-MARGIN/2, sKeyHeight-MARGIN/2);
|
183
|
keyRed.draw(c);
|
184
|
}
|
185
|
else
|
186
|
{
|
187
|
keyBlue.setBounds( MARGIN/2, MARGIN/2,sKeyWidth-MARGIN/2, sKeyHeight-MARGIN/2);
|
188
|
keyBlue.draw(c);
|
189
|
}
|
190
|
|
191
|
if( currPressed==BUTTON_BKSP )
|
192
|
{
|
193
|
keyRed.setBounds( width-2*sKeyWidth+MARGIN/2, MARGIN/2, width-sKeyWidth-MARGIN/2,sKeyHeight-MARGIN/2);
|
194
|
keyRed.draw(c);
|
195
|
}
|
196
|
else
|
197
|
{
|
198
|
keyBlue.setBounds(width-2*sKeyWidth+MARGIN/2, MARGIN/2, width-sKeyWidth-MARGIN/2,sKeyHeight-MARGIN/2);
|
199
|
keyBlue.draw(c);
|
200
|
}
|
201
|
|
202
|
if( currPressed==BUTTON_CAPS )
|
203
|
{
|
204
|
keyRed.setBounds( width-sKeyWidth+MARGIN/2, MARGIN/2, width-MARGIN/2,sKeyHeight-MARGIN/2);
|
205
|
keyRed.draw(c);
|
206
|
}
|
207
|
else
|
208
|
{
|
209
|
keyBlue.setBounds(width-sKeyWidth+MARGIN/2, MARGIN/2, width-MARGIN/2,sKeyHeight-MARGIN/2);
|
210
|
keyBlue.draw(c);
|
211
|
}
|
212
|
|
213
|
c.drawBitmap(ok , MARGIN/2+sKeyWidth/2-bmpSize/2, MARGIN/2+sKeyHeight/2-bmpSize/2, mPaint);
|
214
|
c.drawBitmap(bksp, width-2*sKeyWidth+MARGIN/2+sKeyWidth/2-bmpSize/2, MARGIN/2+sKeyHeight/2-bmpSize/2, mPaint);
|
215
|
c.drawBitmap(caps, width- sKeyWidth+MARGIN/2+sKeyWidth/2-bmpSize/2, MARGIN/2+sKeyHeight/2-bmpSize/2, mPaint);
|
216
|
|
217
|
int hei = (width<=height ? textFieldHeight+sKeyHeight : textFieldHeight);
|
218
|
int numCol = (width<=height ? lowerCaseP[0].length : lowerCaseL[0].length);
|
219
|
int numRow = (width<=height ? lowerCaseP.length : lowerCaseL.length);
|
220
|
|
221
|
for(int j=0; j<numRow; j++)
|
222
|
{
|
223
|
for(int i=0; i<numCol; i++)
|
224
|
{
|
225
|
if( currPressed==j*numCol+i )
|
226
|
{
|
227
|
keyRed.setBounds( i*width/numCol+ MARGIN/2, hei+ MARGIN/2,
|
228
|
(i+1)*width/numCol- MARGIN/2, hei+ MARGIN/2 +keyHeight );
|
229
|
keyRed.draw(c);
|
230
|
keyWhite.setBounds(i*width/numCol+WMARGIN/2, hei+WMARGIN/2-keyHeight,
|
231
|
(i+1)*width/numCol-WMARGIN/2, hei-WMARGIN/2 );
|
232
|
keyWhite.draw(c);
|
233
|
|
234
|
if( width<=height )
|
235
|
c.drawText( uppercase? upperCaseP[j]:lowerCaseP[j], i,1,(float)(i*width/numCol+keyWidth/2),
|
236
|
(float)(hei-keyHeight/2+charH*0.4), mPaint);
|
237
|
else
|
238
|
c.drawText( uppercase? upperCaseL[j]:lowerCaseL[j], i,1,(float)(i*width/numCol+keyWidth/2),
|
239
|
(float)(hei-keyHeight/2+charH*0.4), mPaint);
|
240
|
}
|
241
|
else
|
242
|
{
|
243
|
keyBlue.setBounds( i*width/numCol+ MARGIN/2, hei+ MARGIN/2,
|
244
|
(i+1)*width/numCol- MARGIN/2, hei+ MARGIN/2 +keyHeight );
|
245
|
keyBlue.draw(c);
|
246
|
}
|
247
|
|
248
|
if( width<=height )
|
249
|
c.drawText( uppercase? upperCaseP[j]:lowerCaseP[j], i,1,(float)(i*width/numCol+keyWidth/2),
|
250
|
(float)(hei+keyHeight/2+charH*0.4), mPaint);
|
251
|
else
|
252
|
c.drawText( uppercase? upperCaseL[j]:lowerCaseL[j], i,1,(float)(i*width/numCol+keyWidth/2),
|
253
|
(float)(hei+keyHeight/2+charH*0.4), mPaint);
|
254
|
}
|
255
|
hei+=keyHeight;
|
256
|
}
|
257
|
}
|
258
|
|
259
|
///////////////////////////////////////////////////////////////////
|
260
|
|
261
|
public boolean onTouchEvent(MotionEvent event)
|
262
|
{
|
263
|
switch(event.getAction())
|
264
|
{
|
265
|
case MotionEvent.ACTION_DOWN: buttonPressed( (int)event.getX(), (int)event.getY() );
|
266
|
break;
|
267
|
case MotionEvent.ACTION_UP : buttonReleased();
|
268
|
break;
|
269
|
case MotionEvent.ACTION_MOVE: buttonPressed( (int)event.getX(), (int)event.getY() );
|
270
|
break;
|
271
|
}
|
272
|
|
273
|
invalidate();
|
274
|
return true;
|
275
|
}
|
276
|
|
277
|
////////////////////////////////////////////////////////////////////////////////
|
278
|
|
279
|
private void buttonPressed(int x, int y)
|
280
|
{
|
281
|
if( width<height )
|
282
|
{
|
283
|
if( y>=0 && y<sKeyHeight )
|
284
|
{
|
285
|
if( x<= sKeyWidth ) currPressed = BUTTON_OK;
|
286
|
else if( x<=2*sKeyWidth ) currPressed = BUTTON_BKSP;
|
287
|
else currPressed = BUTTON_CAPS;
|
288
|
}
|
289
|
else if( y>=sKeyHeight+textFieldHeight && y<=height )
|
290
|
{
|
291
|
currPressed = (int)((y-sKeyHeight-textFieldHeight)/keyHeight)*lowerCaseP[0].length + x/keyWidth;
|
292
|
}
|
293
|
}
|
294
|
else
|
295
|
{
|
296
|
if( y>=0 && y<textFieldHeight )
|
297
|
{
|
298
|
if( x<=sKeyWidth ) currPressed = BUTTON_OK;
|
299
|
else if( x>=width-2*sKeyWidth && x<=width-sKeyWidth ) currPressed = BUTTON_BKSP;
|
300
|
else if( x>=width- sKeyWidth && x<=width ) currPressed = BUTTON_CAPS;
|
301
|
else currPressed = BUTTON_NONE;
|
302
|
}
|
303
|
else if( y>=textFieldHeight && y<=height)
|
304
|
{
|
305
|
currPressed = (int)((y-textFieldHeight)/keyHeight)*lowerCaseL[0].length + x/keyWidth;
|
306
|
}
|
307
|
}
|
308
|
}
|
309
|
|
310
|
////////////////////////////////////////////////////////////////////////////////
|
311
|
|
312
|
private void buttonReleased()
|
313
|
{
|
314
|
if( currPressed==BUTTON_OK ) okButtonAction();
|
315
|
else if( currPressed==BUTTON_BKSP ) bkspButtonAction();
|
316
|
else if( currPressed==BUTTON_CAPS ) capsButtonAction();
|
317
|
else if( currPressed>=0 ) charAreaAction(currPressed);
|
318
|
|
319
|
currPressed = BUTTON_NONE;
|
320
|
}
|
321
|
|
322
|
////////////////////////////////////////////////////////////////////////////////
|
323
|
|
324
|
@Override public boolean onKeyDown(int keyCode, KeyEvent event)
|
325
|
{
|
326
|
if( currPressed!=BUTTON_NONE ) return false;
|
327
|
/*
|
328
|
switch( keyCode )
|
329
|
{
|
330
|
case Keypad.KEY_ALT :
|
331
|
case Keypad.KEY_SHIFT_RIGHT:
|
332
|
case Keypad.KEY_SHIFT_LEFT : currPressed= BUTTON_CAPS; invalidate(); break;
|
333
|
case Keypad.KEY_ENTER : currPressed= BUTTON_OK ; invalidate(); break;
|
334
|
case Keypad.KEY_DELETE :
|
335
|
case Keypad.KEY_BACKSPACE : currPressed= BUTTON_BKSP; invalidate(); break;
|
336
|
}
|
337
|
|
338
|
if( key>='A' && key<='Z' ) { currPressed = key-'A' ; invalidate(); }
|
339
|
if( key>='a' && key<='z' ) { currPressed = key-'a' ; invalidate(); }
|
340
|
if( key>='0' && key<='9' ) { currPressed = 'z'-'a'+1+key-'0'; invalidate(); }
|
341
|
*/
|
342
|
return true;
|
343
|
}
|
344
|
|
345
|
////////////////////////////////////////////////////////////////////////////////
|
346
|
|
347
|
@Override public boolean onKeyUp(int keyCode, KeyEvent event)
|
348
|
{
|
349
|
buttonReleased();
|
350
|
return true;
|
351
|
}
|
352
|
|
353
|
////////////////////////////////////////////////////////////////////////////////
|
354
|
|
355
|
private void capsButtonAction()
|
356
|
{
|
357
|
uppercase = !uppercase;
|
358
|
}
|
359
|
|
360
|
////////////////////////////////////////////////////////////////////////////////
|
361
|
|
362
|
private void okButtonAction()
|
363
|
{
|
364
|
if ( invoker != null )
|
365
|
{
|
366
|
String text = textField.getText();
|
367
|
|
368
|
if( text.length()>= minSize )
|
369
|
invoker.okPressed(text);
|
370
|
}
|
371
|
}
|
372
|
|
373
|
////////////////////////////////////////////////////////////////////////////////
|
374
|
|
375
|
private void bkspButtonAction()
|
376
|
{
|
377
|
textField.deleteLastChar();
|
378
|
}
|
379
|
|
380
|
////////////////////////////////////////////////////////////////////////////////
|
381
|
|
382
|
private void charAreaAction(int pressed)
|
383
|
{
|
384
|
int numCol = (width<height ? lowerCaseP[0].length:lowerCaseL[0].length);
|
385
|
int j = pressed/numCol;
|
386
|
int i = pressed%numCol;
|
387
|
|
388
|
if( width<height )
|
389
|
textField.insertNewChar( uppercase ? upperCaseP[j][i]:lowerCaseP[j][i]);
|
390
|
else
|
391
|
textField.insertNewChar( uppercase ? upperCaseL[j][i]:lowerCaseL[j][i]);
|
392
|
}
|
393
|
|
394
|
////////////////////////////////////////////////////////////////////////////////
|
395
|
|
396
|
public void setText(String text)
|
397
|
{
|
398
|
textField.setText( (text==null||text.length()==0)?"":text);
|
399
|
invalidate();
|
400
|
}
|
401
|
|
402
|
////////////////////////////////////////////////////////////////////////////////
|
403
|
|
404
|
public void setTextFieldBkgColor(int color)
|
405
|
{
|
406
|
textField.setTextFieldBkgColor(color);
|
407
|
}
|
408
|
|
409
|
////////////////////////////////////////////////////////////////////////////////
|
410
|
|
411
|
public void setTextFieldBorderColor(int color)
|
412
|
{
|
413
|
textField.setTextFieldBorderColor(color);
|
414
|
}
|
415
|
|
416
|
////////////////////////////////////////////////////////////////////////////////
|
417
|
|
418
|
public void setTextFieldFontColor(int color)
|
419
|
{
|
420
|
textField.setTextFieldFontColor(color);
|
421
|
}
|
422
|
|
423
|
////////////////////////////////////////////////////////////////////////////////
|
424
|
|
425
|
public int getBackgroundColor()
|
426
|
{
|
427
|
return backgroundColor;
|
428
|
}
|
429
|
|
430
|
////////////////////////////////////////////////////////////////////////////////
|
431
|
|
432
|
public void setBackgroundColor(int backgroundColor)
|
433
|
{
|
434
|
this.backgroundColor = backgroundColor;
|
435
|
}
|
436
|
|
437
|
////////////////////////////////////////////////////////////////////////////////
|
438
|
|
439
|
public void setMaxSize(int maxSize)
|
440
|
{
|
441
|
textField.setMaxSize(maxSize);
|
442
|
}
|
443
|
|
444
|
////////////////////////////////////////////////////////////////////////////////
|
445
|
|
446
|
public void setMinSize(int minSize)
|
447
|
{
|
448
|
this.minSize = minSize;
|
449
|
}
|
450
|
|
451
|
////////////////////////////////////////////////////////////////////////////////
|
452
|
|
453
|
public void setVirtualKeyboardListener(VirtualKeyboardListener invoker)
|
454
|
{
|
455
|
this.invoker = invoker;
|
456
|
}
|
457
|
////////////////////////////////////////////////////////////////////////////////
|
458
|
// end of TouchKeyboard
|
459
|
}
|