Difference between revisions of "Tool Integration Development"

m (Implementing the Requirements)
m (Next Steps)
Line 106: Line 106:
 
There is still much more to be talked about when building an EiffelStudio tool. Hopefully this page has given you the ground work needed to start building your own tool.
 
There is still much more to be talked about when building an EiffelStudio tool. Hopefully this page has given you the ground work needed to start building your own tool.
  
In the next installation [Tool Integration Development 2] tool shortcuts, preferences and helper implementation will be explained.
+
In the next installation [Tool Integration Development 2] tool shortcuts, preferences, internationalization and helper implementation will be explained.

Revision as of 09:44, 13 August 2007


Construction.png Not Ready for Review: This Page is Under Development!

Welcome to the the EiffelStudio tool integration development page. The content held within this page will show you how to develop and integrate a new tool into the EiffelStudio IDE.

Getting Started

We are just getting started so this tutorial will only cover the basics for more advanced tutorials, see Tool Integration Development 2 and Tool Integration Service Development and Services.

Requirements

The content of this tutorial relates to the working version of EiffelStudio 6.1, current attainable from the open source repository https://eiffelsoftware.origo.ethz.ch/svn/es/trunk/Src/Eiffel. Please see the pages on attain the EiffelStudio source code from the Repository, as well as information on Compiling EiffelStudio and Debugging EiffelStudio.

Once you have EiffelStudio compiled and in a state where it can be debugged then continue reading.

An Implemented Tool Reference

If at any time you need to reference an actually implementation of a tool using the information in these pages, see the implementation of ES_ERRORS_AND_WARNINGS_TOOL in the EiffelStudio code. It was one of the first tools developed to use the new tool development base and helper classes you'll used to develop EiffelStudio tools.

Creating a Tool

Before anything else can be done you need to create a new tool class. Most tools inside EiffelStudio utilized a base class call EB_TOOL (as of 6.1.) EB_TOOL is currently the most basic of tool classes and has become a little outdated. In 6.1 a new abstract base class call ES_DOCKABLE_TOOL_WINDOW was created for the purpose of creating EiffelStudio tools with a greater amount of ease. ES_DOCKABLE_TOOL_WINDOW still derives from EB_TOOL but this may change in the future if all tools are converted to use ES_DOCKABLE_TOOL_WINDOW instead. With that said you should not use EB_TOOL directly, it was only mentioned for those curious about the class hierarchy.

Information.png Note: So to be clear, only use ES_DOCKABLE_TOOL_WINDOW as your base for tool development.

The use of ES_DOCKABLE_TOOL_WINDOW requires a generic parameter constrained to EV_WIDGET. The generic parameter, G, represents the tool's "user widget". The user widget defined by the feature user_widget is the top level widget the tool should interact with. For instance, if the tool consists of just a grid, list or tree widget then the user control will be of the respective type. For more complex scenarios the generic parameter could just as easily be a composite widget or a simple container like EV_HORIZONTAL_BOX or EV_VERTICAL_BOX.

To start out, create a new Eiffel class and inherit ES_DOCKABLE_TOOL_WINDOW, specifying the generic parameter for the tool's user widget.

Information.png Note: ES_DOCKABLE_TOOL_WINDOW has many advantages to being a base class for all tools; simplified implementation, a small number of required to implement features and delayed initialization of the tool itself. This last aspect is important because the more tools put into EiffelStudio the more time it takes the IDE to start up. Using delayed initialization comes with a few gotchas that you may possibly run into but it's recommended that it is used, so not to slow down EiffelStudio.

Declaring the Tool's Creation Routine

ES_DOCKABLE_TOOL_WINDOW even comes complete with a basic creation routine, make, which should be passed the active development window object the tool is created with. EiffelStudio supports the display of mutli IDE windows and the passed object represents the window the tool is active within. If the tool has no further actions required to be performed on creation then simply specify your tool's creation routine as the one from ES_DOCKABLE_TOOL_WINDOW (which is actually from EB_TOOL.) On the other hand, if the tool has other creation initialization to perform either redefine make or specify an alternative creation routine. It is important that develop_window be set correctly for ES_DOCKABLE_TOOL_WINDOW to function correctly.

Alternatively if simplicity is what you are after, simply redefine on_before_initialize to initialize any class attributes or other data. Please be aware that this routine is called during creation of the tool and affects the overall EiffelStudio start up time.

Implementing the Requirements

There is less than a hand full of deferred features from ES_DOCKABLE_TOOL_WINDOW to implement for a tool to compile and execute in EiffelStudio. The following are the list of deferred features requiring implementation (as of 6.1):

  • build_tool_interface
  • create_tool_bar_items
  • create_widget
  • tool_icon_buffer
  • tool_title

Each of these routines will be discussed, firs the rudimentary feature and then optional implementation for which empty routines can simply be defined.

tool_title

Every tool requires it has a title. The title is the text that is displayed when the tool is first created and will appear on the tool's tab button or tool's window title when undocked. It is also used when building a menu entry under View > Tools in the EiffelStudio IDE. Generally the title should be internationalized but internationalization details are discussed in a further tutorial. For now, it is good enough to simple return a attached non-empty Eiffel string.

It should be noted that tool_title and title can represent different values. tool_title should remain constant, title is a mutable title of the tool settable via set_title. tool_title is used in the initialization of title and nothing more. Of course you are free to base a new title using tool_title as part of an aggregated string.

tool_icon_buffer

As well as title, all tools require an icon to distiguish them from other tools. Instead of an EV_PIXMAP and EV_PIXEL_BUFFER is require, which retains information related to the alpha channel of a pixmap.

