Web Design & Development Blog
RSS Feed
Subscribe to my
RSS feed
RSS

The Web Design & Development Blog is written, coded and maintained by Duncan Midwinter. It regularly features articles on HTML, CSS, Javascript, PHP, Web Design and more…

Posts for tag: objective c 2

How I created a set of Pantone swatches for the Mac OSX color picker

For a long time now I have wanted to have a full set of Pantone swatches in the Mac OSX color picker. I searched for a quick solution online but never found anything. So in the end I realised that if this was going to happen I would have to do something about it myself…

pantone colors in the Mac OSX color picker
Pantone Swatches in the Mac OSX Color Picker

 

Stage 1 – getting a list of swatches

Whilst it’s very easy to create a custom color palette and add your own colors to it I had no particular desire to try and enter an entire Pantone swatch book by hand. A quick search online revealed several sites with lists of swatches and their respective rgb values. So that’s great – the difficult part has already been done by someone else! I checked out a few lists and in the end settled on this one: http://en.labelpartners.com/pantone_coated_table.html which gave a full set with hex and rgb values laid out in a <table> just perfect for scraping with php.

Stage 2 – scraping the data into a database

The next task was to get the data off the webpage and into a database. For tasks like this I always use PHP Simple HTML DOM Parser. It’s very easy to learn – and makes this kind of task very simple.

Before writing a script to scrape the data I set up a myqsl database ‘pantone_swatches’ with a table ‘coated_swatches’ to hold the data. The table structure was as follows:


CREATE TABLE `coated_swatches` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  `hex` varchar(7) DEFAULT NULL,
  `red` varchar(5) DEFAULT NULL,
  `green` varchar(5) DEFAULT NULL,
  `blue` varchar(5) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

At this point I wasn’t really sure if I needed the rgb values or the hex values so I decided to get everything just in case.

Now, with the database ready it was time to scrape the data. I wrote the following php script making use of PHP Simple HTML DOM Parser to sort through each table row (<tr>) and get the text content from each table data cell (<td>) and inset as a row in the database:


//connect to mysql...
$user="root";
$host="localhost";
$password="YOUR_PASSWORD_HERE";
$database="pantone_swatches";
$table="coated_swatches";
$cxn = mysqli_connect ($host, $user, $password, $database)
or die (mysqli_error($cxn));

//include simple html dom...
require('simple_html_dom.php');

//get page source...
$html = file_get_html('http://en.labelpartners.com/pantone_coated_table.html');

$count = 0;

//loop through each <tr>...
foreach($html->find('tr') as $row) {

	//extract values from each <td>...    
	$name 	= $row->find('td', 0)->innertext;		
	$hex 	= $row->find('td', 1)->innertext;
	$red 	= $row->find('td', 2)->innertext;
	$green 	= $row->find('td', 3)->innertext;
	$blue 	= $row->find('td', 4)->innertext;
	
	//ignore <table> 'header' row...
	if($count > 0) {
	
		echo $count.': '.$name.'<br>';
		
		//inset in to db...
		$query="
			INSERT INTO
			$table
			(name, hex, red, green, blue)
			VALUES
			('$name', '$hex', '$red', '$green', '$blue')
		";
		
		$result = mysqli_query ($cxn,$query) or die (mysqli_error($cxn));		
	}
	
	$count++;
}

Once the script was ready I launched it and waited for it to complete then checked out the new table to see if everything was OK. The script performed perfectly but now, how to get those values into the Mac OSX color picker?

Stage 3 – building a list of NSColors

You can manually create a custom color palette by opening the color picker, clicking on the third tab ‘color palettes’ and then clicking on the small ‘gear’ icon and selecting ‘new’. When you do this the new palette is saved in ~/Library/Colors/ with .clr for its file extension. The first thing I tried to do was open one of these .clr files in a text editor. Once I had tried that I quickly realised it wasn’t as simple as copying the structure and saving a new file! So, back to the internet and a bit more research revealed a way to generate a .clr file using Xcode. .clr files can be generated by creating a new NSColorList object and setting colors, like this:


//create list
NSColorList *list = [NSColorList.alloc initWithName:@"My Custom Color Palette"];

//add colors
[list setColor:[NSColor colorWithRed:0.831 green:0.835 blue:0.831 alpha:1.0] forKey:@"Custom Color 1"];
[list setColor:[NSColor colorWithRed:0.765 green:0.773 blue:0.769 alpha:1.0] forKey:@"Custom Color 2"];
[list setColor:[NSColor colorWithRed:0.725 green:0.733 blue:0.733 alpha:1.0] forKey:@"Custom Color 3"];

