-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcalc-gui.cs
211 lines (185 loc) · 5.49 KB
/
calc-gui.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;
using static System.Console;
using System.Web.Script.Serialization;
using System.Linq;
public class CalcGui : Form
{
// add text box to form
private TextBox TB(Font f, ref Point p, int width, int cg) {
var tb = new TextBox();
tb.Location = p;
tb.Font = f;
tb.Width = width;
tb.ReadOnly = true;
tb.TextAlign = HorizontalAlignment.Right;
this.Controls.Add(tb);
p = p + new Size(0,tb.Height+cg);
return tb;
}
/*-------------------------------------------------------------------------
Script the button layout. This is much easier (and more reliable) to change
than a bunch of mousing around in form editor. Map ascii art into a list of
structs. This is used to dynamically create buttons.
*/
private struct ButtonLayout {
public int row; // 0,1,...
public int col; // 0,1,...
public string text; // eg: "+" or "bs"
public int width; // 1,2,...
};
private string ButtonLayoutString = @"
+---+---+---+---+---+
| 1 | 2 | 3 | + | C |
+---+---+---+---+---+
| 4 | 5 | 6 | - | bs|
+---+---+---+---+---+
| 7 | 8 | 9 | * | % |
+---+---+---+---+---+
| 0 | . | / | = |
+-------+---+---+---+
";
private List<ButtonLayout> GetButtonLayout() {
// get array of lines
var a1 = ButtonLayoutString.Split('\n');
// remove leading and trailing spaces in each line
var a2 = new List<string>();
foreach (string l in a1) {
var l1 = l.Trim();
a2.Add(l1);
}
// remove unneeded lines
var a3 = new List<string>();
foreach (string l in a2) {
if ( ("" != l) && ('+' != l[0]) ) {
a3.Add(l);
}
}
// get text items
var js = new JavaScriptSerializer();
var t = new List<List<string>>();
foreach (string l in a3) {
var l1 = l.Replace("|","");
var l2 = l1.Split(" ",StringSplitOptions.RemoveEmptyEntries);
var l3 = new List<string>(l2);
t.Add(l3);
}
//WriteLine(js.Serialize(t));
// get widths
var w = new List<List<int>>();
foreach (string l in a3) {
var l1 = l.Split("|",StringSplitOptions.RemoveEmptyEntries);
var w1 = new List<int>();
foreach(string l2 in l1) {
w1.Add(l2.Length);
}
w.Add(w1);
}
// assumes that there is one narrow button in first row
int cell_width = w[0].Min();
// convert width to multiples of smallest cell
var w2 = new List<List<int>>();
foreach (List<int> l in w) {
var w3 = new List<int>();
foreach(int i in l) {
w3.Add(i/cell_width);
}
w2.Add(w3);
}
//WriteLine(js.Serialize(w2));
// combine text and widths to get final layout
var lbl = new List<ButtonLayout>();
for (int i=0; i<t.Count; i++) {
var tr = t[i];
var wr = w2[i];
int k=0;
for (int j=0; j<tr.Count; j++) {
ButtonLayout bl;
bl.row = i;
bl.col = k;
bl.text = tr[j];
bl.width = wr[j];
lbl.Add(bl);
k += wr[j];
}
}
//WriteLine(js.Serialize(lbl));
return lbl;
}
/*------------------------------------------------------------------------
Initialize the window
*/
private TextBox tb_out;
private TextBox tb_in;
private TextBox tb_msg;
private Logic logic;
public CalcGui() {
Text = "P1 Calculator";
// form spacing
int bs = 80; // button size
int br = 4; // button rows
int bc = 5; // button columns
int cg = 20; // gap between controls
int wbf = 4; // window border fudge
// window width
int wx = bc*bs + (bc+1)*cg;
// text box width
int tbx = wx-2*cg;
// size of 1-wide and 2-wide buttons
var bs1 = new Size(bs,bs);
var bs2 = new Size(bs*2+cg,bs);
var font_btn = new Font("Microsoft Sans Serif", 20);
var font_in = new Font("Microsoft Sans Serif", 12);
var font_out = new Font("Microsoft Sans Serif", 20);
var font_msg = new Font("Microsoft Sans Serif", 10);
// starting location to add controls
var loc = new Point(cg-wbf,cg);
// input and output text boxes
var ti = TB(font_in, ref loc, tbx, cg);
var to = TB(font_out, ref loc, tbx, cg);
var tm = TB(font_msg, ref loc, tbx, cg);
// window height, now can set size
int wy = br*bs + (br+1)*cg + loc.Y;
Size = new Size(wx,wy);
// keep window from being resized
this.MinimumSize = this.Size;
this.MaximumSize = this.Size;
this.MaximizeBox = false;
// instantiate all the buttons
var lbl = GetButtonLayout();
foreach(ButtonLayout bl in lbl) {
var b = new Button();
b.Text = bl.text;
int x = bl.col*(bs+cg);
int y = bl.row*(bs+cg);
b.Location = loc + new Size(x,y);
int w = bl.width*bs + (bl.width-1)*cg;
b.Size = new Size(w,bs);
b.Font = font_btn;
b.Click += ButtonClick;
b.Visible = true;
this.Controls.Add(b);
}
// initialize members
this.tb_in = ti;
this.tb_out = to;
this.tb_msg = tm;
this.logic = new Logic();
}
private void ButtonClick(object sender, EventArgs e) {
var s = (sender as Button).Text;
//WriteLine($"clicked {s}");
bool ok = this.logic.DoKey(s);
string m = this.logic.GetError();
string i = this.logic.GetInputs();
string o = this.logic.Eval();
this.tb_in.Text = i;
this.tb_out.Text = o;
this.tb_msg.Text = m;
}
static public void Main() {
Application.Run(new CalcGui());
}
}