PDA

View Full Version : how do you say an NSColor isVisible?




Darkroom
Jun 23, 2008, 08:26 AM
so for windows and panels i can write:

if (myWindow isVisible) {bla bla bla};


but if i want to say if my color is red:

if (NSColor = redColor) {doesn't work};
if (NSColor isEqual:redColor) {doesn't work, etc.};


any thoughts?



gnasher729
Jun 23, 2008, 08:33 AM
so for windows and panels i can write:

if (myWindow isVisible) {bla bla bla};


but if i want to say if my color is red:

if (NSColor = redColor) {doesn't work};
if (NSColor isEqual:redColor) {doesn't work, etc.};


any thoughts?

The way to send a message to an object is to write for example

[myWindow isVisible]

The way to use a result in an if-statement is to write for example

if (result) { ... }

If you want to use the result of sending a message to an object in an if-statement, you write for example

if ([myWindow isVisible]) { ... }

gnasher729
Jun 23, 2008, 08:41 AM
but if i want to say if my color is red:

if (NSColor = redColor) {doesn't work};
if (NSColor isEqual:redColor) {doesn't work, etc.};


any thoughts?

NSColor is a class. The expression "NSColor = redColor" looks like an assignment statement trying to assign something called redColor to a class named NSColor. What is that supposed to mean?

In the second if, we have something looking slightly like a method call. Let's change it to

if ([NSColor isEqual:redColor])

Now you compare send the isEqual message to the class NSColor. That doesn't make sense. The NSColor class itself cannot be red or green or blue, only objects of that class can. So say we have

NSColor* myColor = ...;
if ([myColor isEqual:redColor])

then I would think that you possibly meant the class method "redColor". You would write

if ([myColor isEqual: [NSColor redColor]]) { ... }

Darkroom
Jun 23, 2008, 08:41 AM
The way to send a message to an object is to write for example...


right, sorry... i forgot the square brackets...

i have the following function:


- (BOOL)validateMenuItem:(NSMenuItem *)item
{
int itemTag = [item tag];
if ((itemTag == 5 || itemTag == 6) && ([[NSColorPanel sharedColorPanel] isVisible]))
return NO;
if ((itemTag == 7 || itemTag == 8) && ([NSColor whiteColor]))
return NO;
return YES;
}


but it doesn't really do anything because im trying to say if the color is currently white, than return no... you know?

robbieduncan
Jun 23, 2008, 09:02 AM
is currently[/I] white, than return no... you know?

What colour? Or more accurately the colour of what? There is no general nebulous concept of the current colour...

lucasgladding
Jun 23, 2008, 09:06 AM
What are you trying to check for the color? My first guess would be the current color in the color panel. If this is the case, your check would be:


NSColorPanel *cp = [NSColorPanel sharedColorPanel];
NSColor *cpColor = [cp color];
if ([cpColor isEqual:[NSColor whiteColor])
{
// insert your code here
}


As gnasher suggested, you should be comparing against a variable instead of a class. In the example above, cpColor would be your color instance that you would check against the color white.

Note:
If you ever want to compare whether two colors are similar, you can get the individual color components of each, find the difference between the individual components, get the absolute values of the differences, then compare the sum of those against any tolerance.

Darkroom
Jun 23, 2008, 09:14 AM
the color of my NSView...

robbieduncan
Jun 23, 2008, 09:21 AM
the color of my NSView...

NSViews don't have a single colour, unless your view has a custom attribute which is it's colour (most NSViews have at least background and foreground colours).

Anyway you should ask your view for it's current colour and compare that with the other colour. There is no way the NSColor class can guess what the hell you are thinking there: it's not as clever as us and we couldn't :p

So assuming your custom NSView responds to -(NSColor *) color and we have an instance variable called myView pointing at the correct instance of the view something like this:


if ([myView color]==[NSColor whiteColor])
{
}

lucasgladding
Jun 23, 2008, 09:50 AM
robbieduncan is correct about creating an NSView color property or accessor method. For the code, however, you will need to use isEqual: instead of == . The == operator will return false as it compares the memory addresses rather than the color value. == typically is only used to compare scalar values.


if ([[myView color] isEqual:[NSColor whiteColor]])
{

}

robbieduncan
Jun 23, 2008, 10:07 AM
robbieduncan is correct about creating an NSView color property or accessor method. For the code, however, you will need to use isEqual: instead of == . The == operator will return false as it compares the memory addresses rather than the color value. == typically is only used to compare scalar values.

In general I agree with you, but my understanding of NSColor was that any given colour was singleton. For example [NSColor whiteColor]==[NSColor whiteColor] should return true as NSColor returns the same object every time for whiteColor instead of creating a new instance which is white...

lucasgladding
Jun 23, 2008, 10:33 AM
I didn't know that, thanks for the tip.

HiRez
Jun 23, 2008, 10:35 AM
In general I agree with you, but my understanding of NSColor was that any given colour was singleton. For example [NSColor whiteColor]==[NSColor whiteColor] should return true as NSColor returns the same object every time for whiteColor instead of creating a new instance which is white...They might be singletons, but does writing [NSColor redColor] give you the same object as, for example, [colorWithDeviceRed:1.0 green:0.0 blue:0.0 alpha:1.0]? Not sure. It's the same color but does Cocoa detect when you're trying to make red by components and hand you the singleton?

robbieduncan
Jun 23, 2008, 10:47 AM
They might be singletons, but does writing [NSColor redColor] give you the same object as, for example, [colorWithDeviceRed:1.0 green:0.0 blue:0.0 alpha:1.0]? Not sure. It's the same color but does Cocoa detect when you're trying to make red by components and hand you the singleton?

I'd have to say I'm not sure, but I suspect that it does not so the isEqual: method is probably safer. I'd hazard a guess that CMYK colours returned are also not equal to their RGB equivalents when using ==

Darkroom
Jun 23, 2008, 06:56 PM
NSViews don't have a single colour, unless your view has a custom attribute which is it's colour (most NSViews have at least background and foreground colours).

Anyway you should ask your view for it's current colour and compare that with the other colour. There is no way the NSColor class can guess what the hell you are thinking there: it's not as clever as us and we couldn't :p

So assuming your custom NSView responds to -(NSColor *) color and we have an instance variable called myView pointing at the correct instance of the view something like this:


if ([myView color]==[NSColor whiteColor])
{
}


humm... i'm sure you're right, and i've tried lots but still can't get it to work... currently, i have this code:


- (BOOL)validateMenuItem:(NSMenuItem *)item
{
if ((itemTag == 7 || itemTag == 8) && ([NSView color] isEqual:[NSColor whiteColor]))
return NO;
return YES;
}


i'm probably missing something... it seems that because the NSView is in a different class i can't access it maybe? eventhough i've imported that class at the top of this implementation file.

Catfish_Man
Jun 23, 2008, 07:46 PM
You're calling color on the *class* NSView, not a particular instance of it. That definitely won't work.

Darkroom
Jun 23, 2008, 08:12 PM
You're calling color on the *class* NSView, not a particular instance of it. That definitely won't work.

but if i make an instance variable in the header file

@interface ColorController : NSObject
{
NSView *myView;
}


and write this:

- (BOOL)validateMenuItem:(NSMenuItem *)item
{
if ((itemTag == 7 || itemTag == 8) && ([myView color]==[NSColor whiteColor]))
return NO;
return YES;
}


it still doesn't work. it keeps saying that NSView may not respond to color... driving me crazy... totally TOTALLY lost.

Catfish_Man
Jun 23, 2008, 08:32 PM
Well, you might read up the thread to where someone pointed out that NSView doesn't have a color method... I'm really not sure where you got that method name from.

lee1210
Jun 23, 2008, 08:35 PM
I don't really know what you're trying to achieve here... but maybe the reference documents will be helpful?
NSView reference:
http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSView_Class/Reference/NSView.html

Any methods with a + are called on the Class NSView. Anything with a - are called on an instance of NSView that you have instantiated.

NSColor reference:
http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Classes/NSColor_Class/Reference/Reference.html

Reviewing the NSView document there is nothing that returns an NSColor which you could compare to, for example [NSColor whiteColor], which returns an NSColor with preset values.

lucasgladding mentioned above something that you COULD compare an NSColor to, but I really have no idea what you're wanting to evaluate. Do you want to see if the window's background color is some value? The frame? Some text?

-Lee

Darkroom
Jun 23, 2008, 08:58 PM
Do you want to see if the window's background color is some value? The frame? Some text?

-Lee

the window background... the NSRect... but it's in a different class than my validateMenuItem function and i can't seem t reach it

lee1210
Jun 23, 2008, 09:16 PM
the window background... the NSRect... but it's in a different class than my validateMenuItem function and i can't seem t reach it

I don't think there's any NSRect involved here, but you can get the NSColor for your window background with:
NSColor *myBGColor = [[myView window] backgroundColor];
if([myBGColor isEqual: [NSColor whiteColor]]) {
//do something
}

This thread:
http://www.cocoabuilder.com/archive/message/cocoa/2005/5/3/134581

Discusses differences in color spaces. You may not have to worry about this, I can't say for sure.

Darkroom
Jun 23, 2008, 11:19 PM
thanks for the help everyone... i'm learning slowly but surely...

one new problem is that my About window, and every other Menu Item under the APPLICATION menu bar (except for hide, hide others, show all and quit) now makes the app crash... does having more than one validateMenuItem function in different classes cause problems? these menu items that cause the app to crash have a tag of 0 because i don't need to validate them, so i'm not sure what the problem is? it acts like a memory problem, but my app only use to crash before because i forgot to retain certain objects, so i only have experience with bad memory management... any thoughts?

lee1210
Jun 24, 2008, 09:32 AM
If we've resolved or mostly resolved the NSColor issue, it would be best if you posted a new question in a separate thread regarding your menu behavior. Someone who knows a great deal about menu setup may never look at a thread about NSColor.

-Lee

lucasgladding
Jun 24, 2008, 12:56 PM
Darkroom

I'm not sure whether or not your original question was ever answered...

Your view is likely a subclass of NSView. Assuming this to be correct, you should have an instance variable declared for the background color of the view as well as getter/setter methods (or an equivalent property).


@interface ColorView : NSView
{
NSColor *backgroundColor
}
- (NSColor *)backgroundColor;
- (void)setBackgroundColor:(NSColor *)newColor;


The other problem lies in the interface for your view controller. Make sure you declare your subclass not the superclass (NSView in this case). The class determines which methods are available to the object. Even if you initialize the object with your subclass, The compiler will look at the class name to determine which methods are available. You may have already written the accessors for the backgroundColor variable of the ColorView, but you have defined myView as an NSView.


@class ColorView;
@interface ColorController : NSObject
{
ColorView *myView;
}


Regarding the other problem, set a breakpoint in the validate method and use the debugger to check for problems. If you haven't already, read through the debugging sections of the Xcode user manual.

Best of luck

Darkroom
Jun 24, 2008, 11:33 PM
ok... still no go... i'll post the code of the 2 classes (windowColor and ColorController)... i'm assuming that some of the posted code isn't really applicable to this problem, so i apologize for posting it if it's not (fade outs, etc.). the problem code is near the bottom of the 2nd class (bolded and red):

NSView:

#import <Cocoa/Cocoa.h>
------------ windowColor.h ------------
@interface windowColor : NSView
{
NSColor *fillColor;
}

- (IBAction)changeColor:(id)sender;
- (IBAction)changeWhite:(id)sender;

@end


------------ windowColor.m ------------
#import "windowColor.h"

@implementation windowColor

- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
NSData *defaultViewColorData = [[NSUserDefaults standardUserDefaults] dataForKey:DEFAULTS_VIEW_COLOR_KEY];
if (defaultViewColorData != nil)
{
[fillColor release];
fillColor = [[NSUnarchiver unarchiveObjectWithData:defaultViewColorData] retain];
}
}
return self;
}

- (void)dealloc
{
[super dealloc];
[fillColor release];
}

- (IBAction)changeColor:(id)sender
{
NSData *defaultViewColorData = [NSArchiver archivedDataWithRootObject:[sender color]];
[[NSUserDefaults standardUserDefaults] setObject:defaultViewColorData forKey:DEFAULTS_VIEW_COLOR_KEY];
[fillColor release];
fillColor = [[sender color] retain];
[self setNeedsDisplay:YES];
}

- (IBAction)changeWhite:(id)sender
{
NSData *defaultViewColorData = [NSArchiver archivedDataWithRootObject:[NSColor whiteColor]];
[[NSUserDefaults standardUserDefaults] setObject:defaultViewColorData forKey:DEFAULTS_VIEW_COLOR_KEY];
[fillColor release];
fillColor = [[NSColor whiteColor] retain];
[self setNeedsDisplay:YES];
}

- (void)drawRect:(NSRect)rect
{
[fillColor set];
NSRectFill(rect);
}

@end


ColorController:

------------ ColorController.h ------------
#import <Cocoa/Cocoa.h>
#import "windowColor.h"

@interface ColorController : NSObject
{
IBOutlet windowColor *myColorSelection;
IBOutlet windowColor *myWhiteSelection;
NSTimer *timer;
}

- (IBAction)selectColor:(id)sender;
- (IBAction)selectWhite:(id)sender;

@end


------------ ColorController.m ------------
#import "ColorController.h"
#import "windowColor.h"
#import "HUDColorPanel.h"

@implementation ColorController

+ (void)initialize
{
[[HUDColorPanel class] poseAsClass:[NSColorPanel class]];
NSData *defaultViewColorData = [NSArchiver archivedDataWithRootObject:[NSColor whiteColor]];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *myDefaults = [NSDictionary dictionaryWithObject:defaultViewColorData forKey:DEFAULTS_VIEW_COLOR_KEY];
[defaults registerDefaults:myDefaults];
}

- (id)init
{
if (self = [super init])
{
[[NSColorPanel sharedColorPanel] setDelegate:self];
}
return self;
}

- (IBAction)selectColor:(id)sender
{
if ([[NSColorPanel sharedColorPanel] isVisible])
{
[[NSColorPanel sharedColorPanel] makeKeyAndOrderFront:nil];
}
else
{
[[NSColorPanel sharedColorPanel] makeKeyAndOrderFront:nil];
[[NSColorPanel sharedColorPanel] setAlphaValue:0.0];
timer = [[NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(colorPanelFadeIN:) userInfo:nil repeats:YES] retain];
}
}

- (void)colorPanelFadeIN:(NSTimer *)theTimer
{
if ([[NSColorPanel sharedColorPanel] alphaValue] < 1.0)
{
[[NSColorPanel sharedColorPanel] setAlphaValue:[[NSColorPanel sharedColorPanel] alphaValue] + 0.1];
}
else
{
[timer invalidate];
[timer release];
timer = nil;
}
[[NSColorPanel sharedColorPanel] setTarget:myColorSelection];
[[NSColorPanel sharedColorPanel] setAction:@selector(changeColor:)];
}

- (BOOL)windowShouldClose:(id)window
{
timer = [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(colorPanelFadeOUT:) userInfo:window repeats:YES];
return NO;
}

- (void)colorPanelFadeOUT:(NSTimer *)theTimer
{
NSWindow* window = [timer userInfo];
[window setAlphaValue:[window alphaValue] -0.1];
if([window alphaValue] <= 0.0)
{
[timer invalidate];
[window close];
}
}

- (IBAction)selectWhite:(id)sender
{
[myWhiteSelection changeWhite:nil];
}

#pragma mark Disable Menu Items

- (BOOL)validateMenuItem:(NSMenuItem *)item
{
int itemTag = [item tag];
if ((itemTag == 5 || itemTag == 6) && ([[NSColorPanel sharedColorPanel] isKeyWindow]))
return NO;
if ((itemTag == 7 || itemTag == 8) && (??? WHAT ??? == [color whiteColor]))
return NO;
return YES;
}

@end

lucasgladding
Jun 25, 2008, 12:44 AM
A couple notes:

As suggested in my earlier post, try adding getter and setter methods to your view class. You can remove some duplicate code by doing so.


- (NSColor *)fillColor
{
return fillColor;
}
- (void)setFillColor:(NSColor *)newColor
{
NSData *defaultViewColorData = [NSArchiver archivedDataWithRootObject:newColor];
[[NSUserDefaults standardUserDefaults] setObject:defaultViewColorData forKey:DEFAULTS_VIEW_COLOR_KEY];
[fillColor release];
fillColor = [newColor retain];
[self setNeedsDisplay:YES];
}


From your view controller:


...
if ((itemTag == 7 || itemTag == 8) && ([myWhiteSelection fillColor] == [NSColor whiteColor]))
...


Classes typically talk to each other through accessor methods. Take some serious time going through tutorials line for line before getting ambitious. It looks like you will also need to do some reading about class methods vs instance methods. Finally, be careful to review your own code before asking for input. Things like the missing brackets from your first post will deter help from most programmers.

Good luck

Darkroom
Jun 25, 2008, 02:24 AM
i've read one book on Objective-C, am currently reading a book on Cocoa Programming, and i've just ordered 2 more books on C and Objective C... after reading those i plan on reading the Cocoa Programming book again... learning is a process that's different for everyone... i learn a lot from example.

and it's still not working... it tells me that windowColor may not respond to fillColor...?

i will be continuing to learn cocoa programming after i manage to have this problem solved, and over time it will become easier... but for now, it's not easy... and i'm not sure how correct it is that some people feel they have to walk on egg shells for asking questions in a developer forum.

[EDIT] ok so at first i didn't really get what you were talking about (classes communicating thru accessors), and i sort of still don't, but i *think* i do now...

so to the view class i added:


.h file-------------------------------
- (NSColor *)fillColor;

.m file------------------------------
- (NSColor *)fillColor
{
return fillColor;
}


and the controller class i added as you suggested:

.m file------------------------------
- (BOOL)validateMenuItem:(NSMenuItem *)item
{
int itemTag = [item tag];
if ((itemTag == 5 || itemTag == 6) && ([[NSColorPanel sharedColorPanel] isKeyWindow]))
return NO;
if ((itemTag == 7 || itemTag == 8) && ([myWhiteSelection fillColor] == [NSColor whiteColor]))
return NO;
return YES;
}


i do not receive any compile errors, but ultimately it doesn't work. when the view is white, the menu item is still enabled.

[EDIT AGAIN] nevermind, it totally works now... i forgot to change the tags in interface builder :o

thanks to everyone for replying

lucasgladding
Jun 25, 2008, 08:01 AM
i've read one book on Objective-C, am currently reading a book on Cocoa Programming, and i've just ordered 2 more books on C and Objective C... after reading those i plan on reading the Cocoa Programming book again... learning is a process that's different for everyone... i learn a lot from example.

and it's still not working... it tells me that windowColor may not respond to fillColor...?

i will be continuing to learn cocoa programming after i manage to have this problem solved, and over time it will become easier... but for now, it's not easy... and i'm not sure how correct it is that some people feel they have to walk on egg shells for asking questions in a developer forum.

It's great that you're reading, but you should be pretty comfortable with what you have read before you move onto your own projects. Take the time to write and build the examples/tutorials provided in the books. Some of the issues you have had suggest that you should go back to re-read anything about class methods vs instance methods and getter and setter methods. I'm not trying to insult you, it's just that many of your questions should have been answered by examples in the books. Many of these issues are the kinds of things that I suspect are skimmed over by new programmers because they seem obvious.

I'm guessing that you haven't declared the getter/setter methods in your view's header file.

There is a very, very, very big difference between walking on egg shells and checking your code before coming to other programmers for help. It wasn't long ago that I began programming and I'm trying to help where I can on these forums. If you read your thread, you will see that many have corrected you about class methods vs instance methods and your last post still contained:


...[color whiteColor]...


Again, I'm sorry if I'm coming across as harsh, but you have missed some concepts that have been pointed out multiple times in this thread.

lucasgladding
Jun 25, 2008, 08:02 AM
Good to hear. Congrats on the success and good luck.