Copyright (c) Hyperion Entertainment and contributors.
Difference between revisions of "AmiWest 2013 Lesson 3"
Steven Solie (talk | contribs) |
Steven Solie (talk | contribs) |
||
Line 24: | Line 24: | ||
== handle_gui_window() == |
== handle_gui_window() == |
||
− | The purpose of this function is to handle the GUI window. |
+ | The purpose of this function is to handle the GUI window itself. Before it can do that, it needs to gather some information to display in the window. It gathers all the data required into one data structure (''struct GuiData'') to make things easier. |
+ | |||
+ | == open_gui_window() == |
||
+ | |||
+ | We are finally down to the function which does the real job of opening the window. This is a function because, in general, there will be many options you will want to consider for your GUI. That usually means a plethora of tags and a lot of autodoc reading to figure out what they all do. |
||
+ | |||
+ | One tag in particular we will be studying is LAYOUT_DeferLayout. More about this critical option will be covered later. |
||
+ | |||
+ | == handle_gui_window_events() == |
||
+ | |||
+ | This is the real meat of your GUI. Pretty much every GUI toolkit on the planet operates with some form of ''event handling'' scheme. An event is something of interest to your application. It could be a mouse button press. It could be a key press. It could be a pressure sensor from a tablet. You may also get refresh events from the OS which tells you when to redraw parts of your GUI. |
||
+ | |||
+ | === Wait() === |
||
+ | |||
+ | The secret to the entire thing is this line: |
||
+ | <syntaxhighlight> |
||
+ | uint32 sigmask = IExec->Wait(wait_mask); |
||
+ | </syntaxhighlight> |
||
+ | |||
+ | Without that Wait(), multitasking would grind to a halt. |
||
+ | |||
+ | After your program is done waiting for something to happen, it needs to act on whatever events show up. Events can show up in any order at any time. Such is life in a multitasking system. So you need to code defensively and be able to handle any situation. |
||
+ | |||
+ | === WM_HANDLEINPUT === |
||
+ | |||
+ | Here is where things get a bit murky. When you are working with a basic Intuition Window, you need to handle a lot more details than you will have to handle here. See [[Intuition_Windows|Intuition Windows]] for all the details. |
||
+ | |||
+ | The reason you don't have to do most of the work is because the ''window.class'' object is taking over some of the responsibility. It tries to do all the basic things you need so that your application is not burdened with details. This can be a good thing and it can be a bad thing. It all depends on what you expect your GUI to do. |
||
+ | |||
+ | For our purposes, the WM_HANDLEINPUT method is a very good thing. We want to know when a user clicks on a few of the buttons. We don't want to know if the user moves the window and it needs redrawing; that is handled for us. |
||
+ | |||
+ | It can be frustrating for beginners because you just don't know all the ins and outs. There will also appear to be conflicting advice floating around and conflicting examples. Rest assured, the information out there is correct. You just don't know how to tell the difference between a basic Intuition example, a basic BOOPSI example, a window.class example, a GadTools example, etc. |
||
+ | |||
+ | === Context is Everything === |
||
+ | |||
+ | When I say ''context'' I mean the AmigaOS Process or Task which is executing your code. This is important when working with a GUI. If you don't understand what context is running your code you will spend many hours fighting problems. |
||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
Revision as of 20:24, 14 October 2013
Contents
ProcTree Redux
At AmiWest 2012 we took a look at a simple application which presented a graphical tree of all the Processes running on your Amiga. I don't believe we spent enough time exploring this example which is what this lesson will focus on.
Full source code is available from here.
Setup
The ProcTree example uses many Amiga-only features to setup the application including:
- Embedded version string
- Stack cookie
- stdio window control
- Startup from Shell and Workbench
- C library provided interfaces
main()
For an application you generally want to keep main() simple and to the point. This enables easier cleanup when errors occur because you only have a limited number of function calls to clean up after during a failure.
handle_gui()
This function handles the GUI overall. It will open the various BOOPSI classes and set up the global pointers. It must always clean up whatever resources are allocated as well.
handle_gui_window()
The purpose of this function is to handle the GUI window itself. Before it can do that, it needs to gather some information to display in the window. It gathers all the data required into one data structure (struct GuiData) to make things easier.
open_gui_window()
We are finally down to the function which does the real job of opening the window. This is a function because, in general, there will be many options you will want to consider for your GUI. That usually means a plethora of tags and a lot of autodoc reading to figure out what they all do.
One tag in particular we will be studying is LAYOUT_DeferLayout. More about this critical option will be covered later.
handle_gui_window_events()
This is the real meat of your GUI. Pretty much every GUI toolkit on the planet operates with some form of event handling scheme. An event is something of interest to your application. It could be a mouse button press. It could be a key press. It could be a pressure sensor from a tablet. You may also get refresh events from the OS which tells you when to redraw parts of your GUI.
Wait()
The secret to the entire thing is this line:
uint32 sigmask = IExec->Wait(wait_mask);
Without that Wait(), multitasking would grind to a halt.
After your program is done waiting for something to happen, it needs to act on whatever events show up. Events can show up in any order at any time. Such is life in a multitasking system. So you need to code defensively and be able to handle any situation.
WM_HANDLEINPUT
Here is where things get a bit murky. When you are working with a basic Intuition Window, you need to handle a lot more details than you will have to handle here. See Intuition Windows for all the details.
The reason you don't have to do most of the work is because the window.class object is taking over some of the responsibility. It tries to do all the basic things you need so that your application is not burdened with details. This can be a good thing and it can be a bad thing. It all depends on what you expect your GUI to do.
For our purposes, the WM_HANDLEINPUT method is a very good thing. We want to know when a user clicks on a few of the buttons. We don't want to know if the user moves the window and it needs redrawing; that is handled for us.
It can be frustrating for beginners because you just don't know all the ins and outs. There will also appear to be conflicting advice floating around and conflicting examples. Rest assured, the information out there is correct. You just don't know how to tell the difference between a basic Intuition example, a basic BOOPSI example, a window.class example, a GadTools example, etc.
Context is Everything
When I say context I mean the AmigaOS Process or Task which is executing your code. This is important when working with a GUI. If you don't understand what context is running your code you will spend many hours fighting problems.
Working with AmigaOS GUIs can be quite challenging. There are several toolkits available including the original Intuition, GadTools, basic BOOPSI, ReAction and MUI. Although all toolkits are still available, new applications should use either ReAction or MUI for best results.
This tutorial will focus on using ReAction to create a simple GUI. The GUI displays and automatically updates the system Process tree. This simple example touches on many aspects of AmigaOS programming.
Topics explored include:
- Opening/Closing BOOPSI classes correctly
- BOOPSI class interfaces
- MEMF_PRIVATE data
- Exec lists
- ReAction GUIs using window.class
- Deferred GUI refreshing
- Hierarchical listbrowser
- BOOPSI object user data fields
- Process break signals
- Process list change notification
- Listbrowser labels detachment and reattachment
- Refreshing a BOOPSI object
- Process IDs
- Exec objects (LIST, HOOK, NODE)
- Proper GUI cleanup and exit