📄 dw_table.c
字号:
/* * File: dw_table.c * * Copyright (C) 2001-2003 Sebastian Geerken <sgeerken@users.sourceforge.net> * * 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. */#include <string.h>#include "dw_table.h"#include "list.h"#include "prefs.h"#include "dw_gtk_viewport.h"#define DEBUG_CALC_LEVEL 0#define DEBUG_EXTR_LEVEL 10#define DEBUG_WIDTH_LEVEL 0#define DEBUG_ITERATOR_LEVEL 0/*#define DEBUG_LEVEL 10*/#include "debug.h"/* * Some notes: * * - table->num_children always has the value table->num_cols * * table->num_rows, and shows the minimal size of * table->children, *not* the number of children. * * - table->children[i] may be NULL (unused cells), or a pointer to * DwTableChild. A DwTableChild may be a span space (blocked by * COLSPAN or ROWSPAN of another cell), or a cell starting at * this position. In the last case, the macro CHILD_DEFINED * returns TRUE. *//*#define BORDERS*/#define CHILD_DEFINED(table, n) ((n) < (table)->num_children && \ (table)->children[(n)] != NULL && \ (table)->children[(n)]->type != \ DW_TABLE_SPAN_SPACE)static void Dw_table_init (DwTable *table);static void Dw_table_class_init (DwTableClass *klass);static void Dw_table_destroy (GtkObject *object);static void Dw_table_size_request (DwWidget *widget, DwRequisition *requisition);static void Dw_table_get_extremes (DwWidget *widget, DwExtremes *extremes);static void Dw_table_size_allocate (DwWidget *widget, DwAllocation *allocation);static void Dw_table_set_width (DwWidget *widget, gint32 width);static void Dw_table_set_ascent (DwWidget *widget, gint32 ascent);static void Dw_table_set_descent (DwWidget *widget, gint32 descent);static void Dw_table_draw (DwWidget *widget, DwRectangle *area, GdkEventExpose *event);static gboolean Dw_table_button_press (DwWidget *widget, gint32 x, gint32 y, GdkEventButton *event);static gboolean Dw_table_button_release(DwWidget *widget, gint32 x, gint32 y, GdkEventButton *event);static gboolean Dw_table_motion_notify (DwWidget *widget, gint32 x, gint32 y, GdkEventMotion *event);static void Dw_table_add (DwContainer *container, DwWidget *widget);static void Dw_table_remove (DwContainer *container, DwWidget *widget);static void Dw_table_forall (DwContainer *container, DwCallback callback, gpointer callback_data);static DwIterator* Dw_table_iterator (DwWidget *widget, gint mask, gboolean at_end);static gboolean Dw_table_iterator_next (DwIterator *it);static gboolean Dw_table_iterator_prev (DwIterator *it);static void Dw_table_realloc_children (DwTable *table);static void Dw_table_sub_create (DwTable *table);static void Dw_table_sub_free (DwTableSub *sub);static void Dw_table_sub_get_extremes (DwTableSub *sub);static void Dw_table_sub_calc_col_widths (DwTableSub *sub, gint32 width, gint32 total_width);static DwContainerClass *parent_class;enum { /* values of use_percentage */ USE_PERCENTAGE_NO, /* No percentage in subtable, and USE_PERCENTAGE_NO * in all sub-subtables. */ USE_PERCENTAGE_SOME, /* None of the other cases. This affects the minimal, * but not the maximal width of the subtable. */ USE_PERCENTAGE_ALL /* Percentage in subtable, or USE_PERCENTAGE_ALL in * all sub-subtables. This affects the minimal and * the maximal width of the subtable. */};/* * Standard Gtk+ function. */GtkType a_Dw_table_get_type (void){ static GtkType type = 0; if (!type) { GtkTypeInfo info = { "DwTable", sizeof (DwTable), sizeof (DwTableClass), (GtkClassInitFunc) Dw_table_class_init, (GtkObjectInitFunc) Dw_table_init, (GtkArgSetFunc) NULL, (GtkArgGetFunc) NULL, (GtkClassInitFunc) NULL }; type = gtk_type_unique (DW_TYPE_CONTAINER, &info); } return type;}/* * Standard Gtk+ function. */DwWidget* a_Dw_table_new (void){ GtkObject *object; object = gtk_object_new (DW_TYPE_TABLE, NULL); DBG_OBJ_CREATE (object, "DwTable"); return DW_WIDGET (object);}/* * Standard Gtk+ function. */static void Dw_table_init (DwTable *table){ DW_WIDGET_SET_FLAGS (table, DW_USES_HINTS); /* random value */ table->avail_width = 100; table->cur_row = -1; table->cur_col = 0; table->num_children_max = 1; /* 16 */ table->num_children = 0; table->children = NULL; table->num_col_width_max = 1; /* 8 */ table->num_cols = 0; table->col_width = NULL; table->cum_height_max = 1; /* row cumulative height array */ table->num_rows = 0; /* num_cum_height is (num_rows + 1) */ table->cum_height = g_new(gint32, table->cum_height_max); table->row_style_max = 1; table->row_style = g_new(DwStyle*, table->row_style_max); table->baseline_max = 1; table->baseline = g_new(gint32, table->baseline_max); table->sub = NULL;}/* * Standard Gtk+ function. */static void Dw_table_class_init (DwTableClass *klass){ GtkObjectClass *object_class; DwWidgetClass *widget_class; DwContainerClass *container_class; object_class = (GtkObjectClass*) klass; widget_class = (DwWidgetClass*) klass; container_class = (DwContainerClass*) klass; parent_class = gtk_type_class (DW_TYPE_CONTAINER); object_class->destroy = Dw_table_destroy; widget_class->size_request = Dw_table_size_request; widget_class->get_extremes = Dw_table_get_extremes; widget_class->size_allocate = Dw_table_size_allocate; widget_class->set_width = Dw_table_set_width; widget_class->set_ascent = Dw_table_set_ascent; widget_class->set_descent = Dw_table_set_descent; widget_class->draw = Dw_table_draw; widget_class->button_press_event = Dw_table_button_press; widget_class->button_release_event = Dw_table_button_release; widget_class->motion_notify_event = Dw_table_motion_notify; widget_class->iterator = Dw_table_iterator; container_class->add = Dw_table_add; container_class->remove = Dw_table_remove; container_class->forall = Dw_table_forall;}/* * Standard Gtk+ function. */static void Dw_table_destroy (GtkObject *object){ DwTable *table = DW_TABLE (object); gint i; for (i = 0; i < table->num_children; i++) if (table->children[i]) { if (table->children[i]->type == DW_TABLE_CELL) gtk_object_unref(GTK_OBJECT(table->children[i]->data.cell.widget)); g_free (table->children[i]); } g_free (table->children); table->num_children = 0; g_free (table->col_width); g_free (table->cum_height); for (i = 0; i < table->num_rows; i++) if (table->row_style[i]) a_Dw_style_unref (table->row_style[i]); g_free (table->row_style); g_free (table->baseline); if (table->sub) Dw_table_sub_free (table->sub); GTK_OBJECT_CLASS(parent_class)->destroy (object);}/* * Standard Dw function. * Furthermore, table->width and table->cum_height are filled. */static void Dw_table_size_request (DwWidget *widget, DwRequisition *requisition){ DwExtremes extremes; gint32 avail_width; DwTable *table = DW_TABLE (widget); gint row, row2, col, col2, n; gint32 child_height, set_width; DwWidget *child; DwRequisition child_requisition; /* Calculate the widths of the columns, and store it in table->col_width. */ if (table->num_cols > 0) { a_Dw_widget_get_extremes (DW_WIDGET (table), &extremes); if (DW_STYLE_IS_ABS_LENGTH (widget->style->width)) avail_width = DW_STYLE_ABS_LENGTH_VAL (widget->style->width); else if (DW_STYLE_IS_PER_LENGTH (widget->style->width)) /* * If the width is > 100%, we use 100%, this prevents ugly * results. (May be changed in future, when a more powerful * rendering is implemented, to handle fixed positions etc., * as defined by CSS2.) */ avail_width = table->avail_width * MIN (DW_STYLE_PER_LENGTH_VAL (widget->style->width), 1.0); else avail_width = table->avail_width; if (avail_width < extremes.min_width) avail_width = extremes.min_width; if (widget->style->width == DW_STYLE_LENGTH_AUTO && avail_width > extremes.max_width) avail_width = extremes.max_width; DEBUG_MSG (DEBUG_WIDTH_LEVEL + 3, "--> Calculating column widths for (%d x %d) table.\n", table->num_cols, table->num_rows); DEBUG_MSG (DEBUG_WIDTH_LEVEL + 3, " [ %d --(%d, %d)--> %d ]\n", table->avail_width, extremes.min_width, extremes.max_width, avail_width); avail_width -= (2 * widget->style->border_spacing + p_Dw_style_box_diff_width (widget->style)); Dw_table_sub_calc_col_widths (table->sub, avail_width, avail_width - (table->num_cols - 1) * widget->style->border_spacing); DEBUG_MSG (DEBUG_WIDTH_LEVEL + 2, "<-- END\n"); } /* Calculate the total width. */ requisition->width = p_Dw_style_box_diff_width (widget->style) + (table->num_cols + 1) * widget->style->border_spacing; for (col = 0; col < table->num_cols; col++) requisition->width += table->col_width[col]; /* Calculate the height. */ for (row = 0; row <= table->num_rows; row++) table->cum_height[row] = widget->style->border_spacing; for (row = 0; row < table->num_rows; row++) { /* Calculate the baselines, for cells only with valign=baseline. */ table->baseline[row] = 0; for (col = 0; col < table->num_cols; col++) { n = col + row * table->num_cols; if (CHILD_DEFINED (table, n)) { child = table->children[n]->data.cell.widget; if (child->style->valign == DW_STYLE_VALIGN_BASELINE) { a_Dw_widget_size_request (child, &child_requisition); if (child_requisition.ascent > table->baseline[row]) table->baseline[row] = child_requisition.ascent; } } } for (col = 0; col < table->num_cols; col++) { n = col + row * table->num_cols; if (CHILD_DEFINED (table, n)) { child = table->children[n]->data.cell.widget; set_width = 0; for (col2 = col; col2 < col + table->children[n]->data.cell.colspan;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -