summaryrefslogtreecommitdiff
path: root/lib/bottompanel/calculator.tcl
diff options
context:
space:
mode:
authorAndrej Shadura <andrewsh@debian.org>2018-05-08 15:59:29 +0200
committerAndrej Shadura <andrewsh@debian.org>2018-05-08 15:59:29 +0200
commit5b8466f7fae0e071c0f4eda13051c93313910028 (patch)
tree7061957f770e5e245ba00666dad912a2d44e7fdc /lib/bottompanel/calculator.tcl
Import Upstream version 1.3.7
Diffstat (limited to 'lib/bottompanel/calculator.tcl')
-rwxr-xr-xlib/bottompanel/calculator.tcl2071
1 files changed, 2071 insertions, 0 deletions
diff --git a/lib/bottompanel/calculator.tcl b/lib/bottompanel/calculator.tcl
new file mode 100755
index 0000000..5196b40
--- /dev/null
+++ b/lib/bottompanel/calculator.tcl
@@ -0,0 +1,2071 @@
+#!/usr/bin/tclsh
+# Part of MCU 8051 IDE ( http://mcu8051ide.sf.net )
+
+############################################################################
+# Copyright (C) 2007-2009 by Martin Ošmera #
+# martin.osmera@gmail.com #
+# #
+# This program is free software; you can redistribute it and#or modify #
+# it under the terms of the GNU General Public License as published by #
+# the Free Software Foundation; either version 2 of the License, or #
+# (at your option) any later version. #
+# #
+# This program is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# GNU General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program; if not, write to the #
+# Free Software Foundation, Inc., #
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #
+############################################################################
+
+# --------------------------------------------------------------------------
+# DESCRIPTION
+#
+# --------------------------------------------------------------------------
+
+class Calculator {
+
+ common count 0 ;# counter of instances
+ # Font for numerical keypad
+ common large_font [font create \
+ -family {helveticat} \
+ -size -12 \
+ -weight {bold} \
+ ]
+
+ common oper_fg_color {#0000FF} ;# Foreground color for operator display
+ common error_bg_color {#FF6666} ;# Background color for display containing too many characters
+ common display_bg_color {#DDFFDD} ;# Background color for main display
+ common buffer_bg_color {#DDDDFF} ;# Background color for buffer display
+
+ # Variables related to object initialization
+ private variable parent ;# Teportary variable -- GUI parent
+ private variable calculatorList ;# Teportary variable -- COnfiguration list
+ private variable gui_initialized 0 ;# Bool: GUI created
+
+ # GUI variables
+ private variable calc_num_keypad ;# Container of left side of calc. (keypad)
+ private variable calc_num_display ;# Container for right side (displays etc.)
+ private variable calc_timers_calc ;# ID of label frame of timer preset calculator
+ private variable calc_display_widget ;# ID of main display widget
+ private variable calc_oper_widget ;# ID of operator display widget
+ private variable calc_buffer_widget ;# ID of buffer display widget
+ private variable timerscalc_THxDec_label ;# ID of THx (dec) label
+ private variable timerscalc_THxHex_label ;# ID of THx (hex) label
+ private variable timerscalc_THxOct_label ;# ID of THx (oct) label
+ private variable timerscalc_TLxDec_label ;# ID of TLx (dec) label
+ private variable timerscalc_TLxHex_label ;# ID of TLx (hex) label
+ private variable timerscalc_TLxOct_label ;# ID of TLx (oct) label
+ private variable timerscalc_RepeatDec_label ;# ID of Repeat (dec) label
+ private variable timerscalc_RepeatHex_label ;# ID of Repeat (hex) label
+ private variable timerscalc_RepeatOct_label ;# ID of Repeat (oct) label
+ private variable timerscalc_CorrectionDec_label ;# ID of Correction (dec) label
+ private variable timerscalc_CorrectionHex_label ;# ID of Correction (hex) label
+ private variable timerscalc_CorrectionOct_label ;# ID of Correction (oct) label
+ private variable timerscalc_freq_entry ;# ID of frequency entry widget
+ private variable timerscalc_mode_spinbox ;# ID of mode spinbox widget
+ private variable timerscalc_time_entry ;# ID of tim entry widget
+ private variable mem_entry_0 ;# ID of memory 0 entry widget
+ private variable mem_entry_1 ;# ID of memory 1 entry widget
+ private variable mem_entry_2 ;# ID of memory 2 entry widget
+
+ # Core variables
+ private variable base ;# Numeric base (Hex, Dec. Oct, Bin)
+ private variable last_base ;# Last numeric base
+ private variable angle ;# Angle unit (rad, deg, grad)
+ private variable last_angle ;# Last angle unit
+ private variable calc_oper {} ;# Chosen mathematical operation
+ private variable calc_oper_h ;# Human readible $calc_oper
+ private variable calc_last_oper ;# Last $calc_oper
+ private variable calc_display ;# Actual display text variable
+ private variable calc_buffer ;# Last display text variable
+ private variable calc_last_display ;# Var. for UNDO/REDO (takes back $calc_display)
+ private variable calc_last_buffer ;# Var. for UNDO/REDO (takes back $calc_buffer)
+ private variable ena_undo 0 ;# Undo enabled
+ private variable ena_redo 0 ;# Redo enabled
+ private variable after_eval 0 ;# Clear display if actual display val. is result of last operation
+ private variable scrollable_frame ;# Widget: Scrollable area (parent for all other widgets)
+ private variable horizontal_scrollbar ;# Widget: Horizontal scrollbar for scrollable area
+
+ # other public variables
+ private variable calc_idx ;# number of current instance
+ private variable timerscalc_validation_dis 1 ;# Disabled validation of timers calc
+
+ # definition of calculator keyboard
+ # {
+ # # row
+ # { # button
+ # {text path_part command_postfix
+ # columnspan rowspan
+ # helptext width
+ # height bgColor
+ # activeBackground bool_large_font
+ # }
+ # {separator}
+ # }
+ # }
+ common calculator_keyboard {
+ {
+ {{AND} {and} {calc_opr and 1} {} {}
+ {Bit-wise AND}
+ {5} {} {} {Calculator_GREEN} {#CCFFCC} 0
+ {Bit-wise AND. Valid for integer operands only.}}
+ {{Sin} {S} {calc_opr Sin 1} {} {}
+ {Sine}
+ {5} {} {} {Calculator_RED} {#FFDDDD} 0
+ {Sine}}
+ {{Cos} {Cs} {calc_opr Cos 1} {} {}
+ {Cosine}
+ {5} {} {} {Calculator_RED} {#FFDDDD} 0
+ {Cosine}}
+ {{Tan} {T} {calc_opr Tan 1} {} {}
+ {Tangent}
+ {5} {} {} {Calculator_RED} {#FFDDDD} 0
+ {Tangent}}
+ {{A} {A} {calc_val A} {} {} {} {} {} {5} {Calculator_PURPLE} {#DDDDFF} 1}
+ {{F} {F} {calc_val F} {} {} {} {} {} {} {Calculator_PURPLE} {#DDDDFF} 1}
+ {{/} {div} {calc_opr div 1} {} {} {} {} {} {} {Calculator_YELLOW} {#FFFFDD} 1}
+ {{*} {mul} {calc_opr mul 1} {} {} {} {} {} {} {Calculator_YELLOW} {#FFFFDD} 1}
+ {{-} {min} {calc_opr min 1} {} {} {} {} {} {} {Calculator_YELLOW} {#FFFFDD} 1}
+ } {
+ {{OR} {or} {calc_opr or 1} {} {}
+ {Bit-wise OR}
+ {5} {} {} {Calculator_GREEN} {#CCFFCC} 0
+ {Bit-wise OR. Valid for integer operands only.}}
+ {{ASin} {AS} {calc_opr ASin 1} {} {}
+ {Arc sine}
+ {5} {} {} {Calculator_RED} {#FFDDDD} 0
+ {Arc sine. Argument should be in the range \[-1,1\].}}
+ {{ACos} {AC} {calc_opr ACos 1} {} {}
+ {Arc cosine}
+ {5} {} {} {Calculator_RED} {#FFDDDD} 0
+ {Arc cosine. Argument should be in the range \[-1,1\].}}
+ {{ATan} {AT} {calc_opr ATan 1} {} {}
+ {Arc tangent}
+ {5} {} {} {Calculator_RED} {#FFDDDD} 0
+ {Arc tangent}}
+
+ {{B} {B} {calc_val B} {} {} {} {} {} {} {Calculator_PURPLE} {#DDDDFF} 1}
+ {{7} {7} {calc_val 7} {} {} {} {} {} {} {Calculator_PURPLE} {#DDDDFF} 1}
+ {{8} {8} {calc_val 8} {} {} {} {} {} {} {Calculator_PURPLE} {#DDDDFF} 1}
+ {{9} {9} {calc_val 9} {} {} {} {} {} {} {Calculator_PURPLE} {#DDDDFF} 1}
+ {{+} {add} {calc_opr add 1} {} {2} {} {} {2} {} {Calculator_YELLOW} {#FFFFDD} 1}
+ } {
+ {{NOT} {not} {calc_opr not 1} {} {}
+ {Bit-wise NOT}
+ {5} {} {} {Calculator_GREEN} {#CCFFCC} 0
+ {Bit-wise NOT. Valid for integer operands only.}}
+ {{e**} {exp} {calc_opr Exp 1} {} {}
+ {Exponential of argument (e**arg)}
+ {5} {} {} {Calculator_CYAN} {#AAFFFF} 0
+ {Exponential of argument (e**arg)}}
+ {{sqrt} {sqr} {calc_opr Sqr 1} {} {}
+ {Square root}
+ {5} {} {} {Calculator_CYAN} {#AAFFFF} 0
+ {Square root. Argument must be non-negative.}}
+ {{pow} {power} {calc_opr pow 1} {} {}
+ {Power}
+ {5} {} {} {Calculator_CYAN} {#AAFFFF} 0
+ {Computes the value of x raised to the power y. If x is negative, y must be an integer value.}}
+
+ {{C} {C} {calc_val C} {} {} {} {} {} {} {Calculator_PURPLE} {#DDDDFF} 1}
+ {{4} {4} {calc_val 4} {} {} {} {} {} {} {Calculator_PURPLE} {#DDDDFF} 1}
+ {{5} {5} {calc_val 5} {} {} {} {} {} {} {Calculator_PURPLE} {#DDDDFF} 1}
+ {{6} {6} {calc_val 6} {} {} {} {} {} {} {Calculator_PURPLE} {#DDDDFF} 1}
+ } {
+ {{XOR} {xor} {calc_opr xor 1} {} {}
+ {Bit-wise exclusive OR}
+ {5} {} {} {Calculator_GREEN} {#CCFFCC} 0
+ {Bit-wise exclusive OR. Valid for integer operands only.}}
+ {{Log} {L} {calc_opr Log 1} {} {}
+ {Base 10 logarithm}
+ {5} {} {} {Calculator_CYAN} {#AAFFFF} 0
+ {Returns the base 10 logarithm of argument. Argument must be a positive value.}}
+ {{Ln} {Ln} {calc_opr Ln 1} {} {}
+ {Natural logarithm}
+ {5} {} {} {Calculator_CYAN} {#AAFFFF} 0
+ {Returns the natural logarithm of argument. Argument must be a positive value.}}
+ {{PI} {P} {calc_val PI} {} {}
+ {Constant Pi}
+ {5} {} {} {Calculator_CYAN} {#AAFFFF} 0
+ {Constant Pi}}
+
+ {{D} {D} {calc_val D} {} {} {} {} {} {} {Calculator_PURPLE} {#DDDDFF} 1}
+ {{1} {1} {calc_val 1} {} {} {} {} {} {} {Calculator_PURPLE} {#DDDDFF} 1}
+ {{2} {2} {calc_val 2} {} {} {} {} {} {} {Calculator_PURPLE} {#DDDDFF} 1}
+ {{3} {3} {calc_val 3} {} {} {} {} {} {} {Calculator_PURPLE} {#DDDDFF} 1}
+ {{=} {=} {calc_Evaluate} {} {2} {} {} {2} {} {Calculator_YELLOW} {#FFFFDD} 1}
+ } {
+ {{>>} {right} {calc_opr right 1} {} {}
+ {Right shift}
+ {5} {} {} {Calculator_GREEN} {#CCFFCC} 0
+ {Right shift. Valid for integer operands only. A right shift always propagates the sign bit.}}
+ {{Mod} {M} {calc_opr mod 1} {} {}
+ {Modulo}
+ {5} {} {} {Calculator_CYAN} {#AAFFFF} 0
+ {Computes remainder of integer division}}
+ {{UNDO} {U} {calc_UNDO} {} {}
+ {Undo last operation}
+ {5} {} {} {Calculator_GRAY} {#F8F8F8} 0
+ {Undo last operation. Not all operations are supported.}}
+ {{REDO} {RE} {calc_REDO} {} {}
+ {Take back last undo operation}
+ {5} {} {} {Calculator_GRAY} {#F8F8F8} 0
+ {Take back last undo operation. Not all operations are supported.}}
+
+ {{E} {E} {calc_val E} {} {} {} {} {} {} {Calculator_PURPLE} {#DDDDFF} 1}
+ {{0} {0} {calc_val 0} {2} {} {} {5} {} {} {Calculator_PURPLE} {#DDDDFF} 1}
+
+ {{.} {dot} {calc_val .} {} {} {} {} {} {} {Calculator_PURPLE} {#DDDDFF} 1}
+ }
+ }
+
+ ## object constructor
+ constructor {} {
+ # Initialize some variables
+ incr count ;# Instance counter
+ set calc_idx $count ;# Index of this object
+ set base Dec ;# Default numeric base
+ set angle rad ;# Default angle unit
+ set last_base $base ;# Last numeric base
+ set last_angle $angle ;# Last angle unit
+
+ # Configure ttk styles
+ ttk::style configure Calculator_Buffer.TEntry \
+ -fieldbackground $buffer_bg_color
+ ttk::style configure Calculator_Oper.TEntry \
+ -fieldbackground {#FFDDDD} \
+ -fieldforeground $oper_fg_color \
+ -justify center
+ ttk::style configure Calculator_OperError.TEntry\
+ -fieldbackground {#FFDDDD} \
+ -foreground {#FF0000} \
+ -justify center
+ ttk::style configure Calculator_Display.TEntry \
+ -fieldbackground $display_bg_color
+ ttk::style configure Calculator_Error.TEntry \
+ -fieldbackground $error_bg_color
+
+ ttk::style configure Calculator_GREEN.TButton -padding 2
+ ttk::style map Calculator_GREEN.TButton \
+ -background [list active {#AAFFAA} {!active !disabled} {#CCFFCC} disabled {#DDEEDD}]
+
+ ttk::style configure Calculator_RED.TButton -padding 2
+ ttk::style map Calculator_RED.TButton \
+ -background [list active {#FFAAAA} {!active !disabled} {#FFDDDD} disabled {#EEDDDD}]
+
+ ttk::style configure Calculator_CYAN.TButton -padding 2
+ ttk::style map Calculator_CYAN.TButton \
+ -background [list active {#88EEEE} {!active !disabled} {#AAFFFF} disabled {#DDEEEE}]
+
+ ttk::style configure Calculator_GRAY.TButton -padding 2
+ ttk::style map Calculator_GRAY.TButton \
+ -background [list active {#DDDDDD} {!active !disabled} {#F8F8F8} disabled {#EEEEEE}]
+
+ ttk::style configure Calculator_PURPLE.TButton -padding 2 -font $large_font
+ ttk::style map Calculator_PURPLE.TButton \
+ -background [list active {#AAAAFF} {!active !disabled} {#DDDDFF} disabled {#DDDDEE}]
+
+ ttk::style configure Calculator_YELLOW.TButton -padding 2 -font $large_font
+ ttk::style map Calculator_YELLOW.TButton \
+ -background [list active {#FFFFAA} {!active !disabled} {#FFFFDD} disabled {#EEEEDD}]
+ }
+
+ ## object destructor
+ destructor {
+ # Unallocate GUI related variables
+ catch {
+ unset ::Calculator::calc_base$calc_idx
+ unset ::Calculator::calc_angle$calc_idx
+ unset ::Calculator::calc_buffer$calc_idx
+ unset ::Calculator::calc_oper$calc_idx
+ unset ::Calculator::calc_displ$calc_idx
+ unset ::Calculator::calc_mem0_$calc_idx
+ unset ::Calculator::calc_mem1_$calc_idx
+ unset ::Calculator::calc_mem2_$calc_idx
+ }
+ }
+
+ ## Append given value to the end of the display
+ # Use carefully, it does not check value validity !
+ # @parm String value - value to append
+ # @return String - new display content
+ public method calc_val {value} {
+ # Read raw content of the main display
+ reread_display 1
+
+ # Insert PI
+ if {$value == {PI}} {
+ # Conver PI to selected numeric base
+ switch -- $base {
+ {Hex} {set value [NumSystem::dec2hex ${Angle::PI}]}
+ {Dec} {set value ${Angle::PI}}
+ {Oct} {set value [NumSystem::dec2oct ${Angle::PI}]}
+ {Bin} {set value [NumSystem::dec2bin ${Angle::PI}]}
+ }
+ # Save current values
+ set calc_last_display [reread_display] ;# Main display
+ set calc_last_buffer [reread_buffer] ;# Buffer
+ # Clear main display
+ set calc_display {}
+ # Save current opetaror
+ set calc_last_oper $calc_oper
+ enable_undo ;# enable UNDO operation
+
+ # Clear main display if current value is result of the last operation
+ } elseif {$after_eval} {
+ set calc_last_display $calc_display ;# Save current content of display
+ set calc_last_buffer {}
+ set calc_last_oper {}
+ set calc_display {}
+ set after_eval 0
+ enable_undo ;# enable UNDO operation
+ }
+
+ # Append given value to the end of main display
+ set tmp "$calc_display$value"
+ if {[calc_validate $calc_display_widget $tmp]} {
+ set ::Calculator::calc_displ$calc_idx $tmp
+
+ catch {
+ $calc_display_widget delete sel.first sel.last
+ }
+ }
+
+ $calc_display_widget icursor end
+ $calc_buffer_widget icursor end
+ return $calc_display
+ }
+
+ ## Choose mathematical operation
+ # @parm String operation - Selected operation
+ # @parm Bool external - Evaluate result
+ # @return void
+ public method calc_opr {operation external} {
+
+ # Save current operator and set the new one
+ set calc_last_oper $calc_oper
+ set calc_oper $operation
+ # Clear displays if external
+ if {$external} {
+ set calc_last_display [reread_display]
+ set calc_last_buffer [reread_buffer]
+ set calc_buffer $calc_display
+ set calc_display {}
+ enable_undo
+ rewrite_buffer
+ rewrite_display
+ }
+
+ # Evaluate specified operation
+ switch -- $operation {
+ {div} { ;# Division
+ set calc_oper_h {/}
+ }
+ {mul} { ;# Multiplication
+ set calc_oper_h {*}
+ }
+ {min} { ;# Subtraction
+ set calc_oper_h {-}
+ }
+ {add} { ;# Addition
+ set calc_oper_h {+}
+ }
+ {pow} { ;# Power
+ set calc_oper_h {**}
+ }
+ {mod} { ;# Modulo
+ set calc_oper_h {mod}
+ }
+ {and} { ;# Bit-wise and
+ set calc_oper_h {&}
+ }
+ {or} { ;# Bit-wise inclusive or
+ set calc_oper_h {|}
+ }
+ {xor} { ;# Bit-wise exclusive or
+ set calc_oper_h {^}
+ }
+ {right} { ;# Right shift
+ set calc_oper_h {>>}
+ }
+
+ {not} { ;# Bit-wise inversion
+ set calc_oper_h {~}
+ if {$external} {calc_Evaluate}
+ }
+ {Exp} { ;# Exponential of argument
+ set calc_oper_h {e**}
+ if {$external} {calc_Evaluate}
+ }
+ {Sqr} { ;# Square root
+ set calc_oper_h {sqrt}
+ if {$external} {calc_Evaluate}
+ }
+ {Log} { ;# Decimal logarithm
+ set calc_oper_h {lg}
+ if {$external} {calc_Evaluate}
+ }
+ {Ln} { ;# Natural logarithm
+ set calc_oper_h {ln}
+ if {$external} {calc_Evaluate}
+ }
+ {Sin} { ;# Sine
+ set calc_oper_h {sin}
+ if {$external} {calc_Evaluate}
+ }
+ {Cos} { ;# Cosine
+ set calc_oper_h {cos}
+ if {$external} {calc_Evaluate}
+ }
+ {Tan} { ;# Tangent
+ set calc_oper_h {tan}
+ if {$external} {calc_Evaluate}
+ }
+ {ASin} { ;# Arc sine
+ set calc_oper_h {asin}
+ if {$external} {calc_Evaluate}
+ }
+ {ACos} { ;# Arc cosine
+ set calc_oper_h {acos}
+ if {$external} {calc_Evaluate}
+ }
+ {ATan} { ;# Acr cotangent
+ set calc_oper_h {atan}
+ if {$external} {calc_Evaluate}
+ }
+ default { ;# No operand
+ set calc_oper_h {}
+ }
+ }
+
+ # Display selected operand
+ set ::Calculator::calc_oper$calc_idx $calc_oper_h
+ }
+
+ ## Perform operation with calulator memory
+ # @parm String action - "Save" (to main display) or "Load" (from main display)
+ # @parm Int cell - Index of memory cell
+ # @return void
+ public method mem {action cell} {
+ if {$action == {Save}} {
+ # Show message on status bar
+ Sbar [mc "Calculator: M%s saved" $cell]
+ # Save content of main display
+ set calc_mem [reread_display]
+ if {[regexp {\.0$} $calc_mem]} {
+ set calc_mem [string range $calc_mem 0 {end-2}]
+ }
+ set ::Calculator::calc_mem${cell}_$calc_idx $calc_mem
+ } {
+ # Load memory content into main display
+ set calc_display [subst "\$::Calculator::calc_mem${cell}_$calc_idx"]
+ rewrite_display
+ }
+ }
+
+ ## Perform evaluation of given mathematical expression
+ # @return void
+ public method calc_Evaluate {} {
+
+ ## Check for presence of nessesary values
+ # * For unary operations
+ set display [reread_display]
+ set buffer [reread_buffer]
+ if {$buffer == {} || $buffer == {-}} {
+ Sbar [mc "Calculator: Unable to evaluate, missing argument"]
+ return 0
+ }
+ if {$calc_oper == {}} {
+ Sbar [mc "Calculator: Unable to evaluate, missing operator"]
+ return 0
+ }
+ # * For binary operations
+ if {
+ $calc_oper == {div} || $calc_oper == {mul} ||
+ $calc_oper == {min} || $calc_oper == {add} ||
+ $calc_oper == {pow} || $calc_oper == {mod} ||
+ $calc_oper == {and} || $calc_oper == {or} ||
+ $calc_oper == {xor} || $calc_oper == {nand}
+ } {
+ # Check display value length
+ if {$display == {}} {
+ Sbar [mc "Calculator: Unable to evaluate, missing argument"]
+ return 0
+ }
+ }
+
+ # Make backup for display, buffer and operator
+ enable_undo ;# enable UNDO operation
+ set calc_last_display $display
+ set calc_last_buffer $buffer
+
+ # Load up content of buffer and display
+ read_buffer_inDec
+ read_display_inDec
+
+ # Perform evaluation in safe environment
+ if {[catch {
+ switch -- $calc_oper {
+ {and} { ;# Bit-wise and
+ set calc_display [expr {wide($calc_buffer) & wide($calc_display)}]
+ }
+ {or} { ;# Bit-wise or
+ set calc_display [expr {wide($calc_buffer) | wide($calc_display)}]
+ }
+ {xor} { ;# Bit-wise xor
+ set calc_display [expr {wide($calc_buffer) ^ wide($calc_display)}]
+ }
+ {right} { ;# Right shift
+ set tmp [expr {wide($calc_display)}]
+ if {$tmp > 0} {
+ set calc_display [expr {wide($calc_buffer) >> $tmp}]
+ } elseif {$tmp < 0} {
+ set calc_display [expr {wide($calc_buffer) << abs($tmp)}]
+ } else {
+ set calc_display [expr {wide($calc_buffer)}]
+ }
+ }
+ {mul} { ;# Multiplication
+ set calc_display [expr {$calc_buffer * $calc_display}]
+ }
+ {min} { ;# Subtraction
+ set calc_display [expr {$calc_buffer - $calc_display}]
+ }
+ {add} { ;# Addtion
+ set calc_display [expr {$calc_buffer + $calc_display}]
+ }
+ {mod} { ;# Modulo
+ set calc_display [expr {int(fmod($calc_buffer,$calc_display))}]
+ }
+ {pow} { ;# Power
+ set calc_display [expr {pow($calc_buffer, $calc_display)}]
+ }
+ {div} { ;# Division
+ if {$calc_display == 0} {
+ Sbar [mc "Calculator: WARNING result is +/- infinity => operation terminated !"]
+ return
+ }
+ if {![regexp {\.} $calc_buffer]} {
+ set calc_buffer "$calc_buffer.0"
+ }
+ set calc_display [expr {$calc_buffer / $calc_display}]
+ }
+ {not} { ;# Bit-wise inversion
+ set len [string length [format {%X} [expr {int($calc_buffer)}]]]
+ if {$len > 8} {
+ Sbar [mc "Calculator: This value is too high to invert (max. 0xFFFFFFFF)"]
+ return
+ }
+ incr len -1
+ set calc_display [expr {0x7FFFFFFF ^ int($calc_buffer)}]
+ set calc_display [format {%X} $calc_display]
+ set calc_display [string range $calc_display end-$len end]
+ set calc_display [expr "0x$calc_display"]
+ }
+ {Exp} { ;# Exponential of argument
+ set calc_display [expr {exp($calc_buffer)}]
+ }
+ {Sqr} { ;# Square root
+ set calc_display [expr {sqrt($calc_buffer)}]
+ }
+ {Log} { ;# Decimal logarithm
+ set calc_display [expr {log10($calc_buffer)}]
+ }
+ {Ln} { ;# Natiral logarithm
+ set calc_display [expr {log($calc_buffer)}]
+ }
+ {ASin} { ;# Arc sine
+ set calc_display [expr {asin($calc_buffer)}]
+ set calc_display [rad_to_Xangle $calc_display]
+ }
+ {ACos} { ;# Arc cosine
+ set calc_display [expr {acos($calc_buffer)}]
+ set calc_display [rad_to_Xangle $calc_display]
+ }
+ {ATan} { ;# Arc Tangent
+ set calc_display [expr {atan($calc_buffer)}]
+ set calc_display [rad_to_Xangle $calc_display]
+ }
+ {Sin} { ;# Sine
+ set calc_buffer [Xangle_to_rad $calc_buffer]
+ set calc_display [expr {sin($calc_buffer)}]
+ }
+ {Cos} { ;# Cosine
+ set calc_buffer [Xangle_to_rad $calc_buffer]
+ set calc_display [expr {cos($calc_buffer)}]
+ }
+ {Tan} { ;# Arc tangent
+ set calc_buffer [Xangle_to_rad $calc_buffer]
+ set calc_display [expr {tan($calc_buffer)}]
+ }
+ }
+ }]} {
+ # If error occured -> show error message
+ Sbar [mc "Calculator: ERROR (result value is out of allowed range)"]
+ return
+ }
+
+ # If result value contain exponent -> show error message
+ if {[regexp {e} $calc_display]} {
+ Sbar[mc "Calculator: Unable to evaluate, result value is too high"]
+ return
+ }
+
+ # Display result
+ set calc_buffer {}
+ set after_eval 1
+ rewrite_buffer
+ calc_opr {} 0
+ write_display_inXbase $calc_display
+ }
+
+ ## Safely clear display
+ # @return void
+ public method calc_ClearActual {} {
+ # enable UNDO operation
+ enable_undo
+ # save actual values
+ set calc_last_display [reread_display]
+ set calc_display {}
+ set calc_last_buffer [reread_buffer]
+ # show new values
+ rewrite_display
+ }
+
+ ## Safely clear display and buffer
+ # @return void
+ public method calc_Clear {} {
+ # enable UNDO operation
+ enable_undo
+ # save actual values
+ set calc_last_display [reread_display]
+ set calc_display {}
+ set calc_last_buffer [reread_buffer]
+ set calc_buffer {}
+ calc_opr {} 0
+ # show new values
+ rewrite_display
+ rewrite_buffer
+ }
+
+ ## Enable execution of UNDO operation and disable REDO
+ # @return void
+ private method enable_undo {} {
+ # set status
+ set ena_undo 1
+ set ena_redo 0
+ # enable/disable UNDO and REDO buttons
+ enable_buttons {U}
+ disable_buttons {RE}
+ }
+
+ ## Enable execution of REDO operation and disable UNDO
+ # @return void
+ private method enable_redo {} {
+ # set status
+ set ena_undo 0
+ set ena_redo 1
+ # enable/disable UNDO and REDO buttons
+ enable_buttons {RE}
+ disable_buttons {U}
+ }
+
+ ## Take back the last operation
+ # @return void
+ public method calc_UNDO {} {
+ # enable REDO operation
+ enable_redo
+ # ....
+ set after_eval 0
+ # save actual status and restore previous
+ calc_opr $calc_last_oper 0
+ set tmp [reread_display]
+ set calc_display $calc_last_display
+ set calc_last_display $tmp
+ set tmp [reread_buffer]
+ set calc_buffer $calc_last_buffer
+ set calc_last_buffer $tmp
+ # show new values
+ rewrite_display
+ rewrite_buffer
+ # inform user by starts bar
+ Sbar [mc "Calculator: UNDO: previous state was: %s %s %s" $calc_last_buffer $calc_last_oper $calc_last_display]
+ }
+
+ ## Take back the UNDO operation
+ # @return void
+ public method calc_REDO {} {
+ # enable UNDO operation
+ enable_undo
+ # save actual status and restore previous
+ calc_opr $calc_last_oper 0
+ set tmp [reread_display]
+ set calc_display $calc_last_display
+ set calc_last_display $tmp
+ set tmp [reread_buffer]
+ set calc_buffer $calc_last_buffer
+ set calc_last_buffer $tmp
+ # show new values
+ rewrite_display
+ rewrite_buffer
+ # inform user by starts bar
+ Sbar [mc "Calculator: REDO: previous state was: %s %s %s" $calc_last_buffer $calc_last_oper $calc_last_display]
+ }
+
+ ## Convert content of both displays and all merory cells using given command
+ # @parm String command - command to use for converion
+ # @return void
+ private method convert_displays {command} {
+
+ # Determinate what displays aren't empty
+ if {[reread_display] == {}} {set dis 0} {set dis 1}
+ if {[reread_buffer] == {}} {set buf 0} {set buf 1}
+
+ # Determinate what memory cells aren't empty
+ for {set i 0} {$i < 3} {incr i} {
+ set mem [[subst "\$mem_entry_$i"] get]
+ if {[string index $mem end] == {.}} {
+ append mem 0
+ }
+ set memory$i $mem
+ if {$mem == {} || $mem == 0} {
+ set mem$i 0
+ } {
+ set mem$i 1
+ }
+ }
+
+ # Convert all non empty displays
+ foreach cnd "$dis $buf $mem0 $mem1 $mem2" \
+ var {calc_display calc_buffer memory0 memory1 memory2} {
+ if {$cnd} {
+ if {[catch {
+ set $var [$command [subst "\$$var"]]
+ }]} {
+ Sbar [mc "Calculator: Value is too high to convert, value deleted !"]
+ set $var 0
+ }
+ }
+ }
+
+ # Display new content of memory cells
+ for {set i 0} {$i < 3} {incr i} {
+ [subst "\$mem_entry_$i"] delete 0 end
+ [subst "\$mem_entry_$i"] insert end [subst "\$memory$i"]
+ }
+ }
+
+ ## Switch numeric base
+ # @return void
+ public method cal_switchBase {} {
+
+ # Get chosen value
+ set base [subst "\$::Calculator::calc_base$calc_idx"]
+
+ # Convert display content to setected numeric system
+ if {$base == $last_base} {
+ set last_base $base
+ return
+ }
+
+ # Adjust value in display and buffer
+ if {[regexp {\.0$} $calc_display]} {
+ set calc_display [string range $calc_display 0 {end-2}]
+ }
+ if {[regexp {\.0$} $calc_buffer]} {
+ set calc_buffer [string range $calc_buffer 0 {end-2}]
+ }
+
+ # Covert content of all displays to new numeric base
+ switch -- $base {
+ {Hex} { ;# to Hexadecimal
+ enable_buttons {0 1 2 3 4 5 6 7 8 9 A B C D E F}
+ switch -- $last_base {
+ {Dec} {convert_displays NumSystem::dec2hex}
+ {Oct} {convert_displays NumSystem::oct2hex}
+ {Bin} {convert_displays NumSystem::bin2hex}
+ }
+ }
+ {Dec} { ;# to Decimal
+ disable_buttons {A B C D E F}
+ enable_buttons {0 1 2 3 4 5 6 7 8 9}
+ switch -- $last_base {
+ {Hex} {convert_displays NumSystem::hex2dec}
+ {Oct} {convert_displays NumSystem::oct2dec}
+ {Bin} {convert_displays NumSystem::bin2dec}
+ }
+ }
+ {Oct} { ;# to Octal
+ disable_buttons {8 9 A B C D E F}
+ enable_buttons {0 1 2 3 4 5 6 7}
+ switch -- $last_base {
+ {Hex} {convert_displays NumSystem::hex2oct}
+ {Dec} {convert_displays NumSystem::dec2oct}
+ {Bin} {convert_displays NumSystem::bin2oct}
+ }
+ }
+ {Bin} { ;# to Binary
+ disable_buttons {2 3 4 5 6 7 8 9 A B C D E F}
+ enable_buttons {0 1}
+ switch -- $last_base {
+ {Hex} {convert_displays NumSystem::hex2bin}
+ {Dec} {convert_displays NumSystem::dec2bin}
+ {Oct} {convert_displays NumSystem::oct2bin}
+ }
+ }
+ }
+
+ # Display new values
+ rewrite_display
+ rewrite_buffer
+
+ # set last value
+ set last_base $base
+ }
+
+ ## Disable buttons specified in the given list
+ # example: disable_buttons {1 2} ;# disable .calc_1_0 and .calc_2_0
+ # @return void
+ private method disable_buttons {buttons_list} {
+ foreach path $buttons_list {
+ $calc_num_keypad.calc_${path} \
+ configure -state disabled
+ }
+ }
+
+ ## Enable buttons specified in the given list
+ # example: enable_buttons {1 2} ;# enable .calc_1_0 and .calc_2_0
+ # @return void
+ private method enable_buttons {buttons_list} {
+ foreach path $buttons_list {
+ $calc_num_keypad.calc_${path} \
+ configure -state normal
+ }
+ }
+
+ ## Switch angle unit
+ # @return void
+ public method cal_switchAngle {} {
+
+ # Get chosen unit
+ set angle [subst "\$::Calculator::calc_angle$calc_idx"]
+
+ # Convert all displays
+ if {$angle != $last_angle} {
+ # Convert display if is not empty
+ if {[read_display_inDec] != {}} {
+ write_display_inXbase [Angle::${last_angle}2${angle} $calc_display]
+ }
+ # Convert buffer if is not empty
+ if {[read_buffer_inDec] != {}} {
+ write_buffer_inXbase [Angle::${last_angle}2${angle} $calc_buffer]
+ }
+ # Conver memory cells
+ for {set i 0} {$i <3} {incr i} {
+ # Get memory cell value
+ set mem [[subst "\$mem_entry_$i"] get]
+ # Adjust that value
+ if {[string index $mem end] == {.}} {
+ append mem 0
+ }
+ # Display new value
+ if {$mem != {}} {
+ set mem [Angle::${last_angle}2${angle} $mem]
+ [subst "\$mem_entry_$i"] delete 0 end
+ [subst "\$mem_entry_$i"] insert end $mem
+ }
+ }
+ }
+
+ # Set last unit
+ set last_angle $angle
+ }
+
+ ## Read content of main display in decimal system
+ # @return Float result
+ private method read_display_inDec {} {
+ # get display content
+ if {[reread_display] != {}} {
+ # convert to decimal value
+ if {$base != {Dec}} {
+ switch -- $base {
+ {Hex} { ;# from Hexadecimal
+ set calc_display [NumSystem::hex2dec $calc_display]
+ }
+ {Oct} { ;# from Octal
+ set calc_display [NumSystem::oct2dec $calc_display]
+ }
+ {Bin} { ;# from Binary
+ set calc_display [NumSystem::bin2dec $calc_display]
+ }
+ }
+ }
+ }
+ # done
+ return $calc_display
+ }
+
+ ## Write the given number (in dec) to main display (in selected base)
+ # @parm Float dec_content - number to display
+ # @return void
+ private method write_display_inXbase {dec_content} {
+
+ # If selected numeric base isn't Dec -> perform conversion
+ if {$base != {Dec}} {
+ switch -- $base {
+ {Hex} { ;# to Hexadecimal
+ if {[catch {
+ set calc_display [NumSystem::dec2hex $dec_content]
+ }]} {
+ Sbar [mc "Calculator: ERROR, result is too high (cannot be displayed)"]
+ set calc_display 0
+ }
+ }
+ {Oct} { ;# to Octal
+ if {[catch {
+ set calc_display [NumSystem::dec2oct $dec_content]
+ }]} {
+ Sbar [mc "Calculator: ERROR, result is too high (cannot be displayed)"]
+ set calc_display 0
+ }
+ }
+ {Bin} { ;# to Binary
+ if {[catch {
+ set calc_display [NumSystem::dec2bin $dec_content]
+ }]} {
+ Sbar [mc "Calculator: ERROR, result is too high (cannot be displayed)"]
+ set calc_display 0
+ }
+ }
+ }
+ # If selected numeric base is Dec -> do nothing
+ } {
+ set calc_display $dec_content
+ }
+
+ # display (new) value
+ rewrite_display
+ }
+
+ ## Read content of buffer in decimal system
+ # @return Float result
+ private method read_buffer_inDec {} {
+ # Get content buffer display
+ if {[reread_buffer] != {}} {
+ # Convert to decimal value
+ if {$base != {Dec}} {
+ switch -- $base {
+ {Hex} { ;# from Hexadecimal
+ set calc_buffer [NumSystem::hex2dec $calc_buffer]
+ }
+ {Oct} { ;# from Octal
+ set calc_buffer [NumSystem::oct2dec $calc_buffer]
+ }
+ {Bin} { ;# from BInary
+ set calc_buffer [NumSystem::bin2dec $calc_buffer]
+ }
+ }
+ }
+ }
+ # done
+ return $calc_buffer
+ }
+
+ ## Write the given number (in dec) to buffer display (in selected base)
+ # @parm Float dec_content - number to display
+ # @return void
+ private method write_buffer_inXbase {dec_content} {
+
+ # If selected numeric base isn't Dec -> perform conversion
+ if {$base != {Dec}} {
+ switch -- $base {
+ {Hex} { ;# to Hexadecimal
+ if {[catch {
+ set calc_buffer [NumSystem::dec2hex $dec_content]
+ }]} {
+ Sbar [mc "Calculator: ERROR, value is too high"]
+ set calc_buffer 0
+ }
+ }
+ {Oct} { ;# to Octal
+ if {[catch {
+ set calc_buffer [NumSystem::dec2oct $dec_content]
+ }]} {
+ Sbar [mc "Calculator: ERROR, value is too high"]
+ set calc_buffer 0
+ }
+ }
+ {Bin} { ;# to Binary
+ if {[catch {
+ set calc_buffer [NumSystem::dec2bin $dec_content]
+ }]} {
+ Sbar [mc "Calculator: ERROR, value is too high"]
+ set calc_buffer 0
+ }
+ }
+ }
+ # If selected numeric base is Dec -> do nothing
+ } {
+ set calc_buffer $dec_content
+ }
+
+ # display (new) value
+ rewrite_buffer
+ }
+
+ ## Write adjusted content of variable calc_display to main display widget
+ # @return void
+ private method rewrite_display {} {
+ # Adust content of source variable
+ if {[regexp {\.0$} $calc_display]} {
+ set calc_display [string range $calc_display 0 {end-2}]
+ }
+ # Show its content
+ set ::Calculator::calc_displ$calc_idx $calc_display
+ }
+
+ ## Write adjusted content of variable calc_buffer to buffer display widget
+ # @return void
+ private method rewrite_buffer {} {
+ # Adust content of source variable
+ if {[regexp {\.0$} $calc_buffer]} {
+ set calc_buffer [string range $calc_buffer 0 {end-2}]
+ }
+ # Show its content
+ set ::Calculator::calc_buffer$calc_idx $calc_buffer
+ }
+
+ ## Read true content of main display widget converted
+ # @parm args = False - adjust to float
+ # @return Float - content of the main display
+ private method reread_display args {
+
+ # Get content of the widget
+ set calc_display [$calc_display_widget get]
+ regsub {\,} $calc_display {.} calc_display
+
+ # Adhust to float (if requested)
+ if {$args != 1} {
+ if {[regexp {^\.} $calc_display]} {
+ set calc_display "0$calc_display"
+ } elseif {[regexp {\.$} $calc_display]} {
+ append calc_display 0
+ }
+ if {[string first {.} $calc_display] == -1} {
+ append calc_display {.0}
+ }
+ }
+
+ # Remove trailing '.0'
+ if {[regexp {^\.0$} $calc_display]} {
+ set calc_display {}
+ }
+
+ # Return result
+ return $calc_display
+ }
+
+ ## Read true content of buffer display widget converted
+ # @return Float - content of the buffer
+ private method reread_buffer {} {
+
+ # Get content of the widget
+ set calc_buffer [$calc_buffer_widget get]
+ regsub {\,} $calc_buffer {.} calc_buffer
+
+ # Adhust to float
+ if {[regexp {^\.} $calc_buffer]} {
+ set calc_buffer "0$calc_buffer"
+ } elseif {[regexp {\.$} $calc_buffer]} {
+ append calc_buffer 0
+ }
+ if {[string first {.} $calc_buffer] == -1} {
+ append calc_buffer {.0}
+ }
+
+ # Remove trailing '.0'
+ if {[regexp {^\.0$} $calc_buffer]} {
+ set calc_buffer {}
+ }
+
+ # Return result
+ return $calc_buffer
+ }
+
+ ## Covert given angle to current angle unit
+ # @parm Float dec_angle - angle to convert in decimal
+ # @return Float - angle in radians
+ private method Xangle_to_rad {dec_angle} {
+ # If current angle unit isn't radians -> perform converison
+ if {$angle != {rad}} {
+ # From grad
+ if {$angle == {grad}} {
+ set dec_angle [Angle::grad2rad $dec_angle]
+ # From degrees
+ } {
+ set dec_angle [Angle::deg2rad $dec_angle]
+ }
+ }
+ # return result
+ return $dec_angle
+ }
+
+ ## Convert given angle in radians to current angle unit
+ # @parm Float dec_angle - angle to conver in radians (decimal)
+ # @return Float - converted angle
+ private method rad_to_Xangle {dec_angle} {
+ # If current angle unit isn't radians -> perform converison
+ if {$angle != {rad}} {
+ # To grad
+ if {$angle == {grad}} {
+ set dec_angle [Angle::rad2grad $dec_angle]
+ # To degrees
+ } {
+ set dec_angle [Angle::rad2deg $dec_angle]
+ }
+ }
+ # return result
+ return $dec_angle
+ }
+
+ ## Validate display content
+ # @parm Widget widget - entry widget
+ # @parm String content - content to validate
+ # @return bool - result
+ public method calc_validate {widget content} {
+
+ # Set default background color for that widget
+ if {$widget == $calc_display_widget} {
+ $widget configure -style Calculator_Display.TEntry
+ } elseif {$widget == $calc_buffer_widget} {
+ $widget configure -style Calculator_Buffer.TEntry
+ } else {
+ $widget configure -style TEntry
+ }
+
+ # Valid if content is empty
+ set len [string length $content]
+ if {$len == 0 || $content == {-}} {
+ return 1
+ }
+
+ # Invalid if content is too wide
+ if {$len > 40} {
+ Sbar [mc "Calculator: ERROR, value is too high"]
+ if {[string length [$widget get]] > 13} {
+ $widget configure -style Calculator_Error.TEntry
+ }
+ return 0
+ }
+
+ # Adjust content
+ regsub {\,} $content {.} content
+ if {[regexp {\.$} $content]} {
+ append content 0
+ }
+
+ # Check for valid numeric base
+ switch -- $base {
+ {Hex} {set content [NumSystem::ishex $content]}
+ {Dec} {set content [NumSystem::isdec $content]}
+ {Oct} {set content [NumSystem::isoct $content]}
+ {Bin} {set content [NumSystem::isbin $content]}
+ default {set content 0}
+ }
+
+ # Evaluate filan result
+ if {$content} {
+ if {$len > 13} {
+ $widget configure -style Calculator_Error.TEntry
+ }
+ return 1
+ } {
+ Sbar [mc "Calculator: Trying to insert invalid value"]
+ return 0
+ }
+ }
+
+ ## Validate content of operator diaplay
+ # @parm String content - string to validate
+ # @return Bool - result of validation
+ public method calc_oper_validate {content} {
+
+ # Check for length
+ if {[string length $content] > 4} {
+ return 0
+ }
+
+ # Check for allowed content
+ switch -- $content {
+ {/} {set calc_oper {div}}
+ {*} {set calc_oper {mul}}
+ {-} {set calc_oper {min}}
+ {+} {set calc_oper {add}}
+ {**} {set calc_oper {pow}}
+ {mod} {set calc_oper {mod}}
+ {&} {set calc_oper {and}}
+ {|} {set calc_oper {or}}
+ {^} {set calc_oper {xor}}
+ {>>} {set calc_oper {right}}
+ {~} {set calc_oper {not}}
+ {e**} {set calc_oper {Exp}}
+ {sqrt} {set calc_oper {Sqr}}
+ {lg} {set calc_oper {Log}}
+ {ln} {set calc_oper {Ln}}
+ {sin} {set calc_oper {Sin}}
+ {cos} {set calc_oper {Cos}}
+ {tan} {set calc_oper {Tan}}
+ {asin} {set calc_oper {ASin}}
+ {acos} {set calc_oper {ACos}}
+ {atan} {set calc_oper {ATan}}
+ default {
+ # Set foteground color to #FF0000 if content is invalid
+ set calc_oper {}
+ $calc_oper_widget configure -style Calculator_OperError.TEntry
+ return 1
+ }
+ }
+
+ # Set foreground color to default and return result (True)
+ $calc_oper_widget configure -style Calculator_Oper.TEntry
+ return 1
+ }
+
+ ## Negate content of the main display
+ # @return void
+ public method calc_NegateDis {} {
+ # Empty display -> abort
+ if {[reread_display] == {}} {
+ return
+
+ # Negate value
+ } {
+ if {[regexp {^\-} $calc_display]} {
+ set calc_display [string range $calc_display 1 end]
+ } {
+ set calc_display "-$calc_display"
+ }
+ }
+
+ # Write result
+ rewrite_display
+ }
+
+ ## Prepare object for creating its GUI
+ # @parm Widget _parent - parent widget (some frame)
+ # @parm List _calculatorList - List of initial values (displays,, memory, radix, angle unit)
+ # @return void
+ public method PrepareCalculator {_parent _calculatorList} {
+ set parent $_parent
+ set calculatorList $_calculatorList
+ set gui_initialized 0
+ }
+
+ ## Inform this tab than it has became active
+ # @return void
+ public method CalculatorTabRaised {} {
+ $calc_display_widget selection range 0 end
+ $calc_display_widget icursor end
+ focus $calc_display_widget
+ }
+
+ ## Initialize calculator GUI
+ # @return void
+ public method CreateCalculatorGUI {} {
+ if {$gui_initialized} {return}
+ set gui_initialized 1
+
+ # Create scrollable area
+ set scrollable_frame [ScrollableFrame $parent.scrollable_frame \
+ -xscrollcommand "$this calc_gui_scroll_set" \
+ ]
+ set horizontal_scrollbar [ttk::scrollbar $parent.horizontal_scrollbar \
+ -orient horizontal -command "$scrollable_frame xview" \
+ ]
+ pack $scrollable_frame -fill both -side bottom -expand 1
+ set parent [$scrollable_frame getframe]
+
+ # LEFT HALF
+
+ # create numeric keypad
+ set calc_num_keypad [frame $parent.calc_num_keypad]
+ makeKeypad $calc_num_keypad $calculator_keyboard
+
+
+ # RIGHT HALF
+
+ # create display
+ set calc_num_display [frame $parent.calc_num_display]
+ set frame0 [frame $calc_num_display.calc_num_display0]
+ set frame1 [frame $calc_num_display.calc_num_display1]
+
+ # Buffer display
+ set calc_buffer_widget [ttk::entry $frame0.calc_buffer \
+ -textvariable ::Calculator::calc_buffer$calc_idx \
+ -validate key \
+ -validatecommand "$this calc_validate %W %P" \
+ -width 13 \
+ -style Calculator_Buffer.TEntry \
+ ]
+ DynamicHelp::add $frame0.calc_buffer -text [mc "Buffer display"]
+ setStatusTip -widget $calc_buffer_widget \
+ -text [mc "Calculator buffer"]
+ # Operator display
+ set calc_oper_widget [ttk::entry $frame0.calc_oper \
+ -textvariable ::Calculator::calc_oper$calc_idx \
+ -validate all \
+ -width 3 \
+ -validatecommand "$this calc_oper_validate %P" \
+ -style Calculator_Oper.TEntry \
+ ]
+ DynamicHelp::add $frame0.calc_oper -text [mc "Selected operation"]
+ setStatusTip -widget $calc_oper_widget \
+ -text [mc "Selected operation"]
+ # Main display
+ set calc_display_widget [ttk::entry $frame0.calc_displ \
+ -textvariable ::Calculator::calc_displ$calc_idx \
+ -validate key \
+ -validatecommand "$this calc_validate %W %P" \
+ -width 13 \
+ -style Calculator_Display.TEntry \
+ ]
+ DynamicHelp::add $frame0.calc_displ -text [mc "Main display"]
+ setStatusTip -widget $calc_display_widget \
+ -text [mc "Main display"]
+ # Pack displays
+ pack $calc_buffer_widget -side left
+ pack $calc_oper_widget -side left
+ pack $calc_display_widget -side left
+ # Create binding for displays
+ bind $calc_buffer_widget <KP_Enter> "$this calc_Evaluate"
+ bind $calc_oper_widget <KP_Enter> "$this calc_Evaluate"
+ bind $calc_display_widget <KP_Enter> "$this calc_Evaluate"
+ bind $calc_buffer_widget <Return> "$this calc_Evaluate"
+ bind $calc_oper_widget <Return> "$this calc_Evaluate"
+ bind $calc_display_widget <Return> "$this calc_Evaluate"
+
+
+ ## Create: numeric base and angle unit switch + CA + C
+ frame $frame1.lf
+ # Numeric base switch
+ pack [ttk::combobox $frame1.lf.calc_base_CB \
+ -state readonly \
+ -values {Hex Dec Oct Bin} \
+ -textvariable ::Calculator::calc_base$calc_idx \
+ -width 4 \
+ ] -side left
+ bind $frame1.lf.calc_base_CB <<ComboboxSelected>> "$this cal_switchBase"
+ DynamicHelp::add $frame1.lf.calc_base_CB -text [mc "Numeric base"]
+ setStatusTip -widget $frame1.lf.calc_base_CB \
+ -text [mc "Numeric base"]
+ # Angle unit switch
+ pack [ttk::combobox $frame1.lf.calc_angle_CB \
+ -state readonly \
+ -values {rad deg grad} \
+ -textvariable ::Calculator::calc_angle$calc_idx \
+ -width 4 \
+ ] -side left
+ bind $frame1.lf.calc_angle_CB <<ComboboxSelected>> "$this cal_switchAngle"
+ DynamicHelp::add $frame1.lf.calc_angle_CB -text [mc "Angle unit"]
+ setStatusTip -widget $frame1.lf.calc_angle_CB \
+ -text [mc "Angle unit"]
+ pack $frame1.lf -side left -padx 5
+
+ frame $frame1.rf
+ # Button "Clear"
+ pack [ttk::button $frame1.rf.calc_Clear \
+ -text {C} \
+ -command "$this calc_Clear" \
+ -width 3 \
+ ] -side left
+ DynamicHelp::add $frame1.rf.calc_Clear \
+ -text [mc "Clear both displays"]
+ setStatusTip -widget $frame1.rf.calc_Clear \
+ -text [mc "Clear both displays"]
+ # Button "Clear actual"
+ pack [ttk::button $frame1.rf.calc_Clear_act \
+ -text {CA} \
+ -command "$this calc_ClearActual" \
+ -width 3 \
+ ] -side left
+ DynamicHelp::add $frame1.rf.calc_Clear_act \
+ -text [mc "Clear main display"]
+ setStatusTip -widget $frame1.rf.calc_Clear_act \
+ -text [mc "Clear main display"]
+ # Button "Negate"
+ pack [ttk::button $frame1.rf.calc_Negate_dis \
+ -text {+/-} \
+ -command "$this calc_NegateDis" \
+ -width 3 \
+ ] -side left
+ DynamicHelp::add $frame1.rf.calc_Negate_dis \
+ -text [mc "Negate value in main display"]
+ setStatusTip -widget $frame1.rf.calc_Negate_dis \
+ -text [mc "Negate value in main display"]
+ pack $frame1.rf -side right -padx 5
+
+ # Create calculator memory cells
+ for {set i 0} {$i < 3} {incr i} {
+ # Determinate ID of target frame
+ set frame_id [frame $calc_num_display.calc_num_display[expr $i + 2]]
+ # Label "Mx:"
+ pack [Label $frame_id.calc_mem_label_${i} \
+ -text "M$i: " -helptext [mc "Memory bank %s" $i]\
+ ] -side left
+ setStatusTip -widget $frame_id.calc_mem_label_${i} \
+ -text [mc "Memory bank %s" $i]
+ # Entry widget
+ set entry [ttk::entry $frame_id.calc_mem_entry_${i} \
+ -textvariable ::Calculator::calc_mem${i}_${calc_idx} \
+ -validate all \
+ -validatecommand "$this calc_validate %W %P" \
+ ]
+ DynamicHelp::add $frame_id.calc_mem_entry_${i} -text [mc "Memory bank %s" $i]
+ pack $entry -side left
+ set mem_entry_$i $entry
+ setStatusTip -widget $entry -text [mc "Memory bank %s" $i]
+ # Button "Save"
+ pack [ttk::button $frame_id.calc_mem_save_button_${i} \
+ -text [mc "Save"] \
+ -command "$this mem Save $i" \
+ -width 5 \
+ ] -side left
+ DynamicHelp::add $frame_id.calc_mem_save_button_${i} \
+ -text [mc "Save content of main display to this memory bank %s" $i]
+ setStatusTip -widget $frame_id.calc_mem_save_button_${i} \
+ -text [mc "Save content of main display to this memory bank %s" $i]
+ # Button "Load"
+ pack [ttk::button $frame_id.calc_mem_load_button_${i} \
+ -text [mc "Load"] \
+ -command "$this mem Load $i" \
+ -width 5 \
+ ] -side left
+ DynamicHelp::add $frame_id.calc_mem_load_button_${i} \
+ -text [mc "Load content of this bank into main display"]
+ setStatusTip -widget $frame_id.calc_mem_load_button_${i} \
+ -text [mc "Load content of memory bank %s into calculator main display" $i]
+ }
+
+ bind $mem_entry_0 <Up> "focus $mem_entry_2"
+ bind $mem_entry_0 <Down> "focus $mem_entry_1"
+
+ bind $mem_entry_1 <Up> "focus $mem_entry_0"
+ bind $mem_entry_1 <Down> "focus $mem_entry_2"
+
+ bind $mem_entry_2 <Up> "focus $mem_entry_1"
+ bind $mem_entry_2 <Down> "focus $mem_entry_0"
+
+
+ # TIMERS CALC
+
+ set calc_timers_calc [ttk::labelframe $parent.calc_timers_calc -text [mc "Timers preset"]]
+ makeTimersCalc $calc_timers_calc
+
+
+ # INNER INITIALIZATION
+
+ # pack "left side" of calculator
+ pack $calc_num_keypad -side left
+
+ # pack "right side" of calculator
+ for {set i 0} {$i < 5} {incr i} {
+ if {$i == 1} {
+ pack $calc_num_display.calc_num_display${i} -pady 10
+ } {
+ pack $calc_num_display.calc_num_display${i}
+ }
+ }
+ pack $calc_num_display -side left -padx 10
+
+ # pack timres calc
+ pack $calc_timers_calc -side left -expand 0 -anchor nw
+
+ ## save data given by $calculatorList
+ # "$base $angle $calc_display $calc_oper $calc_buffer $calc_mem0 $calc_mem1 $calc_mem2"
+ set base [lindex $calculatorList 0]
+ set angle [lindex $calculatorList 1]
+ if {
+ $base != {Hex} && $base != {Dec} &&
+ $base != {Oct} && $base != {Bin}
+ } {
+ set base [lindex ${X::project_edit_defaults} {3 1}]
+ puts stderr [mc "Invalid numerical base: '%s'" $base]
+ }
+ if {$angle != {rad} && $angle != {deg} && $angle != {grad}} {
+ puts stderr [mc "Invalid angle unit: '%s'" $angle]
+ set angle [lindex ${X::project_edit_defaults} {4 1}]
+ }
+ set ::Calculator::calc_base$calc_idx $base
+ set ::Calculator::calc_angle$calc_idx $angle
+
+ set last_base $base
+ set last_angle $angle
+
+ # Enable/Disable buttons on numeric keypad
+ switch -- $base {
+ {Hex} {
+ enable_buttons {0 1 2 3 4 5 6 7 8 9 A B C D E F}
+ disable_buttons {U RE}}
+ {Dec} {
+ enable_buttons {0 1 2 3 4 5 6 7 8 9}
+ disable_buttons {A B C D E F U RE}}
+ {Oct} {
+ enable_buttons {0 1 2 3 4 5 6 7}
+ disable_buttons {8 9 A B C D E F U RE}}
+ {Bin} {
+ enable_buttons {0 1}
+ disable_buttons {2 3 4 5 6 7 8 9 A B C D E F U RE}}
+ }
+
+ # Fill displays
+ set calc_display [lindex $calculatorList 2]
+ rewrite_display
+ calc_opr [lindex $calculatorList 3] 0
+ set calc_buffer [lindex $calculatorList 4]
+ rewrite_buffer
+ set ::Calculator::calc_mem0_$calc_idx [lindex $calculatorList 5]
+ set ::Calculator::calc_mem1_$calc_idx [lindex $calculatorList 6]
+ set ::Calculator::calc_mem2_$calc_idx [lindex $calculatorList 7]
+
+ # Set frequenci and mode in timers calculator
+ set freq [lindex $calculatorList 8]
+ set mode [lindex $calculatorList 10]
+ if {$freq == {} || [regexp {^\d\+$} $freq] || $freq < 0 || $freq > 99999} {
+ set freq 12000
+ }
+ if {$mode != 0 && $mode != 1 && $mode != 2} {
+ set mode 0
+ }
+ $timerscalc_freq_entry insert 0 $freq
+ $timerscalc_time_entry insert 0 [lindex $calculatorList 9]
+ $timerscalc_mode_spinbox delete 0 end
+ $timerscalc_mode_spinbox insert 0 $mode
+
+ # Unset teportary variables
+ unset parent
+ unset calculatorList
+ }
+
+ ## Get calculator list for later initialization
+ # @return List - resulting list of values
+ public method get_calculator_list {} {
+ if {!$gui_initialized} {CreateCalculatorGUI}
+ return [list $base $angle \
+ [$calc_display_widget get] \
+ $calc_oper \
+ [$calc_buffer_widget get] \
+ [subst "\$::Calculator::calc_mem0_$calc_idx"] \
+ [subst "\$::Calculator::calc_mem1_$calc_idx"] \
+ [subst "\$::Calculator::calc_mem2_$calc_idx"] \
+ [$timerscalc_freq_entry get] \
+ [$timerscalc_time_entry get] \
+ [$timerscalc_mode_spinbox get]]
+ }
+
+ ## Validate and evaluate content of Frequency entry (timers calculator)
+ # @parm String content - String to validate (and evaluate)
+ # @return Bool - result of validation
+ public method calc_timerscalc_freq_validate {content} {
+ # If validation disabled -> abort
+ if {$timerscalc_validation_dis} {
+ return 1
+ }
+ # If content is decimal number (max 5. digits) -> evaluate and return True
+ if {[regexp {^\d*$} $content] && ([string length $content] < 6)} {
+ calc_timerscalc_evaluate \
+ $content \
+ [$timerscalc_time_entry get] \
+ [$timerscalc_mode_spinbox get] \
+
+ return 1
+ }
+ # Otherwise -> return False
+ Sbar [mc "Calculator - timers preset: you are trying to insert an invalid value"]
+ return 0
+ }
+
+ ## Validate and evaluate content of Mode entry (timers calculator)
+ # @parm String content - String to validate (and evaluate)
+ # @return Bool - result of validation
+ public method calc_timerscalc_mode_validate {content} {
+ # If validation disabled -> abort
+ if {$timerscalc_validation_dis} {
+ return 1
+ }
+ # If the given value is one of {0 1 2} the evaluate and return True
+ if {[regexp {^\d?$} $content]} {
+ if {$content > 2} {
+ return 0
+ }
+ calc_timerscalc_evaluate \
+ [$timerscalc_freq_entry get] \
+ [$timerscalc_time_entry get] \
+ $content
+ return 1
+ }
+ # Otherwise -> return False
+ Sbar [mc "Calculator - timers preset: you are trying to insert an invalid value"]
+ return 0
+ }
+
+ ## Validate and evaluate content of Time entry (timers calculator)
+ # @parm String content - String to validate (and evaluate)
+ # @return Bool - result of validation
+ public method calc_timerscalc_time_validate {content} {
+ # If validation disabled -> abort
+ if {$timerscalc_validation_dis} {
+ return 1
+ }
+ # If content is decimal number (max 9. digits) -> evaluate and return True
+ if {[regexp {^\d*$} $content] && ([string length $content] < 10)} {
+ calc_timerscalc_evaluate \
+ [$timerscalc_freq_entry get] \
+ $content \
+ [$timerscalc_mode_spinbox get]
+ return 1
+ }
+ # Otherwise -> return False
+ Sbar [mc "Calculator - timers preset: you are trying to insert an invalid value"]
+ return 0
+ }
+
+ ## Highlight result of timer preset calculator
+ # @parm Bool valid - highlight for valid results
+ # @return void
+ private method calc_timerscalc_highlight {valid} {
+
+ # List of widgets to highlight
+ set widgets "
+ $timerscalc_THxDec_label
+ $timerscalc_THxHex_label
+ $timerscalc_THxOct_label
+ $timerscalc_TLxDec_label
+ $timerscalc_TLxHex_label
+ $timerscalc_TLxOct_label
+ $timerscalc_RepeatDec_label
+ $timerscalc_RepeatHex_label
+ $timerscalc_RepeatOct_label
+ $timerscalc_CorrectionDec_label
+ $timerscalc_CorrectionHex_label
+ $timerscalc_CorrectionOct_label
+ "
+
+ # Perform highlighting
+ if {$valid} {
+ foreach widget $widgets {
+ $widget configure -state normal
+ }
+ } {
+ foreach widget $widgets {
+ $widget configure -state disabled
+ }
+ }
+ }
+
+ ## Evaluate tmers preset (timers preset calculator)
+ # @parm Int freq - Frequency
+ # @parm Int time - Time in miliseconds
+ # @parm Int mode - Mode {0 1 2}
+ # @return Bool - Resulting status
+ private method calc_timerscalc_evaluate {freq time mode} {
+
+ # Set default results
+ set TLx 0
+ set THx 0
+ set repeat 0
+ set correction 0
+
+ # Check for validity of given values
+ if {$freq == {} || $freq == 0 || $time == {} || $mode == {} } {
+ set mode {invalid}
+ } {
+ # Compute time in machine cycles
+ set time [expr {int($time * (12000.0 / $freq))}]
+ }
+
+ # Perform computation for the given mode
+ switch -- $mode {
+ 0 {
+ # Determinate apparent number of repeats
+ set repeat [expr {($time >> 13) + 1}]
+ # Compute tempotary results
+ if {[expr {!($time & 0x1FFF)}]} {
+ incr repeat -1
+ set stepsPerIter 0x1FFF
+ } {
+ set stepsPerIter [expr {$time / $repeat}]
+ set tmp [expr {0x2000 - $stepsPerIter}]
+ set TLx [expr {$tmp & 0x1F}]
+ set THx [expr {$tmp >> 5}]
+ set correction [expr {$time - ((0x1FFF - $tmp) * $repeat)}]
+ }
+ }
+ 1 {
+ # Determinate apparent number of repeats
+ set repeat [expr {($time >> 16) + 1}]
+ # Compute tempotary results
+ if {[expr {!($time & 0xFFFF)}]} {
+ incr repeat -1
+ set stepsPerIter 0xFFFF
+ } {
+ set stepsPerIter [expr {$time / $repeat}]
+ set tmp [expr {0x10000 - $stepsPerIter}]
+ set TLx [expr {$tmp & 0xFF}]
+ set THx [expr {$tmp >> 8}]
+ set correction [expr {$time - ((0x10000 - $tmp) * $repeat)}]
+ }
+ }
+ 2 {
+ # Determinate apparent number of repeats
+ set repeat [expr {($time >> 8) + 1}]
+ # Compute tempotary results
+ if {[expr {!($time & 0xFF)}]} {
+ incr repeat -1
+ set stepsPerIter 0xFF
+ } {
+ set stepsPerIter [expr {$time / $repeat}]
+ set TLx [expr {0x100 - $stepsPerIter}]
+ set THx $TLx
+ set correction [expr {$time - ((0xFF - $THx) * $repeat)}]
+ }
+ }
+ {invalid} { ;# Invalid input data
+ calc_timerscalc_highlight 0
+ }
+ default { ;# Something went wrong
+ error "Calculator error: Invalid timer mode $mode"
+ return 0
+ }
+ }
+
+ # If pre-computation was performed succesfully -- finish the results
+ if {$mode != {invalid}} {
+ # Highlight results as valid
+ calc_timerscalc_highlight 1
+
+ # Perform correction
+ if {$correction >= $stepsPerIter} {
+ incr repeat [expr {$correction / $stepsPerIter}]
+ set correction [expr {$correction % $stepsPerIter}]
+ }
+ }
+
+ # Check for allowed length of results (string representation)
+ if {
+ [string length [format "%o" $repeat]] > 6
+ ||
+ [string length [format "%o" $correction]] > 6
+ } {
+ set TLx 0
+ set THx 0
+ set repeat 0
+ set correction 0
+ calc_timerscalc_highlight 0
+ Sbar [mc "Calculator: Unable to evaluate, result value is too high"]
+ }
+
+ ## Write results
+ # THx values
+ $timerscalc_THxDec_label configure -text $THx
+ $timerscalc_THxHex_label configure -text [format "%X" $THx]
+ $timerscalc_THxOct_label configure -text [format "%o" $THx]
+ # TLx values
+ $timerscalc_TLxDec_label configure -text $TLx
+ $timerscalc_TLxHex_label configure -text [format "%X" $TLx]
+ $timerscalc_TLxOct_label configure -text [format "%o" $TLx]
+ # Repeat values
+ $timerscalc_RepeatDec_label configure -text $repeat
+ $timerscalc_RepeatHex_label configure -text [format "%X" $repeat]
+ $timerscalc_RepeatOct_label configure -text [format "%o" $repeat]
+ # Correction values
+ $timerscalc_CorrectionDec_label configure -text $correction
+ $timerscalc_CorrectionHex_label configure -text [format "%X" $correction]
+ $timerscalc_CorrectionOct_label configure -text [format "%o" $correction]
+
+ return 1
+ }
+
+ ## Create widgets of timers preset calculator
+ # @parm widget parent - parent contaner (some frame)
+ # @return void
+ private method makeTimersCalc {parent} {
+ # TOP HALF
+ set top_frame [frame $parent.calc_timerscalc_top_frame]
+ # frequency
+ grid [label $top_frame.calc_timerscalc_freq_label \
+ -text [mc "Frequency \[kHz\]"] \
+ ] -row 0 -column 0 -sticky w
+ set timerscalc_freq_entry [ttk::entry \
+ $top_frame.calc_timerscalc_freq_entry \
+ -width 5 \
+ -validate all \
+ -validatecommand "$this calc_timerscalc_freq_validate %P" \
+ ]
+ grid $timerscalc_freq_entry -row 0 -column 1 -sticky we
+ # mode
+ grid [label $top_frame.calc_timerscalc_mode_label \
+ -text [mc "Mode"] \
+ ] -row 0 -column 2 -sticky w
+ set timerscalc_mode_spinbox [spinbox \
+ $top_frame.calc_timerscalc_mode_spinbox \
+ -bg {#FFFFFF} -highlightthickness 0 \
+ -from 0 -to 2 -width 1 -validate key \
+ -vcmd "$this calc_timerscalc_mode_validate %P" \
+ ]
+ grid $timerscalc_mode_spinbox -row 0 -column 3 -sticky we
+ # time
+ grid [label $top_frame.calc_timerscalc_time_label \
+ -text [mc "Time \[us\]"] \
+ ] -row 1 -column 0 -sticky w
+ set timerscalc_time_entry [ttk::entry \
+ $top_frame.calc_timerscalc_time_entry \
+ -width 8 \
+ -validate all \
+ -validatecommand "$this calc_timerscalc_time_validate %P" \
+ ]
+ grid $timerscalc_time_entry -row 1 -column 1 -sticky we -columnspan 3
+
+ # BOTTOM HALF
+ set bottom_frame [frame $parent.calc_timerscalc_bottom_frame]
+
+ # "dec" "hex" "oct"
+ grid [label $bottom_frame.calc_timerscalc_dec_label \
+ -text [mc "DEC"] -font $::smallfont -anchor e \
+ -highlightthickness 0 \
+ ] -row 0 -column 1 -ipadx 12
+ grid [label $bottom_frame.calc_timerscalc_hex_label \
+ -text [mc "HEX"] -font $::smallfont -anchor e \
+ -highlightthickness 0 \
+ ] -row 0 -column 2 -ipadx 12
+ grid [label $bottom_frame.calc_timerscalc_oct_label \
+ -text [mc "OCT"] -font $::smallfont -anchor e \
+ -highlightthickness 0 \
+ ] -row 0 -column 3 -ipadx 12
+
+ # "THx" "TLx" "Repeat" "Correction"
+ grid [label $bottom_frame.calc_timerscalc_thx_label \
+ -text "THx" \
+ ] -row 1 -column 0 -sticky w
+ grid [label $bottom_frame.calc_timerscalc_tlx_label \
+ -text "TLx" \
+ ] -row 2 -column 0 -sticky w
+ grid [label $bottom_frame.calc_timerscalc_repeat_label \
+ -text [mc "Repeats"] \
+ ] -row 3 -column 0 -sticky w
+ grid [label $bottom_frame.calc_timerscalc_correction_label \
+ -text [mc "Correction"] \
+ ] -row 4 -column 0 -sticky w
+
+ # THx values
+ set timerscalc_THxDec_label [label \
+ $bottom_frame.calc_timerscalc_THxDec_label \
+ -text "0" -disabledforeground {#AAAAAA} -fg {#000033} \
+ ]
+ set timerscalc_THxHex_label [label \
+ $bottom_frame.calc_timerscalc_THxHex_label \
+ -text "0" -disabledforeground {#AAAAAA} -fg {#000033} \
+ ]
+ set timerscalc_THxOct_label [label \
+ $bottom_frame.calc_timerscalc_THxOct_label \
+ -text "0" -disabledforeground {#AAAAAA} -fg {#000033} \
+ ]
+
+ # TLx values
+ set timerscalc_TLxDec_label [label \
+ $bottom_frame.calc_timerscalc_TLxDec_label \
+ -text "0" -disabledforeground {#AAAAAA} -fg {#000033} \
+ ]
+ set timerscalc_TLxHex_label [label \
+ $bottom_frame.calc_timerscalc_TLxHex_label \
+ -text "0" -disabledforeground {#AAAAAA} -fg {#000033} \
+ ]
+ set timerscalc_TLxOct_label [label \
+ $bottom_frame.calc_timerscalc_TLxOct_label \
+ -text "0" -disabledforeground {#AAAAAA} -fg {#000033} \
+ ]
+
+ # Repeat values
+ set timerscalc_RepeatDec_label [label \
+ $bottom_frame.calc_timerscalc_RepeatDec_label \
+ -text "0" -disabledforeground {#AAAAAA} -fg {#000033} \
+ ]
+ set timerscalc_RepeatHex_label [label \
+ $bottom_frame.calc_timerscalc_RepeatHex_label \
+ -text "0" -disabledforeground {#AAAAAA} -fg {#000033} \
+ ]
+ set timerscalc_RepeatOct_label [label \
+ $bottom_frame.calc_timerscalc_RepeatOct_label \
+ -text "0" -disabledforeground {#AAAAAA} -fg {#000033} \
+ ]
+
+ # Correction values
+ set timerscalc_CorrectionDec_label [label \
+ $bottom_frame.calc_timerscalc_CorrectionDec_label \
+ -text "0" -disabledforeground {#AAAAAA} -fg {#000033} \
+ ]
+ set timerscalc_CorrectionHex_label [label \
+ $bottom_frame.calc_timerscalc_CorrectionHex_label \
+ -text "0" -disabledforeground {#AAAAAA} -fg {#000033} \
+ ]
+ set timerscalc_CorrectionOct_label [label \
+ $bottom_frame.calc_timerscalc_CorrectionOct_label \
+ -text "0" -disabledforeground {#AAAAAA} -fg {#000033} \
+ ]
+
+ # Show widgets
+ grid $timerscalc_THxDec_label -row 1 -column 1 -sticky e
+ grid $timerscalc_THxHex_label -row 1 -column 2 -sticky e
+ grid $timerscalc_THxOct_label -row 1 -column 3 -sticky e
+ grid $timerscalc_TLxDec_label -row 2 -column 1 -sticky e
+ grid $timerscalc_TLxHex_label -row 2 -column 2 -sticky e
+ grid $timerscalc_TLxOct_label -row 2 -column 3 -sticky e
+ grid $timerscalc_RepeatDec_label -row 3 -column 1 -sticky e
+ grid $timerscalc_RepeatHex_label -row 3 -column 2 -sticky e
+ grid $timerscalc_RepeatOct_label -row 3 -column 3 -sticky e
+ grid $timerscalc_CorrectionDec_label -row 4 -column 1 -sticky e
+ grid $timerscalc_CorrectionHex_label -row 4 -column 2 -sticky e
+ grid $timerscalc_CorrectionOct_label -row 4 -column 3 -sticky e
+
+ # Make widgets in table as small as possible
+ foreach widget "
+ $bottom_frame.calc_timerscalc_dec_label
+ $bottom_frame.calc_timerscalc_hex_label
+ $bottom_frame.calc_timerscalc_oct_label
+ $bottom_frame.calc_timerscalc_thx_label
+ $bottom_frame.calc_timerscalc_tlx_label
+ $bottom_frame.calc_timerscalc_repeat_label
+ $bottom_frame.calc_timerscalc_correction_label
+ $timerscalc_THxDec_label
+ $timerscalc_THxHex_label
+ $timerscalc_THxOct_label
+ $timerscalc_TLxDec_label
+ $timerscalc_TLxHex_label
+ $timerscalc_TLxOct_label
+ $timerscalc_RepeatDec_label
+ $timerscalc_RepeatHex_label
+ $timerscalc_RepeatOct_label
+ $timerscalc_CorrectionDec_label
+ $timerscalc_CorrectionHex_label
+ $timerscalc_CorrectionOct_label
+ " {
+ $widget configure -bd 0 -relief raised -pady 0 -highlightthickness 0
+ }
+
+ # Pack frames
+ pack $top_frame -padx 5 -pady 2
+ pack $bottom_frame -padx 5 -pady 2
+
+ # Highlight calculator results as invalid
+ calc_timerscalc_highlight 0
+ set timerscalc_validation_dis 0
+ }
+
+ ## Create calculator keypad
+ # @parm widget parent - target contaner (some frame)
+ # @parm List definition - keypad definition (see class header)
+ # @return void
+ private method makeKeypad {parent definition} {
+ # Local variables
+ set row 0 ;# Current row in the grid
+
+ # Oterate over row definitions in the given keypad definition
+ foreach line $definition {
+ # Local variables
+ set col 0 ;# current column in the grid
+
+ # Iterate over button definitions in the row
+ foreach item $line {
+ if {$item == "separator"} {continue}
+
+ # Inicalize array of button features
+ for {set i 0} {$i < 13} {incr i} {
+ set parm($i) [lindex $item $i]
+ }
+
+ if {[lsearch -ascii -exact {A B C D E} $parm(0)] != -1} {
+ incr col
+ }
+
+ # Initialize default values for some items
+ foreach i {3 4 7} {
+ if {$parm($i) == {}} {set parm($i) 1}
+ }
+ if {$parm(6) == {}} {set parm(6) 2}
+ if {$parm(8) == {}} {set parm(8) 0}
+ if {$parm(9) == {}} {set parm(9) {#FFFFFF}}
+ if {$parm(10) == {}} {set parm(10) {#FFFFFF}}
+
+ if {[string index $parm(9) 0] == {#}} {
+ set parm(9) {Calculator}
+ }
+
+ # Set button ID
+ set path "$parent.calc_$parm(1)"
+ # Create button
+ ttk::button $path \
+ -text $parm(0) \
+ -command "$this $parm(2)" \
+ -width $parm(6) \
+ -style $parm(9).TButton
+# -activebackground $parm(10) \
+# -height $parm(7) \
+ DynamicHelp::add $path -text [mc $parm(5)]
+ # Confugure button
+# if {$parm(11) == 1} {$path configure -font $large_font -pady 2}
+ if {$parm(12) != {}} {
+ setStatusTip -widget $path -text [mc $parm(12)]
+ }
+
+ if {$parm(3) > 1} {
+ set sticky {we}
+ } elseif {$parm(4) > 1} {
+ set sticky {ns}
+ } else {
+ set sticky {}
+ }
+
+ # Show button
+ grid $path \
+ -columnspan $parm(3) \
+ -rowspan $parm(4) \
+ -sticky $sticky \
+ -padx 2 \
+ -pady 2 \
+ -column $col \
+ -row $row
+
+ # Incremet number of current column
+ incr col $parm(3)
+ }
+ # Incremet number of current row
+ incr row
+ }
+
+ grid columnconfigure $parent 4 -minsize 10
+ }
+
+ ## Adjust scrollbar for scrollable area
+ # @parm Float frac0 - 1st fraction
+ # @parm Float frac0 - 2nd fraction
+ # @return void
+ public method calc_gui_scroll_set {frac0 frac1} {
+ # Hide scrollbar
+ if {$frac0 == 0 && $frac1 == 1} {
+ if {[winfo ismapped $horizontal_scrollbar]} {
+ pack forget $horizontal_scrollbar
+ update
+ }
+ # Show scrollbar
+ } {
+ if {![winfo ismapped $horizontal_scrollbar]} {
+ pack $horizontal_scrollbar -fill x -side top -before $scrollable_frame
+ }
+ $horizontal_scrollbar set $frac0 $frac1
+ update
+ }
+ }
+}