=pod

=head1 NAME

IUP::Manual::05_DialogLayout - Dialog layout composition

=head1 IUP MANUAL

=over

=item * L<IUP::Manual::01_Introduction|IUP::Manual::01_Introduction>

=item * L<IUP::Manual::02_Elements|IUP::Manual::02_Elements>

=item * L<IUP::Manual::03_Attributes|IUP::Manual::03_Attributes>

=item * L<IUP::Manual::04_Callbacks|IUP::Manual::04_Callbacks>

=item * L<IUP::Manual::06_HandlingKeyboard|IUP::Manual::06_HandlingKeyboard>

=item * IUP::Manual::05_DialogLayout E<nbsp>E<nbsp>E<nbsp>E<nbsp>E<nbsp> B<E<lt>E<lt>E<lt> this document>

=item * L<IUP::Manual::07_UsingImageLibrary|IUP::Manual::07_UsingImageLibrary>

=item * L<IUP::Manual::08_DragAndDrop|IUP::Manual::08_DragAndDrop>

=back

=head1 INTRODUCTION

=head1 LAYOUT COMPOSITION

=head2 Abstract Layout

Most interface toolkits employ the concrete layout model, that is,
control positioning in the dialog is absolute in coordinates relative
to the upper left corner of the dialogs client area. This makes it easy
to position the controls on it by using an interactive tool usually
provided with the system. It is also easy to dimension them. Of course,
this positioning intrinsically depends on the graphics systems
resolution. Moreover, when the dialog size is altered, the elements
remain on the same place, thus generating an empty area below and to
the right of the elements. Besides, if the graphics systems resolution
changes, the dialog inevitably will look larger or smaller according to
the resolution increase or decrease.

IUP implements an abstract layout concept, in which the positioning of
controls is done relatively instead of absolutely. For such,
composition elements are necessary for composing the interface
elements. They are boxes and fillings invisible to the user, but that
play an important part. When the dialog size changes, these containers
expand or retract to adjust the positioning of the controls to the new
situation.

Watch the codes below. The first one refers to the creation of a dialog
for the Microsoft Windows environment using its own resource API. The
second uses IUP. Note that, apart from providing the specification
greater flexibility, the IUP specification is simpler, though a little
larger. In fact, creating a dialog on IUP with several elements will
force you to plan your dialog more carefully on the other hand, this
will actually make its implementation easier.

Moreover, this IUP dialog has an indirect advantage: if the user
changes its size, the elements (due to being positioned on an abstract
layout) are automatically re-positioned horizontally.

The composition elements includes vertical boxes (L<IUP::Vbox>), horizontal
boxes (L<IUP::Hbox>) and filling (L<IUP::Fill>). There is also a depth box
(L<IUP::Zbox>) in which layers of elements can be created for the same
dialog, and the elements in each layer are only visible when that given
layer is active.

 $dialog = IUP::Dialog->new( TITLE=>'Title',child=>
               IUP::Hbox->new( MARGIN=>"15x15", GAP=>10, child=>[
                   IUP::Fill->new(),
                   IUP::Button->new(TITLE=>"Ok", SIZE=>"40"),
                   IUP::Button->new(TITLE=>"Cancel", SIZE=>"40"),
                   IUP::Fill->new(),
               ])
           );

Following, the abstract layout representation of this dialog:

B<Layout Hierarchy:>

 IUP::Dialog
 |
 +-> IUP::Hbox
     |
     +->IUP::Fill
     |
     +->IUP::Button
     |
     +->IUP::Button
     |
     +->IUP::Fill

B<Layout Visualization:>

=begin html

<p><img src="http://kmx.github.io/perl-iup/img-3.9/images/dlg_led.png"></p>

=end html

=head1 LAYOUT GUIDE

=head2 Native Sizes (Window and Client)

Because of the dynamic nature of the abstract layout IUP elements have
implicit many types of size. But the native elements have only two
types of size: B<Window> and B<Client>. The B<Window> size reflects the
bounding rectangle of the element. The B<Client> size reflects the
inner size of the window that excludes the decorations and margins. For
many elements these two sizes are equal, but for many containers they
are quite different. See some examples bellow.

=begin html

