Difference between revisions of "Tutorial:Window"

From Freepascal Amiga wiki
Jump to navigation Jump to search
(Starting for window/taglist)
 
(First batch of typo's removed. Some grammar corrected.)
Line 1: Line 1:
 
== About Windows ==
 
== About Windows ==
  
When Amiga was released in 1985 the availability of two interfaces to interact with the computer was a novel feature. Amiga's can be operated via command line interface and graphical user interface. For the later free movable windows are very important. In this tutorial we will open a window using AmigaOS routines and makes some simple drawing. On the way we have to deal with Tags, variable parameter, messaging, drawing principles and intuition structures.<br/>
+
When Amiga was released in 1985 the availability of two interfaces to interact with the computer was quite a novel feature. Amiga's can be operated via command line interface and graphical user interface. For the latter free movable windows are very important. In this tutorial we will open a window using AmigaOS routines and perform some simple drawing. Along the way we have to deal with Tags, variable parameter, messaging, drawing principles and intuition structures.<br/>
  
The part of AmigaOS handle Windows, Mouse/Keyboard inputs is named Intuition and is accessible to the developer with the intuition.library in combination with the graphics.library for drawing routines. There are more things involved but this two are the most important. This two libraries are represented in Free Pascal with the unit intuition and agraphics. There is already a unit named graphics in the Lazarus component library. To prevent problems of double unit names we decided to change the name to agraphics. This happens for some library/unit names and also other structures a list can be found at [[Specifics]] Page.<br/>
+
The part of AmigaOS that handles Windows, Mouse and/or Keyboard input is named Intuition and is accessible by the developer through intuition.library and can be combined with use of graphics.library for drawing routines. There are more things involved but these two libraries are the most important. Both libraries with their functions can be accessed in Free Pascal with the units named intuition and agraphics. The latter had to be named AGraphics because Free Pascal itself already has a (generic) unit named graphics and which is available in the Lazarus component library. To prevent issues due to name collision we decided to change the name for Amiga platforms to agraphics. Unfortunately we have to deal with such name collisions for some of the units/libraries and also applies to some of the declared structures. A list with names that had to be changed can be found at our [[Specifics]] wiki Page.<br/>
  
 
== Tags, Taglists ==
 
== Tags, Taglists ==
  
Some really cool invention of Amiga are hidden to the average user. The Taglist feature is such invention.
+
Some really cool innovations that the Amiga offers are hidden from the average user. The Taglist feature is such an innovation.
Imagine you want to design a function to open a window then you need a lot of parameters, like x,y position, width, height, kind of window and some more. If you put them all into the parameter list it become very long and hard to use. The usual way is to create a record so you supply only a pointer to the record which contains all this informations. But now after some years developing you noticed that you need more parameters because the function/window become much more powerful. One way to solve that without destroying compatibility to old programs is, to create a new function or record which includes new fields as well. Windows for example did that very often. You will find many functions/records with an additional ending "Ex" which is the extended version to support new properties.<br/>
+
Imagine you want to design a function that opens a window and which requires a lot of parameters in order to accomplish this. F.e. x and y coordinates, width, height, the type of window and even more if wanted. If you want to put them all into the parameter list of a declaration of a function or procedure then the list of parameters will become significant in length quickly and because of that such a lengthy list becomes very tedious to use. Usually such long lists of parameters can be avoided by using a record instead so that you would only have to supply a pointer to this record and which could then contain all parameters and other relevant information. But, after years of developing you'll notice that you need to add more and more parameters simply because more and more (powerful) features are added to their parameter list in order to be able to make use of this newly added window functionality.
Amiga took a different path: Tags. You supply a list of Tags and Value pairs to the function. Every Tags is just a simple integer number and stands for one property of the window. Just as an example (not real example: Left = 1, Top = 2, Width = 3, Height = 4). And if you ignore all Tags you don't know and fill properties which are not supplied with some meaningful default values then you can later add some more Tags for more properties to it, without harm the compatibility forward and backwards.<br/>
+
 
A taglist could look like this (part of a real taglist to open a window):
+
One way to solve that without destroying compatibility to old programs is, to create a new function or record which includes these new fields as well. MS-Windows for example did that very often. You will find many functions/records with an additional suffix "Ex" which is the extended version that is able to support new properties.<br/>
 +
Amiga took a different path: Tags. You supply a list of Tags and Value pairs to the function. Every supplied Tag is just a simple integer number and corresponds to a single property of the window. Just as an example (a fictional example though, let's assume we have the following TAG-value-pairs: Left = 1, Top = 2, Width = 3, Height = 4). If we also assume that you ignore all Tags that you don't know about and by default fill all other (unknown) properties which are not provided with some meaningful default values then this offers a rather ingenious and clever way of being able to add new tag properties to such a tag-list without actually breaking either backward or forward compatibility.<br/>
 +
A taglist could look like this (this is actually part of a real taglist that is used to open a window):
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 26: Line 28:
 
|}
 
|}
  
