I am trying to create a basic RPN calculator on C#. Currently I am developing it using Monomac, as a Mac app, but I wanted to make it easier to port and develop for several platforms (I'm thinking about Android). For that purpose, rather than making all the buttons in Interface Builder, I am making everything(except the enter button, the field where the numbers are typed, and the area where the stack is shown) programmatically.
To achieve this, I made a class called AgnosticLayout
. You can create AgnosticLayouts
either with the Button
function, which creates a single button that executes an action, or the Horizontally
and Vertically
functions, which group AgnosticLayout
s together. The important method of this class is Display<T>
, which, given a way to turn single operations into T
s, and a way to group T
s together, returns a complete layout of type T:
so that I can describe my buttons as an AgnosticLayout
, and each platform is able to turn it into its own kind of GUI(in the case of Mac, into an NSView).
I already was able to implement the function that turns operations into buttons, and was able to show one, but I'm struggling with joining buttons.
My current function is:
NSView Joiner(IEnumerable<NSView> elems, bool isLeftRight)
{
NSView view = new NSView();
int i = 0; // used to give a unique key to each element
string[] keys = new string[elems.Count()];
NSView[] elemarray = new NSView[elems.Count()]; // array of elements to be fed to NSDictionary for the constraint
string visualformat;
if (isLeftRight) // Creating the visual format string
{
visualformat = "|-0-";
}
else
{
visualformat = "V:|-0-";
}
foreach (NSView elem in elems)
{
char a = (char) (i+97);
keys[i] = a.ToString();
elemarray[i] = elem;
i += 1;
view.AddSubview(elem);
visualformat += "[" + a.ToString() + "]-0-";
}
visualformat += "|";
NSDictionary elemsdict = NSDictionary.FromObjectsAndKeys(keys,elemarray);
view.AddConstraints (NSLayoutConstraint.FromVisualFormat (
visualformat,
NSLayoutFormatOptions.None,
new NSDictionary (),
elemsdict)
);
This is not only ugly as fuck, but also doesn't work. I get this when I run everything:
2013-11-10 14:00:14.971 CalculatorMac[2006:1007] -[NSButton copyWithZone:]: unrecognized selector sent to instance 0x6555bc0
2013-11-10 14:00:14.972 CalculatorMac[2006:1007] -[NSButton copyWithZone:]: unrecognized selector sent to instance 0x6555bc0
I suppose this is an ObjC exception rather than a C# one, which means that Cocoa is crashing, not the program itself. I don't know what the message means.
I haven't found any useful solution in Google, mainly because most of them are for ObjC, a language I do not understand.
Relevant files:
Calculator: two important classes live here, Calculator
(receives orders and keeps the stack) and AgnosticLayout
.
The buttons being displayed are those in Calculator.AgnosticLayout.DefaultLayout()
.
I know that the way to make unique names on Joiner
is ugly: I don't care about that yet, and I think it's working right atm, because if don't use any constraints at all the whole still fails.
Also, I come from playing in Haskell for a lot of time, and I don't have a lot of experience with OO, so if there is a more idiomatic way to do what I want to do, I'm all ears.
I am not sure that I see anything(not that I would know in this gibberish language;) ) but your error is coming from copying an NSButton, which doesn't adopt NSCopying...
this could happen if you are copying a button or using it as a key in a dictionary which implicitly retains it's objects and copies it's keys.
EDIT
your parameters are backwards here:
NSDictionary.FromObjectsAndKeys(keys,elemarray);
should be ->
NSDictionary.FromObjectsAndKeys(elemarray,keys);
so you are actually using the buttons as keys.