<p>
  <table border="1">
    <tbody align="center">
      <tr>
        <th>IUP::Dialog</th>
        <th>IUP::Frame</th>
	<th>IUP::Canvas</th>
      </tr>
      <tr>
        <td><img src="http://kmx.github.io/perl-iup/img-3.9/images/nativesize1.gif"></td>
        <td><img src="http://kmx.github.io/perl-iup/img-3.9/images/nativesize2.gif"></td>
	<td><img src="http://kmx.github.io/perl-iup/img-3.9/images/nativesize3.gif"></td>
      </tr>
    </tbody>
  </table>
</p>

=end html

The IUP sizes (B<User>, B<Natural> and B<Current>) described bellow
are all related to the B<Window> size.

The native B<Client> size is used only internally to reposition the
elements in the abstract layout, but it is available using the
CLIENTSIZE attribute.

=head2 IUP Sizes

=head3 Natural Size

IUP does not require that the application specifies the size of any
element. The sizes are automatically calculated so the contents of each
element is fully displayed. This size is called B<Natural> size. The
B<Natural> size is calculated just before the element is mapped to the
native system and every time L<Map|IUP::Manual::02_Elements/"Map()"> is called, even if the element
is already mapped.

The B<Natural> size of a container is the size that allows all the
elements inside the container to be fully displayed. Important: even if
the element is invisible its size will be included in the size of its
containers, except when FLOATING=Yes.

So consider the following code and its result. Each button size is
large enough to display their respective text. If the dialog size is
increased or reduced by the size handlers in the dialog borders the
buttons do not move or change their sizes.

 use IUP ':all';
 my $dialog = IUP::Dialog->new( TITLE=>"IupDialog", FONT=>"Helvetica, Bold 14" ,child=>
                IUP::Vbox->new( child=>[
                  IUP::Button->new(TITLE=>"Button Very Long Text"),
                  IUP::Button->new(TITLE=>"short"),
                  IUP::Button->new(TITLE=>"Mid Button"),
                ])
              );
 $dialog->Show();
 IUP->MainLoop;

=begin html

<p><img src="http://kmx.github.io/perl-iup/img-3.9/images/naturalsize.gif"></p>

=end html

=head3 Current Size and User Size (SIZE or RASTERSIZE)

When the application defines the L<SIZE|attrib/iup_size.html> or
L<RASTERSIZE|attrib/iup_rastersize.html> attributes, it changes the
B<User> size in IUP. The initial internal value is "0x0". When set to
C<undef> the B<User> size is internally set to "0x0".

By default the layout computation uses the B<Natural> size of the
elements to compose the layout of the dialog, but if the B<User> size
is defined then it is used instead of the B<Natural> size, except for
containers (not including the dialog) where the B<User> size will be
used only if bigger than the B<Natural> size. For the dialog, when the
B<User> size is not defined, the B<Natural> size is used only if bigger
than the B<Current> size, so in this case the dialog will automatically
increase its size to fit all its contents, but if the B<Natural> size
is smaller then the dialog size will remains the same, i.e. the dialog
will not automatically shrink its size.

The returned value for SIZE or RASTERSIZE is the B<Current> size in
IUP. It returns the native B<Window> size of the element after the
element is mapped to the native system. Before mapping, the returned
value is the B<User> size defined by SIZE or RASTERSIZE attributes if
any, otherwise they are C<undef>.

Defining the SIZE attribute of the buttons in the example we can make
all have the same size. (In the following example the dialog size was
changed after it was displayed on screen)

 use IUP ':all';
 my $dialog = IUP::Dialog->new( TITLE=>"IupDialog", FONT=>"Helvetica, Bold 14" ,child=>
                IUP::Vbox->new( child=>[
                  IUP::Button->new(TITLE=>"Button Very Long Text", SIZE=>"50x"),
                  IUP::Button->new(TITLE=>"short", SIZE=>"50x"),
                  IUP::Button->new(TITLE=>"Mid Button", SIZE=>"50x"),
                ])
              );
 $dialog->Show();
 IUP->MainLoop;

=begin html
 
<p><img src="http://kmx.github.io/perl-iup/img-3.9/images/usersize.gif"></p>

=end html

So when EXPAND=NO (see bellow) for elements that are not containers if
B<User> size is defined then the B<Natural> size is ignored.

If you want to adjust sizes in the dialog do it after the layout size
and positioning are done, i.e. after the dialog is mapped or after
L<Refresh|IUP::Manual::02_Elements/"Refresh()"> is called.

