How can I disable a CPView? (so that the user can't interact with it while it's still visible)
It's useful for example when the user clicks on something that sends a request to the server and it should get disabled till the result comes back.
CPControls (as abstract subclass of CPView) contains a -setEnabled: method which most UI components inherit from.
http://cappuccino.org/learn/documentation/interface_c_p_control.html#a68d3dc4f2d0a4fad8699fd5982cddc2d
CPViews do not contain such a method, so in your CPView subclass you need to write your own method for enabling and disabling. Then override -mouseDown: and whatever else you need to (look at the docs for CPResponder for a complete list) and implement like so:
- (void)mouseDown:(id)sender
{
if ([self isEnabled])
[super mouseDown:sender];
}
Related
Can I use the item's tag attribute to store a special key/ID or is it meant for something else?
Example of intended use:
- (void)awakeFromNib {
[self.popup addItemWithTitle: [NSString stringWithFormat: #"dummy title" ]];
[[self.popup lastItem] setTag: 1658 ];
}
- (IBAction)popupAction: (id)sender {
[self someMethod: [sender selectedItem].tag];
}
yeah the tag of all controls is free for your devious use, you may use different numbers for different items, or to identify them as a kind of item, it is up to you.
As the documentation says:
You typically assign tags to menu items from Interface Builder, but you can also assign them programmatically using the setTag: method of NSMenuItem.
For further details, read the Application Menus and Pop-Up Lists and User Interface Validation guides. But the basic idea is that Cocoa doesn't care what you put there.
I believe the intended purpose is to let you loosely couple parts of your code together—the code that validates user actions doesn't have to know how your interface is designed, and your interface doesn't have to know anything about the validator; they just have to agree on a number. However, in modern Cocoa, it's just as easy, and even more loose, to just look at the action, so the tag is freed up for anything you want.
at the risk of a public flogging, I was hoping someone could clarify my understanding of communicating between the app controller and a window controller. Here is the scenario using xcode4.
using the default AppDelegate.h and .m as the "controller" (which is also a delegate to MainMenu.xib). Have an ivar called int counter.
Created page.xib and PageController.h and .m (subclass NSWindowController). Imported it into AppDelegate.m
Used IBAction to create and view the page object. Like this:
if (!page1) {
PageController *page1 = [[Page
if (!page1) {
page1 = [[PageControoer alloc] initWithWindowNibName:#"page"];
}
[page1 showWindow:sender];
So the new window pops and we can press buttons, etc. The code for the new window is all in PageController.h and .m. and things basically work.
That is the context, here is where I'm confused.
a) question: let's say I want to access that original ivar in AppDelegate.h called counter from PageController. Either retrieving or updating the variable. What approach would I take?
b) confirm: let's say I'm back in the AppDelegate and want to get access to a selector from page1. I believe I can do this as so: [page1 runaction]; or [[page1 variable] setStringValue:#"hello"];
(this complies but I'm not sure it really works because I can't get the changes into the xib view.)
ok and the stumper. Say another view was created with another view controller call it Page2Controller.h and .m.
c) how should data flow between page and page2 -> via the AppDelegate or directly? what would the syntax look like to connect them together?
I've been following tutorials, but they don't really cover this back and forth messaging. Thanks for all the help!
a) Generally, if you want to have data that is accessed by your controllers, it should be in a model which they are given access to in some way. You can access things in the app delegate using this method:
AppDelegate* appDelegate = [[NSApplication sharedApplication] delegate];
[appDelegate <some method>];
b) I don't understand what you're asking. If the app delegate has a pointer to page1, then yes, you can call it directly.
c) Again, you should have a data model of some sort. The controllers should update the data model when the user changes the view. You can use notifications, IBActions, and direct calls to do the updating, for example. You should look up the Model, View, Controller design pattern.
I feel like this should be rather simple but my google-foo is failing me right now. How can I have a button send actions to two things (in this case add a new Coredata object to an Array Controller and open the editing panel).
Thanks!
Call one method which does both things.
E.g.
- (void)doCoreDataStuff {
//Core Data Stuff
}
- (IBAction)buttonAction:(id)sender {
[self doCoreDataStuff];
// Show the edit panel
}
Link it up to the second method...
When coding with cocoa I've noticed that it's not necessary to have sender parameter when defining IBAction, hence following action:
- (IBAction)showUserInfo:(id)sender;
can be declared as
- (IBAction)showUserInfo;
So I'm wondering if there is any other benefit besides having the button/menu item that sent the action? Only other situation I can think of is having few objects calling same IBAction. Anything else?
Doc says,
The sender parameter usually identifies the control sending the action message (although it can be another object substituted by the actual sender). The idea behind this is similar to a return address on a postcard. The target can query the sender for more information if it needs to.
The sender parameter helps if you want any data from it. For example, on UISegmentControl value change, as in #Mark Adams answer. So if you don't want any information from the sender, you can just omit it, as in your - (IBAction)showUserInfo; example.
It can be handy to use the sender argument when you're connecting the method to UI objects whose values can change and you may need to work with.
For instance if I wired up a method to a UISegmentedControl and set it's control event to UIControlEventValueChanged, I can use the object passed as the sender: argument to obtain it's selected segment index and then, based on the value, make a change in the UI.
-(IBAction)segmentedControlValueChanged:(id)sender
{
UISegmentedControl *control = (UISegmentedControl *)sender;
// Show or hide views depending on the selected index of the segmented control.
if (control.selectedSegmentIndex == 0)
someView.hidden = YES;
else
someView.hidden = NO;
}
I have following requirements:
Obtain action associated with NSButton using : - (SEL)action
Call the obtained action.
Can we perform 2nd pt. Generally we invoke an action like this- [self abc:nil] just thinking if we can invoke the method obtained from 2nd pt. in same way!
Try:
SEL actionSelector = [button action];
[self performSelector: actionSelector withObject:nil];
The action is just a selector—the name of a method. Any number of objects may have a method by that name, and even if only one class implements the method, you may have any number of instances of that class. So, you can't just call the name of a method, because that doesn't express what object will respond to it. You need an object that implements that method, and you need to send that message by that name to that object.
The most likely object you want to send the action message to is the button's target, so get that, the same way you got its action, and send the message to that object. Or, better yet, send the button a performClick: message; if you want to simulate the user clicking the button, that's the way to do that.