As visible in the table, the value can have very different types. But we need to transfer them using the same interface. The solution for that is "PtrUInt" (or "NativeUInt", which is the same). An unsigned integer value which is guaranteed to have enough space for a pointer as well. We cast all our Values to PtrUInt. Strings need to be converted to a PChar (zero terminated C like strings) and then treated like a common Pointer. For the casting special wrapper functions are inserted to utility unit. AsTag() converts all possible types to PtrUInt. Every Taglist must end with TAG_END to tell the program where your list ends, it does not requires an vlaue. Adding these things to the list now looks like that:
+
As can been seen from the table above, there are different types (integer, string and boolean) that can be assigned as a Tag-value although the Tag's property name itself dictates which type that should actually be. But, in order to keep things simple we should be able to transfer all these different types using the same interface. There is a very simple but rather clever way that can solve this problem for us and that is by declaring tag values to be of type "PtrUInt" (or "NativeUInt", which is the same). This type is an unsigned integer value which is guaranteed to have enough room in order to even store a pointer. This way we are able to supply all our Tag-Values by simply casting them to PtrUInt. For example strings can be converted this way as a PChar (zero terminated C like strings) and would then be treated as any other common Pointer. Instead of casting (which is a rather tedious thing to do) there is also another solution available and that is offered by unit Utility, that offers a special set of wrapper functions named AsTag(). AsTag() will automatically convert all possible types into a PtrUint. Another notable feature of such tag-lists is that the list itself always needs to end with a special closing tag named TAG_END. That let every other function that work with tag-lists know where the actual end of the list is located. The TAG_END-Tag does not really require an actual tag-value. Since its common for a picture to be able to tell more than a thousand words, adding a list of tag-value pairs to a list looks something like:
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 45: Line 47:
 
|}
 
|}
  
Free Pascal is smart enough to create the string for WA_Title as PChar. Take care that is not possible if the string is calculated at this point. Besides one have to care about if the PChar supplied to the function is copied we will later come back to this.<br/>
+
Free Pascal is smart enough to create the string for WA_Title as type PChar. Be aware that this is not possible if the string is calculated at this point. Besides that, we also have to take into account whether or not the PChar that is going to be supplied to the function is copied or not (but more on that later).<br/>
  