=head3 EXPAND

Another way to increase the size of elements is to use the EXPAND
attribute. When there is room in the container to expand an element,
the container layout will expand the elements that have the EXPAND
attribute set to YES, HORIZONTAL or VERTICAL accordingly, even if they
have the B<User> size defined.

The default is EXPAND=NO, but for containers is EXPAND=YES.

Using EXPAND in the example, we obtain the following result:

 use IUP ':all';
 my $dialog = IUP::Dialog->new( TITLE=>"IupDialog", FONT=>"Helvetica, Bold 14" ,child=>
                IUP::Vbox->new( child=>[
                  IUP::Button->new(TITLE=>"Button Very Long Text"),
                  IUP::Button->new(TITLE=>"short", EXPAND=>"HORIZONTAL"),
                  IUP::Button->new(TITLE=>"Mid Button", EXPAND=>"HORIZONTAL"),
                ])
              );
 $dialog->Show();
 IUP->MainLoop;

=begin html
 
<p><img src="http://kmx.github.io/perl-iup/img-3.9/images/expand.gif"></p>

=end html

So for elements that are NOT containers, when EXPAND is enabled the B<
Natural> size and the B<User> size are ignored.

For containers the default behavior is to always expand or if expand is
disabled they are limited to the B<Natural> size. As a consequence (if
the B<User> size is not defined in all the elements) the dialog
contents can only expand and its minimum size is the B<Natural> size,
even if EXPAND is enabled for its elements. In fact the actual dialog
size can be smaller, but its contents will stop to follow the resize
and they will be clipped at right and bottom.

=begin html
 
<p><img src="http://kmx.github.io/perl-iup/img-3.9/images/no_shrink.gif"></p>

=end html

If the expansion is in the same direction of the box, for instance
expand="VERTICAL" in the Vbox of the previous example, then the
expandable elements will receive equal spaces to expand according to
the remaining empty space in the box. This is why elements in diferent
boxes does not align perfectly when EXPAND is set.

=head3 SHRINK

To reduce the size of the dialog and its containers to a size smaller
than the B<Natural> size the SHRINK attribute of the dialog can be
used. If set to YES all the containers of the dialog will be able to
reduce its size. But be aware that elements may overlap and the layout
result could be visually bad if the dialog size is smaller than its
B<Natural> size.

Notice that in the example the dialog inicial size will be 0x0 because
it is not defined. The picture shown was captured after manually
resizing the dialog. So when using SHRINK usually you will also need to
set the dialog initial size.

 use IUP ':all';
 my $dialog = IUP::Dialog->new( TITLE=>"IupDialog", FONT=>"Helvetica, Bold 14", SHRINK=>"YES" ,child=>
                IUP::Vbox->new( child=>[
                  IUP::Button->new(TITLE=>"Button Very Long Text"),
                  IUP::Button->new(TITLE=>"short", EXPAND=>"HORIZONTAL"),
                  IUP::Button->new(TITLE=>"Mid Button", EXPAND=>"HORIZONTAL"),
                ])
              );
 $dialog->Show();
 IUP->MainLoop;

=begin html
 
<p><img src="http://kmx.github.io/perl-iup/img-3.9/images/shrink.gif"></p>

=end html

=head2 Layout Hierarchy

The layout of the elements of a dialog in IUP has a natural hierarchy
because of the way they are composed together.

To create a node simply call one of the pre-defined constructors like
B<IUP::Label>, L<IUP::Button|IUP::Button>, L<IUP::Canvas|IUP::Canvas>, and so on. To create a branch
just call the constructors of containers like L<IUP::Dialog|IUP::Dialog>,
L<IUP::Frame|IUP::Frame>, L<IUP::Vbox|IUP::Vbox>, and so on. Internally they all call
L<Create|IUP::Manual::02_Elements/"Create()"> to create branches or nodes. To
destroy a node or branch call L<Destroy|IUP::Manual::02_Elements/"Destroy()">.

Some of the constructors already append children to its branch, but you
can add other children using L<Append|IUP::Manual::02_Elements/"Append()"> or
L<Insert|IUP::Manual::02_Elements/"Insert()">. To remove from the tree call
L<Detach|IUP::Manual::02_Elements/"Detach()">.

