Create the RGBPickerProvider class

After the project is created, we need to create a class for our custom picker. In the src folder of your project, create a class called RGBPickerProvider. Make sure that you create both an .h file and a .cpp file (if you click New > Class to create the class, both of these files are created for you). Don't worry about creating method stubs; all of the code you need is generated and put into each file.

Complete the RGBPickerProvider header file

Open the RGBPickerProvider.h file first. We include PickerProvider as a supporting class, and make sure to use the bb and cascades namespaces so we don't have to use fully qualified names for the Cascades controls we use.

#include <bb/cascades/PickerProvider>

namespace bb {
    namespace cascades {}
}

Next, we override several functions in the RGBPickerProvider class.

class RGBPickerProvider: public bb::cascades::PickerProvider {
public:
	RGBPickerProvider();
	virtual ~RGBPickerProvider();
	VisualNode * createItem(Picker * pickerList, int columnIndex);
	void updateItem(Picker * pickerList, int columnIndex, 
    int rowIndex, VisualNode * pickerItem);
	int columnCount() const;
	void range(int column, int * lowerBoundary, int * upperBoundary);
	QVariant value(Picker * picker, const QList<int> & indices) const;
	
// ...

You can use the createItem() function to create and return a Control that you want to represent in a column.

You can use the updateItem() function to define the values for an item at a specific row and column.

You can use the columnCount() function to return the number of columns in your custom picker. The columnCount() function is run after your PickerProvider object is created.

You can use the range() function to return the boundaries for the columns in your custom picker. If you don't implement the range() function, your columns will scroll infinitely.

You can use the value() function to customize the value of the picker entries based on the columns you've specified. If you don't override value(), PickerProvider::value() returns a QList inside the QVariant which corresponds to the int values of each of your columns.

Finally, we declare a private function, hexOf(), that returns hex values for decimal values.

private:
	QString hexOf(int value) const;
};

Your finished RGBPickerProvider.h file should look like this:

#ifndef RGBPICKERPROVIDER_H_
#define RGBPICKERPROVIDER_H_

#include <bb/cascades/PickerProvider>

namespace bb {
    namespace cascades {
        class RGBPickerProvider: public bb::cascades::PickerProvider {
            public:
            	RGBPickerProvider();
            	virtual ~RGBPickerProvider();
            	VisualNode * createItem(Picker * pickerList, int columnIndex);
            	void updateItem(Picker * pickerList, int columnIndex, int rowIndex, 
                VisualNode * pickerItem);
            	int columnCount() const;
            	void range(int column, int * lowerBoundary, int * upperBoundary);
            	QVariant value(Picker * picker, const QList<int> & indices) const;
            
            private:
            	QString hexOf(int value) const;
        };
    }
}
#endif /* RGBPICKERPROVIDER_H_ */

Save and close the RGBPickerProvider.h file.

Provide the logic for RGBPickerProvider

Next, we must provide the logic for our custom picker. Open the RGBPickerProvider.cpp file and make sure that the class contains the following include statements:

#include <bb/cascades/Container>
#include <bb/cascades/Label>
#include <bb/cascades/Color>
#include "RGBPickerProvider.h"

namespace bb {
    namespace cascades {
        RGBPickerProvider::RGBPickerProvider() {}
        RGBPickerProvider::~RGBPickerProvider() {}
    }
}

Our constructors are empty. Let's define what happens when a picker item is created using RGBPickerProvider. First, we pass in a pickerList object, and add a Container object called returnItem to it. Then we create a Label in the Container and give it an objectName of desc that we populate when we update the pickerList object.

// Pass in pickerList when RGBPickerProvider is called
VisualNode * RGBPickerProvider::createItem
    (Picker * pickerList, int columnIndex) {
	Container * returnItem = Container::create();
	Label * desc = Label::create().objectName("desc");
	returnItem->add(desc);
	return returnItem;
}

Next, we need to update our pickerList object for the specific column and row entry in our custom picker. We create a Label in the Container to display the hex value of the color that the user has selected using the custom picker, and update the background color of the Container based on the current selection of picker entries. We define a float value for each of our red, green, and blue columns, and pass in rowIndex as a parameter for each entry. The Label is populated as a hex value of the rowIndex, and the text color in the Label is defined based on the current position in the rowIndex.