//save file to ~/Library/Colors/
[list writeToFile: [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Colors/"]];

So now, all I needed to do was generate the objective-c code from the data in the database, the only difference being that the rgb values in the database range from 0 to 255 whereas the rgb values for the NSColor class range from 0 to 1. This small difference was rectified by dividing the database rgb values by 255 and rounding the result to 3 decimal places. The code I used to output the objective-c code was as follows:


//connect to mysql...
$user="root";
$host="localhost";
$password="YOUR_PASSWORD_HERE";
$database="pantone_swatches";
$table="coated_swatches";
$cxn = mysqli_connect ($host, $user, $password, $database)
or die (mysqli_error($cxn));

//get data...
$query = "SELECT * FROM $table";
$result = mysqli_query ($cxn,$query)
		or die (mysqli_error($cxn));
		
$nrows = mysqli_num_rows ($result);

//loop through data...
for($i=0;$i<$nrows;$i++) {

	$row = mysqli_fetch_assoc ($result);
	extract ($row);
	
	//divide rgb values by 255 and echo...
	echo '[list setColor:[NSColor colorWithRed:'.round(($red/255),3).' green:'.round(($green/255),3).' blue:'.round(($blue/255),3).' alpha:1.0] forKey:@"Pantone '.$name.'"];<br />';	
}

Which when executed produced the following result:


[list setColor:[NSColor colorWithRed:0.996 green:0.867 blue:0 alpha:1.0] forKey:@"Pantone Yellow C"];
[list setColor:[NSColor colorWithRed:1 green:0.843 blue:0 alpha:1.0] forKey:@"Pantone Yellow 012 C"];
[list setColor:[NSColor colorWithRed:0.996 green:0.314 blue:0 alpha:1.0] forKey:@"Pantone Orange 021 C"];
// etc…
// etc…
// etc…

Stage 4 – using Xcode to generate the .clr file

To generate the final .clr file I opened Xcode and created a new project of type Cococa Application. Once this was ready I opened the AppDelegate.m file and where the comment ‘// Insert code here to initialize your application’ appeared in the – (void)applicationDidFinishLaunching:(NSNotification *)aNotification method I replaced it with the following:


NSColorList *list = [NSColorList.alloc initWithName:@"Pantone Coated"];

/* COPY AND PASTE THE GENERATED LIST OF COLORS HERE */

[list writeToFile: [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Colors/"]];

Once that was done I did a build and run and as soon as the application had launched I checked out the contents of my ~/Library/Colors/ folder to see a new Pantone Coated.clr file. The next thing to do was open an app (Sketch.app) and then open the color picker to check out the new color palette!

Using Pantone swatches in Sketch
Using Pantone swatches in Sketch

 

Conclusion

In hindsight the way I went about this was perhaps more lengthy that it could have been. There’s no reason why I couldn’t scrape the page and generate the objective-c code all in one step missing out the database. But as I was not sure how to proceed it seemed better to store the data then work out what to do next. Anyway here’s a short example that does just that:


//include simple html dom...
require('simple_html_dom.php');

//get page source...
$html = file_get_html('http://en.labelpartners.com/pantone_coated_table.html');

$count = 0;

echo 'NSColorList *list = [NSColorList.alloc initWithName:@"Pantone Coated"];';

//loop through each <tr>...
foreach($html->find('tr') as $row) {

	//extract values from each <td>...    
	$name 	= $row->find('td', 0)->innertext;		
	$hex 	= $row->find('td', 1)->innertext;
	$red 	= $row->find('td', 2)->innertext;
	$green 	= $row->find('td', 3)->innertext;
	$blue 	= $row->find('td', 4)->innertext;
	
	//ignore <table> 'header' row...
	if($count > 0) {
	
		//divide rgb values by 255 and echo objective-c code...
		echo '[list setColor:[NSColor colorWithRed:'.round(($red/255),3).' green:'.round(($green/255),3).' blue:'.round(($blue/255),3).' alpha:1.0] forKey:@"Pantone '.$name.'"];<br />';
			
	}
	
	$count++;
}

echo '[list writeToFile: [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Colors/"]];';

There are many sites online with lists of Pantone colors. I also creates a Pantone Pastels, Pantone Metallics and a set of CMYK swatches using the CMYK values and creating the NSColors like this:


[NSColor colorWithDeviceCyan: C_VALUE magenta: M_VALUE yellow: Y_VALUE black: K_VALUE alpha:1.0]

resources

Color Lists
http://en.labelpartners.com/pantone_coated_table.html
http://euro-bags.eu/pantone?limit=all
http://www.ediy.co.nz/pantone-to-rgb
http://www.umsiko.co.za/links/color.html
http://color2u.cocolog-nifty.com/color4u/archives.html
PHP Simple HTML DOM Parser
http://simplehtmldom.sourceforge.net

 

You can download an archive of compiled .clr containing a set of Pantone Coated, Metallic, Pastel and CMYK swatches on my resources page:
Pantone Swatches for the OSX Color Picker

xCode5 Cocoa bindings tutorial

Cocoa Bindings makes keeping your view objects and data objects in sync with minimum fuss and minimum code. This tutorial introduces the concept by demonstrating how to sync a slider with a text field that displays its value. Changing the slider will result in the text field being updated and vice versa.

1 Open xCode and create a new project. Select OSX and Application from the left column, then choose Cocoa Application and type ‘Cocoa Bindings Demo’ for the Product Name. Once you choose a location on your Mac to create the project you will be presented with a standard blank application containing an AppDelegate class and a MainMenu.xib file.

creating a new project in xCode

2 You’re going to be adding a slider and text field to the main application window, and then connecting their values using cocoa bindings but first you will need a variable to store this value, so you must create a controller class to store this value.

Select File -> New -> File… (or press cmd N), then select OSX and Cocoa from the left column and then choose Objective-C class and click Next.

adding a new class in xCode

Call the new class ‘AppController’ with a Subclass of NSObject, click Next and create the object.

3 Now you need to add the AppController class to the workbench in InterfaceBuilder, so click on the MainMenu.xib to open it and from the Object Library in the Utilities sidebar select Object and drag an instance to the workbench.

adding a new object to the workbench in xCode

Select the object in the workbench and click on the Identity Inspector in the Utilities sidebar. In the top section (Custom Class), click in the Class text field and type ‘AppController’ (you should find that it auto completes).

linking the object to the AppController in xCode

4 Now you can create the variable to hold the slider / text field value. Open the AppController.h and add an int. Call it sliderAmount. Your code should look like this:


#import <Foundation/Foundation.h>

@interface AppController : NSObject {
@private

	int sliderAmount;
	
}

@property int sliderAmount;

@end

You will also need to add a property, so that the int can be used with KVC and KVO, which is necessary for Cocoa Bindings to work.

Once that is done open the AppController.m and synthesize the sliderAmount. Your AppController.m file should look like this:


#import "AppController.h"

@implementation AppController

@synthesize sliderAmount;

@end

5 So now that you’ve got the Controller Class with an int to hold the value, it’s time to create the interface. Go back to the MainMenu.xib file and click on the Window object in the workbench to open the main application window. Once it is open, go to the Object Library and drag in a span class=”turquoise”>Horizontal Slider and a span class=”turquoise”>Text Field.

Note: In the example I’ve spent a bit of time sizing and positioning the objects, I’ve also given the slider tick marks, but I’ve left its default values of Minimum 0, Maximum 100 and Current 50.

designing the Application Window in Interface Builder

6 So now it’s time for you to bind the interface elements to the int value in the Controller Class.

Click on the slider to select it, then in the Utilities sidebar, click on the Bindings Inspector. You will see a list of all the various values that you can bind. In our case we want to bind the value of the slider, so click the disclosure triangle next to ‘Value’ and click on the checkbox Bind, then from the drop-down menu, select App Controller. Finally, under the field for Model Key Path you should see that it has the value self. Remove this and add the name of the int in the AppController class: sliderAmount (it should auto complete). The slider is now bound to the int value in the AppController class – you should see the correct key path next to Value in the Bindings inspector – (App Controller.sliderAmount).

the Bindings Inspector in xCode

7 So now our slider is correctly bound to the int value but on its own not much is going to happen! Now it’s time to bind the text field to the same int value. To do that we just repeat the exact same procedure that we used to bind the slider.

8 Now that both interface elements are bound to the same int value it’s time to build an run the app. You should see that when the slider is moved, the text field updates to the new value. It’s fine, but there’s something not quite right – two things actually…

Firstly, the value in the text field only updates when the slider is released and secondly, wasn’t the default value of our slider set to 50?

To get the slider / text filed to update in realtime as the slider is moved, select the slider then in the Utilities sidebar click on the Attributes inspector. Under the ‘control’ section check the checkbox ‘Continuous’. A quick build and run should show the value updating as the slider is moved.

making the slider continuous in xCode

As for the initial value of the slider: normally it would be initialised with the value in the current field of the Attributes inspector, but as the slider is now bound to the int value of sliderAmount it is initialised with that value. To get it to start at 50 (or any other amount for that matter), you need to add an -init method to your AppController class. So open your AppController.m file and edit the code as follows:


#import "AppController.h"

@implementation AppController

@synthesize sliderAmount;

- (id)init
{
	self = [super init];
	
	if(self) {
		
		sliderAmount = 50;
		
	}
	
	return self;
}

@end

A final build and run should see your slider and text field starting with an initial value of 50.

You can find a sample xCode project of this tutorial on my Resources page.

HOME