; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; File: calculator.lsp ; RCS: $Header: /users/npm/src/widgit/examples/RCS/calculator.lsp,v 2.7 1994/06/06 14:43:21 npm Exp npm $ ; Description: A simple calculator. The layout on this example leaves ; much to be desired. Shows a use of widget subclassing. ; Just load this file to bring up application. ; Author: Niels Mayer ; Created: Wed Jun 27 23:39:09 1990 ; Modified: Sat May 27 00:57:36 1995 (Niels Mayer) npm@indeed ; Language: Lisp ; Package: N/A ; Status: X11r6 contrib release ; ; Copyright (C) 1994, Enterprise Integration Technologies Corp. and Niels Mayer. ; WINTERP 1.15-1.99, Copyright (c) 1993, Niels P. Mayer. ; WINTERP 1.0-1.14, Copyright (c) 1989-1992 Hewlett-Packard Co. and Niels Mayer. ; ; Permission to use, copy, modify, distribute, and sell this software and its ; documentation for any purpose is hereby granted without fee, provided that ; the above copyright notice appear in all copies and that both that ; copyright notice and this permission notice appear in supporting ; documentation, and that the name of Enterprise Integration Technologies, ; Hewlett-Packard Company, or Niels Mayer not be used in advertising or ; publicity pertaining to distribution of the software without specific, ; written prior permission. Enterprise Integration Technologies, Hewlett-Packard ; Company, and Niels Mayer makes no representations about the suitability of ; this software for any purpose. It is provided "as is" without express or ; implied warranty. ; ; ENTERPRISE INTEGRATION TECHNOLOGIES, HEWLETT-PACKARD COMPANY AND NIELS MAYER ; DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED ; WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ENTERPRISE ; INTEGRATION TECHNOLOGIES, HEWLETT-PACKARD COMPANY OR NIELS MAYER BE LIABLE ; FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ; RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF ; CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ; CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (require "lib-utils/initialize") ;define :set-pname, etc. (setq top_w (send TOP_LEVEL_SHELL_WIDGET_CLASS :new "calc_shell" :XMN_TITLE "WINTERP: Calculator" :XMN_ICON_NAME "W:calcultator" )) (setq paned_w (send XM_PANED_WINDOW_WIDGET_CLASS :new :managed "pane" top_w )) ;============================================================================== ;============================== The display object============================= ;============================================================================== ;; make a subclass of XM_TEXT_WIDGET_CLASS (setq *calc_display_class* (send Class :new '(cursor_pos positive_p ins_mode_p begin_numentry_p accumulator prev_operator_symbol ) '() ;no class variables for subclass XM_TEXT_WIDGET_CLASS)) (send *calc_display_class* :set-pname "*CALC_DISPLAY_CLASS*") ;; override XM_TEXT_WIDGET_CLASS's instance initializer (send *calc_display_class* :answer :isnew '(init-value managed_k widget_name widget_parent &rest args) '( (setq cursor_pos 0) (setq positive_p t) (setq ins_mode_p t) (setq begin_numentry_p nil) (setq accumulator 0.0) (setq prev_operator_symbol nil) ;; create 'self', an instance of XM_TEXT_WIDGET_CLASS (apply #'send-super :isnew ;call superclass's init to create widget managed_k widget_name widget_parent :XMN_STRING "" :XMN_EDIT_MODE :single_line_edit :XMN_AUTO_SHOW_CURSOR_POSITION t :XMN_CURSOR_POSITION cursor_pos :XMN_EDITABLE nil args) ;splice in method arguments passed in above )) (send *calc_display_class* :answer :enter_keystroke '(key_str) '( (cond (begin_numentry_p (send self :clear) (setq begin_numentry_p nil) ) ) (cond (ins_mode_p (send self :REPLACE cursor_pos cursor_pos key_str) (setq cursor_pos (1+ cursor_pos)) (send self :SET_INSERTION_POSITION cursor_pos) ) (t (send self :REPLACE cursor_pos (1+ cursor_pos) key_str) )) ) ) (send *calc_display_class* :answer :change_sign '() '( (cond (positive_p (send self :REPLACE 0 0 "-") (setq cursor_pos (1+ cursor_pos)) (send self :SET_INSERTION_POSITION cursor_pos) (setq positive_p nil) ) (t (send self :REPLACE 0 1 "") (setq cursor_pos (1- cursor_pos)) (send self :SET_INSERTION_POSITION cursor_pos) (setq positive_p t) ))) ) (send *calc_display_class* :answer :clear '() '( (setq cursor_pos 0) (setq positive_p t) (setq ins_mode_p t) (send self :set_values :XMN_STRING "" :XMN_CURSOR_POSITION cursor_pos ) )) (send *calc_display_class* :answer :exec_unary_operator '(operator_symbol) '( (send self :set_accumulator_and_display (funcall operator_symbol (send self :get_display_as_flonum))) (setq prev_operator_symbol nil) )) (send *calc_display_class* :answer :exec_binary_operator '(operator_symbol) '( (if prev_operator_symbol (send self :set_accumulator_and_display (funcall prev_operator_symbol (send self :get_accumulator) (send self :get_display_as_flonum))) (send self :set_accumulator_and_display (send self :get_display_as_flonum)) ) (setq prev_operator_symbol operator_symbol) )) ;; sets the accumulator to result_flonum, and displays that. ;; sets begin_numentry_p to true so that upon numentry, display is cleared ;; and new number input. (send *calc_display_class* :answer :set_accumulator_and_display '(result_flonum) '( (setq accumulator result_flonum) (setq cursor_pos 0) (setq positive_p (not (minusp result_flonum))) (setq ins_mode_p t) (setq begin_numentry_p t) (send self :set_values :XMN_STRING (format NIL "~A" result_flonum) :XMN_CURSOR_POSITION cursor_pos ) )) (send *calc_display_class* :answer :get_accumulator '() '( accumulator )) (send *calc_display_class* :answer :get_display_as_flonum '() '( (float (read (make-string-input-stream (send self :get_string)))) )) (setq *calc_display* (send *calc_display_class* :new 0 :managed "disp" paned_w )) ;============================================================================== ;========================= The Numberpad ====================================== ;============================================================================== (defun make-number-button (parent_widget name) (send (send XM_PUSH_BUTTON_GADGET_CLASS :new :managed name parent_widget ;;; :XMN_FOREGROUND "Yellow" ;;; :XMN_BACKGROUND "DimGrey" ) :add_callback :xmn_activate_callback '() `( (send *calc_display* :enter_keystroke ,name) ) )) (defun make-chs-button (parent_widget name) (send (send XM_PUSH_BUTTON_GADGET_CLASS :new :managed name parent_widget ;;; :XMN_FOREGROUND "DimGrey" ;;; :XMN_BACKGROUND "Yellow" ) :add_callback :xmn_activate_callback '() `( (send *calc_display* :change_sign) ) )) (setq numpad_w (send XM_ROW_COLUMN_WIDGET_CLASS :new :managed "numbers" paned_w :XMN_ORIENTATION :vertical :XMN_PACKING :pack_column :XMN_NUM_COLUMNS 3 :XMN_ADJUST_LAST nil :XMN_ENTRY_ALIGNMENT :alignment_center )) (make-number-button numpad_w "7") (make-number-button numpad_w "4") (make-number-button numpad_w "1") (make-chs-button numpad_w "+/-") (make-number-button numpad_w "8") (make-number-button numpad_w "5") (make-number-button numpad_w "2") (make-number-button numpad_w "0") (make-number-button numpad_w "9") (make-number-button numpad_w "6") (make-number-button numpad_w "3") (make-number-button numpad_w ".") ;============================================================================== ;========================= Function Keys ====================================== ;============================================================================== (setq funcpad_w (send XM_ROW_COLUMN_WIDGET_CLASS :new :managed "functions" paned_w :XMN_ORIENTATION :vertical :XMN_PACKING :pack_column :XMN_NUM_COLUMNS 3 :XMN_ADJUST_LAST nil :XMN_ENTRY_ALIGNMENT :alignment_center )) (defun make-unary-operator (parent_widget operator_symbol name) (send (send XM_PUSH_BUTTON_GADGET_CLASS :new :managed name parent_widget ;;; :XMN_FOREGROUND "White" ;;; :XMN_BACKGROUND "Blue" ) :add_callback :xmn_activate_callback '() `( (send *calc_display* :exec_unary_operator operator_symbol) ) )) (defun make-binary-operator (parent_widget operator_symbol name) (send (send XM_PUSH_BUTTON_GADGET_CLASS :new :managed name parent_widget ;;; :XMN_FOREGROUND "White" ;;; :XMN_BACKGROUND "Blue" ) :add_callback :xmn_activate_callback '() `( (send *calc_display* :exec_binary_operator operator_symbol) ) )) (make-binary-operator funcpad_w #'/ "/") (make-binary-operator funcpad_w #'* "*") (make-binary-operator funcpad_w #'- "-") (make-binary-operator funcpad_w #'+ "+") (make-binary-operator funcpad_w #'expt "x^y") (make-binary-operator funcpad_w NIL "=" ) ; NOTE: = is a special NO-OP (make-unary-operator funcpad_w #'sin "Sin") (make-unary-operator funcpad_w #'cos "Cos") (make-unary-operator funcpad_w #'tan "Tan") (make-unary-operator funcpad_w #'asin "ArcSin") (make-unary-operator funcpad_w #'acos "ArcCos") (make-unary-operator funcpad_w #'atan "ArcTan") (make-unary-operator funcpad_w #'exp "Exp") (make-unary-operator funcpad_w #'sqrt "Sqrt") (send (send XM_PUSH_BUTTON_GADGET_CLASS :new :managed "Clear" funcpad_w ;;; :XMN_FOREGROUND "White" ;;; :XMN_BACKGROUND "Blue" ) :add_callback :xmn_activate_callback '() `( (send *calc_display* :set_accumulator_and_display 0) ) ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (send top_w :realize) ;(let (height) ; (send controlpanel_w :get_values :xmn_height 'height) ; (send controlpanel_w :set_values ; :xmn_maximum height ; :xmn_minimum height ; ) ; )