Managing Plug-in Resources

From Code::Blocks


Prerequisites

Please read the tutorial Creating a simple "Hello_World" plugin before starting this tutorial

This tutorial assumes you have a working version of Code::Blocks installed and some knowledge of how to deal with projects, in particular how to compile them. In order to use the Code::Blocks SDK you must also have a working version of wxWidgets installed. For more information see Compiling wxWidgets 2.6.2 to develop Code::Blocks

REVISE THIS...To develop Code::Blocks plugins you will also need a copy of the Code::Blocks SDK, which can be found on the Code::Blocks download page. Install this to somewhere sensible that you will remember later on. Personally I keep the SDK in a folder called CodeBlocks\sdk (which contains the include/ and lib/ from in the zip). This means that the header files refered to in the tutorial would be found under Codeblocks\sdk\include, so cbPlugin.h is Codeblocks\sdk\include\cbPlugin.h for example.

Overview

This tutorial will show you how to package and access Resources (toolbars, forms, dialogs and bitmaps) and other static data in your plug-in.

Plugin File Structure

Every plugin in its undeployed state is simply a nested file structure in compressed archive form (zip). The typical structure of a plugin (which we'll call "myplugin" in this tutorial) is as follows:

+myplugin.cbplugin
 +myplugin.dll
 +myplugin.png
 +myplugin-off.png
 +myplugin.zip
  +manifest.xml
  +XML Based Resources
 +Extra Files

Most of this structure is created automatically when you build a plugin project created with the CB Plugin Wizard. What are these files?

  • myplugin.cbplugin: this is simply a zip archive containing all of the plugins files and resources. It is given a cbplugin extension to make it easy for the Code::Blocks plugin installer to recognize.
  • myplugin.dll (or _libmy-plugin.so_ on linux): the compiled shared library containing you plugins executable content
  • myplugin.png: this is an 80x80 bitmap displayed by default in the image list in "Environment Settings" when the plugins configuration has the focus (for plugins that have a configuaration panel). This file is optional
  • myplugin-off.png: this is an 80x80 bitmap displayed by default in the image list in "Environment Settings" when the plugins configuration does not have the focus(for plugins that have a configuaration panel). This file is optional
  • myplugin.zip: a compressed archive file containing the file manifest.xml and resources
  • manifest.xml: a file containing information about the plugin. (see the Creating a simple "Hello_World" plugin)
  • XML Based Resources: One or more wxWidgets XML based resource files (XRC files) such as toolbars, dialogs and forms. You can also place binary bitmap images in this archive if they are accompanied by and XRC descriptor file. XML Resources are option
  • Extra Files: Place other static, non-XRC resources here. You should keep these files to a mimimum because they are copied to the shared space of the users Code::Blocks installation. These files are optional

In this tutorial we will discuss the use of XML Based Resources and Extra Files

Working with XML Based wxWidgets Resources

What is XRC and why would I want to use it?

XRC is a standardized way of describing wxWidgets forms (including panels and dialogs), menus, toolbars and bitmap lists in a human readable XML format. A simple example is the XRC file for the compiler toolbar (found in the CB source at: src/plugins/compilergcc/resources/compiler_toolbar.xrc):

<?xml version="1.0" ?>
<resource>
  <object class="wxToolBarAddOn" name="compiler_toolbar">
    <object class="tool" name="idCompilerMenuCompile">
      <tooltip>Build</tooltip>
      <longhelp>Build the active project</longhelp>
      <bitmap>images/compile.png</bitmap>
    </object>
    <object class="tool" name="idCompilerMenuRun">
      <tooltip>Run</tooltip>
      <longhelp>Run the active project</longhelp>
      <bitmap>images/run.png</bitmap>
    </object>
...
...
...
    <object class="separator"/>
    <object class="wxStaticText" name="idToolTargetLabel">
      <label>Build target:</label>
    </object>
    <object class="wxChoice" name="idToolTarget">
      <content/>
        <size>160,-1</size>
    </object>
  </object>
</resource>

As you can see, this file specifies that it is an XML file in the first line, that it contains resources denoted by the <resource> and </resource> tags in the second and last lines respectively. Within the resource tags, the XRC file specifies a sequence of objects laid out in an hierarchical structure. Each object belongs to a class (specified with the attribute class, and corresponding to a wxWidgets form or control class) and has a unique identifier. In this file there is only one base level object, named "compiler_toolbar" derived from the Code::Blocks class "wxToolBarAddOn", a Code::Blocks extension of the wxWidgets type "wxToolbar". Note that base level objects are restricted to a handful of types, namely:

  • Frames
  • Dialogs
  • Panels
  • MenuBars
  • Menus
  • Toolbars
  • Bitmaps
  • Icons

In contrast, the objects owned by base level objects run the entire gamut of wxWidgets controls. In the case of the Compiler toolbar, it owns a sequence of standard bitmap toolbar buttons (idCompilerMenuCompile, idCompilerMenuRun etc), a static text control (idToolTargetLabel) and a choice box (idToolTarget). Panels and dialogs will also contain layout objects derived from classes such as wxSizer. In addition to the basic class and name attributes, base and lower level objects in an XRC file will specify additional detail about their structure, such as associated images, sizing and layout (basically giving you the same control over the intialization of an object as if you had executed its constructor in your c++ code).

While somewhat verbose, the XML-based XRC file is far more readable than the terse 50+ lines of equivalent C++ code required to create a toolbar, load its images and assign unique ids. XRC files can be loaded and displayed in a few lines of C++. You still retain the ability to access individual objects loaded from the XRC. We'll deal with these issues shortly.

In addition to its readability, XRC offers the advantage of separating form layout (contained in the XRC file) from form logic (coded into your plugin binary). XRC files are loaded each time you start your plugin, which allows you to make changes to the layout of a form without the need to recompile you plugin.

A definitive description of the XRC syntax is described in the wxWidgets wiki at http://www.wxwidgets.org/wiki/index.php/Using_XML_Resources_with_XRC

Creating XRC files for use in your plugin

While you can create your own XRC widget layouts by coding the XML in a simple text editor, it is far easier to use a GUI program to create the layout, XML and accompanying C++ code for you. For example, in Code::Blocks you can use the wxSmith plugin (TODO: link) to design your XRC forms and accompanying C++ classes for your plugin. wxFormBuilder (TODO: link) is another alternative.

Example creation of XRC form using wxSmith

Now we will add a simple XRC panel to our plugin using wxSmith:

7. Select wxSmith -> Add panel

8. Use the class name "TaskPanel", check "XRC file", then press OK

9. The management window should now show a "Resources" tab and open a new editor window displaying an empty panel with a toolbar containing widgets below it. (TODO: screen shot)

10. From the widget toolbar, select "Layout" tab, then choose wxBoxSizer and click anywhere in the panel. After you click the panel, it will be resized and you should see a border indicating the presence of a sizer. A Box Sizer is a container for widgets, that lays out the widgets in either a horizontal or vertical layout. (TODO: Link to more info on sizers)

11. From the widget toolbar, select "Standard" tab, then choose wxComboBox and click within the sizer. This adds a ComboBox to the sizer

12. Choose wxTextCtrl and click within the sizer. This adds a Text Control to the sizer (it should be located to the right of the combo box)

13. In the resources tab, click on the wxBoxSizer entry in the widget tree. Properties for the Box Sizer should appear in the bottom half of this tab. Change the orientation property to wxVertical.

14. Now click on the wxTextCtrl entry in the widget tree, open the styles property and check "wxTE_MULTILINE". Also check the "Expand" property, which will expand the control to the full width of the panel.

15. Now click on the wxComboBox entry in the widget tree, change the proportion property to zero. This tells the Box Sizer to only expand the Text Control when the size of the panel changes (the Text Control has a positive proportion). Also check the "Expand" property.

16. Save your work. This will save the panel as a wxSmith file and, in addition, create the XRC file "TaskPanel.xrc" and C++ header and sources TaskPanel.cpp/TaskPanel.h. You should now have a panel that looks like the following screen shot:

(TODO: Add screen shot)

17. Close the wxSmith editor.

Working with XRC files in your plugin

CONTENT COMING SOON...

Working with Extra Files

MORE CONTENT COMING SOON...

Further Information

It is essential to learn how wxWidgets works if you seriously plan on working on plugins, since most of Code::Blocks depends on it, and you will find it easier to add and manipulate components if you have a firm grasp of its principles. More information on this can be found in the wxWidgets documentation. Another good place to learn from is the source code from the existing Code::Blocks plugins, which can be downloaded along with the rest of the Code::Blocks source code from the download page.