The Toolbox offers a lot of flexibility to the application author. The gadgets are, mostly, implemented in a sensible way, and a number of different library implementations had been produced to make a more object oriented representation of the Toolbox structures. It would be useful to encourage these and make it easier for library, and development environment, authors lives easier.
It would also be useful to provide some more guides on how to write applications. Unfortunately the Toolbox examples which Acorn supplied were a few rudimentary applications which performed incredibly simple tasks, and a full blown hyperlinking application. It is good to show a flexible application, but there was a very steep learning curve beyond the simple applications.
Some examples of how applications might be written, providing examples of common operations, would have been very useful. If presented properly, these examples could lead into a guide about how to develop new Toolbox objects. I had found that the most reliable way to write a Toolbox gadget or object was to start from a plain application, with the operations to be performed being tightly defined and structured. Not only does this make for reusable code in general, but it means that lifting the code and placing it directly into a module is a simpler process. Maybe not trivial, but still easier than starting out with a blank slate.
Additionally, developing in this way meant that the base implementation in the application could be debugged easily, and could be used in applications if it was decided that a gadget or object actually was not appropriate.
One of the areas of the documentation that needed improvement within the manuals was that of example code. Although there existed example code for some of the main system interfaces in the PRMs, the Toolbox had few examples within its method call documentation. This could be improved relatively easily, although in many cases it was reasonably clear how code should be written. On the other hand, the disconnect between the methods or the object definitions and the the event delivery meant that documenting them clearly was more difficult.
In addition, it would be very useful to provide some wider examples within the chapters themselves in order to clarify a real use of the gadget. It is likely that, in order to work well, each gadget should have its own chapter. Sometimes they would be very short chapters, but it would ensure that they were given a good place to be documented. As with testing, documentation is often blocked because there is no initial work to start from. Once a test, or basic document, exists it is far easier to extend them.
It was common for applications to provide a toolbar, and the Window object supported a number of ways to associate the toolbar with the window - attached to the tops, side, or bottom, depending on the author's preference). This was useful for many cases, but it wasn't as flexible as you might like. It was common for applications on other systems to allow toolbars to be rearranged, and for different renditions of the toolbar gadgets to be supported.
There were two things that I wanted to be able to do with the toolbars, which could be implemented in stages, to make them more easily implemented. The first was that the toolbar should be able to be presented in different ways to help users. The default toolbar should include buttons that were an icon plus a text description underneath. These toolbars would be larger than normal, with larger sprites for the icon, and space for the text underneath. The toolbar could be changed (by a default menu, or under the application's control) to display only the icon, or to use a smaller icon, (comparable to the normal size of icons, about 26x26).
Reducing the toolbar to just its icon form could be achieved on a per gadget basis, under the control of the Toolbar object (a part of the Window object). The application would be unaware of any changes other than that there was a change in the vertical space - the application could still be informed, but might not need to know. To reduce the icon size further, a second set of gadgets would be provided within the Toolbar object, which would be able to be used in place of their larger versions.
The replacement gadgets would use a gadget identifier offset of (say)
&1000, which would allow the Toolbar object to perform
the replacements without the application's intervention. The application
would still apply the necessary operations to the gadgets using the base
identifier number - the Toolbar object would filter the operations so that
both forms of the gadget would receive the events. That would mean that
if you faded a gadget whichever form was visible would be displayed faded.
The smaller variants would be designed within the toolbar workspace, below a
configurable vertical position which controlled the maximum extent of the
toolbar. Additional icons (with both the base and small
&1000 offset) could also be included in the toolbar, below
this vertical position, and would not be visible by default.
This first stage of the toolbar changes would allow the type of toolbar to be controlled by the user - the application would have to read the state of the toolbars and store them in its configuration. When the application was loaded, or a new window opened the application could restore the state from this configuration. Hopefully this would be the only thing needed to support these toolbars.
The second stage would allow the toolbar ordering to be changed by the application, and by the user through an interface handled entirely by the Toolbar object. This could be presented in the default menu for the toolbar by offering an extra option to place the toolbar into 'edit mode', and allowing the gadgets to be dragged around. The 'edit mode' would also be able to be triggered by the application, which would allow a configuration example window to be set up by the user, as desired.
Although the icons would be dragged around by a user, they would be placed as a linear ordering from the left and right. Icons dragged to the right edge would 'lock' to the right edge, and line up against other icons in the row. Icons on the left would do the same for that side. Any icon could be removed from the toolbar, but may be restored from a palette of the icons which the Toolbar gadget would provide whilst in the editing mode.
Help messages for the gadgets would be generated by the primary icons, and
the toolbar gadget would automatically redirect requests for help to the
correct gadget - the secondary icons at
&1000 would not
need to duplicate the help messages. This, and a few of the other operations
to mask the gadgets, might need some updates to the core Toolbox or Window
handling to allow the Toolbar to make modifications to the messages returned
to the client application or operations being performed by the application
on the underlying gadgets.
Depending on how successful the second iteration of the changes was, it might be possible to extend the implementation further to allow the toolbar to occupy multiple lines, doubling or more the height of the toolbar, but allowing more control over the application. For toolbars arranged vertically, the above descriptions of 'left' and 'right' would be represented as 'top' and 'bottom'.
Because the eventual layout of the toolbar might be different, the state preservation implemented in the first iteration should be defined such that the extra information about the ordering of the gadgets could also be preserved (and restored) by the application without changing the code. As such, a bare option for the size of the toolbar might be provided as an interface, but there would have been a generalised 'preserve state' operation which obtained data of variable size, the format of which was not defined (but was guaranteed to be transferable between versions of the module, to allow a default configuration to be used as the user upgraded the OS and Toolbox modules).
The state configuration and restore used by the OptionsWindow might be a basis for the messaging used by the toolbars. In particular, only requesting state changes when it is first needed would help the application by reducing the complexity for initially setting up windows.
The difficulty with this type of change was that it had definite advantages to the user, and for application designers in terms of flexibility, but it did not offer much in the way of immediate gains for the OS itself. It might have been more useful if the core applications were updated to use the Toolbox and could therefore use the new functionality.
If the Toolbars are going to provide greater flexibility for the management of gadgets, it is very likely that there will need to be some more complex operations needed for the buttons. The functionality of the ToolAction gadget may need to be extended. I had not investigated it too much, but I do remember that it was still quite an immature gadget. It might be better than the other core gadgets, but it had not been given as good a looking over.
There are quite a few gadgets I wanted to get written, and to rework. I have already discussed things like the HTML rendering gadget, which would have been a very useful addition, albeit a little processing intensive for a filter. Some of the existing gadgets need to have a little work done on them to make them a little more useful.
Whilst the HTML gadget would be nice, a simplified text editor that allowed basic formatting would have been incredibly useful for some cases. However, you have to consider the use case. Having a fancy renderer is one thing, but if it is only available on the screen, it isn't all that useful. It needs to be able to be exported. So really what you want is a rich text rendering module which can export (to DrawFile, say) and render (to the screen or printer using the standard APIs). Then the gadget becomes just a way to control the editing and/or presentation of the content through the rendering module.
The ImageFileGadget needed some tidying up so that it wasn't quite as tedious to control. More importantly, though I wanted it be used without running in a nested window. Instead of rendering as part of a nested window, it could be rendered within the main window itself as part of the redraw loop, using the newer RedrawManager handling.
The Scrolling List gadget needed to have sortable and re-orderable columns. Some of that work had been done, but it wasn't quite complete enough to be considered usable. Alternatively, a 'Table' gadget could be created which provided a much more sensible management of layout, and allowed individual cells to be addressed. I had begun some work on such a gadget, as part of the spreadsheet mini-project, although that had spun off in an odd direction. The rendering code was quite reusable, and could easily have been converted to a gadget in its own right.
Rik Griffin had already written a Tree gadget, so I had no plans on pursuing that sort of thing, but a Filer object was something I wanted to do. In many of the cases that you want to present data for selections, the list isn't really suitable, and the table would not do the job. A filer type interface was a common mechanism for interacting with objects within RISC OS, and would have made for a reasonable gadget - or possibly an object. It is difficult to draw the line, but as the content is contained like a window, it makes reasonable sense for it to be an object, with the individual gadget identifiers referring to the items associated within it.
There are at least two good Filer implementations in RISC OS, not including the assembler version that is the true Filer. The implementation in the !CPIShell is not perfect, but it was designed to be modular after I ripped apart the original, with the final thought that it be turned into a Toolbox component eventually. In much the same way that the OptionsWindow object was created from the work that went into the !Configure Window setup tool, the object could easily be created from the library it used. The other implementation is in the !OmniClient application (well, module), and uses DeskLib - it was not quite so flexible.
There was a Date object that I discovered that someone had created, which looked reasonable initially, but was very buggy and did not perform very well. It could do with being reimplemented - or seriously reworked to avoid the problems. Of course I could have just been unlucky when I looked at it. Maybe I am being unfair, though. I know that the original Toolbox modules, when I first got hold of them, were in a terrible state. So it is not surprising that there be problems with other third party components.
The database components needed to be reconsidered. Whilst they had not worked out in the initial implementation, it should have been very reasonable to rip out the code from the TextGadgets and 'do it properly' in a new gadget, so that a gadget can be populated from a data source. In theory, the MDNSService gadget could then be implemented using the database API, with Multicast DNS resolution as the data source.
I always wanted to write a ZapRedraw gadget, so that it would be simpler to control such windows. The glue should be pretty trivial, but not trivial enough that it might as well be code you wrote in your application. Of course, if it turned out to just be trivial, then there would be no point in having a gadget - instead, the second stage of my plan could be followed... grab the terminal implementation from !Nettle and shove it into a gadget. Thus you have an instant ANSI terminal implementation in a gadget.
I did want to create a DrawChart gadget, on the grounds that feeding the data to a toolbox object and having a chart plotted would be neat. However, what you are really doing is feeding the DrawChart module only to have something like ImageFileGadget render the resulting DrawFile - there is no actual benefit in having a specialisation. However, if one could be found, it might be useful.
I did want to finish the AnimatedIcon gadget so that it could be used as a progress or activity indicator. The little 'Pace' animation was quite neat, but there are other uses it could be put to, I am sure. It would also have been useful to extend its API so that you could use it directly as a progress indicator, giving it an Hourglass like API to show percentages or the like.
The URLImage gadget was pretty nice, and handled multiple operations simultaneously quite well, but could really do with being finished. The error handling could do with being improved, and it desperately needed to be able to cache data so that where the same content was referenced multiple times it was only obtained once. Visually, it needed to be updated so that it could be rendered within a region, using RedrawManager instead of the nested window which ImageFileGadget used. Of course, if ImageFileGadget were to be improved to use RedrawManager this would become a simple change.
The RedrawManager itself should probably be updated so that it could control the order of rendering. At present the interface allows the registered clients to be either before or after the icons are rendered. The remaining order of the redraw is determined by registration, which means that an icon which is created by the application with a gadget number lower than the existing gadgets will find itself being rendered later. Adding a new interface that allows a prioritisation to be set would help. Whether that would directly utilise the gadget number as the priority isn't obvious to me right now. The ordering problem is similar to that of the Icon bar, so it is possible that a 'before priority x', 'after priority y' interface might be suitable.
It would have been useful in some cases to create a gadget that could handle multi-state icons. For example, a tri-state gadget would be very useful for some form interfaces, allowing a "Yes", "No" or "Don't care" to be selected for a search field - after all, the sprites had been available in the standard Wimp pool since at least RISC OS 2. Multi-state icons are relatively rare, but on those occasions that you need them it would be handy if you did not have to create it from scratch. It is possible that this is one area that the ToolAction gadget could be extended. Alternatively, a completely new gadget could be created which could change state under the application's control, or by the user clicking Select and Adjust to step through the choices, or even by using a pair of adjuster arrows.
This also makes me wonder if there is any need for an combined sprite icon and StringSet gadget, allowing you to associate an icon with a selectable string. Of course, implementing such a control in an application is pretty trivial, so maybe it is a bad candidate for a gadget. Really, the only place I can think of such a control being useful is in an export dialogue, for selecting the filetype to export as. But maybe there are more cases that might be useful.
In general, gadgets had been extended to add redraw handlers, timer handlers and to make some of the scroll operations easier to use. There were bound to be other operations that the gadget should be able to perform, and with the extension of the gadget operations it was easy to extend them. One of the existing areas that had not been exploited properly was the use of extending based on APIs. Essentially each gadget would be called for its own method and would handle them, but could actually handle more methods. Some gadgets provide a superset of operations, so it might make sense to allow direct access to the original operations.
For example, the ToolAction gadget should really be able to perform the same operations as the Action Button gadget, so why not respond properly to the Action Button methods. Allowing such operations would make it significantly easier to provide a superset of the methods that the base gadget they are using. In some cases, the methods could just be passed down to the sub-gadgets that make up its implementation, but in other cases the methods could be completely reimplemented. I am thinking of more advanced operations, such as a rich editing gadget, which might also support all the Text Area gadget methods in order that it be used in place of it easily.
I seriously doubt that anyone spent any time looking at the things that I had done on the Toolbox previously, so whether it would be seen as important to add new features, I am not sure.
As for objects, I liked the application update checker object that I wrote, but I think it needed more thought into how it was going to be used. When I showed it to a few testers, one of the comments I got back was that they expected it to work quite differently, with more automation. That would need to be addressed.
A generalised 'download file(s)' object might be handy, as it could be used for a number of different applications that commonly needed to download content and provide feedback. In a similar way that the Print object could be customised, the window used by such an object could be designed around the style needed for the application, with the progress indicators and other controls optional.
The questions that you have to ask yourself when thinking about gadgets come down to the simple 'what do I actually need that is not already provided'. Some of the gadgets I would like to write are quite specialised and do not really meet the criteria for making a library. There is a general rule that you should write something when you need it, generalise it when you need it again, and make it a library when you need it a third time. That can quite readily be applied to the Toolbox stack.
ResEd and friends
The !ResEd tool was already quite modular, making it possible to add new object editors easily (albeit writing such an editor was not incredibly clear). The gadgets editing had been updated so that it was mostly a dynamic library system. This needed to be finished so that the palette was generated dynamically, which would allow a complete drop in update for new gadgets, or upgrades to existing gadget support.
One thing that was becoming a concern, as I added new gadgets, was that the palette would very easily fill up and become a mess of gadgets which you would not need most of the time. The main way I wanted to address that would be to have different views on the palette, so that you could reduce its size to just those you needed. Particularly, grouping the gadgets by their functional area would help. Initially the gadgets supplied would all be 'core' or 'basic' gadgets, but the new ones which did more advanced things could appear in new sections.
I cannot remember what I was envisaging, but at the moment I can imagine at least a 'network' section, which held things like the MDNSService gadget and the URLImage gadget. More could be added relatively easily once the structure was in place. Most of the experimental gadgets would have to fall into a 'test' category, so that they didn't get in the way of 'real' gadgets.
The !ResTest integration needed to be completed properly. As it stood, !ResEd would just launch the !ResTest application and let it do its thing. This doesn't fit with the way that !ResEd works - it should be hiding the fact that the tool is separate from the shell. The plan was to remove the IconBar icon, if !ResTest was invoked on the editor's behalf, and move the core operations to the main editor menu.
Instead of invoking 'Test' on the resource file, you would 'Test' the objects individually. This would load the !ResTest application, or communicate with it over the Wimp protocol to test that object. There would need to be more communication in the protocol to handle the testing, and to make sure that the operations were clear. You couldn't just offer the option to 'delete' the object as you had in !ResTest because the user might select the wrong 'delete' and actually remove the object.
In such cases though, another improvement I had planned would help - making it possible to 'undo' operations. The Resource files are quite small, and the shell is only managing the files - the editors do the work. Consequently, maintaining an undo list to revert changes would be reasonably simple. Obviously it would be limited in what operations it could undo, and the granularity of those changes would need to be defined. The editors should be able to inform the shell that a significant change had been made and the shell could determine whether to take an undo checkpoint. The undo checkpoint would just be a return from the editor of the changed version, and preserving the earlier version for restore.
If we do not save checkpoints often, then the user might find they have gone back too far and cannot undo a given operation. Or if we save too often, it becomes annoying as you have to step through many changes to get back to the original. I was thinking of a way of describing the change that had been made so that the 'undo' operations would be understandable. However, that would mean more internationalisation problems, particularly if those descriptions were passed through the Wimp messages.
Undo would be simple to add, but needed thought to get to the point at which is wasn't frustrating or burdensome.
I wanted to make it easier to build !ResEd into a IDE. As it stands, the editor is a standalone application which edits Resource files - it invokes other tools in order to do so, but that implementation detail is hidden from the user. It would be useful to be able to make the application itself able to be controlled by other tools. I wasn't planning on making the whole application as integrated as its editors are, but making it able to be controlled and to be able to provide interaction with an IDE would help.
As well as being able to be controlled, providing extra features in the Resource file would help significantly. There are problems with creating a code generation tool using the current Resource system. One of the issues is that the Resource file only contains the necessary details for executing the Resource - there is no metadata included to describe how it reacts. In some respects that is very useful, as it means that the code in the application can be written to react exactly as necessary. However, it doesn't make it easy to determine the use of the Resources if you're not the author.
Some examples. When you are writing your application you need to know what events it needs to respond to. Every object and gadget can generate different events. How do you know what those events are? They are in the header files, of course. That isn't great from a development point of view. Additionally, objects and gadgets can raise their own events if they wish - and those only appear as numbers unless you, as the application author, define them. The same is also true of the gadget identifiers in every Window object. They are only numbers. Invariably you are forced to write your own header file defining each gadget number with a symbolic name. Even !WinEdit allowed you to name your icons and use those names in code.
As a first stage, what I would like to have seen would have been the ability to name gadget identifiers and export them into a header. This would allow you to get on with writing application code, rather than worrying about gadget numbering - which isn't a huge issue, but it would help. It would also allow gadgets like the Action Button to be able to refer to a gadget by its name in the edit box. In theory, the !ResTest tool could provide additional guidance in its event windows.
I would have liked to have improved the key shortcuts somehow. It is fiddly to make them duplicate the operation of another gadget and invariably requires extra code to do so. Ideally it should be possible to associate a shortcut with a gadget operation, so that it wasn't necessary to write special code for the shortcuts. For example, pressing a key should be able to generate exactly the same event as a mouse click on a button, an increment of a field, or similar.
Pushing this processing into the Toolbox, rather than requiring code be written to do it, would improve the flexibility significantly. Obviously this re-binding of keys to gadgets would need to be exposed programmatically, in the gadget API, but the benefits could be significant for application authors. Not only would it become simple to change the bindings, but it would be easier to ensure that your code always did the right thing, because the gadget actions and the key actions would not have different code paths to be maintained.
It would be possible to produce a simple report for each gadget which described the key shortcuts. For example, a report might say "Ctrl-C triggers the Copy gadget" (paraphrased - it is not going to be that easy). A simple report like that across an entire Resource file would make it very easy to see problems without having to check every window for its actions. Whether that is a worthy benefit, I am not sure, but the ability to do so is useful - and it could always be left to third parties to deal with such non-core functionality.
As mentioned above, knowing what events the Resource can generate is important. After creating your Action button, what are you getting out after that? Did you define your own event codes, and so have to remember the numbers? First stage would be to include an event symbol table in the Resource file (not the Object - events are global across the entire resource). This would mean some interaction between object editors, but that is an internal matter for !ResEd to handle.
Events could still be referred to by number, and internally in the Resource file would be stored as their numeric identifier, but would have symbolic names assigned to those numbers. These names would be edited in the main shell application (or maybe in a child editor, as that is how it handles editing of objects), and a header could be exported to reflect them. Any header exports would be possible in two ways - both from the application interface, and through a command line tool, which would allow its inclusion in Makefiles.
This would allow the interface to give more explicit descriptions to the events - for example, instead of an Action Button giving you the option to deliver event '&170' in an input box, it could offer you a menu of the event names that are known, and use the name in the description box instead of (or as well as) the number.
One tool that would be very nice to have - and which I had played with for Templates - is a tool which could convert a Resource file to a text file and also perform the reverse operation. This makes performing comparisons significantly easier, and is useful for some source control systems. I believe that some third parties produced something like this, but it would be useful to have as a core part of the tools.
So now we have got symbolic names for objects (because they are already named in the Resource file), for the custom events that can be generated, and for the gadgets themselves. The gadget editors would be updated to give a list of events that each individual gadget can raise. This will change depending on their configuration and would not be static - for example a Number Range gadget would never produce adjuster events if it didn't have adjuster icons enabled.
In some respects it would be useful if the gadget implementation in the module returned this information, rather than the editor, but it is kind of expected that the two stay reasonably in step. In any case, with this information you can do a simple report for each gadget, object or the entire Resource file, to say what events could be triggered. This would allow the developer to see the cases they were missing, for a start. In many cases they might not care, but it would be possible to generate the Toolbox message filter list from just that information.
It might also spot logical problems. For example, a gadget that could trigger the parent window closing if used in a particular way (non-local Action Buttons for example) would result in a window close message, which the developer did not intend. Again, I am not sure that is a useful case, but it might help sometimes!
Following the train of thought that the gadgets could return their details, the simplest way to make the Window Gadgets more accessible might be to place the editing resources and dynamic library inside the Gadget module as objects within ResourceFS. This would mean that the Window editor tool could edit any gadget that you had an implementation module for - and they would always be kept in step.
There might be issues with keeping the ABI in step, but this is always the case with the Toolbox. You have to be constantly aware of the implications when writing any modules, so this isn't that different to what you would do normally.
For the template files, I had produced a simple tool called FixUpTemplate, which would modify a template to correct some common problems, and produce a report of suggestions for a better design. Many of the rules would still apply to the Toolbox windows, and it would be very useful to either extend the tool to be able to process Toolbox objects, or to create another tool that could do that job. Because of the way that !ResEd works, it would be less likely that there would be very bad designs, but it might help to give some suggestions.
With a bit of thought, the tool could even be provided as another application which would offer suggestions whilst you were editing the file. That would really be quite irritating as a designer, but even providing an interface to show the problems on demand it would help. My immediate thought on this is that problems could be highlighted within a scrolling list, and selecting the problem would open the object in question with the gadget or item in question highlighted.
If you were really keen on the idea, the tool might even suggest ways to fix the issue, and offer to make the changes for you. Really, though, you are only looking at changes like toggling some flags, or moving the gadgets around slightly. It wouldn't make a huge change to the design process. Maybe the tool could find a place as an optional plug in for the main !ResEd application - in much the same way that the Doom WAD mapping tools were plug ins for the main !Doom application, when I created them.
All this is leading up to the ability to provide the IDE with information about the events that can be generated, and descriptively named, which will allow it to either locate, or generate the relevant handler code for those events. It might even be possible to create a block diagram application with all the code except the final processing being drawn out diagrammatically. There are people who hate this kind of integration and automation of code (and I include myself in that group for certain things), but having the ability to do so lowers the barriers for programmers. And when you have got programmers who are still using BASIC, sometimes that barrier needs to be pretty low.
The external edit work for the !ResEd shell application was nearly complete, but could have provided the foundations for a more structured interface for integration. The alternative is to build a dedicated communication protocol for passing details about events, objects, gadgets, keys, and so on, between the controlling application and the shell. Not that that is a bad thing, but it is useful to reuse protocols that exist, where appropriate.
It is possible that this might be re-inventing the wheel - the OLE protocol from Computer Concepts, or the PCA protocol from Clares, could be meet some of the requirements.
I had thought that it would be nice to be able to provide an introspection interface to the Toolbox Object and Gadget definitions. This way, the modules would be able to provide the definitions of the methods, events and structures that they provided. I liked the idea of doing this for all modules, but the Toolbox provides more structured ground for such things.
Such information would mean that decoding message blocks could be done in debuggers without any special configuration - the existing module would provide the relevant information. If the method calls were defined then examples of their use could be prompted in an integrated environment, and template structures laid out easily. Of course, instead of being within the integrated environment you might just generate static header files (or generate them dynamically as part of your build process) for each gadget or object you used.
I was never sure if the benefit was worth it. You could easily end up including a lot of information in a small module, which resulted in a very high data to implementation ratio.