
Normalize coding style by removing consecutive empty lines from C sources and headers. https://github.com/NetworkManager/NetworkManager/pull/108
463 lines
13 KiB
C
463 lines
13 KiB
C
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Copyright 2013 Red Hat, Inc.
|
|
*/
|
|
|
|
/**
|
|
* SECTION:nmt-editor-grid
|
|
* @short_description: Grid widget for #NmtEditorPages
|
|
*
|
|
* #NmtEditorGrid is the layout grid used by #NmtEditorPages. It
|
|
* consists of a number of rows, each containing either a single
|
|
* widget that spans the entire width of the row, or else containing a
|
|
* label, a widget, and an optional extra widget.
|
|
*
|
|
* Each row of the grid can take up multiple on-screen rows, if
|
|
* its main widget is multiple rows high. The label and extra widgets
|
|
* will be top-aligned if the row is taller than they are.
|
|
*
|
|
* The #NmtEditorGrids in a form behave as though they are all in a
|
|
* "size group" together; they will all use the same column widths,
|
|
* which will be wide enough for the widest labels/widgets in any of
|
|
* the grids. #NmtEditorGrid is also specially aware of #NmtNewtSection,
|
|
* and grids inside sections will automatically take the size of the
|
|
* section border into account as well.
|
|
*/
|
|
|
|
#include "nm-default.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include "nmt-editor-grid.h"
|
|
|
|
G_DEFINE_TYPE (NmtEditorGrid, nmt_editor_grid, NMT_TYPE_NEWT_CONTAINER)
|
|
|
|
#define NMT_EDITOR_GRID_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NMT_TYPE_EDITOR_GRID, NmtEditorGridPrivate))
|
|
|
|
typedef struct {
|
|
GArray *rows;
|
|
int *row_heights;
|
|
int indent;
|
|
} NmtEditorGridPrivate;
|
|
|
|
typedef struct {
|
|
NmtNewtWidget *label;
|
|
NmtNewtWidget *widget;
|
|
NmtNewtWidget *extra;
|
|
NmtEditorGridRowFlags flags;
|
|
} NmtEditorGridRow;
|
|
|
|
typedef struct {
|
|
int col_widths[3];
|
|
} NmtEditorGridFormState;
|
|
|
|
/**
|
|
* nmt_editor_grid_new:
|
|
*
|
|
* Creates a new #NmtEditorGrid
|
|
*
|
|
* Returns: a new #NmtEditorGrid
|
|
*/
|
|
NmtNewtWidget *
|
|
nmt_editor_grid_new (void)
|
|
{
|
|
return g_object_new (NMT_TYPE_EDITOR_GRID,
|
|
NULL);
|
|
}
|
|
|
|
static void
|
|
nmt_editor_grid_init (NmtEditorGrid *grid)
|
|
{
|
|
NmtEditorGridPrivate *priv = NMT_EDITOR_GRID_GET_PRIVATE (grid);
|
|
|
|
priv->rows = g_array_new (FALSE, TRUE, sizeof (NmtEditorGridRow));
|
|
}
|
|
|
|
static void
|
|
nmt_editor_grid_finalize (GObject *object)
|
|
{
|
|
NmtEditorGridPrivate *priv = NMT_EDITOR_GRID_GET_PRIVATE (object);
|
|
|
|
g_array_unref (priv->rows);
|
|
g_clear_pointer (&priv->row_heights, g_free);
|
|
|
|
G_OBJECT_CLASS (nmt_editor_grid_parent_class)->finalize (object);
|
|
}
|
|
|
|
/**
|
|
* nmt_editor_grid_append:
|
|
* @grid: the #NmtEditorGrid
|
|
* @label: (allow-none): the label text for @widget, or %NULL
|
|
* @widget: (allow-none): the (main) widget
|
|
* @extra: (allow-none): optional extra widget
|
|
*
|
|
* Adds a row to @grid.
|
|
*
|
|
* If @label and @widget are both non-%NULL, this will add a three-column row,
|
|
* containing a right-aligned #NmtNewtLabel in the first column, @widget in the
|
|
* second column, and @extra (if non-%NULL) in the third column.
|
|
*
|
|
* If either @label or @widget is %NULL, then the other column will expand into
|
|
* it.
|
|
*
|
|
* See also nmt_editor_grid_set_row_flags().
|
|
*/
|
|
void
|
|
nmt_editor_grid_append (NmtEditorGrid *grid,
|
|
const char *label,
|
|
NmtNewtWidget *widget,
|
|
NmtNewtWidget *extra)
|
|
{
|
|
NmtEditorGridPrivate *priv = NMT_EDITOR_GRID_GET_PRIVATE (grid);
|
|
NmtNewtContainerClass *parent_class = NMT_NEWT_CONTAINER_CLASS (nmt_editor_grid_parent_class);
|
|
NmtNewtContainer *container = NMT_NEWT_CONTAINER (grid);
|
|
NmtEditorGridRow row;
|
|
|
|
g_return_if_fail (label != NULL || widget != NULL);
|
|
|
|
memset (&row, 0, sizeof (row));
|
|
|
|
if (label && !widget) {
|
|
widget = nmt_newt_label_new (label);
|
|
label = NULL;
|
|
}
|
|
|
|
if (label) {
|
|
row.label = nmt_newt_label_new (label);
|
|
parent_class->add (container, row.label);
|
|
}
|
|
|
|
row.widget = widget;
|
|
parent_class->add (container, widget);
|
|
if (row.label) {
|
|
g_object_bind_property (row.widget, "valid",
|
|
row.label, "highlight",
|
|
G_BINDING_INVERT_BOOLEAN | G_BINDING_SYNC_CREATE);
|
|
}
|
|
|
|
if (extra) {
|
|
row.extra = extra;
|
|
parent_class->add (container, extra);
|
|
}
|
|
|
|
g_array_append_val (priv->rows, row);
|
|
}
|
|
|
|
static int
|
|
nmt_editor_grid_find_widget (NmtEditorGrid *grid,
|
|
NmtNewtWidget *widget)
|
|
{
|
|
NmtEditorGridPrivate *priv = NMT_EDITOR_GRID_GET_PRIVATE (grid);
|
|
NmtEditorGridRow *rows = (NmtEditorGridRow *) priv->rows->data;
|
|
int i;
|
|
|
|
for (i = 0; i < priv->rows->len; i++) {
|
|
if (rows[i].label == widget || rows[i].widget == widget || rows[i].extra == widget)
|
|
return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* NmtEditorGridRowFlags:
|
|
* @NMT_EDITOR_GRID_ROW_LABEL_ALIGN_LEFT: the row's label should be
|
|
* aligned left instead of right.
|
|
* @NMT_EDITOR_GRID_ROW_EXTRA_ALIGN_RIGHT: the row's extra widget
|
|
* should be aligned right instead of left.
|
|
*
|
|
* Flags to alter an #NmtEditorGrid row's layout.
|
|
*/
|
|
|
|
/**
|
|
* nmt_editor_grid_set_row_flags:
|
|
* @grid: an #NmtEditorGrid
|
|
* @widget: the widget whose row you want to adjust
|
|
* @flags: the flags to set
|
|
*
|
|
* Sets flags to adjust the layout of @widget's row in @grid.
|
|
*/
|
|
void
|
|
nmt_editor_grid_set_row_flags (NmtEditorGrid *grid,
|
|
NmtNewtWidget *widget,
|
|
NmtEditorGridRowFlags flags)
|
|
{
|
|
NmtEditorGridPrivate *priv = NMT_EDITOR_GRID_GET_PRIVATE (grid);
|
|
NmtEditorGridRow *rows = (NmtEditorGridRow *) priv->rows->data;
|
|
int i;
|
|
|
|
i = nmt_editor_grid_find_widget (grid, widget);
|
|
if (i != -1)
|
|
rows[i].flags = flags;
|
|
}
|
|
|
|
static void
|
|
nmt_editor_grid_remove (NmtNewtContainer *container,
|
|
NmtNewtWidget *widget)
|
|
{
|
|
NmtEditorGrid *grid = NMT_EDITOR_GRID (container);
|
|
NmtEditorGridPrivate *priv = NMT_EDITOR_GRID_GET_PRIVATE (grid);
|
|
NmtNewtContainerClass *parent_class = NMT_NEWT_CONTAINER_CLASS (nmt_editor_grid_parent_class);
|
|
NmtEditorGridRow *rows = (NmtEditorGridRow *) priv->rows->data;
|
|
int i;
|
|
|
|
i = nmt_editor_grid_find_widget (grid, widget);
|
|
if (i != -1) {
|
|
if (rows[i].label)
|
|
parent_class->remove (container, rows[i].label);
|
|
parent_class->remove (container, rows[i].widget);
|
|
if (rows[i].extra)
|
|
parent_class->remove (container, rows[i].extra);
|
|
|
|
g_array_remove_index (priv->rows, i);
|
|
return;
|
|
}
|
|
|
|
// FIXME: shouldn't happen
|
|
parent_class->remove (container, widget);
|
|
}
|
|
|
|
static newtComponent *
|
|
nmt_editor_grid_get_components (NmtNewtWidget *widget)
|
|
{
|
|
NmtEditorGridPrivate *priv = NMT_EDITOR_GRID_GET_PRIVATE (widget);
|
|
NmtEditorGridRow *rows = (NmtEditorGridRow *) priv->rows->data;
|
|
newtComponent *child_cos;
|
|
GPtrArray *cos;
|
|
int i, c;
|
|
|
|
cos = g_ptr_array_new ();
|
|
|
|
for (i = 0; i < priv->rows->len; i++) {
|
|
if (!nmt_newt_widget_get_visible (rows[i].widget))
|
|
continue;
|
|
|
|
if (rows[i].label) {
|
|
child_cos = nmt_newt_widget_get_components (rows[i].label);
|
|
g_assert (child_cos[0] && !child_cos[1]);
|
|
g_ptr_array_add (cos, child_cos[0]);
|
|
g_free (child_cos);
|
|
}
|
|
|
|
child_cos = nmt_newt_widget_get_components (rows[i].widget);
|
|
for (c = 0; child_cos[c]; c++)
|
|
g_ptr_array_add (cos, child_cos[c]);
|
|
g_free (child_cos);
|
|
|
|
if (rows[i].extra) {
|
|
child_cos = nmt_newt_widget_get_components (rows[i].extra);
|
|
for (c = 0; child_cos[c]; c++)
|
|
g_ptr_array_add (cos, child_cos[c]);
|
|
g_free (child_cos);
|
|
}
|
|
}
|
|
|
|
g_ptr_array_add (cos, NULL);
|
|
return (newtComponent *) g_ptr_array_free (cos, FALSE);
|
|
}
|
|
|
|
static NmtEditorGridFormState *
|
|
get_form_state (NmtNewtWidget *widget)
|
|
{
|
|
NmtNewtForm *form = nmt_newt_widget_get_form (widget);
|
|
NmtEditorGridFormState *state;
|
|
|
|
if (!form)
|
|
return NULL;
|
|
|
|
state = g_object_get_data (G_OBJECT (form), "NmtEditorGridFormState");
|
|
if (state)
|
|
return state;
|
|
|
|
state = g_new0 (NmtEditorGridFormState, 1);
|
|
g_object_set_data_full (G_OBJECT (form), "NmtEditorGridFormState", state, g_free);
|
|
return state;
|
|
}
|
|
|
|
static void
|
|
nmt_editor_grid_realize (NmtNewtWidget *widget)
|
|
{
|
|
NmtEditorGridPrivate *priv = NMT_EDITOR_GRID_GET_PRIVATE (widget);
|
|
NmtNewtWidget *parent;
|
|
|
|
NMT_NEWT_WIDGET_CLASS (nmt_editor_grid_parent_class)->realize (widget);
|
|
|
|
/* This is a hack, but it's the simplest way to make it work... */
|
|
priv->indent = 0;
|
|
|
|
parent = nmt_newt_widget_get_parent (widget);
|
|
while (parent) {
|
|
if (NMT_IS_NEWT_SECTION (parent)) {
|
|
priv->indent = 2;
|
|
break;
|
|
}
|
|
parent = nmt_newt_widget_get_parent (parent);
|
|
}
|
|
}
|
|
|
|
static void
|
|
nmt_editor_grid_unrealize (NmtNewtWidget *widget)
|
|
{
|
|
NmtEditorGridFormState *state = get_form_state (widget);
|
|
|
|
if (state)
|
|
memset (state->col_widths, 0, sizeof (state->col_widths));
|
|
|
|
NMT_NEWT_WIDGET_CLASS (nmt_editor_grid_parent_class)->unrealize (widget);
|
|
}
|
|
|
|
static void
|
|
nmt_editor_grid_size_request (NmtNewtWidget *widget,
|
|
int *width,
|
|
int *height)
|
|
{
|
|
NmtEditorGridPrivate *priv = NMT_EDITOR_GRID_GET_PRIVATE (widget);
|
|
NmtEditorGridRow *rows = (NmtEditorGridRow *) priv->rows->data;
|
|
NmtEditorGridFormState *state = get_form_state (widget);
|
|
gboolean add_padding = FALSE;
|
|
int i;
|
|
|
|
g_free (priv->row_heights);
|
|
priv->row_heights = g_new0 (int, priv->rows->len);
|
|
|
|
*height = 0;
|
|
for (i = 0; i < priv->rows->len; i++) {
|
|
int lwidth, lheight, wwidth, wheight, ewidth, eheight;
|
|
|
|
if (!nmt_newt_widget_get_visible (rows[i].widget))
|
|
continue;
|
|
|
|
if (rows[i].label) {
|
|
nmt_newt_widget_size_request (rows[i].label, &lwidth, &lheight);
|
|
lwidth += priv->indent;
|
|
state->col_widths[0] = MAX (state->col_widths[0], lwidth);
|
|
|
|
nmt_newt_widget_size_request (rows[i].widget, &wwidth, &wheight);
|
|
state->col_widths[1] = MAX (state->col_widths[1], wwidth);
|
|
priv->row_heights[i] = wheight;
|
|
|
|
add_padding = TRUE;
|
|
} else {
|
|
nmt_newt_widget_size_request (rows[i].widget, &wwidth, &wheight);
|
|
priv->row_heights[i] = wheight;
|
|
}
|
|
|
|
if (rows[i].extra) {
|
|
nmt_newt_widget_size_request (rows[i].extra, &ewidth, &eheight);
|
|
state->col_widths[2] = MAX (state->col_widths[2], ewidth);
|
|
priv->row_heights[i] = MAX (priv->row_heights[i], eheight);
|
|
}
|
|
|
|
*height += priv->row_heights[i];
|
|
}
|
|
|
|
*width = state->col_widths[0] + state->col_widths[1] + state->col_widths[2];
|
|
if (add_padding)
|
|
*width += 2;
|
|
}
|
|
|
|
static void
|
|
nmt_editor_grid_size_allocate (NmtNewtWidget *widget,
|
|
int x,
|
|
int y,
|
|
int width,
|
|
int height)
|
|
{
|
|
NmtEditorGridPrivate *priv = NMT_EDITOR_GRID_GET_PRIVATE (widget);
|
|
NmtEditorGridRow *rows = (NmtEditorGridRow *) priv->rows->data;
|
|
NmtEditorGridFormState *state = get_form_state (widget);
|
|
int col0_width, col1_width, col2_width;
|
|
int i, row;
|
|
|
|
col0_width = state->col_widths[0] - priv->indent;
|
|
col1_width = state->col_widths[1];
|
|
col2_width = state->col_widths[2];
|
|
|
|
for (i = row = 0; i < priv->rows->len; i++) {
|
|
if (!nmt_newt_widget_get_visible (rows[i].widget))
|
|
continue;
|
|
|
|
if (rows[i].label) {
|
|
int lwidth, lheight, lx;
|
|
|
|
if (rows[i].flags & NMT_EDITOR_GRID_ROW_LABEL_ALIGN_LEFT)
|
|
lx = x;
|
|
else {
|
|
nmt_newt_widget_size_request (rows[i].label, &lwidth, &lheight);
|
|
lx = x + col0_width - lwidth;
|
|
}
|
|
|
|
nmt_newt_widget_size_allocate (rows[i].label,
|
|
lx,
|
|
y + row,
|
|
col0_width,
|
|
priv->row_heights[i]);
|
|
|
|
nmt_newt_widget_size_allocate (rows[i].widget,
|
|
x + col0_width + 1,
|
|
y + row,
|
|
col1_width,
|
|
priv->row_heights[i]);
|
|
} else {
|
|
nmt_newt_widget_size_allocate (rows[i].widget,
|
|
x,
|
|
y + row,
|
|
col0_width + col1_width + 1,
|
|
priv->row_heights[i]);
|
|
}
|
|
|
|
if (rows[i].extra) {
|
|
int wwidth, wheight, ex;
|
|
|
|
if (rows[i].flags & NMT_EDITOR_GRID_ROW_EXTRA_ALIGN_RIGHT)
|
|
ex = x + col0_width + col1_width + 2;
|
|
else {
|
|
nmt_newt_widget_size_request (rows[i].widget, &wwidth, &wheight);
|
|
ex = x + col0_width + wwidth + 2;
|
|
}
|
|
|
|
nmt_newt_widget_size_allocate (rows[i].extra,
|
|
ex,
|
|
y + row,
|
|
col2_width,
|
|
priv->row_heights[i]);
|
|
}
|
|
|
|
row += priv->row_heights[i];
|
|
}
|
|
}
|
|
|
|
static void
|
|
nmt_editor_grid_class_init (NmtEditorGridClass *grid_class)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (grid_class);
|
|
NmtNewtWidgetClass *widget_class = NMT_NEWT_WIDGET_CLASS (grid_class);
|
|
NmtNewtContainerClass *container_class = NMT_NEWT_CONTAINER_CLASS (grid_class);
|
|
|
|
g_type_class_add_private (grid_class, sizeof (NmtEditorGridPrivate));
|
|
|
|
/* virtual methods */
|
|
object_class->finalize = nmt_editor_grid_finalize;
|
|
|
|
widget_class->realize = nmt_editor_grid_realize;
|
|
widget_class->unrealize = nmt_editor_grid_unrealize;
|
|
widget_class->get_components = nmt_editor_grid_get_components;
|
|
widget_class->size_request = nmt_editor_grid_size_request;
|
|
widget_class->size_allocate = nmt_editor_grid_size_allocate;
|
|
|
|
container_class->remove = nmt_editor_grid_remove;
|
|
}
|