Read Me
The Allegro GUI Un-uglification Project
= The Allegro GUI Un-uglification Project
== Version 1.0
= Contents
+contents
= Introduction
Let's be honest. When you see an Allegro dialog, don't you just want to stick
your fingers down your throat, and make choking noises? Haven't you started your
own GUI system before, simply because the GUI objects Allegro provides are
*damned ugly*? Don't you wish Shawn had grown up with an Apple Macintosh,
instead of an Atari ST?
The Allegro GUI Un-uglification Project is here to help. Its purpose is to make
Allegro DIALOGs look *good*, so you don't have to choke yourself, reinvent lots of
wheels, or wish a fate worse than death upon deity Shawn (lest you be struck
down by the non-portability bug).
== What it provides, so far
Some sets of GUI objects which act almost exactly like Allegro's d_*_procs.
*Almost*, because there are some very minor differences, which are described
further below.
Here is the list of procs.
- d_agup_box_proc
- d_agup_shadow_box_proc
- d_agup_button_proc
- d_agup_push_proc (1)
- d_agup_check_proc
- d_agup_radio_proc
- d_agup_icon_proc
- d_agup_edit_proc
- d_agup_list_proc
- d_agup_text_list_proc
- d_agup_textbox_proc
- d_agup_slider_proc
- d_agup_menu_proc
- d_agup_window_proc (2)
- d_agup_text_proc
- d_agup_ctext_proc
- d_agup_rtext_proc
- d_agup_clear_proc
(1) d_agup_push_proc implements a "push" button, which I think is more
useful than Allegro's "toggle" buttons. The dp3 field should
point to a callback function, which will be called whenever the
button is clicked (with the DIALOG entry as an argument), or NULL.
The callback should have a function prototype of the form:
int foobar(DIALOG *d);
It will be passed the dialog entry that was pressed, and should
return a value that will be passed back to the GUI control loop,
e.g. D_O_K or D_CLOSE.
(2) d_agup_window_proc implements a window frame, which can be used in
place of d_box_proc or d_shadow_box_proc. It expects the title of
the window in the dp field, or NULL.
Additionally, each theme sets the following two Allegro menu callbacks to
functions which render a themed menu:
- gui_menu_draw_menu
- gui_menu_draw_menu_item
== The API
AGUP can select from different widget sets ("themes") on the fly. You select the
theme at initialisation, e.g.
+ agup_init(agtk_theme);
Then to switch themes, shutdown the old one, and initialise the new:
+ agup_shutdown ();
+ agup_init(awin95_theme);
Remember to shutdown again before the end of your program.
If you don't want to deal with global theme pointers, you can also get a
theme by its name.
+ AGUP_THEME *theme = agup_theme_by_name("Photon");
This will select the theme by its string name. The names for the non-bitmap
themes are: "GTK", "Win95", "Photon", "BeOS", "NeXTStep", "ASE", "Allegro".
Bitmap themes will register with their theme-specific names as well. The
two example bitmap themes use "Blue" and "Fleur de Lis".
There's one more function for bitmap themes. In order to not require bitmap
themes to be compiled into the program, you need to load them before using.
E.g.
+ blue_theme = agup_load_bitmap_theme ("blue.cfg", NULL);
will load a new bitmap theme which is read from the file "blue.cfg". See the
section about bitmap themes for information about how the actual bitmaps are
found and loaded.
Also, if you only have need for one specific widget set, there's no need to use
AGUPs theme functions: Just use the widget set you want directly (see the header
files).
Furthermore, nothing stops you from using the stock Allegro dialogs at the
same time as agup. In fact, things like e.g. d_text_proc can be quite
useful to have colored text.
== About "the project"
So far, there are seven widget sets, so it's starting to become more
of a project. Please consider contributing emulations of other widget
sets. It does not have to look *exactly* the same as the original,
just close enough to be recognised.
Here are some that I would like to see:
MacOS (Platinum?), Motif, SGI,
or maybe your own (if it's not damned ugly ;)
Also send in bitmap themes which you would like to share with others, they
will be hosted on the AGUP site, with your name displayed.
Thanks to Robert Ohannessian for stepping up and creating the first
"3rd-party" widget set (awin95). As promised, there is now a wrapper
layer.
Thanks to David A. Capello for creating the second 3rd-party widget
set (aase).
[ Warning: The aase theme isn't 100% complete, and probably won't ever
be completed. It will likely be removed in later versions of AGUP. ]
Thanks to Eric Botcazou for creating the fourth widget set
(aphoton). Wow, that's really sweet!
Thanks to Elias Pschernig for creating the BeOS widget set. Very
cool, and very yellow.
Thanks to Joao Neves for creating the NeXTStep widget set. My list
of OS themes to emulate is diminishing :-)
Well, and thanks to Peter Wang for creating the first theme, and maintaining
AGUP for so long. Hm, and who thanks me now again for creating the bitmap
theme? Maybe the next maintainer should there ever be one.
== For C++ people
AGUP is basically a C library, but it can be compiled as C++
source too. You have two options:
(1) Compile AGUP as C, then include like so:
+ extern "C" {
+ #include "agup.h"
+ }
(2) Compile AGUP as C++.
== Contacting
See http://agup.sf.net.
= The AGUP Bitmap Theme Engine
Everyone who tried creating his/her own Allegro GUI knows how hard it is to get
it looking good. And the same applies for creating a new GUI theme inside AGUP -
it requires to write a replacement for every single Allegro dialog as well as
menus. This is why the bitmap engine might be useful. It only requires you to
draw bitmaps, and specify which bitmap or part of a bitmap to use for Allegro's
dialog elements. The amount of bitmaps is your choice, you can use a different
bitmap for every single element and every state of it, or at the other extreme,
draw the complete theme into one bitmap - or anything in between.
Of course, the drawback of a bitmapped theme is that it is possibly slower than
the other themes - but not necessarily, especially if the provided bitmaps aren't
too small, so there don't need to be multiple blits per widget. And other themes
can be much slower than the bitmap engine, e.g. if they draw gradients line by
line or even pixel by pixel. In this case, a bitmap is faster.
And then, the real proble, if you're not an artist, creating a bitmap theme will
be much harder than writing replacement dialog procedures. But if you're not an
artist, you need one anyway to make your program look good.
== Overview about the supported widgets
This contains a list of all the dialog elements, and a short description
how the bitmap engine displays them - in order to aid in creating a new theme.
The bitmap engine is accurate down to the pixel - so your themes will look
perfect (of course, all the restriction of the Allegro GUI apply).
=== Stock Allegro widgets
==== keyboard, yield
These two are not provided by AGUP, since they are invisible.
==== bitmap
This one is not provided by AGUP, since it is independent of the theme.
==== box, shadow_box, button, check, radio, icon
They all can be customized with the bitmap engine..
==== clear
This one is special, since it ignores its dimensions - so AGUP does the same. It
can only be used as first element, and you should fill in the right dimensions
anyway.
==== text, ctext, rtext
Draw text. The specified bitmap is put just behind the text (not the entire
DIALOG area).
==== edit
Input text. In Allegro, this doesn't have any border, just like the text items.
In AGUP, this is changed, and a 3 pixel border is added.
==== list, text_list, textbox
Draw a list/text list/text box with a vertical scrollbar. The scrollbar of the
stock Allegro GUI always is 12 pixels wide and right aligned - AGUP follows
this of course.
==== slider
Draws a horizontal or vertical slider.
==== menu
Draws a menu bar. This is named "menubar" in the AGUP bitmap engine, and "menu"
means an actual popup-menu.
=== Additional AGUP widgets
==== push
Like button, but with a callback instead of 2 states.
==== window
Like box/shadow_box.
=== Allegro Menus
==== menu
This is the area of the complete menu. It has a border of one pixel
at the top, and a border of 2 pixels at the bottom.
==== menu_item
A single menu item.
==== menubar
It has a border of 1 pixel to the left, and a border of 2 pixels to the right.
==== menubar_item
A single menubar item.
== Which files do I need to provide for a bitmap theme?
All that is needed is a configuration file, and a set of bitmaps. There are
various ways to pass them to AGUP, so for simplicity, lets consider some
examples:
+ agup_load_bitmap_theme (NULL, my_dat);
This will load a theme using the provided datafile "my_dat" to find all its
data. The configuration file must be a binary object named "agup.cfg" inside
the datafile. The bitmap names inside that agup.cfg will be found by passing
them directly to find_datafile_object. For example, if the agup.cfg contains:
+ box = box.bmp
Then my_dat should have a BITMAP element named "box.bmp" in it.
+ agup_load_bitmap_theme ("my.dat", NULL);
Normally, themes are loaded externally, so just NULL is passed as datafile, and
the file extension is used to determine what to do. In the above example, the
loadeded theme will load "my.dat" when it is initialized later, and the
datafile then is used in the same was as if it was passed directly (needs
"agup.cfg" and bitmap objects inside it).
+ agup_load_bitmap_theme ("my.cfg", NULL);
This will load the file "my.cfg" as configuration file, and pass bitmap names to
load_bitmap. This means, you can use any bitmap names and formats that are
understood by load_bitmap. This includes the special # separator, and handling
of user registered formats like PNG or JPG with appropriate Allegro addons.
+ agup_load_bitmap_theme ("my", NULL);
This will first try to find "my.dat", and if it is not found, try "my.cfg".
+ agup_load_bitmap_theme (NULL, NULL);
If you pass NULL to both the path and the datafile, the current Allegro
configuration is used to find the AGUP configuration. This requires a config
section named "[agup.cfg]" to be present. If it is found, then its contents are
used as agup.cfg. Bitmap names are directly passed to load_bitmap again. Note
that you can use Allegro functions like set_config_file or override_config_file
to specify where the configuration should be read from.
+ agup_load_bitmap_theme ("my.dat", my_dat);
Rarely useful, but in this case, if "my.dat" fails to load, my_dat is used instead.
== So, what goes into the agup.cfg file?
At the top of the file, there must be this line:
+ [agup.cfg]
Then there follow various options (read with Allegro's config file routines).
+ name = <string>
+ prefix = <string>
+ suffix = <string>
That way, you can specify a name for theme, and a prefix/suffix to be
prepended/appened to all the bitmap names. The name is currently unused.
For example:
+ prefix = my/
+ suffix = .png
will be useable to look for ".png" files in the directoy "my", i.e. instead of
+ box = my/mybox.png
you can just use:
+ box = mybox
Most important is of course the entries for all the different bitmaps. There's
an entry for every bitmap, with 3 states each. (If not all entries are present,
some bitmaps will inherit from others.) The "box" entry must be present, else the
theme won't load.
Bitmaps marked with *M can contain transparency (color #ff00ff, or index
0 if a palette is used, like you know from Allegro).
- box
- shadowbox
- button
- check *M
- radio *M
- icon
- scroller *M
- sliderh *M
- sliderv *M
- buttonsel
- iconsel
- scroll
- slidev
- slideh
- cursor *M
- menusep *M
- checked *M
- radiosel *M
- menucheck *M
- menusub *M
- edit
- list
- textbox
- menu
- menuitem
- menubar
- menubaritem
- window
- clear
- checkback
- checkbacksel
- radioback
- radiobacksel
- text
- listitem
== Short descriptions what the bitmaps do
=== clear, text
Background used for d_agup_clear_proc and d_agup_text_proc.
=== box, shadowbox, window
Boxes, used by d_agup_box_proc, d_agup_shadow_box_proc,
and d_agup_window_proc.
=== button icon buttonsel iconsel
Buttons for d_agup_button_proc and d_agup_push_proc and d_agup_icon_proc.
Plus each time a version for when D_SELECTED is set.
=== checkback radioback checkbacksel radiobacksel
Background bitmaps for d_agup_check_proc and d_agup_radio_proc, with versions
when D_SELECTED is set.
=== check radio checked radiosel
Buttons for d_agup_check_proc and d_agup_radio_proc, plus versions when
D_SELECTED is set. They can contain transparency, since they are drawn over the
previous *back bitmaps.
=== textbox listbox edit
Box for d_agup_textbox_proc, d_agup_list_proc/d_agup_text_list_proc and
d_edit_proc.
=== cursor listsel
Cursor for d_agup_edit_proc, and highlighted list line for the list procs.
They can contain transparency, since they are drawn over their parent boxes.
=== scroll slideh slidev
Frame for the scroller of textbox and list procs, and frames for horizontal and
vertical sliders.
=== scroller sliderh sliderv
Handles for the scroller and sliders. They can contain transparency, since they
are drawn over the scroll/slideh/slidev bitmaps.
=== menu menubar
Menu and menbar frames.
=== menuitem menubaritem
Single menu items/menubar items. They can't be transparent because of the way
Allegro menus work.
=== menusep menucheck menusub
Menu separator, menu check mark, and submenu indicator. They can all be
transparent and are drawn over the menuitem bitmap.
The 3 states for each element are normal, highlighted, and disabled. They are
specified with <name> <name_hl> and <name_dis>. The _hl version is used when
D_GOTFOCUS is set for an element, the _dis version with D_DISABLED. The hl and
dis variants are inherited from the normal state if not specified. Again, it's
best to leave them all in the config file, to avoid any confusion.
== How are bitmaps used?
A bitmap is used in the AGUP bitmap engine to fill a rectangular dialog area.
You can provide many separate bitmaps, or use the "cut" option below to use
areas inside bitmaps. In both cases, a bitmap will never get loaded twice - AGUP
is clever enough and keeps track of what bitmaps it has already loaded since the
last call to agup_init.
Each bitmap entry has the following format:
+ <bitmap> = <name> [options]
Options are:
+ [tile_h|sretch_h|center_h|align_h]
+ [tile_v|sretch_v|center_v|align_v]
+ [border <l> <r> <t> <b>]
+ [cut <x> <y> <w> <h>]
+ [color 0xrrggbb] (See next section)
<bitmap> may be any of the valid elements, <name> is the file/object name.
A bitmap is either centered, stretched, or tiled across a dimension of the box
it is used for. The tiling aligns in the center when no align option is set,
else the top left corner is aligned with the top left screen corner.
The cut option can be used to use a sub-bitmap. That is, only the given pixel
region out of the loaded bitmap is considered. So you can use this to create a
skin bitmap, which contains everything on a certain position, and then just
specify the positions with cut, always specifying the skin bitmap. The bitmap
will be loaded only once, and subbitmaps used to draw the single widgets.
If a border is given, it is cut out off the given (sub-)bitmap. The 4 required
numbers after 'border' are the pixels used as border to the left, right, top and bottom,
respectively. A border results in splitting the source bitmap into 9 bitmaps
like this:
+ ______________
+ / | | \
+ | lt | t | rt |
+ |____|____|____|
+ | | | |
+ | l | c | r |
+ |____|____|____|
+ | | | |
+ | lb | b | rb |
+ \____|____|____/
Only the center bitmap <c> is then used for filling the destination rectangle,
the other 8 are used as a border.
The default is to tile the source bitmap across the destination rectangle,
aligning at the center, and using no borders.
Examples:
+ bitmap = test.bmp
Tiles <test.bmp> across the box, aligning its center with the box center.
+ bitmap = test.bmp tileh stretchv border 8 8 4 4
Cuts a 8-8-4-4 border off <test.bmp>. It means, <lt>,<rt>,<lb> and <rb> are
all sized 8 times 4 pixels, <t> and <b> are 4 pixels high and bitmap width
minus 16 pixels wide, <l> and <r> are 8 pixels wide and bitmap height minus 8
pixels high. <c> is the rest. It then fills in the 4 edges <lt> <rt> <lb>
<rb>. Tiles two 4 pixel high stripes at the top and bottom (<t> and <b>).
Then scales <l> and <r> vertically and fills out the left and right border.
Finally, scales <c> vertically, and tiles it horizontally, filling the
remaing area in the middle.
+ bitmap = test.bmp center
Centers <test.bmp> inside the box.
If the bitmap is too big to fit inside the target box, and no stretching is
done, the following applies: If no border is used, it is centered in the box,
and clipped at the sides. If a border is used, the <c> bitmap is reduced until
it is completely gone. After that, the right and bottom borders overlap the left
and top ones.
The above descriptions may sound complicated, but it should get clear when
seeing it used. Just look at the example bitmap themes.
== How can I set text colors?
Some AGUP GUI elements require text to be displayed. In this case, the text is
printed transparently on top of whatever bitmap the AGUP bitmap engine provides.
But, just having a single color is often not enough, since the text is most
important part of some widgets and therefore its color is very important.
The color being used for text can be specified with 'color'. It expects an RGB
hex-triplet in the form '0xRRGGBB', for example '0xFF0000' is red. Colors are
always inherited from their parent (and never from another state, unlike bitmaps).
Therefore, if you want all your text to be in the same colors, it is sufficient
to set the colors for the 'box' element.
== What else can I modify?
Currently, there are the following other settings: fg, bg, mg, px, py. They
are the foreground, background and disabled colors, and the amount a
clicked button is shifted.
== What other advices are there?
Don't make the bitmaps too small. There is no size optimizations applied, so if
you tile a 1x1 sized bitmap across the screen, it will result into a blit for
every pixel on the screen - which is much slower than say a few 32x32 blits.