Advertisement
nm9505

Thread Task

Nov 5th, 2023
764
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 8.47 KB | Science | 0 0
  1. //This example requires the 'Xamarin.Android GUI' option to be enabled
  2. //This is a calculator using Mono.CSharp.Evaluator to evaluate expressions
  3.  
  4. //+ref=Mono.CSharp.dll
  5. using System;
  6. using System.Text.RegularExpressions;
  7. using System.IO;
  8. using Mono.CSharp;
  9. using Android.Widget;
  10. using Android.Content;
  11. using Android.Views.InputMethods;
  12. using System.Threading.Tasks;
  13. using NativeUiLib; //This adds the UI controls
  14.  
  15. namespace CSharp_Shell
  16. {
  17.  
  18.     public static class Program
  19.     {
  20.         static Evaluator evaluator;
  21.         static StringWriter sw; //Results and errors are printed here
  22.         static string evalCodeStart = "public static class Calc { public static void Eval(){ result=";
  23.         static EditText txtDisplay; //calculator display/result line
  24.         static TextView lblError; //calculator evaluation error line
  25.         static LinearLayout layNumpad;
  26.         static LinearLayout layArithmetics;
  27.        
  28.         public static void Main()
  29.         {
  30.            var layMain = new LinearLayout(); //Primary layout
  31.            layMain.Orientation = Orientation.Vertical;  
  32.            txtDisplay = layMain.AddEditText(true);
  33.            txtDisplay.Click += txtDisplay_Click;
  34.            lblError = layMain.AddTextView(true);
  35.            var hpx = Ui.Context.Resources.DisplayMetrics.HeightPixels * 0.1;
  36.            txtDisplay.SetMinHeight((int)hpx);
  37.            
  38.            
  39.            var layHor = new LinearLayout(); //This layout will contains 2 others
  40.            layHor.Orientation = Orientation.Horizontal;  
  41.            layMain.AddView(layHor); //Add to primary layout
  42.  
  43.            layNumpad = GenerateNumpad();
  44.            layArithmetics = GenerateArithmetics();
  45.            
  46.            layHor.AddView(layNumpad);
  47.            layHor.AddView(layArithmetics);
  48.            
  49.            
  50.            //Set layNumpad and layArithmetics to take up a specific percantage of space
  51.            var np= new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WrapContent);
  52.            np.Weight = 0.85f;//Take up 85% of parent layout (parent layout is width=fill_parent)
  53.            layNumpad.LayoutParameters = np;
  54.            
  55.            var ap= new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WrapContent);
  56.            ap.Weight = 0.25f; //Take up 25% of parent layout
  57.            layArithmetics.LayoutParameters = ap;
  58.            
  59.            
  60.            layMain.Show(); //Show primary layout
  61.            txtDisplay_Click(null, null);//Hide keyboard popup
  62.            
  63.         }
  64.        
  65.         //Hide the keyboard on click
  66.         private static async void txtDisplay_Click(object sender, EventArgs args)
  67.         {
  68.             var im = ((InputMethodManager)Ui.Context.GetSystemService(Context.InputMethodService));
  69.             await Task.Delay(10); //Hiding keyboard doesn't work without a delay
  70.             im.HideSoftInputFromWindow(txtDisplay.WindowToken, Android.Views.InputMethods.HideSoftInputFlags.None);
  71.         }
  72.        
  73.         private static LinearLayout GenerateNumpad()
  74.         {
  75.             //This layout is basically a table with 6 rows and 3 columns           
  76.             var linNum = new LinearLayout();
  77.             linNum.Orientation = Orientation.Vertical;
  78.  
  79.             var linRow1 = new LinearLayout();
  80.             linRow1.Orientation = Orientation.Horizontal;
  81.             linRow1.AddView(NewCalcButton("1"));
  82.             linRow1.AddView(NewCalcButton("2"));
  83.             linRow1.AddView(NewCalcButton("3"));
  84.            
  85.             var linRow2 = new LinearLayout();
  86.             linRow2.Orientation = Orientation.Horizontal;
  87.             linRow2.AddView(NewCalcButton("4"));
  88.             linRow2.AddView(NewCalcButton("5"));
  89.             linRow2.AddView(NewCalcButton("6"));
  90.            
  91.             var linRow3 = new LinearLayout();
  92.             linRow3.Orientation = Orientation.Horizontal;
  93.             linRow3.AddView(NewCalcButton("7"));
  94.             linRow3.AddView(NewCalcButton("8"));
  95.             linRow3.AddView(NewCalcButton("9"));
  96.            
  97.             var linRow4 = new LinearLayout();
  98.             linRow4.Orientation = Orientation.Horizontal;
  99.             linRow4.AddView(NewCalcButton("0"));
  100.             linRow4.AddView(NewCalcButton("."));
  101.             linRow4.AddView(NewCalcButton("="));
  102.            
  103.             var linRow5 = new LinearLayout();
  104.             linRow5.Orientation = Orientation.Horizontal;
  105.             linRow5.AddView(NewCalcButton("("));
  106.             linRow5.AddView(NewCalcButton(")"));
  107.             linRow5.AddView(NewCalcButton("%"));
  108.            
  109.             var linRow6 = new LinearLayout();
  110.             linRow6.Orientation = Orientation.Horizontal;
  111.             linRow6.AddView(NewCalcButton("sqrt"));
  112.             linRow6.AddView(NewCalcButton("pow"));
  113.             linRow6.AddView(NewCalcButton("mod"));
  114.            
  115.             linNum.AddView(linRow1);
  116.             linNum.AddView(linRow2);
  117.             linNum.AddView(linRow3);
  118.             linNum.AddView(linRow4);
  119.             linNum.AddView(linRow5);
  120.             linNum.AddView(linRow6);
  121.            
  122.             return linNum;
  123.         }
  124.        
  125.         private static LinearLayout GenerateArithmetics()
  126.         {
  127.             var linArth = new LinearLayout();
  128.             linArth.Orientation = Orientation.Vertical;
  129.            
  130.             linArth.AddView(NewCalcButton("+"));   
  131.             linArth.AddView(NewCalcButton("-"));   
  132.             linArth.AddView(NewCalcButton("*"));   
  133.             linArth.AddView(NewCalcButton("/"));
  134.             linArth.AddView(NewCalcButton("DEL"));
  135.             linArth.AddView(NewCalcButton("CLR"));
  136.             return linArth;
  137.         }
  138.        
  139.         //Helper method for adding buttons to the calculator
  140.         private static Button NewCalcButton(string text)
  141.         {
  142.            var btn = new Button();
  143.            btn.Text = text;
  144.            btn.Click += PerformButtonAction;
  145.            return btn;
  146.         }
  147.        
  148.        
  149.         //Decide what to do when a button is pressed
  150.         private static void PerformButtonAction(object sender, EventArgs args)
  151.         {
  152.             var btn = (Button)sender;
  153.             if (btn.Text == "=") Task.Run(()=> Calculate(txtDisplay.Text));
  154.             else if (btn.Text == "CLR")
  155.             {
  156.                 txtDisplay.Text = string.Empty;
  157.                 lblError.Text=string.Empty;
  158.             }
  159.             else if (btn.Text == "DEL") //Remove character at cursor
  160.             {
  161.                 if (txtDisplay.Text.Length == 0) return;
  162.                 var ind = txtDisplay.SelectionStart;
  163.                 txtDisplay.Text = txtDisplay.Text.Remove(ind - 1, 1);
  164.                 txtDisplay.SetSelection(--ind);
  165.             }
  166.             else
  167.             {
  168.                 var text = btn.Text;
  169.                 var ind = txtDisplay.SelectionStart;
  170.                 if (text == "pow") text = "pow(,)";
  171.                 else if (text == "sqrt") text = "sqrt()";
  172.                 else if (text == "mod") text = "mod()";
  173.                
  174.                 txtDisplay.Text = txtDisplay.Text.Insert(ind, text);
  175.                 txtDisplay.SetSelection(ind + text.Length);
  176.             }
  177.         }
  178.        
  179.        
  180.         private static void Calculate(string expr)
  181.         {
  182.             try
  183.             {
  184.                 InitEvaluator();
  185.                
  186.                 //Convert shorthand pseudo-methods into real ones
  187.                 expr = expr.Split('=')[0];
  188.                 expr = expr.Replace("pow", "Math.Pow");
  189.                 expr = expr.Replace("sqrt", "Math.Sqrt");
  190.                 expr = expr.Replace("mod", "Math.Abs");
  191.                
  192.                 var ok = evaluator.Run(evalCodeStart + expr + ";}}"); //Create evaluation class
  193.                 if (!ok) throw new ApplicationException(sw.ToString());
  194.                 ok = evaluator.Run("Calc.Eval()"); //Start evaluatuion
  195.                 if (!ok || !string.IsNullOrWhiteSpace(sw.ToString()))
  196.                 {
  197.                     //throw exception due to evaluation error.
  198.                     throw new ApplicationException(sw.ToString());
  199.                 }
  200.                 //Show the result
  201.                 Ui.RunOnUiThread(()=>
  202.                 {
  203.                   txtDisplay.Text = txtDisplay.Text.Split('=')[0] + "=" + GetEvalResult();
  204.                   txtDisplay.SetSelection(txtDisplay.Text.Length);
  205.                   lblError.Text = string.Empty;
  206.                 });
  207.             }
  208.             catch(Exception ex)
  209.             {
  210.                 //Show the exception message
  211.                 Ui.RunOnUiThread(()=>
  212.                 {
  213.                     lblError.Text = ex.Message;
  214.                     if (ex.InnerException != null)
  215.                     {
  216.                        lblError.Text +=  ex.InnerException.Message;
  217.                     }
  218.                 });
  219.             }
  220.         }
  221.        
  222.         //Get evaluator result variable and process it for display
  223.         private static string GetEvalResult()
  224.         {
  225.             var errorRegex = @"\((\d*),\s*(\d*)\):(.*)";
  226.             var res = evaluator.GetVars().Replace("object result = ", string.Empty).Trim();
  227.             if (Regex.IsMatch(res,  errorRegex))
  228.             {
  229.                 var offset = evalCodeStart.Length +  "using System;\nobject result;".Length;
  230.                 var matches = Regex.Matches(res, errorRegex);
  231.                 res = string.Empty;
  232.                 foreach (Match match in matches)
  233.                 {
  234.                     var pos = int.Parse(match.Groups[2].Value) - offset;
  235.                     var error = match.Groups[3].Value;
  236.                     res += $"{pos}: {error}";
  237.                 }
  238.             }
  239.            
  240.             return res;
  241.         }
  242.        
  243.         private static void InitEvaluator()
  244.         {
  245.            sw = new StringWriter();
  246.            var setting = new CompilerSettings();
  247.            var pr = new ConsoleReportPrinter(sw);
  248.            var ctx = new CompilerContext(setting, pr);
  249.            evaluator = new Evaluator(ctx);
  250.            
  251.            evaluator.Run("using System;"); //We probably need this
  252.            evaluator.Run("object result;"); //Result variable, very important.
  253.         }
  254.     }
  255. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement