Cross-platform C SDK logo

Cross-platform C SDK

Panel

❮ Back
Next ❯
This page has been automatically translated using the Google Translate API services. We are working on improving texts. Thank you for your understanding and patience.

Functions

Panel*panel_create (void)
Panel*panel_scroll (...)
Panel*panel_custom (...)
voidpanel_data (...)
type*panel_get_data (...)
voidpanel_size (...)
uint32_tpanel_layout (...)
Layout*panel_get_layout (...)
voidpanel_visible_layout (...)
voidpanel_update (...)
real32_tpanel_scroll_width (...)
real32_tpanel_scroll_height (...)

A Panel is a control within a window that groups other controls. It defines its own reference system, that is, if we move a panel all its descendants will move in unison since their locations will be relative to its origin. It will support other (sub)-panels as descendants, which allows to form a Window Hierarchy (Figure 1). For portability, this Gui library does not support specific coordinates and sizes for elements linked to a panel, but the association is carried out by a Layout object which is responsible for calculating at runtime the final locations of controls based on the platform and window manager. In Hello Subpanel! you have an elementary example of using panels.

  • Use panel_create to create a new panel.
  • Use panel_scroll to create a panel with scroll bars.
  • Use panel_custom to create a new fully configurable panel.
  • Use panel_layout to add child controls to the panel.
  • Use panel_size to set the default size of the visible area.
  • Scheme showing the hierarchy produced by panels, subpanels and controls.
    Figure 1: Window hierarchy.

Each panel supports several layouts and allows you to switch between them at runtime (Figure 2). This allows to create dynamic responsive interfaces with very little effort, since the panel itself is responsible for linking and sizing the controls according to the active layout in each case. In Hello Multi-layout! you have an example.

  • Use panel_visible_layout to change the layout.
  • Two different window settings using the same controls.
    Figure 2: Panel with two different organizations for the same controls.

Because the layouts are logical structures outside the window hierarchy, they can share controls as they are linked to the same panel (Figure 3). What is not allowed is to use the same objects in different panels, due to the hierarchy concept.

Unlike panels, layouts do not create any native control (GtkWidget, HWND, NSView, etc.).
Scheme showing how to correctly share the elements between layouts.
Figure 3: It is possible to reuse the same components between layouts of the same panel.

1. Understanding panel sizing

We are going to show, by means of an example, the logic behind the composition and dimensioning of panels. We start with (Listing 1) where we create a relatively large panel in height.

Listing 1: Composition of a panel with multiple edit rows.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
static Window *i_window(void)
{
    uint32_t i, n = 20;
    Window *window_create(ekWINDOW_STDRES);
    Panel *panel = panel_create();
    Layout *layout = layout_create(2, n);

    for (i = 0; i < n; ++i)
    {
        char_t text[64];
        Label *label = label_create();
        Edit *edit = edit_create();
        bstd_sprintf(text, sizeof(text), "Value %02d", i);
        label_text(label, text);
        bstd_sprintf(text, sizeof(text), "Edit here value %02d", i);
        edit_text(edit, text);
        layout_label(layout, label, 0, i);
        layout_edit(layout, edit, 1, i);
    }

    for (i = 0; i < n - 1; ++i)
        layout_vmargin(layout, i, 3);

    layout_hmargin(layout, 0, 5);
    layout_margin4(layout, 10, 10, 10, 10);
    panel_layout(panel, layout);
    window_panel(window, panel);
    return window;
}
  • Lines 3-6 create the window, panel, and layout.
  • Loop 8-19 adds various labels and edit boxes to the layout.
  • Loop 21-22 establishes a small gap between rows.
  • Lines 24-25 establish a column spacing and border margin.
  • Lines 26-27 link the layout to the panel and the layout to the window.

The result of this code is the Natural sizing of the panel (Figure 4), which defaults to a width of 100 pixels for the editing controls. Labels fit to the text they contain. Separations and margins have also been applied.

Panel with a list of edit controls.
Figure 4: Natural sizing of the panel defined in (Listing 1).

In this case it is possible to resize the window, since we have used the ekWINDOW_STDRES flag when creating it (Figure 5).

Window with extended size edit controls.
Figure 5: Behavior of the panel when the window grows.

This behavior may not be the most appropriate for the case at hand. By default, the layout performs the Cell expansion proportionally. But what we really want is to "stretch" the editing controls so that the rows keep their default height (Listing 2).

Listing 2: Change in horizontal and vertical expansion.
 
Layout *layout = layout_create(2, n + 1);
...
layout_hexpand(layout, 1);
layout_vexpand(layout, n);

The previous lines cause the horizontal expansion to fall exclusively on column 1 (that of the EditBoxes). On the other hand, an extra empty row has been created, pouring all the vertical expansion into it (Figure 6).

Window with extended size editing controls, improving the layout.
Figure 6: Desired behavior, when the window expands.

Although the panel now behaves correctly when the window grows, we have difficulties when we want to "shrink" it below a certain limit (Figure 7). This is because natural dimensioning imposes a minimum size, since there comes a time when it is impossible to reduce the controls associated with the layout.

Window with editing controls and reduced size.
Figure 7: Minimum panel size.

This can be a problem as we may have panels large enough that they even exceed the size of the monitor and cannot be fully displayed. To solve this, we can set a default size for the entire panel (Listing 3), which will be the one displayed when the window starts (Figure 8).

Listing 3: Panel default size.
 
...
panel_size(panel, s2df(400, 300));
...
Window with editing controls and default size.
Figure 8: Natural sizing, forced to 400x300.

This command decouples, in a way, the size of the panel from the size of its content. In this way, the Layout is free to reduce the size of the view, regardless of whether or not it can display the entire content (Figure 9).

Window with very small size and editing controls.
Figure 9: Panel boundary reduction.

And finally, if we want, we can create the panel with scroll bars (Listing 4) and scroll through the non-visible content (Figure 10).

Listing 4: Panel with scroll bars.
 
...
Panel *panel = panel_scroll(TRUE, TRUE);
...
Window with edit controls and scroll bars.
Figure 10: Panel with scroll bars.

And, of course, everything said will work the same on any platform (Figure 11).

Window with edit controls and scroll bars, macOS version. Window with edit controls and scroll bars, Linux version.
Figure 11: Our panel running on macOS and Linux.
❮ Back
Next ❯

panel_create ()

Create a panel.

Panel*
panel_create(void);

Return

The new panel.


panel_scroll ()

Create a panel with scroll bars.

Panel*
panel_scroll(const bool_t hscroll,
             const bool_t vscroll);
hscroll

TRUE if we want horizontal scroll bar.

vscroll

TRUE if we want vertical scroll bar.

Return

The new panel.

Remarks

See Understanding panel sizing.


panel_custom ()

Create a fully configurable panel.

Panel*
panel_custom(const bool_t hscroll,
             const bool_t vscroll,
             const bool_t border);
hscroll

TRUE if we want horizontal scroll bar.

vscroll

TRUE if we want vertical scroll bar.

border

TRUE if we want to highlight the border.

Return

The new panel.

Remarks

See Understanding panel sizing.


panel_data ()

Associate user data with the panel.

void
panel_data(Panel *panel,
           type **data,
           FPtr_destroy func_destroy_data,
           type);
panel

The panel.

data

User data.

func_destroy_data

Destructor of user data. It will be called when the panel is destroyed.

type

Type of user data.


panel_get_data ()

Get the user data associated with the panel.

type*
panel_get_data(const Panel *panel,
               type);
panel

The panel.

type

Type of user data.

Return

User data.


panel_size ()

Sets the default size of the visible area of a panel.

void
panel_size(Panel *panel,
           const S2Df size);
panel

The panel.

size

The default size.

Remarks

See Understanding panel sizing.


panel_layout ()

Add a layout to a panel.

uint32_t
panel_layout(Panel *panel,
             Layout *layout);
panel

The panel.

layout

Layout.

Return

The newly added layout index.


panel_get_layout ()

Get a layout of a panel.

Layout*
panel_get_layout(Panel *panel,
                 const uint32_t index);
panel

The panel.

index

The layout index.

Return

Layout.


panel_visible_layout ()

Set the active layout inside the panel.

void
panel_visible_layout(Panel *panel,
                     const uint32_t index);
panel

The panel.

index

The layout index.

Remarks

To make the change effective, you have to call panel_update.


panel_update ()

Update the window that contains the panel.

void
panel_update(Panel *panel);
panel

The panel.

Remarks

It is equivalent to calling window_update.


panel_scroll_width ()

Gets the width of the scroll bar of the associated panel.

real32_t
panel_scroll_width(const Panel *panel);
panel

The panel.

Return

The width of the bar.

Remarks

Only valid if the panel has been created with panel_scroll. Useful if we want to take into account the size of the scroll bars when setting the margins of the Layout.


panel_scroll_height ()

Gets the height of the scroll bar.

real32_t
panel_scroll_height(const Panel *panel);
panel

The panel.

Return

The height of the bar.

Remarks

See panel_scroll_width.

❮ Back
Next ❯