GtkCList updates: Click-Drag column resizing, a couple of layout

fixes, show/hide functions for the title buttons, and I've replaced
gtk_clist_new with gtk_clist_new_with_titles.  gtk_clist_new will
create a list without title bars which can be added later by calling
gtk_clist_set_column_(title/widget) for the column button you want to add.
A column button for column 0 always exhists, and buttons span all columns
until they come to the next exhisting button, or the last column. -Jay
This commit is contained in:
Jay Painter 1998-01-19 09:59:20 +00:00
parent 1a8765e6ce
commit 79f69b1676
4 changed files with 487 additions and 80 deletions

View File

@ -21,7 +21,7 @@
#include "gtkclist.h" #include "gtkclist.h"
/* the width of the column resize windows */ /* the width of the column resize windows */
#define DRAG_WIDTH 5 #define DRAG_WIDTH 6
/* minimum allowed width of a column */ /* minimum allowed width of a column */
#define COLUMN_MIN_WIDTH 5 #define COLUMN_MIN_WIDTH 5
@ -48,7 +48,7 @@
/* gives the left pixel of the given column in context of /* gives the left pixel of the given column in context of
* the clist's hoffset */ * the clist's hoffset */
#define COLUMN_LEFT_YPIXEL(clist, column) ((clist)->column[(column)].area.x + \ #define COLUMN_LEFT_XPIXEL(clist, column) ((clist)->column[(column)].area.x + \
(clist)->hoffset) (clist)->hoffset)
/* returns the column index from a x pixel location in the /* returns the column index from a x pixel location in the
@ -159,24 +159,36 @@ static gint gtk_clist_expose (GtkWidget * widget,
GdkEventExpose * event); GdkEventExpose * event);
static gint gtk_clist_button_press (GtkWidget * widget, static gint gtk_clist_button_press (GtkWidget * widget,
GdkEventButton * event); GdkEventButton * event);
static gint gtk_clist_button_release (GtkWidget * widget,
GdkEventButton * event);
static gint gtk_clist_motion (GtkWidget * widget,
GdkEventMotion * event);
static void gtk_clist_size_request (GtkWidget * widget, static void gtk_clist_size_request (GtkWidget * widget,
GtkRequisition * requisition); GtkRequisition * requisition);
static void gtk_clist_size_allocate (GtkWidget * widget, static void gtk_clist_size_allocate (GtkWidget * widget,
GtkAllocation * allocation); GtkAllocation * allocation);
/* GtkContainer Methods */ /* GtkContainer Methods */
static void gtk_clist_foreach (GtkContainer * container, static void gtk_clist_foreach (GtkContainer * container,
GtkCallback callback, GtkCallback callback,
gpointer callback_data); gpointer callback_data);
/* Resize Column Windows */
static void draw_xor_line (GtkCList * clist);
static gint new_column_width (GtkCList * clist,
gint column,
gint * x);
static void resize_column (GtkCList * clist,
gint column,
gint width);
/* Buttons */ /* Buttons */
static void gtk_clist_column_button_clicked (GtkWidget * widget, static void column_button_create (GtkCList * clist,
gint column);
static void column_button_clicked (GtkWidget * widget,
gpointer data); gpointer data);
/* Scrollbars */ /* Scrollbars */
static void gtk_clist_adjust_scrollbars (GtkCList * clist); static void gtk_clist_adjust_scrollbars (GtkCList * clist);
static void gtk_clist_vadjustment_changed (GtkAdjustment * adjustment, static void gtk_clist_vadjustment_changed (GtkAdjustment * adjustment,
@ -305,6 +317,8 @@ gtk_clist_class_init (GtkCListClass * klass)
widget_class->unmap = gtk_clist_unmap; widget_class->unmap = gtk_clist_unmap;
widget_class->draw = gtk_clist_draw; widget_class->draw = gtk_clist_draw;
widget_class->button_press_event = gtk_clist_button_press; widget_class->button_press_event = gtk_clist_button_press;
widget_class->button_release_event = gtk_clist_button_release;
widget_class->motion_notify_event = gtk_clist_motion;
widget_class->expose_event = gtk_clist_expose; widget_class->expose_event = gtk_clist_expose;
widget_class->size_request = gtk_clist_size_request; widget_class->size_request = gtk_clist_size_request;
widget_class->size_allocate = gtk_clist_size_allocate; widget_class->size_allocate = gtk_clist_size_allocate;
@ -366,6 +380,7 @@ gtk_clist_init (GtkCList * clist)
clist->columns = 0; clist->columns = 0;
clist->title_window = NULL;
clist->column_title_area.x = 0; clist->column_title_area.x = 0;
clist->column_title_area.y = 0; clist->column_title_area.y = 0;
clist->column_title_area.width = 0; clist->column_title_area.width = 0;
@ -393,18 +408,45 @@ gtk_clist_init (GtkCList * clist)
} }
GtkWidget * GtkWidget *
gtk_clist_new (int columns, gtk_clist_new_with_titles (int columns,
gchar * titles[]) gchar * titles[])
{ {
int i; int i;
GtkWidget *widget;
GtkCList *clist;
if (titles == NULL)
return NULL;
widget = gtk_clist_new (columns);
if (!widget)
return NULL;
else
clist = GTK_CLIST (widget);
/* set column titles */
GTK_CLIST_SET_FLAGS (clist, CLIST_SHOW_TITLES);
for (i = 0; i < columns; i++)
{
gtk_clist_set_column_title (clist, i, titles[i]);
clist->column[i].width = gdk_string_width (GTK_WIDGET (clist)->style->font, clist->column[i].title);
}
return widget;
}
GtkWidget *
gtk_clist_new (int columns)
{
GtkCList *clist; GtkCList *clist;
GtkAdjustment *adjustment; GtkAdjustment *adjustment;
/* sanity check */ /* sanity check */
if (columns < 1 || titles == NULL) if (columns < 1)
return NULL; return NULL;
clist = gtk_type_new (gtk_clist_get_type ()); clist = gtk_type_new (gtk_clist_get_type ());
GTK_CLIST_UNSET_FLAGS (clist, CLIST_SHOW_TITLES);
/* initalize memory chunks */ /* initalize memory chunks */
clist->row_mem_chunk = g_mem_chunk_new ("clist row mem chunk", clist->row_mem_chunk = g_mem_chunk_new ("clist row mem chunk",
@ -420,26 +462,10 @@ gtk_clist_new (int columns,
clist->columns = columns; clist->columns = columns;
clist->column = gtk_clist_columns_new (clist); clist->column = gtk_clist_columns_new (clist);
/* create column button and connect signals */ /* there needs to be at least one column button
for (i = 0; i < columns; i++) * because there is alot of code that will break if it
{ * isn't there*/
clist->column[i].button = gtk_button_new (); column_button_create (clist, 0);
gtk_widget_set_parent (clist->column[i].button, GTK_WIDGET (clist));
gtk_signal_connect (GTK_OBJECT (clist->column[i].button),
"clicked",
(GtkSignalFunc) gtk_clist_column_button_clicked,
(gpointer) clist);
/* set column title */
gtk_clist_set_column_title (clist, i, titles[i]);
clist->column[i].width =
gdk_string_width (GTK_WIDGET (clist)->style->font, clist->column[i].title);
gtk_widget_show (clist->column[i].button);
}
/* create and connect scrollbars */ /* create and connect scrollbars */
clist->vscrollbar = gtk_vscrollbar_new (NULL); clist->vscrollbar = gtk_vscrollbar_new (NULL);
@ -513,12 +539,36 @@ gtk_clist_thaw (GtkCList * clist)
gtk_clist_draw_rows (clist, NULL); gtk_clist_draw_rows (clist, NULL);
} }
void
gtk_clist_column_titles_show (GtkCList * clist)
{
g_return_if_fail (clist != NULL);
if (!GTK_CLIST_SHOW_TITLES (clist))
{
GTK_CLIST_SET_FLAGS (clist, CLIST_SHOW_TITLES);
gdk_window_show (clist->title_window);
gtk_widget_queue_resize (GTK_WIDGET (clist));
}
}
void
gtk_clist_column_titles_hide (GtkCList * clist)
{
if (GTK_CLIST_SHOW_TITLES (clist))
{
GTK_CLIST_UNSET_FLAGS (clist, CLIST_SHOW_TITLES);
gdk_window_hide (clist->title_window);
gtk_widget_queue_resize (GTK_WIDGET (clist));
}
}
void void
gtk_clist_set_column_title (GtkCList * clist, gtk_clist_set_column_title (GtkCList * clist,
gint column, gint column,
gchar * title) gchar * title)
{ {
gint new_button = 0;
GtkWidget *old_widget; GtkWidget *old_widget;
GtkWidget *alignment = NULL; GtkWidget *alignment = NULL;
GtkWidget *label; GtkWidget *label;
@ -528,6 +578,14 @@ gtk_clist_set_column_title (GtkCList * clist,
if (column < 0 || column >= clist->columns) if (column < 0 || column >= clist->columns)
return; return;
/* if the column button doesn't currently exhist,
* it has to be created first */
if (!clist->column[column].button)
{
column_button_create (clist, column);
new_button = 1;
}
gtk_clist_column_title_new (clist, column, title); gtk_clist_column_title_new (clist, column, title);
/* remove and destroy the old widget */ /* remove and destroy the old widget */
@ -538,6 +596,7 @@ gtk_clist_set_column_title (GtkCList * clist,
gtk_widget_destroy (old_widget); gtk_widget_destroy (old_widget);
} }
/* create new alignment based no column justification */
switch (clist->column[column].justification) switch (clist->column[column].justification)
{ {
case GTK_JUSTIFY_LEFT: case GTK_JUSTIFY_LEFT:
@ -557,14 +616,16 @@ gtk_clist_set_column_title (GtkCList * clist,
break; break;
} }
if (alignment)
{
label = gtk_label_new (clist->column[column].title); label = gtk_label_new (clist->column[column].title);
gtk_container_add (GTK_CONTAINER (alignment), label); gtk_container_add (GTK_CONTAINER (alignment), label);
gtk_container_add (GTK_CONTAINER (clist->column[column].button), alignment); gtk_container_add (GTK_CONTAINER (clist->column[column].button), alignment);
gtk_widget_show (label); gtk_widget_show (label);
gtk_widget_show (alignment); gtk_widget_show (alignment);
}
/* if this button didn't previously exhist, then the
* column button positions have to be re-computed */
if (GTK_WIDGET_VISIBLE (clist) && new_button)
gtk_clist_size_allocate_title_buttons (clist);
} }
void void
@ -572,6 +633,7 @@ gtk_clist_set_column_widget (GtkCList * clist,
gint column, gint column,
GtkWidget * widget) GtkWidget * widget)
{ {
gint new_button = 0;
GtkWidget *old_widget; GtkWidget *old_widget;
g_return_if_fail (clist != NULL); g_return_if_fail (clist != NULL);
@ -579,6 +641,14 @@ gtk_clist_set_column_widget (GtkCList * clist,
if (column < 0 || column >= clist->columns) if (column < 0 || column >= clist->columns)
return; return;
/* if the column button doesn't currently exhist,
* it has to be created first */
if (!clist->column[column].button)
{
column_button_create (clist, column);
new_button = 1;
}
gtk_clist_column_title_new (clist, column, NULL); gtk_clist_column_title_new (clist, column, NULL);
/* remove and destroy the old widget */ /* remove and destroy the old widget */
@ -595,6 +665,11 @@ gtk_clist_set_column_widget (GtkCList * clist,
gtk_container_add (GTK_CONTAINER (clist->column[column].button), widget); gtk_container_add (GTK_CONTAINER (clist->column[column].button), widget);
gtk_widget_show (widget); gtk_widget_show (widget);
} }
/* if this button didn't previously exhist, then the
* column button positions have to be re-computed */
if (GTK_WIDGET_VISIBLE (clist) && new_button)
gtk_clist_size_allocate_title_buttons (clist);
} }
void void
@ -1257,6 +1332,7 @@ gtk_clist_destroy (GtkObject * object)
/* get rid of all the column buttons */ /* get rid of all the column buttons */
for (i = 0; i < clist->columns; i++) for (i = 0; i < clist->columns; i++)
if (clist->column[i].button)
gtk_widget_destroy (clist->column[i].button); gtk_widget_destroy (clist->column[i].button);
gtk_clist_columns_delete (clist); gtk_clist_columns_delete (clist);
@ -1272,11 +1348,11 @@ gtk_clist_destroy (GtkObject * object)
static void static void
gtk_clist_realize (GtkWidget * widget) gtk_clist_realize (GtkWidget * widget)
{ {
gint i;
GtkCList *clist; GtkCList *clist;
GdkWindowAttr attributes; GdkWindowAttr attributes;
gint attributes_mask; gint attributes_mask;
GdkGCValues values; GdkGCValues values;
gint i;
g_return_if_fail (widget != NULL); g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_CLIST (widget)); g_return_if_fail (GTK_IS_CLIST (widget));
@ -1318,6 +1394,7 @@ gtk_clist_realize (GtkWidget * widget)
/* set things up so column buttons are drawn in title window */ /* set things up so column buttons are drawn in title window */
for (i = 0; i < clist->columns; i++) for (i = 0; i < clist->columns; i++)
if (clist->column[i].button)
gtk_widget_set_parent_window (clist->column[i].button, clist->title_window); gtk_widget_set_parent_window (clist->column[i].button, clist->title_window);
/* clist-window */ /* clist-window */
@ -1329,9 +1406,23 @@ gtk_clist_realize (GtkWidget * widget)
gdk_window_get_size (clist->clist_window, &clist->clist_window_width, gdk_window_get_size (clist->clist_window, &clist->clist_window_width,
&clist->clist_window_height); &clist->clist_window_height);
/* cursor's and GC's */ /* create resize windows */
clist->cursor_drag = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW); attributes.wclass = GDK_INPUT_ONLY;
attributes.event_mask = (GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_POINTER_MOTION_MASK |
GDK_POINTER_MOTION_HINT_MASK);
attributes.cursor = clist->cursor_drag = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
attributes_mask = GDK_WA_CURSOR;
for (i = 0; i < clist->columns; i++)
{
clist->column[i].window = gdk_window_new (clist->title_window, &attributes, attributes_mask);
gdk_window_set_user_data (clist->column[i].window, clist);
gdk_window_show (clist->column[i].window);
}
/* GCs */
clist->fg_gc = gdk_gc_new (widget->window); clist->fg_gc = gdk_gc_new (widget->window);
clist->bg_gc = gdk_gc_new (widget->window); clist->bg_gc = gdk_gc_new (widget->window);
@ -1355,6 +1446,7 @@ gtk_clist_realize (GtkWidget * widget)
static void static void
gtk_clist_unrealize (GtkWidget * widget) gtk_clist_unrealize (GtkWidget * widget)
{ {
gint i;
GtkCList *clist; GtkCList *clist;
g_return_if_fail (widget != NULL); g_return_if_fail (widget != NULL);
@ -1371,6 +1463,13 @@ gtk_clist_unrealize (GtkWidget * widget)
gtk_style_detach (widget->style); gtk_style_detach (widget->style);
for (i = 0; i < clist->columns; i++)
if (clist->column[i].window)
{
gdk_window_destroy (clist->column[i].window);
clist->column[i].window = NULL;
}
gdk_window_destroy (clist->clist_window); gdk_window_destroy (clist->clist_window);
gdk_window_destroy (clist->title_window); gdk_window_destroy (clist->title_window);
gdk_window_set_user_data (widget->window, NULL); gdk_window_set_user_data (widget->window, NULL);
@ -1404,12 +1503,18 @@ gtk_clist_map (GtkWidget * widget)
gdk_window_show (clist->title_window); gdk_window_show (clist->title_window);
gdk_window_show (clist->clist_window); gdk_window_show (clist->clist_window);
/* map column buttons*/ /* map column buttons */
for (i = 0; i < clist->columns; i++) for (i = 0; i < clist->columns; i++)
if (GTK_WIDGET_VISIBLE (clist->column[i].button) && if (clist->column[i].button &&
GTK_WIDGET_VISIBLE (clist->column[i].button) &&
!GTK_WIDGET_MAPPED (clist->column[i].button)) !GTK_WIDGET_MAPPED (clist->column[i].button))
gtk_widget_map (clist->column[i].button); gtk_widget_map (clist->column[i].button);
/* map resize windows AFTER column buttons (above) */
for (i = 0; i < clist->columns; i++)
if (clist->column[i].window && clist->column[i].button)
gdk_window_show (clist->column[i].window);
/* map vscrollbars */ /* map vscrollbars */
if (GTK_WIDGET_VISIBLE (clist->vscrollbar) && if (GTK_WIDGET_VISIBLE (clist->vscrollbar) &&
!GTK_WIDGET_MAPPED (clist->vscrollbar)) !GTK_WIDGET_MAPPED (clist->vscrollbar))
@ -1439,6 +1544,10 @@ gtk_clist_unmap (GtkWidget * widget)
{ {
GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED); GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
for (i = 0; i < clist->columns; i++)
if (clist->column[i].window)
gdk_window_hide (clist->column[i].window);
gdk_window_hide (clist->clist_window); gdk_window_hide (clist->clist_window);
gdk_window_hide (clist->title_window); gdk_window_hide (clist->title_window);
gdk_window_hide (widget->window); gdk_window_hide (widget->window);
@ -1452,7 +1561,8 @@ gtk_clist_unmap (GtkWidget * widget)
/* unmap column buttons */ /* unmap column buttons */
for (i = 0; i < clist->columns; i++) for (i = 0; i < clist->columns; i++)
if (GTK_WIDGET_MAPPED (clist->column[i].button)) if (clist->column[i].button &&
GTK_WIDGET_MAPPED (clist->column[i].button))
gtk_widget_unmap (clist->column[i].button); gtk_widget_unmap (clist->column[i].button);
/* freeze the list */ /* freeze the list */
@ -2030,6 +2140,7 @@ static gint
gtk_clist_button_press (GtkWidget * widget, gtk_clist_button_press (GtkWidget * widget,
GdkEventButton * event) GdkEventButton * event)
{ {
gint i;
GtkCList *clist; GtkCList *clist;
gint x, y, row, column; gint x, y, row, column;
@ -2048,11 +2159,93 @@ gtk_clist_button_press (GtkWidget * widget,
if (gtk_clist_get_selection_info (clist, x, y, &row, &column)) if (gtk_clist_get_selection_info (clist, x, y, &row, &column))
gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW], gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
row, column, event); row, column, event);
return FALSE;
}
/* press on resize windows */
for (i = 0; i < clist->columns; i++)
if (clist->column[i].window && event->window == clist->column[i].window)
{
GTK_CLIST_SET_FLAGS (clist, CLIST_IN_DRAG);
gtk_widget_get_pointer (widget, &clist->x_drag, NULL);
gdk_pointer_grab (clist->column[i].window, FALSE,
GDK_POINTER_MOTION_HINT_MASK |
GDK_BUTTON1_MOTION_MASK |
GDK_BUTTON_RELEASE_MASK,
NULL, NULL, event->time);
draw_xor_line (clist);
return FALSE;
} }
return FALSE; return FALSE;
} }
static gint
gtk_clist_button_release (GtkWidget * widget,
GdkEventButton * event)
{
gint i, x;
GtkCList *clist;
g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
clist = GTK_CLIST (widget);
/* release on resize windows */
if (GTK_CLIST_IN_DRAG (clist))
for (i = 0; i < clist->columns; i++)
if (clist->column[i].window && event->window == clist->column[i].window)
{
GTK_CLIST_UNSET_FLAGS (clist, CLIST_IN_DRAG);
gtk_widget_get_pointer (widget, &x, NULL);
gdk_pointer_ungrab (event->time);
draw_xor_line (clist);
resize_column (clist, i, new_column_width (clist, i, &x));
return FALSE;
}
return FALSE;
}
static gint
gtk_clist_motion (GtkWidget * widget,
GdkEventMotion * event)
{
gint i, x;
GtkCList *clist;
g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
clist = GTK_CLIST (widget);
if (GTK_CLIST_IN_DRAG (clist))
for (i = 0; i < clist->columns; i++)
if (clist->column[i].window && event->window == clist->column[i].window)
{
if (event->is_hint || event->window != widget->window)
gtk_widget_get_pointer (widget, &x, NULL);
else
x = event->x;
new_column_width (clist, i, &x);
if (x != clist->x_drag)
{
draw_xor_line (clist);
clist->x_drag = x;
draw_xor_line (clist);
}
}
return TRUE;
}
static void static void
gtk_clist_size_request (GtkWidget * widget, gtk_clist_size_request (GtkWidget * widget,
GtkRequisition * requisition) GtkRequisition * requisition)
@ -2071,7 +2264,9 @@ gtk_clist_size_request (GtkWidget * widget,
/* compute the size of the column title (title) area */ /* compute the size of the column title (title) area */
clist->column_title_area.height = 0; clist->column_title_area.height = 0;
if (GTK_CLIST_SHOW_TITLES (clist))
for (i = 0; i < clist->columns; i++) for (i = 0; i < clist->columns; i++)
if (clist->column[i].button)
{ {
gtk_widget_size_request (clist->column[i].button, &clist->column[i].button->requisition); gtk_widget_size_request (clist->column[i].button, &clist->column[i].button->requisition);
clist->column_title_area.height = MAX (clist->column_title_area.height, clist->column_title_area.height = MAX (clist->column_title_area.height,
@ -2228,8 +2423,7 @@ gtk_clist_size_allocate (GtkWidget * widget,
child_allocation.y = clist->internal_allocation.y; child_allocation.y = clist->internal_allocation.y;
child_allocation.width = clist->vscrollbar->requisition.width; child_allocation.width = clist->vscrollbar->requisition.width;
child_allocation.height = clist->internal_allocation.height - child_allocation.height = clist->internal_allocation.height -
SCROLLBAR_SPACING (clist) - (hscrollbar_vis ? (clist->hscrollbar->requisition.height + SCROLLBAR_SPACING (clist)) : 0);
(hscrollbar_vis ? clist->hscrollbar->requisition.height : 0);
gtk_widget_size_allocate (clist->vscrollbar, &child_allocation); gtk_widget_size_allocate (clist->vscrollbar, &child_allocation);
} }
@ -2249,8 +2443,7 @@ gtk_clist_size_allocate (GtkWidget * widget,
clist->internal_allocation.height - clist->internal_allocation.height -
clist->hscrollbar->requisition.height; clist->hscrollbar->requisition.height;
child_allocation.width = clist->internal_allocation.width - child_allocation.width = clist->internal_allocation.width -
SCROLLBAR_SPACING (clist) - (vscrollbar_vis ? (clist->vscrollbar->requisition.width + SCROLLBAR_SPACING (clist)) : 0);
(vscrollbar_vis ? clist->vscrollbar->requisition.width : 0);
child_allocation.height = clist->hscrollbar->requisition.height; child_allocation.height = clist->hscrollbar->requisition.height;
gtk_widget_size_allocate (clist->hscrollbar, &child_allocation); gtk_widget_size_allocate (clist->hscrollbar, &child_allocation);
@ -2271,9 +2464,12 @@ gtk_clist_size_allocate (GtkWidget * widget,
static void static void
gtk_clist_size_allocate_title_buttons (GtkCList * clist) gtk_clist_size_allocate_title_buttons (GtkCList * clist)
{ {
gint i; gint i, last_button = 0;
GtkAllocation button_allocation; GtkAllocation button_allocation;
if (!GTK_WIDGET_REALIZED (clist))
return;
button_allocation.x = clist->hoffset; button_allocation.x = clist->hoffset;
button_allocation.y = 0; button_allocation.y = 0;
button_allocation.height = clist->column_title_area.height; button_allocation.height = clist->column_title_area.height;
@ -2294,17 +2490,39 @@ gtk_clist_size_allocate_title_buttons (GtkCList * clist)
button_allocation.width += CELL_SPACING + (2 * COLUMN_INSET); button_allocation.width += CELL_SPACING + (2 * COLUMN_INSET);
} }
gtk_widget_size_allocate (clist->column[i].button, &button_allocation); if (i == (clist->columns - 1) || clist->column[i + 1].button)
{
gtk_widget_size_allocate (clist->column[last_button].button, &button_allocation);
button_allocation.x += button_allocation.width; button_allocation.x += button_allocation.width;
if (clist->column[i + 1].button && i != (clist->columns - 1))
{
gdk_window_show (clist->column[last_button].window);
gdk_window_move_resize (clist->column[last_button].window,
button_allocation.x - (DRAG_WIDTH / 2),
0, DRAG_WIDTH, clist->column_title_area.height);
}
else
{
gdk_window_hide (clist->column[i].window);
}
last_button = i + 1;
}
else
{
gdk_window_hide (clist->column[i].window);
}
} }
} }
static void static void
gtk_clist_size_allocate_columns (GtkCList * clist) gtk_clist_size_allocate_columns (GtkCList * clist)
{ {
gint i, xoffset; gint i, xoffset = 0;
xoffset = 0; if (!GTK_WIDGET_REALIZED (clist))
return;
for (i = 0; i < clist->columns; i++) for (i = 0; i < clist->columns; i++)
{ {
@ -2341,6 +2559,7 @@ gtk_clist_foreach (GtkContainer * container,
/* callback for the column buttons */ /* callback for the column buttons */
for (i = 0; i < clist->columns; i++) for (i = 0; i < clist->columns; i++)
if (clist->column[i].button)
(*callback) (clist->column[i].button, callback_data); (*callback) (clist->column[i].button, callback_data);
/* callbacks for the scrollbars */ /* callbacks for the scrollbars */
@ -2348,10 +2567,99 @@ gtk_clist_foreach (GtkContainer * container,
(*callback) (clist->hscrollbar, callback_data); (*callback) (clist->hscrollbar, callback_data);
} }
/* COLUMN RESIZING */
static void
draw_xor_line (GtkCList * clist)
{
GtkWidget *widget;
g_return_if_fail (clist != NULL);
widget = GTK_WIDGET (clist);
gdk_draw_line (widget->window, clist->xor_gc,
clist->x_drag,
widget->style->klass->ythickness,
clist->x_drag,
clist->column_title_area.height + clist->clist_window_height);
}
/* this function returns the new width of the column being resized given
* the column and x position of the cursor; the x cursor position is passed
* in as a pointer and automagicly corrected if it's beyond min/max limits */
static gint
new_column_width (GtkCList * clist,
gint column,
gint * x)
{
gint cx, rx, width;
cx = *x;
/* first translate the x position from widget->window
* to clist->clist_window */
cx -= GTK_WIDGET (clist)->style->klass->xthickness;
/* rx is x from the list beginning */
rx = cx - clist->hoffset;
/* you can't shrink a column to less than its minimum width */
if (cx < (COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET + COLUMN_MIN_WIDTH))
{
*x = cx = COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET + COLUMN_MIN_WIDTH +
GTK_WIDGET (clist)->style->klass->xthickness;
cx -= GTK_WIDGET (clist)->style->klass->xthickness;
rx = cx - clist->hoffset;
}
/* don't grow past the end of the window */
if (cx > clist->clist_window_width)
{
*x = cx = clist->clist_window_width + GTK_WIDGET (clist)->style->klass->xthickness;
cx -= GTK_WIDGET (clist)->style->klass->xthickness;
rx = cx - clist->hoffset;
}
/* calculate new column width making sure it doesn't end up
* less than the minimum width */
width = (rx - COLUMN_LEFT (clist, column)) - COLUMN_INSET;
if (width < COLUMN_MIN_WIDTH)
width = COLUMN_MIN_WIDTH;
return width;
}
/* this will do more later */
static void
resize_column (GtkCList * clist,
gint column,
gint width)
{
gtk_clist_set_column_width (clist, column, width);
}
/* BUTTONS */ /* BUTTONS */
static void
column_button_create (GtkCList * clist,
gint column)
{
GtkWidget *button;
button = clist->column[column].button = gtk_button_new ();
gtk_widget_set_parent (button, GTK_WIDGET (clist));
if (GTK_WIDGET_REALIZED (clist) && clist->title_window)
gtk_widget_set_parent_window (clist->column[column].button, clist->title_window);
gtk_signal_connect (GTK_OBJECT (button),
"clicked",
(GtkSignalFunc) column_button_clicked,
(gpointer) clist);
gtk_widget_show (button);
}
static void static void
gtk_clist_column_button_clicked (GtkWidget * widget, column_button_clicked (GtkWidget * widget,
gpointer data) gpointer data)
{ {
gint i; gint i;
@ -2573,14 +2881,26 @@ gtk_clist_hadjustment_value_changed (GtkAdjustment * adjustment,
if (adjustment == gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar))) if (adjustment == gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar)))
{ {
/* move the column buttons and resize windows */
for (i = 0; i < clist->columns; i++) for (i = 0; i < clist->columns; i++)
{
if (clist->column[i].button)
{ {
clist->column[i].button->allocation.x -= value + clist->hoffset; clist->column[i].button->allocation.x -= value + clist->hoffset;
if (clist->column[i].button->window) if (clist->column[i].button->window)
{
gdk_window_move (clist->column[i].button->window, gdk_window_move (clist->column[i].button->window,
clist->column[i].button->allocation.x, clist->column[i].button->allocation.x,
clist->column[i].button->allocation.y); clist->column[i].button->allocation.y);
if (clist->column[i].window)
gdk_window_move (clist->column[i].window,
clist->column[i].button->allocation.x +
clist->column[i].button->allocation.width -
(DRAG_WIDTH / 2), 0);
}
}
} }
if (value > -clist->hoffset) if (value > -clist->hoffset)
@ -2673,6 +2993,7 @@ gtk_clist_columns_new (GtkCList * clist)
column[i].area.height = 0; column[i].area.height = 0;
column[i].title = NULL; column[i].title = NULL;
column[i].button = NULL; column[i].button = NULL;
column[i].window = NULL;
column[i].width = 0; column[i].width = 0;
column[i].justification = GTK_JUSTIFY_LEFT; column[i].justification = GTK_JUSTIFY_LEFT;
} }

View File

@ -27,7 +27,6 @@
#include <gtk/gtkhscrollbar.h> #include <gtk/gtkhscrollbar.h>
#include <gtk/gtkvscrollbar.h> #include <gtk/gtkvscrollbar.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
{ {
@ -38,7 +37,8 @@ enum
{ {
CLIST_FROZEN = 1 << 0, CLIST_FROZEN = 1 << 0,
CLIST_IN_DRAG = 1 << 1, CLIST_IN_DRAG = 1 << 1,
CLIST_ROW_HEIGHT_SET = 1 << 2 CLIST_ROW_HEIGHT_SET = 1 << 2,
CLIST_SHOW_TITLES = 1 << 3
}; };
/* cell types */ /* cell types */
@ -62,6 +62,7 @@ typedef enum
#define GTK_CLIST_FROZEN(clist) (GTK_CLIST_FLAGS (clist) & CLIST_FROZEN) #define GTK_CLIST_FROZEN(clist) (GTK_CLIST_FLAGS (clist) & CLIST_FROZEN)
#define GTK_CLIST_IN_DRAG(clist) (GTK_CLIST_FLAGS (clist) & CLIST_IN_DRAG) #define GTK_CLIST_IN_DRAG(clist) (GTK_CLIST_FLAGS (clist) & CLIST_IN_DRAG)
#define GTK_CLIST_ROW_HEIGHT_SET(clist) (GTK_CLIST_FLAGS (clist) & CLIST_ROW_HEIGHT_SET) #define GTK_CLIST_ROW_HEIGHT_SET(clist) (GTK_CLIST_FLAGS (clist) & CLIST_ROW_HEIGHT_SET)
#define GTK_CLIST_SHOW_TITLES(clist) (GTK_CLIST_FLAGS (clist) & CLIST_SHOW_TITLES)
/* pointer casting for cells */ /* pointer casting for cells */
#define GTK_CELL_TEXT(cell) (((GtkCellText *) &(cell))) #define GTK_CELL_TEXT(cell) (((GtkCellText *) &(cell)))
@ -172,6 +173,8 @@ struct _GtkCListColumn
GdkRectangle area; GdkRectangle area;
GtkWidget *button; GtkWidget *button;
GdkWindow *window;
gint width; gint width;
GtkJustification justification; GtkJustification justification;
}; };
@ -261,7 +264,8 @@ struct _GtkCell
guint gtk_clist_get_type (void); guint gtk_clist_get_type (void);
/* create a new GtkCList */ /* create a new GtkCList */
GtkWidget *gtk_clist_new (int columns, GtkWidget *gtk_clist_new (int columns);
GtkWidget *gtk_clist_new_with_titles (int columns,
gchar * titles[]); gchar * titles[]);
/* set the border style of the clist */ /* set the border style of the clist */
@ -285,6 +289,10 @@ void gtk_clist_set_policy (GtkCList * clist,
void gtk_clist_freeze (GtkCList * clist); void gtk_clist_freeze (GtkCList * clist);
void gtk_clist_thaw (GtkCList * clist); void gtk_clist_thaw (GtkCList * clist);
/* show and hide the column title buttons */
void gtk_clist_column_titles_show (GtkCList * clist);
void gtk_clist_column_titles_hide (GtkCList * clist);
/* set the title in the column title button */ /* set the title in the column title button */
void gtk_clist_set_column_title (GtkCList * clist, void gtk_clist_set_column_title (GtkCList * clist,
gint column, gint column,

View File

@ -1658,6 +1658,18 @@ remove_row_clist (GtkWidget *widget, gpointer data)
clist_rows--; clist_rows--;
} }
void
show_titles_clist (GtkWidget *widget, gpointer data)
{
gtk_clist_column_titles_show (GTK_CLIST (data));
}
void
hide_titles_clist (GtkWidget *widget, gpointer data)
{
gtk_clist_column_titles_hide (GTK_CLIST (data));
}
void void
select_clist (GtkWidget *widget, select_clist (GtkWidget *widget,
gint row, gint row,
@ -1736,10 +1748,11 @@ create_clist ()
gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
gtk_widget_show (box2); gtk_widget_show (box2);
/* create this here so we have a pointer to throw at the /* create GtkCList here so we have a pointer to throw at the
* button callbacks -- more is done with it later */ * button callbacks -- more is done with it later */
clist = gtk_clist_new (TESTGTK_CLIST_COLUMNS, titles); clist = gtk_clist_new_with_titles (TESTGTK_CLIST_COLUMNS, titles);
/* control buttons */
button = gtk_button_new_with_label ("Add 1,000 Rows"); button = gtk_button_new_with_label ("Add 1,000 Rows");
gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
@ -1781,12 +1794,38 @@ create_clist ()
gtk_widget_show (button); gtk_widget_show (button);
/* second layer of buttons */
box2 = gtk_hbox_new (FALSE, 10);
gtk_container_border_width (GTK_CONTAINER (box2), 10);
gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
gtk_widget_show (box2);
button = gtk_button_new_with_label ("Show Title Buttons");
gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
gtk_signal_connect (GTK_OBJECT (button),
"clicked",
(GtkSignalFunc) show_titles_clist,
(gpointer) clist);
gtk_widget_show (button);
button = gtk_button_new_with_label ("Hide Title Buttons");
gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
gtk_signal_connect (GTK_OBJECT (button),
"clicked",
(GtkSignalFunc) hide_titles_clist,
(gpointer) clist);
gtk_widget_show (button);
/* vbox for the list itself */
box2 = gtk_vbox_new (FALSE, 10); box2 = gtk_vbox_new (FALSE, 10);
gtk_container_border_width (GTK_CONTAINER (box2), 10); gtk_container_border_width (GTK_CONTAINER (box2), 10);
gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
gtk_widget_show (box2); gtk_widget_show (box2);
/* /*
* the rest of the clist configuration * the rest of the clist configuration
*/ */

View File

@ -1658,6 +1658,18 @@ remove_row_clist (GtkWidget *widget, gpointer data)
clist_rows--; clist_rows--;
} }
void
show_titles_clist (GtkWidget *widget, gpointer data)
{
gtk_clist_column_titles_show (GTK_CLIST (data));
}
void
hide_titles_clist (GtkWidget *widget, gpointer data)
{
gtk_clist_column_titles_hide (GTK_CLIST (data));
}
void void
select_clist (GtkWidget *widget, select_clist (GtkWidget *widget,
gint row, gint row,
@ -1736,10 +1748,11 @@ create_clist ()
gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
gtk_widget_show (box2); gtk_widget_show (box2);
/* create this here so we have a pointer to throw at the /* create GtkCList here so we have a pointer to throw at the
* button callbacks -- more is done with it later */ * button callbacks -- more is done with it later */
clist = gtk_clist_new (TESTGTK_CLIST_COLUMNS, titles); clist = gtk_clist_new_with_titles (TESTGTK_CLIST_COLUMNS, titles);
/* control buttons */
button = gtk_button_new_with_label ("Add 1,000 Rows"); button = gtk_button_new_with_label ("Add 1,000 Rows");
gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
@ -1781,12 +1794,38 @@ create_clist ()
gtk_widget_show (button); gtk_widget_show (button);
/* second layer of buttons */
box2 = gtk_hbox_new (FALSE, 10);
gtk_container_border_width (GTK_CONTAINER (box2), 10);
gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
gtk_widget_show (box2);
button = gtk_button_new_with_label ("Show Title Buttons");
gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
gtk_signal_connect (GTK_OBJECT (button),
"clicked",
(GtkSignalFunc) show_titles_clist,
(gpointer) clist);
gtk_widget_show (button);
button = gtk_button_new_with_label ("Hide Title Buttons");
gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
gtk_signal_connect (GTK_OBJECT (button),
"clicked",
(GtkSignalFunc) hide_titles_clist,
(gpointer) clist);
gtk_widget_show (button);
/* vbox for the list itself */
box2 = gtk_vbox_new (FALSE, 10); box2 = gtk_vbox_new (FALSE, 10);
gtk_container_border_width (GTK_CONTAINER (box2), 10); gtk_container_border_width (GTK_CONTAINER (box2), 10);
gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
gtk_widget_show (box2); gtk_widget_show (box2);
/* /*
* the rest of the clist configuration * the rest of the clist configuration
*/ */