// Update pickerList for each entry in the picker
void RGBPickerProvider::updateItem(Picker * pickerList,
	int columnIndex, int rowIndex, VisualNode * pickerItem) 
{
		Container * container = (Container *)pickerItem;
		Label * desc = pickerItem->findChild<Label *>("desc");
		float red = (columnIndex == 0) ? (float)rowIndex / 255.0f : 0.0f;
		float green = (columnIndex == 1) ? (float)rowIndex / 255.0f : 0.0f;
		float blue = (columnIndex == 2) ? (float)rowIndex / 255.0f : 0.0f;
		container->setBackground(Color::fromRGBA(red, green, blue, 1.0f));
		desc->setText(hexOf(rowIndex));
		if (rowIndex < 128) {
			desc->textStyle()->setColor(Color::White);
		} else {
			desc->textStyle()->setColor(Color::Black);
		}
}

We define the columnCount() function to return the number of columns in our custom picker.

// Use columnCount() to return the number of columns
// in the picker
int RGBPickerProvider::columnCount() const {
	return 3;
}

Because we want the columns in our custom picker to have a fixed length, we specify a lowerBoundary and an upperBoundary in the range() function.

// Specify the range of the picker
void RGBPickerProvider::range(int column, int * lowerBoundary, 
    int * upperBoundary) {
	*lowerBoundary = 0;
	*upperBoundary = 255;
}

We provide a value() to customize the value of the picker based on the selections made in each of the columns. In this case, this function returns an RGB value in the form of #FFFFFF.

// Customize the value of the picker based on selection
QVariant RGBPickerProvider::value
    (Picker * picker, const QList<int> & indices) const 
{
    int red = indices.value(0);
    int green = indices.value(1);
    int blue = indices.value(2);
    QString stringValue = 
        QString("#") + hexOf(red) + hexOf(green) + hexOf(blue);
    return QVariant(stringValue);
}

Finally, we provide the logic for our hexOf() function to display our custom picker selections.

QString RGBPickerProvider::hexOf(int value) const {
	QString zero = "";
	if (value < 16) {
		zero = "0";
	}
	return QString::number(value, 16).toUpper().prepend(zero);
}

Your completed RGBPickerProvider.cpp file should now look like this:

#include <bb/cascades/Container>
#include <bb/cascades/Label>
#include <bb/cascades/Color>
#include "RGBPickerProvider.h"

namespace bb {
    namespace cascades {
        RGBPickerProvider::RGBPickerProvider() {}
        RGBPickerProvider::~RGBPickerProvider() {}
        
        // Pass in pickerList when RGBPickerProvider is called 
        VisualNode * RGBPickerProvider::createItem
            (Picker * pickerList, int columnIndex) 
        {
        	Container * returnItem = Container::create();
        	Label * desc = Label::create().objectName("desc");
        	returnItem->add(desc);
        	return returnItem;
        }
        
        // Update pickerList for each entry in the picker 
        void RGBPickerProvider::updateItem(Picker * pickerList, 
            int columnIndex, int rowIndex, VisualNode * pickerItem)
        {
        	Container * container = (Container *)pickerItem;
        	Label * desc = pickerItem->findChild<Label *>("desc");
        	float red = (columnIndex == 0) ? (float)rowIndex / 255.0f : 0.0f;
        	float green = (columnIndex == 1) ? (float)rowIndex / 255.0f : 0.0f;
        	float blue = (columnIndex == 2) ? (float)rowIndex / 255.0f : 0.0f;
        	container->setBackground(Color::fromRGBA(red, green, blue, 1.0f));
        	desc->setText(hexOf(rowIndex));
        	if (rowIndex < 128) {
        	    desc->textStyle()->setColor(Color::White);
        	} else {
        		desc->textStyle()->setColor(Color::Black);
        	}
        }
    
        // Use columnCount() to return the number of columns 
        // in the picker 
        int RGBPickerProvider::columnCount() const {
        	return 3;
        }
        
        // Specify the range of the picker 
        void RGBPickerProvider::range
            (int column, int * lowerBoundary, int * upperBoundary)
        {
        	*lowerBoundary = 0;
        	*upperBoundary = 255;
        }
        
        // Customize the value of the picker based on selection 
        QVariant RGBPickerProvider::value(Picker * picker, 
            const QList<int> & indices) const
        {
            int red = indices.value(0);
            int green = indices.value(1);
            int blue = indices.value(2);
            QString stringValue = 
                QString("#") + hexOf(red) + hexOf(green) + hexOf(blue);
            return QVariant(stringValue);
        }
    
        QString RGBPickerProvider::hexOf(int value) const {
        	QString zero = "";
        	if (value < 16) {
        		zero = "0";
        	}
        	return QString::number(value, 16).toUpper().prepend(zero);
        }
    }
} 

Last modified: 2015-03-31



Got questions about leaving a comment? Get answers from our Disqus FAQ.

comments powered by Disqus