Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //This example requires the 'Xamarin.Android GUI' option to be enabled
- //This is a calculator using Mono.CSharp.Evaluator to evaluate expressions
- //+ref=Mono.CSharp.dll
- using System;
- using System.Text.RegularExpressions;
- using System.IO;
- using Mono.CSharp;
- using Android.Widget;
- using Android.Content;
- using Android.Views.InputMethods;
- using System.Threading.Tasks;
- using NativeUiLib; //This adds the UI controls
- namespace CSharp_Shell
- {
- public static class Program
- {
- static Evaluator evaluator;
- static StringWriter sw; //Results and errors are printed here
- static string evalCodeStart = "public static class Calc { public static void Eval(){ result=";
- static EditText txtDisplay; //calculator display/result line
- static TextView lblError; //calculator evaluation error line
- static LinearLayout layNumpad;
- static LinearLayout layArithmetics;
- public static void Main()
- {
- var layMain = new LinearLayout(); //Primary layout
- layMain.Orientation = Orientation.Vertical;
- txtDisplay = layMain.AddEditText(true);
- txtDisplay.Click += txtDisplay_Click;
- lblError = layMain.AddTextView(true);
- var hpx = Ui.Context.Resources.DisplayMetrics.HeightPixels * 0.1;
- txtDisplay.SetMinHeight((int)hpx);
- var layHor = new LinearLayout(); //This layout will contains 2 others
- layHor.Orientation = Orientation.Horizontal;
- layMain.AddView(layHor); //Add to primary layout
- layNumpad = GenerateNumpad();
- layArithmetics = GenerateArithmetics();
- layHor.AddView(layNumpad);
- layHor.AddView(layArithmetics);
- //Set layNumpad and layArithmetics to take up a specific percantage of space
- var np= new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WrapContent);
- np.Weight = 0.85f;//Take up 85% of parent layout (parent layout is width=fill_parent)
- layNumpad.LayoutParameters = np;
- var ap= new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WrapContent);
- ap.Weight = 0.25f; //Take up 25% of parent layout
- layArithmetics.LayoutParameters = ap;
- layMain.Show(); //Show primary layout
- txtDisplay_Click(null, null);//Hide keyboard popup
- }
- //Hide the keyboard on click
- private static async void txtDisplay_Click(object sender, EventArgs args)
- {
- var im = ((InputMethodManager)Ui.Context.GetSystemService(Context.InputMethodService));
- await Task.Delay(10); //Hiding keyboard doesn't work without a delay
- im.HideSoftInputFromWindow(txtDisplay.WindowToken, Android.Views.InputMethods.HideSoftInputFlags.None);
- }
- private static LinearLayout GenerateNumpad()
- {
- //This layout is basically a table with 6 rows and 3 columns
- var linNum = new LinearLayout();
- linNum.Orientation = Orientation.Vertical;
- var linRow1 = new LinearLayout();
- linRow1.Orientation = Orientation.Horizontal;
- linRow1.AddView(NewCalcButton("1"));
- linRow1.AddView(NewCalcButton("2"));
- linRow1.AddView(NewCalcButton("3"));
- var linRow2 = new LinearLayout();
- linRow2.Orientation = Orientation.Horizontal;
- linRow2.AddView(NewCalcButton("4"));
- linRow2.AddView(NewCalcButton("5"));
- linRow2.AddView(NewCalcButton("6"));
- var linRow3 = new LinearLayout();
- linRow3.Orientation = Orientation.Horizontal;
- linRow3.AddView(NewCalcButton("7"));
- linRow3.AddView(NewCalcButton("8"));
- linRow3.AddView(NewCalcButton("9"));
- var linRow4 = new LinearLayout();
- linRow4.Orientation = Orientation.Horizontal;
- linRow4.AddView(NewCalcButton("0"));
- linRow4.AddView(NewCalcButton("."));
- linRow4.AddView(NewCalcButton("="));
- var linRow5 = new LinearLayout();
- linRow5.Orientation = Orientation.Horizontal;
- linRow5.AddView(NewCalcButton("("));
- linRow5.AddView(NewCalcButton(")"));
- linRow5.AddView(NewCalcButton("%"));
- var linRow6 = new LinearLayout();
- linRow6.Orientation = Orientation.Horizontal;
- linRow6.AddView(NewCalcButton("sqrt"));
- linRow6.AddView(NewCalcButton("pow"));
- linRow6.AddView(NewCalcButton("mod"));
- linNum.AddView(linRow1);
- linNum.AddView(linRow2);
- linNum.AddView(linRow3);
- linNum.AddView(linRow4);
- linNum.AddView(linRow5);
- linNum.AddView(linRow6);
- return linNum;
- }
- private static LinearLayout GenerateArithmetics()
- {
- var linArth = new LinearLayout();
- linArth.Orientation = Orientation.Vertical;
- linArth.AddView(NewCalcButton("+"));
- linArth.AddView(NewCalcButton("-"));
- linArth.AddView(NewCalcButton("*"));
- linArth.AddView(NewCalcButton("/"));
- linArth.AddView(NewCalcButton("DEL"));
- linArth.AddView(NewCalcButton("CLR"));
- return linArth;
- }
- //Helper method for adding buttons to the calculator
- private static Button NewCalcButton(string text)
- {
- var btn = new Button();
- btn.Text = text;
- btn.Click += PerformButtonAction;
- return btn;
- }
- //Decide what to do when a button is pressed
- private static void PerformButtonAction(object sender, EventArgs args)
- {
- var btn = (Button)sender;
- if (btn.Text == "=") Task.Run(()=> Calculate(txtDisplay.Text));
- else if (btn.Text == "CLR")
- {
- txtDisplay.Text = string.Empty;
- lblError.Text=string.Empty;
- }
- else if (btn.Text == "DEL") //Remove character at cursor
- {
- if (txtDisplay.Text.Length == 0) return;
- var ind = txtDisplay.SelectionStart;
- txtDisplay.Text = txtDisplay.Text.Remove(ind - 1, 1);
- txtDisplay.SetSelection(--ind);
- }
- else
- {
- var text = btn.Text;
- var ind = txtDisplay.SelectionStart;
- if (text == "pow") text = "pow(,)";
- else if (text == "sqrt") text = "sqrt()";
- else if (text == "mod") text = "mod()";
- txtDisplay.Text = txtDisplay.Text.Insert(ind, text);
- txtDisplay.SetSelection(ind + text.Length);
- }
- }
- private static void Calculate(string expr)
- {
- try
- {
- InitEvaluator();
- //Convert shorthand pseudo-methods into real ones
- expr = expr.Split('=')[0];
- expr = expr.Replace("pow", "Math.Pow");
- expr = expr.Replace("sqrt", "Math.Sqrt");
- expr = expr.Replace("mod", "Math.Abs");
- var ok = evaluator.Run(evalCodeStart + expr + ";}}"); //Create evaluation class
- if (!ok) throw new ApplicationException(sw.ToString());
- ok = evaluator.Run("Calc.Eval()"); //Start evaluatuion
- if (!ok || !string.IsNullOrWhiteSpace(sw.ToString()))
- {
- //throw exception due to evaluation error.
- throw new ApplicationException(sw.ToString());
- }
- //Show the result
- Ui.RunOnUiThread(()=>
- {
- txtDisplay.Text = txtDisplay.Text.Split('=')[0] + "=" + GetEvalResult();
- txtDisplay.SetSelection(txtDisplay.Text.Length);
- lblError.Text = string.Empty;
- });
- }
- catch(Exception ex)
- {
- //Show the exception message
- Ui.RunOnUiThread(()=>
- {
- lblError.Text = ex.Message;
- if (ex.InnerException != null)
- {
- lblError.Text += ex.InnerException.Message;
- }
- });
- }
- }
- //Get evaluator result variable and process it for display
- private static string GetEvalResult()
- {
- var errorRegex = @"\((\d*),\s*(\d*)\):(.*)";
- var res = evaluator.GetVars().Replace("object result = ", string.Empty).Trim();
- if (Regex.IsMatch(res, errorRegex))
- {
- var offset = evalCodeStart.Length + "using System;\nobject result;".Length;
- var matches = Regex.Matches(res, errorRegex);
- res = string.Empty;
- foreach (Match match in matches)
- {
- var pos = int.Parse(match.Groups[2].Value) - offset;
- var error = match.Groups[3].Value;
- res += $"{pos}: {error}";
- }
- }
- return res;
- }
- private static void InitEvaluator()
- {
- sw = new StringWriter();
- var setting = new CompilerSettings();
- var pr = new ConsoleReportPrinter(sw);
- var ctx = new CompilerContext(setting, pr);
- evaluator = new Evaluator(ctx);
- evaluator.Run("using System;"); //We probably need this
- evaluator.Run("object result;"); //Result variable, very important.
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement