Creating a Color Selector Control

From Xojo Documentation

In this short tutorial we will see how to create a Color Selector control from scratch. This one will be very useful when you want to include an option so the user can change the drawing color for a given item in your user interface layout.

Through the tutorial we will see how:

  • Create our own controls based on the Canvas class.
  • How to use some of the Graphic class methods to do drawing.
  • How to implement Event Handlers and even redefine them so they are available again from any of the instances based on the class.
  • How to use some useful Color shared methods so our control automatically react to changes between Dark and Clear modes.

Create your own Canvas-based subclass

Canvas is the class you use to create your own custom drawing in Xojo: from buttons to any other kind of control.

For our short tutorial, let's start with creating a new Desktop project. Then, add a new Class from Insert > Class. This item will be added to the Project Browser (leftmost area in the IDE).

Select the just added class in the Project Browser to access its Inspector Panel. There you'll change the following attributes with the given values:

  • Name: ColorSelector
  • Super: Canvas

When we create a new class, we have the option to fill-in the Super field. That means that we enter here an already existing class, then our subclass will inherit and implement all the available properties, methods and events that such class may offer; and that means less code to write!

At this point, we know that our subclass (new data type) has the name of ColorSelector; and that is based on a Canvas class.

A property to store the selected color

The main purpose of our subclass is to store the color selected by the user. We'll be using the OS native dialog to do that; so we need to clearly define a Property to store the value (think about it as a special kind of variable that lives on every class instance).

With our "ColorSelector" still selected in the Project Browser, add a property from Insert > Property; changing these attributes from the Inspector Panel:

  • Name: SelectedColor
  • Type: Color
  • Scope: Public

Selecting the Color

In order to give our users the option to select any color using the native OS dialog, let's add to our ColorSelector class the MouseDown Event. Make sure you still have the ColorSelector item selected in the Project Browser, and then select Insert > Event Handler.

The Event Handler panel will appear, offering all the possible Event Handlers you can implement from those inherited from its Super class. Select MouseDown and confirm your selection. That will bring you into the Code Editor associated with that Event. That it's, the code that will be executed every time the event is raised in response to the user of the control clicking on its area (width and height).

Write the following lines in the Code Editor:

Call Color.SelectedFromDialog(SelectedColor,"")
return RaiseEvent MouseDown(x,y)

The first line of code calls the Color.SelectedFromDialog shared method, passing as its first argument our SelectedColor property, so it can store into it the color value selected by the user. The magic from this shared method is that you don't need to take care of displaying a propper color selector dialog to the user on every OS, the Xojo Framework takes care of it on all the supported OSes: Windows, macOS and Linux!

The second line of code instructs the control to "repainting" itself, because we did something that probably changed its visual representation (in this case, the selected color).

What return RaiseEvent MouseDown(x,y) does it means?

Don't forget that we are creating a class … and if our class consumes a given Event Handler that means that it will not be available for the real control instances we will use in our user interface layouts … except that we redefine it. In that case, that line of code will mean something like "ok, call this same event handler on the instance control that is based on me". And, of course, we will do that using the same event handler signature and passing along the expected parameters.

Defining a new Event Handler

Defining a new Event Handler for our class (and, thus, available for all the instances based on that class) is a pretty simple process in Xojo.

Make sure that the ColorSelect item is still selected in the Project Browser and, then, choose the option Event Definition from the Insert menu.

The previous option will add a new Event Handler Definition into the Class, so we only need to modify the name, parameters and expected returned value from the Inspector Panel. In this case, using these values:

  • Event Name: MouseDown
  • Parameters: X As Integer, Y As Integer
  • Return Type: Boolean

As you can see, this is exactly the same Event Handler signature that the one we added to our class!

Let's paint it!

We have everything set up … except displaying to our control user what the current selected color is. We need to add a second Event Handler for that: Paint.

The Paint event is where you designate how any Canvas based control will display to the user. For that, you can use any of the drawing methods available under the Graphics class. With them, you can control from the drawing color you need in every piece of the drawing, filling a specific control area using the current drawing color, draw simple or complex polygons, etc.

Once added the Pain Event Handler to the ColorSelector class, write the following code in the associated Code Editor:

g.DrawingColor = If(Color.IsDarkMode,&ccccccc,&c000000)
g.DrawingColor = Color.FillColor
g.DrawingColor = SelectedColor
g.FillRectangle(4,4, g.Width-8, g.Height-8)

As you can see, our control drawing is quite simple. The Paint Event Handler receives a Graphics object as its first argument, so we can use it to do all the needed drawing.

Maybe the most interesting line is the first one, because it decides what drawing color to use if the OS is in Dark Mode or not; and to get informed about that we only need to call the IsDarkMode shared method from the Color class itself. The IsDarkMode method will return True if the OS is in Dark Mode and False if not. That will be the color we will use to draw the external marquee of our control, so it looks right both in Dark and Clear modes.

We also use other convenience shared method from the Color class (FillColor) so we can safely fill our control background using the systemwide configured color for that, even when the OS changes between Dark and Clear modes.

Finally, we assign our SelectedColor color value to the DrawingColor property of the "g" (Graphics) variable, and simply fill a rectangle using that color. This will be the visual clue to the user about the current selected color.

Putting our ColorSelector to Work

Is time to test our ColorSelect class! Select the Window1 item in the Project Browser. That will bring-in the Layout Editor for that window. Now, in order to add a new instance (control) of our class, we only need to drag the ColorSelector item from the Project Browser and drop it into the Layout Editor. That's all!

Run the project and click on the ColorSelector control. It will display the panel letting you to select any desired color and, as soon you close that panel, the control will redraw itself to display the selected color.

Of course, when you need to use the selected color in your code you just need to read the SelectedColor property from the instance. for example, something like:

Var CurrentColor as Color = ColorSelector1.SelectedColor