For now, simply use one of the stock EiffelStudio icons available from stock_pixmaps. I would recommend using stock_pixmaps.tool_output_icon_buffer as it is generic enough for now.

If you wish to add your own pixmap matrix and use the Eiffel Matrix Code Generator tool then feel free. The project source root folder contains a file call readme.txt that explains the format of a configuration file.

It should be noted; just like tool_title, tool_icon_buffer should remain unmodified as it is used only during initialization. icon actually represents the icon pixel buffer used by the tool, which may be changed using set_icon. Of course if you need to reset the tool you can always call set_icon with tool_icon_buffer as an argument and the icon will appear as it did on first show.

create_widget

create_widget is a factory function that must return a widget of the same type as defined for the inherited ES_DOCKABLE_TOOL_WINDOW's actual generic parameter. Here your tool should only create the widget and do any must-needed initialization. create_widget will be called the first time the tool requires the user widget and it will only be called once per development window. Any other initialization can be done in build_tool_interface, but more on this later.

build_tool_interface

Briefly mentioned in the description of create_widget, build_tool_interface is implemented to perform the brunt of all tool initialization. Initialization of the tool covers the creation of additional widget objects, setting parameters and extending them to user_widget. When called, build_tool_interface receives the created user widget as an argument a_widget. You are encouraged to use a_widget instead of accessing user_widget directly to avoid any possible, unavoidable future initialization recursion issues.

Tool bars and tool bar buttons need not be created in build_tool_interface because tool bars are created using create_tool_bar_items and other such like factory functions, which will be discussed later.

Information.png Note: build_tool_interface is called only when the window is shown for the first time, which can lead to calls being made on Void targets, if you tool is accessed from other parts of EiffelStudio. If you tool is stand-alone then this is not a concern. See the "Gotcha" information below

create_tool_bar_items

Most tools require some form of propriatery tool bar so it's only natural that the base implementation provide a means to add one. By default create_tool_bar_items is deferred because it's more a case to have a tool bar than it is not to have one. create_tool_bar_items can have no implementation so it a tool bar is not require, simply return Void or an empty list.

create_tool_bar_items is called once upon initialization and only requires any implementation to return a list of tool bar items, which can be any item that derives SD_TOOL_BAR_ITEM. Initialization takes car of constructing the tool bar and placing the buttons on it, determined by the order the buttons appear in the Result list. If Void or and empty list is returned then no tool bar will be created.

For the more adventerous, take a look at and even experiment with the following features; is_tool_bar_bottom_aligned, create_right_tool_bar_items and create_mini_tool_bar_items.

A Delayed Initialization Gotcha

build_tool_interface is called only when the window is shown for the first time, which can lead to calls being made on Void targets, if you tool is accessed from other parts of EiffelStudio. If you tool is stand-alone then this is not a concern.

In the example of the Errors and Warnings tool, the event list service pushes error event list items to the tool. When an error item is pushed the UI must respond by enabling tool bar buttons and other commands. The Errors and Warnings tool may still be hidden and so build_tool_interface not yet called. This creates a situation where the UI widgets are held in an unattached state and making calls on them illegal. There are two solutions:

  • Protect calls to the widget by testing if it is attached to an object.
  • Where access to a widget object, created in build_tool_interface, is required call initialize (respecting the preconditions.)

The Errors and Warnings tool actually uses the latter of these solutions as seen in on_event_added and on_event_removed.

Both of the solution respect the recommended approach fordelaying the initialization of the tool until requested. In the first solution the tool simply ignores any UI manipulation requested, which could be deferred until the tool is show if so applicable. The latter option forces initialization because it is deemed time to initialize. The tool will most likely have already been created and EiffelStudio made visible before any interaction with the tool takes place thereby, in effect, delaying the initialization the tool.

There is another solution, but it is not recommended because it will initialize the tool upon creation, and penalizes start up performance; it is mention for the purpose of an absolute requirement! You can initialize the tool upon creation, when EiffelStudio is starting up, by redefining on_before_initialize and making a call to initialize.

Tool Completed

As far as developing a tool, that is pretty much it. All that is left to do now is to actully integrate the tool into the IDE.

In EiffelStudio open the class EB_DEVELOPMENT_WINDOW_TOOLS. EB_DEVELOPMENT_WINDOW_TOOLS contains all the tools found in EiffelStudio and provides quick access inside EiffelStudio to any of those tools.

Locate errors_and_warnings_tool and underneath add a class attribute for your tool, using the same class name type of your tool itself. Next locate the attribute setter for errors_and_warnings_tool, set_errors_and_warnings_tool. Replicate set_errors_and_warnings_tool and adjust it to set the class attribute for your tool you just added.

Building and Registering

Now you have the accessor and an associated setter it's time to finish up by building and registering the tool. Open EB_DEVELOPMENT_WINDOW_MAIN_BUILDER in EiffelStudio and locate build_errors_and_warnings_tool. Using build_errors_and_warnings_tool as a reference add the code required to build your tool. It should consist of the creation of the tool, calling the setter you just created in EB_DEVELOPMENT_WINDOW_TOOLS and a call to setup_tool.

In the call to setup_tool be sure to replace the shortcut string "show_errors_and_warnings_tool" with the name of your tool, prefixed with "show_". I'm not going to explain shortcut handling here, that will be discussed in the next installment.

The very last thing to do it to call your build routine. You will need to add the call to your build routine in build_tools. In build_tools locate the call to build_errors_and_warnings_tool and place the call to your build routine directly after it.

That's it!

Next Steps

There is still much more to be talked about when building an EiffelStudio tool. Hopefully this page has given you the ground work needed to start building your own tool.

In the next installation [Tool Integration Development 2] tool shortcuts, preferences, internationalization and helper implementation will be explained.