How to open the window using this knowledge. For OpenWindow you will find a lot of different functions in Amiga API:<br/>
+
Now, with all this gained knowledge let's try to open a window om our workbench. The Amiga Api offers quite some different functions that open a window:<br/>
* OpenWindow() [http://www.alb42.de/fpc-docu/intuition/openwindow.html] - The old interface before taglist where invented, still there for compatibility
+
* OpenWindow() [http://www.alb42.de/fpc-docu/intuition/openwindow.html] - This is an older declaration/interface that was used before taglists where invented but is still available for compatibility reasons.
* OpenWindowTagList() [http://www.alb42.de/fpc-docu/intuition/openwindowtaglist.html] - requires a link to a task list as second parameter. You create the tag list before the call. Very handy if you want to have it configurable.
+
* OpenWindowTagList() [http://www.alb42.de/fpc-docu/intuition/openwindowtaglist.html] - This function requires a link to a tag-list for the second parameter. You create the tag-list before making the actual call to the function. This is very convenient in case you wish to manipulate the tag-list beforehand or programmaticaly.
* OpenWindowTags() [http://www.alb42.de/fpc-docu/intuition/openwindowtags.html] - which have a <code>array of PtrUInt</code> as second parameter which can be used to directly supply the tags with values to the function.
+
* OpenWindowTags() [http://www.alb42.de/fpc-docu/intuition/openwindowtags.html] - This function has a <code>array of PtrUInt</code> as second parameter which can be used to directly supply a list of tags and corresponding tag-values to the function.

Revision as of 19:59, 17 February 2017

About Windows

When Amiga was released in 1985 the availability of two interfaces to interact with the computer was quite a novel feature. Amiga's can be operated via command line interface and graphical user interface. For the latter free movable windows are very important. In this tutorial we will open a window using AmigaOS routines and perform some simple drawing. Along the way we have to deal with Tags, variable parameter, messaging, drawing principles and intuition structures.

The part of AmigaOS that handles Windows, Mouse and/or Keyboard input is named Intuition and is accessible by the developer through intuition.library and can be combined with use of graphics.library for drawing routines. There are more things involved but these two libraries are the most important. Both libraries with their functions can be accessed in Free Pascal with the units named intuition and agraphics. The latter had to be named AGraphics because Free Pascal itself already has a (generic) unit named graphics and which is available in the Lazarus component library. To prevent issues due to name collision we decided to change the name for Amiga platforms to agraphics. Unfortunately we have to deal with such name collisions for some of the units/libraries and also applies to some of the declared structures. A list with names that had to be changed can be found at our Specifics wiki Page.

Tags, Taglists

Some really cool innovations that the Amiga offers are hidden from the average user. The Taglist feature is such an innovation. Imagine you want to design a function that opens a window and which requires a lot of parameters in order to accomplish this. F.e. x and y coordinates, width, height, the type of window and even more if wanted. If you want to put them all into the parameter list of a declaration of a function or procedure then the list of parameters will become significant in length quickly and because of that such a lengthy list becomes very tedious to use. Usually such long lists of parameters can be avoided by using a record instead so that you would only have to supply a pointer to this record and which could then contain all parameters and other relevant information. But, after years of developing you'll notice that you need to add more and more parameters simply because more and more (powerful) features are added to their parameter list in order to be able to make use of this newly added window functionality.

One way to solve that without destroying compatibility to old programs is, to create a new function or record which includes these new fields as well. MS-Windows for example did that very often. You will find many functions/records with an additional suffix "Ex" which is the extended version that is able to support new properties.

Amiga took a different path: Tags. You supply a list of Tags and Value pairs to the function. Every supplied Tag is just a simple integer number and corresponds to a single property of the window. Just as an example (a fictional example though, let's assume we have the following TAG-value-pairs: Left = 1, Top = 2, Width = 3, Height = 4). If we also assume that you ignore all Tags that you don't know about and by default fill all other (unknown) properties which are not provided with some meaningful default values then this offers a rather ingenious and clever way of being able to add new tag properties to such a tag-list without actually breaking either backward or forward compatibility.
A taglist could look like this (this is actually part of a real taglist that is used to open a window):

Tag Value
WA_Width 300
WA_Height 200
WA_Title 'My Window'
WA_DepthGadget True
WA_SizeGadget True

As can been seen from the table above, there are different types (integer, string and boolean) that can be assigned as a Tag-value although the Tag's property name itself dictates which type that should actually be. But, in order to keep things simple we should be able to transfer all these different types using the same interface. There is a very simple but rather clever way that can solve this problem for us and that is by declaring tag values to be of type "PtrUInt" (or "NativeUInt", which is the same). This type is an unsigned integer value which is guaranteed to have enough room in order to even store a pointer. This way we are able to supply all our Tag-Values by simply casting them to PtrUInt. For example strings can be converted this way as a PChar (zero terminated C like strings) and would then be treated as any other common Pointer. Instead of casting (which is a rather tedious thing to do) there is also another solution available and that is offered by unit Utility, that offers a special set of wrapper functions named AsTag(). AsTag() will automatically convert all possible types into a PtrUint. Another notable feature of such tag-lists is that the list itself always needs to end with a special closing tag named TAG_END. That let every other function that work with tag-lists know where the actual end of the list is located. The TAG_END-Tag does not really require an actual tag-value. Since its common for a picture to be able to tell more than a thousand words, adding a list of tag-value pairs to a list looks something like:

Tag Value
WA_Width AsTag(300)
WA_Height AsTag(200)
WA_Title AsTag('My Window')
WA_DepthGadget AsTag(True)
WA_SizeGadget AsTag(True)
TAG_END

Free Pascal is smart enough to create the string for WA_Title as type PChar. Be aware that this is not possible if the string is calculated at this point. Besides that, we also have to take into account whether or not the PChar that is going to be supplied to the function is copied or not (but more on that later).

Now, with all this gained knowledge let's try to open a window om our workbench. The Amiga Api offers quite some different functions that open a window:

  • OpenWindow() [1] - This is an older declaration/interface that was used before taglists where invented but is still available for compatibility reasons.
  • OpenWindowTagList() [2] - This function requires a link to a tag-list for the second parameter. You create the tag-list before making the actual call to the function. This is very convenient in case you wish to manipulate the tag-list beforehand or programmaticaly.
  • OpenWindowTags() [3] - This function has a array of PtrUInt as second parameter which can be used to directly supply a list of tags and corresponding tag-values to the function.