picker;
NSButtonCell *cell;
NSMutableArray *cells = [NSMutableArray new];
int i, count;
NSSize size = [_pickerMatrix frame].size;
count = [_pickers count];
for (i = 0; i < count; i++)
{
cell = [[_pickerMatrix prototype] copy];
[cell setTag: i];
picker = [_pickers objectAtIndex: i];
[picker insertNewButtonImage: [picker provideNewButtonImage] in: cell];
[cells addObject: cell];
}
[_pickerMatrix renewRows: 0 columns: count];
[_pickerMatrix addRowWithCells: cells];
RELEASE(cells);
[_pickerMatrix setCellSize: NSMakeSize(size.width / count, size.height)];
[_pickerMatrix setTarget: self];
[_pickerMatrix setAction: @selector(_showNewPicker:)];
// use the space occupied by the matrix of color picker buttons if the
// button matrix is useless, i.e. it contains only one button
if (count < 2)
{
[_pickerBox setFrame: NSUnionRect([_pickerBox frame],
[_pickerMatrix frame])];
[_pickerBox setNeedsDisplay: YES];
// Display the only picker
if (count == 1)
[self _showNewPicker: _pickerMatrix];
}
}
- (void) _showNewPicker: (id)sender
{
_currentPicker = [_pickers objectAtIndex: [sender selectedColumn]];
[_currentPicker setColor: [_colorWell color]];
[_pickerBox setContentView: [_currentPicker provideNewView: NO]];
}
- (id) _initWithoutGModel
{
NSRect contentRect = {{352, 519}, {200, 270}};
NSSize maxContentSize = {500, 675};
NSRect topViewRect = {{0, 0}, {200, 270}};
NSRect magnifyRect = {{4, 230}, {50, 36}};
NSRect wellRect = {{58, 230}, {138, 36}};
NSRect matrixRect = {{4, 190}, {192, 36}};
NSRect splitRect = {{0, 0}, {200, 190}};
NSRect pickerViewRect = {{0, 40}, {200, 150}};
NSRect pickerRect = {{0, 20}, {200, 130}};
NSRect alphaRect = {{4, 4}, {160, 16}};
NSRect swatchRect = {{4, 4}, {200, 30}};
NSView *v;
NSButtonCell *pickerButton;
NSView *pickerView;
NSView *swatchView;
NSColorWell *well;
int i;
unsigned int style = NSTitledWindowMask | NSClosableWindowMask
| NSResizableWindowMask | NSUtilityWindowMask;
self = [super initWithContentRect: contentRect
styleMask: style
backing: NSBackingStoreRetained
defer: NO
screen: nil];
if (nil == self)
return nil;
[self setTitle: _(@"Colors")];
[self setBecomesKeyOnlyIfNeeded: YES];
[self setContentMinSize: contentRect.size];
[self setContentMaxSize: maxContentSize];
v = [self contentView];
_topView = [[NSView alloc] initWithFrame: topViewRect];
[_topView setAutoresizingMask: (NSViewWidthSizable | NSViewHeightSizable)];
[v addSubview: _topView];
RELEASE(_topView);
_magnifyButton = [[NSButton alloc] initWithFrame: magnifyRect];
[_magnifyButton setAutoresizingMask: (NSViewMaxXMargin | NSViewMinYMargin)];
[_magnifyButton setImage: [NSImage imageNamed: @"MagnifyGlass"]];
[_magnifyButton setBordered: YES];
[_magnifyButton setAction: @selector(_magnify:)];
[_magnifyButton setTarget: self];
[_topView addSubview: _magnifyButton];
_colorWell = [[NSColorWell alloc] initWithFrame: wellRect];
[_colorWell setAutoresizingMask: (NSViewWidthSizable | NSViewMinYMargin)];
[_colorWell setBordered: NO];
[_colorWell setTarget: self];
[_colorWell setAction: @selector(_updatePicker:)];
[_topView addSubview: _colorWell];
// Prototype cell for the matrix
pickerButton = [[NSButtonCell alloc] initImageCell: nil];
[pickerButton setButtonType: NSOnOffButton];
[pickerButton setBordered: YES];
_pickerMatrix = [[NSMatrix alloc] initWithFrame: matrixRect
mode: NSRadioModeMatrix
prototype: pickerButton
numberOfRows: 0
numberOfColumns: 0];
RELEASE(pickerButton);
[_pickerMatrix setAutoresizingMask: (NSViewWidthSizable | NSViewMinYMargin)];
[_pickerMatrix setCellSize: matrixRect.size];
[_pickerMatrix setIntercellSpacing: NSMakeSize(1, 0)];
[_pickerMatrix setAutosizesCells: YES];
[_topView addSubview: _pickerMatrix];
_splitView = [[NSSplitView alloc] initWithFrame: splitRect];
[_splitView setVertical: NO];
[_splitView setAutoresizingMask: (NSViewWidthSizable | NSViewHeightSizable)];
[_topView addSubview: _splitView];
pickerView = [[NSView alloc] initWithFrame: pickerViewRect];
[pickerView setAutoresizingMask: (NSViewWidthSizable | NSViewHeightSizable)];
_pickerBox = [[NSBox alloc] initWithFrame: pickerRect];
[_pickerBox setAutoresizingMask: (NSViewWidthSizable | NSViewHeightSizable)];
[_pickerBox setBorderType: NSNoBorder];
[_pickerBox setTitle: @""];
[_pickerBox setTitlePosition: NSNoTitle];
[pickerView addSubview: _pickerBox];
_alphaSlider = [[NSSlider alloc] initWithFrame: alphaRect];
[_alphaSlider setAutoresizingMask: (NSViewWidthSizable | NSViewMaxYMargin)];
[_alphaSlider setMinValue: 0.0];
[_alphaSlider setMaxValue: MAX_ALPHA_VALUE];
[_alphaSlider setFloatValue: MAX_ALPHA_VALUE];
[_alphaSlider setContinuous: YES];
[_alphaSlider setTitle: _(@"Opacity")];
[[_alphaSlider cell] setBezeled: YES];
[_alphaSlider setTarget: self];
[_alphaSlider setAction: @selector(_alphaChanged:)];
[pickerView addSubview: _alphaSlider];
_showsAlpha = YES;
swatchView = [[NSView alloc] initWithFrame: swatchRect];
[swatchView setAutoresizingMask: (NSViewWidthSizable | NSViewHeightSizable)];
// Add all the subviews at the end
[_splitView addSubview: pickerView];
[_splitView addSubview: swatchView];
RELEASE(pickerView);
RELEASE(swatchView);
// FIXME: This should be loaded form somewhere.
// Perhaps a colour list called "custom"?
for (i = 0; i < 14; i++)
{
NSColor *colour;
switch (i)
{
default:
case 0: colour = [NSColor greenColor]; break;
case 1: colour = [NSColor whiteColor]; break;
case 2: colour = [NSColor blackColor]; break;
case 3: colour = [NSColor blueColor]; break;
case 4: colour = [NSColor brownColor]; break;
case 5: colour = [NSColor cyanColor]; break;
case 6: colour = [NSColor darkGrayColor]; break;
case 7: colour = [NSColor grayColor]; break;
case 8: colour = [NSColor lightGrayColor]; break;
case 9: colour = [NSColor magentaColor]; break;
case 10: colour = [NSColor orangeColor]; break;
case 11: colour = [NSColor purpleColor]; break;
case 12: colour = [NSColor redColor]; break;
case 13: colour = [NSColor yellowColor]; break;
}
well = [[NSColorWell alloc] initWithFrame: NSMakeRect(i * 13 + 5, 5, 12, 12)];
[well setColor: colour];
[well setBordered: NO];
[well setEnabled: YES];
[well setTarget: self];
[well setAction: @selector(_bottomWellAction:)];
[swatchView addSubview: well];
RELEASE(well);
}
return self;
}
- (void) _alphaChanged: (id) sender
{
[self setColor: [[self color] colorWithAlphaComponent: [self alpha]]];
}
- (void) _apply: (id) sender
{
// This is currently not used
}
- (void) _magnify: (id) sender
{
NSEvent *currentEvent;
NSCursor *cursor;
[self _captureMouse: self];
/**
* There was code here to dynamically generate a magnifying glass
* cursor with a magnified portion of the screenshot in it,
* but changing the cursor rapidly on X seems to cause flicker,
* so we just use a plain magnifying glass. (dynamic code is in r33543)
*/
cursor = [[[NSCursor alloc] initWithImage: [NSImage imageNamed: @"MagnifyGlass"]
hotSpot: NSMakePoint(12, 13)] autorelease];
[cursor push];
NS_DURING
{
do {
NSPoint mouseLoc;
NSImage *img;
CREATE_AUTORELEASE_POOL(pool);
currentEvent = [NSApp nextEventMatchingMask: NSLeftMouseDownMask | NSLeftMouseUpMask | NSMouseMovedMask
untilDate: [NSDate distantFuture]
inMode: NSEventTrackingRunLoopMode
dequeue: YES];
mouseLoc = [self convertBaseToScreen: [self mouseLocationOutsideOfEventStream]];
img = [GSCurrentServer() contentsOfScreen: [[self screen] screenNumber]
inRect: NSMakeRect(mouseLoc.x, mouseLoc.y, 1, 1)];
if (img != nil)
{
NSBitmapImageRep *rep = (NSBitmapImageRep *)[img bestRepresentationForDevice: nil];
NSColor *color = [rep colorAtX: 0 y: 0];
[self setColor: color];
}
[pool drain];
} while ([currentEvent type] != NSLeftMouseUp &&
[currentEvent type] != NSLeftMouseDown);
}
NS_HANDLER
{
NSLog(@"Exception occurred in -[NSColorPanel _magnify:]: %@",
localException);
}
NS_ENDHANDLER
[NSCursor pop];
[self _releaseMouse: self];
}
- (void) _updatePicker: (id) sender
{
[self setColor: [_colorWell color]];
}
- (void) _bottomWellAction: (id) sender
{
[self setColor: [sender color]];
}
@end
/**TODO Description
*/
@implementation NSColorPanel
/*
* Class methods
*/
+ (void) initialize
{
if (self == [NSColorPanel class])
{
// Initial version
[self setVersion: 1];
_gs_gui_color_panel_lock = [NSLock new];
}
}
/**Creates ( if needed ) and returns the shared NSColorPanel.
*/
+ (NSColorPanel *)sharedColorPanel
{
if (_gs_gui_color_panel == nil)
{
[_gs_gui_color_panel_lock lock];
if (!_gs_gui_color_panel)
{
// if (![NSBundle loadNibNamed: @"ColorPanel" owner: self]);
// Keep this two lines separated so the check in [init] works.
_gs_gui_color_panel = [self alloc];
[_gs_gui_color_panel init];
}
[_gs_gui_color_panel_lock unlock];
}
return _gs_gui_color_panel;
}
/** Returns whether the NSColorPanel has been already created.
*/
+ (BOOL) sharedColorPanelExists
{
return (_gs_gui_color_panel == nil) ? NO : YES;
}
+ (void) setPickerMask: (int)mask
{
_gs_gui_color_picker_mask = mask;
}
/**
*/
+ (void) setPickerMode: (int)mode
{
_gs_gui_color_picker_mode = mode;
}
/**Drags aColor from sourceView at the location
give by the event anEvent ( [NSView-convertPoint:fromView:] ).
The type declared into the pasteboard is NSColorPboardType
See Also: [NSView-convertPoint:fromView:]
[NSView-dragImage:at:offset:event:pasteboard:source:slideBack:
*/
+ (BOOL) dragColor: (NSColor *)aColor
withEvent: (NSEvent *)anEvent
fromView: (NSView *)sourceView
{
NSPasteboard *pb = [NSPasteboard pasteboardWithName: NSDragPboard];
NSImage *image = [NSImage imageNamed: @"common_ColorSwatch"];
NSSize size;
NSPoint point;
[pb declareTypes: [NSArray arrayWithObjects: NSColorPboardType, nil]
owner: aColor];
[aColor writeToPasteboard: pb];
[image setBackgroundColor: aColor];
size = [image size];
point = [sourceView convertPoint: [anEvent locationInWindow] fromView: nil];
point.x -= size.width/2;
point.y -= size.width/2;
[sourceView dragImage: image
at: point
offset: NSMakeSize(0,0)
event: anEvent
pasteboard: pb
source: sourceView
slideBack: NO];
return YES;
}
/*
* Instance methods
*/
- (id) init
{
if (self != _gs_gui_color_panel)
{
RELEASE(self);
return _gs_gui_color_panel;
}
[self _initWithoutGModel];
[self _loadPickers];
[self _setupPickers];
[self setMode: _gs_gui_color_picker_mode];
[self setShowsAlpha: ![NSColor ignoresAlpha]];
return self;
}
- (void) dealloc
{
// As there is only one this will never be called
RELEASE(_topView);
RELEASE(_colorWell);
RELEASE(_magnifyButton);
RELEASE(_pickerMatrix);
RELEASE(_pickerBox);
RELEASE(_alphaSlider);
RELEASE(_splitView);
RELEASE(_pickers);
[super dealloc];
}
/** Returns the NSColorPanel's accessory view if it exists,
nil otherwise.
See Also: -setAccessoryView:
*/
- (NSView *) accessoryView
{
return _accessoryView;
}
/** Returns whether the NSColorPanel continuously sends its action message.
See Also: -setContinuous:-setAction: -setTarget:
*/
- (BOOL) isContinuous
{
return _isContinuous;
}
/** Returns the current mode of the NSColorPanel.
See Also: -setMode:
*/
- (int) mode
{
if (_currentPicker != nil)
return [_currentPicker currentMode];
else
return 0;
}
/** Sets the accessoryView to a view. The old view ( if exists ) will be
removed ( and released ). You need to retain it if you want to use
it later
See Also: -accessoryView
*/
- (void) setAccessoryView: (NSView *)aView
{
if (_accessoryView == aView)
return;
if (_accessoryView != nil)
[_accessoryView removeFromSuperview];
_accessoryView = aView;
[_splitView addSubview: _accessoryView];
}
/**Sets the NSColorPanl action method to aSelector The
action message is usally send in -setColor:, when the picker is updated,
when a new picker is shown, when the alpha is changed or when one of the
color wells at the bottom is selected.
*/
- (void) setAction: (SEL)aSelector
{
_action = aSelector;
}
/** Sets whether the NSColorPanel sends continuously action messages
See Also: -isContinuous
*/
- (void) setContinuous: (BOOL)flag
{
_isContinuous = flag;
}
/** Set the NSColorPanel mode to mode.
See Also: -mode
*/
- (void) setMode: (int)mode
{
int i, count;
if (mode == [self mode])
return;
count = [_pickers count];
for (i = 0; i < count; i++)
{
if ([[_pickers objectAtIndex: i] supportsMode: mode])
{
[_pickerMatrix selectCellWithTag: i];
[self _showNewPicker: _pickerMatrix];
[_currentPicker setMode: mode];
break;
}
}
}
/** Sets whether the NSColorPanel shows alpha values and the alpha
slider.
See Also: -showsAlpha
*/
- (void) setShowsAlpha: (BOOL)flag
{
if (flag == _showsAlpha)
return;
if (flag)
{
NSRect newFrame = [_pickerBox frame];
CGFloat offset = [_alphaSlider frame].size.height + 4.0;
[_alphaSlider setFrameOrigin: newFrame.origin];
[[_pickerBox superview] addSubview: _alphaSlider];
newFrame.origin.y += offset;
newFrame.size.height -= offset;
[_pickerBox setFrame: newFrame];
}
else
{
// Remove the alpha slider, and add its size to the pickerBox
[_alphaSlider removeFromSuperview];
[_pickerBox setFrame: NSUnionRect([_pickerBox frame],
[_alphaSlider frame])];
}
_showsAlpha = flag;
[_pickers makeObjectsPerformSelector: @selector(alphaControlAddedOrRemoved:)
withObject: self];
[_topView setNeedsDisplay: YES];
}
/** Sets the target object to anObject
*/
- (void) setTarget: (id)anObject
{
_target = anObject;
}
/** Returns whether the NSColorPanel shows alpha values and the alpha
slider
See Also: -setShowsAlpha:
*/
- (BOOL) showsAlpha
{
return _showsAlpha;
}
//
// Attaching a Color List
//
- (void) attachColorList: (NSColorList *)aColorList
{
[_pickers makeObjectsPerformSelector: @selector(attachColorList:)
withObject: aColorList];
}
- (void) detachColorList: (NSColorList *)aColorList
{
[_pickers makeObjectsPerformSelector: @selector(detachColorList:)
withObject: aColorList];
}
/** Returns the alpha value of the NSColorPanel. Returns
1.0 if the NSColorPanel does not show alpha
See Also: -showsAlpha -setShowsAlpha:
*/
- (CGFloat) alpha
{
if ([self showsAlpha])
return [_alphaSlider floatValue] / MAX_ALPHA_VALUE;
else
return 1.0;
}
/** Returns the current NSColor displayed by the NSColorPanel.
See Also : -setColor:
*/
- (NSColor *) color
{
return [_colorWell color];
}
/** Sets the NSColor displayed to aColor. This method posts a
NSColorPanelColorDidChangeNotification notification if needed.
See Also: -color [NSColorWell-setColor:]
*/
- (void) setColor: (NSColor *)aColor
{
[_colorWell setColor: aColor];
[_currentPicker setColor: aColor];
if ([self showsAlpha])
[_alphaSlider setFloatValue: [aColor alphaComponent] * MAX_ALPHA_VALUE];
// FIXME: to support [self isContinuous] the API between color pickers
// and NSColorPanel needs some changes. Currently the color panel is
// always continuous
[NSApp sendAction: @selector(changeColor:) to: nil from: self];
if ((_action) && (_target != nil))
[NSApp sendAction: _action to: _target from: self];
[[NSNotificationCenter defaultCenter]
postNotificationName: NSColorPanelColorDidChangeNotification
object: (id)self];
}
- (BOOL) worksWhenModal
{
return YES;
}
@end