Table of Contents
Here is a customizable keypad class that lets you make keypads with any number of push-button keys in any arrangement, with whatever symbols you choose to assign to them. You can include a display line for entered text, and include special keys such as Shift, Clear, Delete, Enter, and so on, or define your own function keys.
The sample code loads and displays two example keypads, one a numeric keypad with English-language key labels, and the other alpha-numeric with French-language key labels. The definition files used to create the two keypads are shown in the Sample Keypad Definition Files section of this chapter. The source code of the Keypad class itself is given in The Keypad Class section.
#!/usr/cogent/bin/phgamma require_lisp("PhotonWidgets"); require_lisp("const/Filesys.lsp"); require ("keypad.g"); require ("utility.g"); PtInit(nil); window = new(PtWindow); window.SetDim (700,380); window.fill_color = PgRGB (250,200,180); class USnumberKeypad Keypad { } method USnumberKeypad.init(parent) { .LoadDefinition("number_en_US.kdef", parent); .BlockAllWindows(t); } class FRalphaKeypad Keypad { } method FRalphaKeypad.init(parent) { .LoadDefinition("alpha_fr_FR.kdef", parent); .BlockAllWindows(t); } PtSetParentWidget(window); kp1 = new(USnumberKeypad); kp1.init(window); PtSetParentWidget(window); kp2 = new(FRalphaKeypad); kp2.init(window); kp2.SetPos(375,90); PtRealizeWidget(window); PtMainLoop();
/* * Keypad definition file for English Numeric keypad */ SetGrid (30,30); GridOffset (0, 0); Font ("helv14b"); SetDim (9 * 30, 10 * 30 + .entryfield.dim.h + 4 * .entryfield.border_width); SetButtons (0, 0, 3, 2, "7", "8", "9"); SetButtons (0, 2, 3, 2, "4", "5", "6"); SetButtons (0, 4, 3, 2, "1", "2", "3"); SetButtons (0, 6, 3, 2, ".", "0"); SignButton (6, 6, 3, 2, "+/-"); DelButton (6, 8, 3, 2, "<--"); Font ("helv10b"); CancelButton(0, 8, 2, 2, "Cancel"); ClearButton (2, 8, 2, 2, "Clear"); EnterButton (4, 8, 2, 2, "Accept");
/* * Keypad definition file for French Alpha keypad */ SetGrid (15,15); GridOffset (0, 0); SetDim (20 * 15, 11 * 15 + .entryfield.dim.h + 4 * .entryfield.border_width); SetButtons (0, 0, 2, 2, "!", "@", "#", "$", "%", "^", "&", "*", "(", ")"); SetButtons (0, 2, 2, 2, "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"); SetButtons (0, 4, 2, 2, "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"); SetButtons (0, 6, 2, 2, "A", "S", "D", "F", "G", "H", "J", "K", "L", "."); SetButtons (1, 8, 2, 2, "Z", "X", "C", "V", "B", "N", "M", "-", "_"); GridOffset (0, 0); CancelButton (0, 11, 5, 2, "Cancelez"); ShiftButton (5, 11, 5, 2, "Shiftez"); DelButton (10, 11, 5, 2, "<--"); EnterButton (15, 11, 5, 2, "Acceptez"); SpaceButton (6, 13, 8, 2, "La Space");
/* * Create a Keypad based on a definition file. We should be able to * handle multiple languages, not necessarily at runtime, but certainly * as part of the startup configuration. * * Todo: * 1) options for: * - no titlebar * - colors, so they are not hardcoded * - block all windows? * * Revision 1.5 1999/05/17 18:36:46 manuel * Minor fixes: missing/unused locals; change local var names (max -> max_val). * * Revision 1.4 1999/04/23 19:02:57 manuel * Changed argument/variable name max to max_val to avoid conflist with * the max function; also min -> min_val * * Revision 1.3 1999/02/01 16:36:47 sam * Keypad definitions are now loaded from the require_path, and the numeric * keypad has a "+/-" key. * * Revision 1.2 1999/01/11 22:42:10 sam * Switches now bring up a digital keypad. * * Revision 1.1 1999/01/09 02:13:51 sam * the slider templates now pop up a keypad to enter a number into * */ //require ("constants.g"); require_lisp ("Modal.lsp"); require_lisp ("PhotonWidgets.lsp"); /* ---------------------- KeypadButton Class ------------------------ */ class KeypadButton PtButton { } method KeypadButton.constructor () { .fill_color = 0xaaaaff; .color = 0xffffff; .arm_fill = 1; .arm_color = 0x5555cc; .flags = cons (Pt_FOCUS_RENDER, nil); .SetDim (50,50); .highlight_roundness = 2; } /* ---------------------- KeypadText Class ------------------------ */ class KeypadText PtText { entered_string; password_char; } method KeypadText.AddChars (str) { if (! .password_char) { .text_string = string (.text_string, str); .cursor_position = strlen (.text_string); } else { .entered_string = string (.entered_string, str); .cursor_position = strlen (.text_string); .text_string = string(.text_string, substr("*******************", 0,strlen(str))); } } method KeypadText.constructor () { // .fill_color = 0xffffff; .highlight_roundness = 0; .text_font = "helv18"; // .top_border_color = TOPBORDER; // .bot_border_color = BOTBORDER; .border_width = 4; .flags = Pt_ETCH_HIGHLIGHT | Pt_HIGHLIGHTED; .flags = cons (Pt_SET, nil); .text_flags = cons ( Pt_CURSOR_VISIBLE | Pt_EDITABLE | Pt_CHANGE_ACTIVATE, nil); .horizontal_alignment = Pt_RIGHT; } /* ------------------------ Keypad Class --------------------------- */ class Keypad { window; entryfield; grid; gridoffset; shifted; blockwindows; blockallwindows; finished; buttonfont = "helv10b"; isnumeric; max; min; range; } method Keypad.CreateButton (x, y, w, h, str) { local but; but = new (KeypadButton); but.SetPos (x * .grid.w + .gridoffset.x, y * .grid.h + .gridoffset.y); but.SetDim (w * .grid.w - 2 * but.border_width, h * .grid.h - 2 * but.border_width); but.text_string = str; but.text_font = .buttonfont; PtRealizeWidget (but); but; } method Keypad.Initialize() { .window = new (PtWindow); .window.fill_color = 0xaadddd; // .window.flags = Pt_DELAY_REALIZE; .window.render_flags = cons(Ph_WM_RENDER_TITLE, nil); .entryfield = new (KeypadText); PtExtentWidget (.entryfield); } method Keypad.OutOfRangeMessage (msg_string) { local val; val = .entryfield.text_string; .entryfield.text_string = msg_string; PtFlush(); nanosleep(1,0); .entryfield.text_string = val; } /* ---------------------- Definition File Functions ---------------- */ /* * Functions callable through the definition file: * SetButton (x, y, w, h, str); * SetButtons (x, y, w, h, str ...); * SetExclButton (x, y, w, h, str); * SetExclButtons (x, y, w, h, str ...); * CancelButton (x, y, w, h, str); * ShiftButton (x, y, w, h, str); * SpaceButton (x, y, w, h, str); * DelButton (x, y, w, h, str); * EnterButton (x, y, w, h, str); * SetGrid (w, h); * GridOffset (x, y); * SetDim (w, h); * SetPos (w, h); */ method Keypad.SetDim (w, h) { .window.SetDim (w, h); .entryfield.SetArea (0, 0, w - 4 * .entryfield.border_width, 24); } method Keypad.SetPos (x, y) { .window.SetPos (x, y); } CLICK_EVENT = Pt_CB_ACTIVATE; method Keypad.SetButton (x, y, w, h, str, exclusive ?= nil) { local but = .CreateButton (x, y, w, h, str); PtAttachCallback (but, CLICK_EVENT, `(@self).ButtonPress(@but, @exclusive)); but; } method Keypad.SetExclButton (x, y, w, h, str) { .SetButton(x, y, w, h, str, t); } method Keypad.SetButtons (x, y, w, h, strings...) { local str, but; with str in strings do { but = .SetButton (x, y, w, h, str); x += w; } } method Keypad.SetExclButtons (x, y, w, h, strings...) { local str, but; with str in strings do { but = .SetExclButton (x, y, w, h, str); x += w; } } method Keypad.CancelButton (x, y, w, h, str) { local but = .CreateButton (x, y, w, h, str); PtAttachCallback (but, CLICK_EVENT, `(@self).Cancel ()); but; } method Keypad.NewlineButton (x, y, w, h, str) { local but = .CreateButton (x, y, w, h, str); PtAttachCallback (but, CLICK_EVENT, `(@self).Newline ()); but; } method Keypad.ClearButton (x, y, w, h, str) { local but = .CreateButton (x, y, w, h, str); PtAttachCallback (but, CLICK_EVENT, `(@self).Clear ()); but; } method Keypad.ShiftButton (x, y, w, h, str) { local but = .CreateButton (x, y, w, h, str); but.flags = Pt_TOGGLE; PtAttachCallback (but, CLICK_EVENT, `(@self).Shift ()); but; } method Keypad.SpaceButton (x, y, w, h, str) { local but = .CreateButton (x, y, w, h, str); PtAttachCallback (but, CLICK_EVENT, `(@self).Space ()); but; } method Keypad.DelButton (x, y, w, h, str) { local but = .CreateButton (x, y, w, h, str); PtAttachCallback (but, CLICK_EVENT, `(@self).Backspace ()); // PtAttachCallback (but, REPEAT_EVENT, `(@self).Backspace ()); but; } method Keypad.EnterButton (x, y, w, h, str) { local but = .CreateButton (x, y, w, h, str); PtAttachCallback (but, CLICK_EVENT, `(@self).Accept ()); but; } method Keypad.SignButton (x, y, w, h, str) { local but = .CreateButton (x, y, w, h, str); PtAttachCallback (but, CLICK_EVENT, `(@self).ChangeSign ()); but; } method Keypad.SetGrid (w, h) { .grid = new (PhDim); .grid.w = w; .grid.h = h; } method Keypad.GridOffset (x, y) { .gridoffset = new (PhPoint); .gridoffset.x = x; .gridoffset.y = y + .entryfield.dim.h + 4 * .entryfield.border_width; } method Keypad.Font (font) { .buttonfont = font; } /* ----------------------------- Callbacks ---------------------------- */ method Keypad.ButtonPress (button, exclusive ?= nil) { local str = button.text_string; if (.shifted) str = toupper (str); else str = tolower (str); if(exclusive) .Clear(); .entryfield.AddChars (str); } method Keypad.Space () { .entryfield.AddChars (" "); } method Keypad.Newline () { .entryfield.AddChars ("\n"); } method Keypad.Backspace () { local str = .entryfield.text_string; .entryfield.text_string = substr (str, 0, strlen(str) - 1); if (.entryfield.password_char) { str = .entryfield.entered_string; .entryfield.entered_string = substr (str, 0, strlen(str) - 1); } .entryfield.AddChars (""); } method Keypad.Shift () { local str = .entryfield.text_string; .shifted = !.shifted; if (.shifted) widget.flags = Pt_SET; else widget.flags = cons (Pt_SET,nil); } method Keypad.Accept () { local num; if (.isnumeric) { if (.max && .min) { num = number(.entryfield.text_string); if (num >= .min && num <= .max) .finished = #Accepted; else .OutOfRangeMessage(string("Valid Range: ", .min,"-",.max)); } } else { if (.range) { if (strlen(.entryfield.text_string) > .range) { .OutOfRangeMessage(string("Too long: ", .range, " chars max")); } else { .finished = #Accepted; } } else { .finished = #Accepted; } } } method Keypad.Cancel () { .finished = #Cancelled; } method Keypad.Clear () { .entryfield.text_string = ""; .entryfield.AddChars (""); } method Keypad.ChangeSign() { local text = .entryfield.text_string; if(!text) text = ""; .Clear(); local lead = substr(text, 0, 1); if(lead == "-") { text = substr(text, 1, -1); if(!text) text = ""; } else if(lead == "+") { text = substr(text, 1, -1); if(!text) text = ""; text = string("-", text); } else { // assume positive text = string("-", text); } .entryfield.AddChars(text); } /* -------------- Initialization and Control -------------------- */ method Keypad.LoadDefinition (filename, parent, path ?= "") { local fptr, line, code; if (fptr = open(string(path, filename), "r", t)) { PtSetParentWidget(parent); .Initialize (); PtSetParentWidget (.window); while ((line = read (fptr)) != _eof_) { /* Quote the method name */ rplaca (line, list (#quote, car(line))); code = `call (@self, @@line); eval (code); } close (fptr); } else { error(string("Keypad failed to load ", path, filename, "!")); } } method Keypad.RemoveTitle () { .window.render_flags = cons(Ph_WM_RENDER_TITLE | Ph_WM_RENDER_RESIZE,nil); } method Keypad.ForceFront ( flag ) { if (flag) .window.state = Ph_WM_STATE_ISFRONT; else .window.state = Ph_WM_STATE_NORMAL; } method Keypad.Show () { .entryfield.text_string = ""; PtRealizeWidget (.window); PtWidgetToFront(.window); } method Keypad.Hide () { PtUnrealizeWidget (.window); } method Keypad.BlockWindows (winlist) { local return = .blockwindows; .blockwindows = winlist; return; } method Keypad.BlockAllWindows (flag) { local return = .blockallwindows; .blockallwindows = flag; return; } method Keypad.SetPasswordChar ( character ) { .entryfield.password_char = character; } method Keypad.SetNumeric ( ) { .isnumeric = t; } method Keypad.ClearNumeric () { .isnumeric = nil; } method Keypad.SetRange (min_val, max_val) { .min = min_val; .max = max_val; } method Keypad.ClearRange () { .min = .max = nil; } method Keypad.Input (defaultstr) { local i, win; if(.blockallwindows) { with i in _photon_widgets_ do if(i != .window && class_of(i) == PtWindow) .blockwindows = cons(i, .blockwindows); } .Show(); .entryfield.text_string = defaultstr; .entryfield.entered_string = ""; .finished = nil; PtSetParentWidget (nil); with win in .blockwindows do win.flags = Pt_BLOCKED; modal (nil, #.finished); with win in .blockwindows do win.flags = cons (Pt_BLOCKED,nil); .Hide(); if (.finished == #Accepted) .entryfield.text_string; else nil; } method Keypad.NumericInput (defaultval, min_val, max_val) { // princ("call Keypad.NumericInput()\n"); local ret_val; .SetNumeric(); .SetRange(min_val,max_val); ret_val = .Input(defaultval ? string(defaultval) : ""); .ClearRange(); .ClearNumeric(); // princ("result: ", ret_val, "\n"); if (ret_val) { if(strlen(ret_val) > 0) number(ret_val); else nil; } else { nil; } } method Keypad.PasswordInput () { local ret_val, inval; .SetPasswordChar("*"); .entryfield.entered_string = ""; inval = .Input(""); .SetPasswordChar(nil); if (inval) ret_val = .entryfield.entered_string; ret_val; }
Copyright © 1995-2010 by Cogent Real-Time Systems, Inc. All rights reserved.