For the element to be visible L<Map|IUP::Manual::02_Elements/"Map()"> must be called
so it can be associated with a native control. L<Show|IUP::Manual::02_Elements/"Show()">, L<ShowXY|IUP::Manual::02_Elements/"ShowXY()"> or L<Popup|IUP::Manual::02_Elements/"Popup()"> will automatically call L<Map|IUP::Manual::02_Elements/"Map()"> 
before showing a dialog. To remove this association call L<Unmap|IUP::Manual::02_Elements/"Unmap()">.

But there is a call order to be able to call theses functions that
depends on the state of the element. As you can see from these
functions there are 3 states: B<created>, B<appended> and B<mapped>.
From B<created> to B<mapped> it is performed one step at a time. Even
when the constructor receives the children as a parameter L<Append|IUP::Manual::02_Elements/"Append()">
is called internally. When you B<detach> an element it will be
automatically B<unmapped> if necessary. When you B<destroy> an element
it will be automatically B<detached> if necessary. So explicity or
implicity there will be a call to:

 $elem->Create  ->>> $elem->Append ->>> $elem->Map
 $elem->Destroy <<<- $elem->Detach <<<- $elem->Unmap

A more simple and fast way to move an element from one position in the
hierarchy to another is using L<Reparent|IUP::Manual::02_Elements/"Reparent()">.

The dialog is the root of the hierarchy tree. To retrieve the dialog of
any element you can simply call L<GetDialog|IUP::Manual::02_Elements/"GetDialog()">,
but there are other ways to navigate in the hierarchy tree.

To get all the children of a container call L<GetChild|IUP::Manual::02_Elements/"GetChild()"> or
L<GetNextChild|IUP::Manual::02_Elements/"GetNextChild()">. To get just the next
control with the same parent use
L<GetBrother|IUP::Manual::02_Elements/"GetBrother()">. To get the parent of a
control call L<GetParent|IUP::Manual::02_Elements/"GetParent()">.

You can access any child of the element using the notation "$elem->[n]->[n]....", where n is the index
of the child. For example:

 XXX-FIXME-NOT-IMLEMENTED-YET
 my $dialog = IUP::Dialog->new(child=>
                  IUP::Hbox->new(child=>[
                      IUP::Button->new(TITLE=>"OK"),
                      IUP::Button->new(TITLE=>"Cancel"),
                  ])
              );
 my $cancel_button = $dialog->[1]->[2];

=head2 Layout Display

The layout size and positioning is automatically updated by L<Map|IUP::Manual::02_Elements/"Map()">.
L<Map|IUP::Manual::02_Elements/"Map()"> also updates the dialog layout even if it is already mapped,
so using it or using L<Show|IUP::Manual::02_Elements/"Show()">, L<ShowXY|IUP::Manual::02_Elements/"ShowXY()"> or L<Popup|IUP::Manual::02_Elements/"Popup()"> (they all
call L<Map|IUP::Manual::02_Elements/"Map()">) will also update the dialog layout. The layout size and
positioning can be manually updated using
L<Refresh|IUP::Manual::02_Elements/"Refresh()">, even if the dialog is not mapped.

After changing containers attributes or element sizes that affect the
layout the elements are NOT immediately repositioned. Call
L<Refresh|IUP::Manual::02_Elements/"Refresh()"> for an element inside the dialog to update the dialog
layout. To force a redraw of an element without layout update call
L<Update|IUP::Manual::02_Elements/"Update()">.

The Layout update is done in two phases. First the layout is computed,
this can be done without the dialog being mapped. Second is the native
elements update from the computed values.

The Layout computation is done in 3 steps: B<Natural> size computation,
update the B<Current> size and update the position.

=over

=item * The B<Natural> size computation is done from the inner elements
up to the dialog (first for the children then the element). B<User>
size (set by RASTERSIZE or SIZE) is used as the B<Natural> size if
defined, if not usually the contents of the element are used to
calculate the B<Natural> size.

=item * Then the B<Current> size is computed starting at the dialog
down to the inner elements on the layout hierarchy (first the element
then the children). Children B<Current> size is computed according to
layout distribution and containers decoration. At the children if
EXPAND is set, then the size specified by the parent is used, else the
natural size is used.

=item * Finally the position is computed starting at the dialog down to
the inner elements on the layout hierarchy, after all sizes are
computed.

=back

=cut