views:

167

answers:

1

Hi everyone.

I am creating an application that has to interact with server data and then display the results from a database accordingly. I am writing the client side app in Cocoa.

Example: A user logs on to a web application. They have some options for filing a web report. Choices: single line and multiple line. They can choose how many of these fields they have for various variables that they want to input. This is then saved in a MYSQL database for later use.

Example (part 2): The client side application fetches the data in the MYSQL databases and then displays it. The problem is that it is a variable number of fields and a variable number of types.

In other words, the database basically stores if we want to display a NSSecureTextField, NSTextField, etc. and then displays that on the screen. As I pointed out above, the problem is that they are allowed to choose how many and the type of the element they want - so I am not quite sure how to transfer this to code.

And just to clarify, I am not attempting to build an online Interface Builder. Simply a online way to input data which has a variable amount of fields, and various types of these fields. I have the online system created, but I am having difficulty with the client side part.

Any help would be greatly appreciated!

+1  A: 

I'm not sure I understand what you're asking for. Isn't it pretty trivial to figure out how many NSTextFields the user wants and then have a little for() loop to create them? You'll probably want to keep track of the textfields, so I would probably do it like this:

NSMutableDictionary * interfaceElements = [[NSMutableDictionary alloc] init];

for (NSInteger i = 0; i < numberOfTextFields; ++i) {
  //this is just to make a frame that's indented 10px
  //and has 10px between it and the previous NSTextField (or window edge)
  NSRect frame = NSMakeRect(10, (i*22 + (i+1)*10), 100, 22);
  NSTextField * newField = [[NSTextField alloc] initWithFrame:frame];
  //configure newField appropriately
  [[myWindow contentView] addSubview:newField];
  [interfaceElements setObject:newField forKey:@"someUniqueIdentifier"];
  [newField release];
}

The dictionary of course would not be local to this method, but I think you get the idea.

Alternatively, you might be able to coerce NSMatrix into automating the layout for you.

If you're writing a client application for the iPhone, then I would highly recommend looking to the Settings Application Schema reference for inspiration. If you're unfamiliar with this, here's a brief introduction: The iPhone allows developers to move their preferences area from the actual app to the Settings app. This is done by creating a settings bundle and building a plist in a very specific way. Settings.app then discovers that plist, parses it, and builds an interface according to the definition it contains. You can do switches, textfields (even secure ones), sliders, groups, and a couple other kinds of interface elements.

Dave DeLong
Dave:Thanks for your reply. Maybe trivial for you, but I haven't used anything but Interface Builder for my layouts before. I think you are spot on when it comes to my question, "dynamically" show NSTextFields and the like to the screen. Thanks to your comments, I think that I basically get what is going on in the code... But how would you draw that NSMutableDictionary to the screen? Probably a very simple question (which I apologize for), but I am rather new to this whole mindset. This is for the desktop only, right now, but I thank you for your link to the iPhone recourse.
PF1
(Continued) And maybe I'm reading your post wrong, but isn't that a pretty automated layout already?Once again, thanks for your help.
PF1
@PF1 apologies; I understand that for those coming from IB-only interfaces, making stuff through code can still be a bit of voodoo. =) As for drawing the NSMD to the screen, you don't. That's what the "[[myWindow contentView] addSubview:newField]" line is doing. The NSMD simply serves to maintain a reference to the field (like a collection of IBOutlets) so that you can pull information from the fields later. And yes, this is somewhat automated in layout, in that it stacks NSTextFields on top of each other. But if you have more textfields than fit on the screen, you'll need an NSScrollView
Dave DeLong
@Dave Perfectly fine, I have excepted by now that generally when I think Cocoa can't do something I am proved wrong. ;) Anyway, I figured out what that line did when I tried leaving it off - the elements don't show up on the screen, obviously. And assuming you want to place these in a NSScrollView, couldn't you just place the view inside of that, or is that what the NSMatrix(ies) are for? In addition, how can I change the properties of the NSTextField like in IB? For instance, in IB you can make it multi-line, simple text, etc. I assume there must be some way in code (my previous point).
PF1
(Continued) Just as a note, this 600 character limit gets rather annoying at times. :) I just wanted to thank you again for your help as I was thinking that I would never find anyone to answer my question.
PF1
@PF1 Check out the documentation for NSTextField. Any property of a text field that you can set in IB can be set through code. The docs are here: http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSTextField_Class/index.html If you need a textfield to be secure, then you'll be creating an NSSecureTextField (which is a subclass of NSTextField). Other than that, you'll be able to do things like "[newField setBezeled:YES];", etc.
Dave DeLong
@Dave Thanks for all your help, it's working great now. I'll post back here with any other related questions, but for now, would you happen to have a link for further reading about this (maybe in the form of a tutorial to get the hang of it)?
PF1
@Dave Just one more question (hopefully) on this topic... Is there some way that I can "refresh" a scroll view to show all the content of the NSView. I believe that because you are drawing it dynamically, it doesn't refresh and therefore doesn't allow you to scroll.
PF1
@PF1 have you tried telling it to setNeedsDisplay:YES? That's the standard command to redraw an (NS|UI)View. Other than that, I'd just go dig in the docs for NSScrollView. Glad you're getting this to work, tho. Feel free to vote up the answer. =)
Dave DeLong
@Dave DeLong Unfortunitly, using setNeedsDisplay on the NSScrollView isn't seeming to fix the problem. So I'll do some more reading and see if I can fix it. On the same basic topic, is there some way that I can get the elements to expand as the page is increased? It is seeming that the NSRect just keeps it in that place no matter what. That is also a bit problematic when you have a LOT of content and it simply goes behind the next element. I suppose the real question is - "Is there any way to make the NSRect 'dynamic'?" Thanks for all your help.
PF1
@PF1 for resizing, you'll need to look at the setAutosizingMask: method, and then make sure that setAutoresizesSubviews: is set to YES on the containing superviews.
Dave DeLong
Hey Dave: Sorry to keep coming back to this question. But now I am attempting to use IFVerticallyExpandingTextfield (from: cocoadev.com/index.pl?IFVerticallyExpandingTextfi…). The problem is that when it expands, it covers over the other content. And I haven't found a combination of setAutosizingMask: that will correct this problem. Any ideas?
PF1
@PF1 I would ask a new question for your problem. =)
Dave DeLong
@Dave Will do, kind of figured this was old. ;-) The link to the new question is: http://stackoverflow.com/questions/1257865/dynamic-results-and-covering-data
PF1