📄 schedule-widget.c
字号:
/* TradeClient <http://tradeclient.sourceforge.net> * $Id: schedule-widget.c,v 1.16 2001/03/20 22:19:33 ttabner Exp $ * * Copyright (C) 1999-2000 Bynari Inc. * Copyright (C) 2001 Project TradeClient * * LGPL * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Library 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 Library * General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#ifndef _SCHEDULE_C_#define _SCHEDULE_C_#include <gdk/gdkkeysyms.h>#include <time.h>#include "schedule-widget.h"#define HANDLEBAR 0#define HANDLE_SIZE 8#define CHILD_HAS_FOCUS (1 << 0)#define CONFLICT 14typedef enum ScheduleSignals{ CHILD_CHANGED, CHILD_SELECTED, CHILD_DOUBLE_CLICKED, CHILD_RIGHT_CLICKED, ROW_SELECTED, ROW_UNSELECTED, LAST_SIGNAL}ScheduleSignals;static GtkContainerClass *parent_class;static int schedule_signals[LAST_SIGNAL] = { 0 };ScheduleDragInfo *info = NULL;int schedule_count = 0;static void schedule_class_init (ScheduleClass * schedule_class);static void schedule_init (Schedule * schedule);static void schedule_realize (GtkWidget * widget);static void schedule_size_allocate (GtkWidget * widget, GtkAllocation * allocation);static void schedule_send_configure (Schedule * schedule);static void schedule_draw (GtkWidget * widget, GdkRectangle * area);static gint schedule_event (GtkWidget * widget, GdkEvent * event);static gint schedule_button_press_event (GtkWidget * widget, GdkEventButton * event);static gint schedule_button_release_event (GtkWidget * widget, GdkEventButton * event);static gint schedule_key_press_event (GtkWidget * widget, GdkEventKey * event);static void schedule_size_request (GtkWidget * widget, GtkRequisition * requisition);static void schedule_destroy (GtkObject * object);static void schedule_paint (GtkWidget * widget);static void schedule_paint_row (GtkWidget * widget, int row);static void schedule_child_show (Schedule * schedule, ScheduleChild * child);static void schedule_child_realize (Schedule * schedule, ScheduleChild * child);static void schedule_child_map (Schedule * schedule, ScheduleChild * child);static void schedule_child_paint (ScheduleChild * child);static void schedule_child_handle_text (Schedule * schedule, ScheduleChild * child);static void schedule_child_key_press (GtkWidget * widget, GdkEventKey * event, gpointer data);static void schedule_child_focus_in (GtkWidget * widget, GdkEventFocus * event, gpointer data);static void schedule_child_focus_out (GtkWidget * widget, GdkEventFocus * event, gpointer data);static void child_changed (Schedule * schedule, char *text, gpointer data, time_t start, time_t stop);static void child_selected (Schedule * schedule, char *text, gpointer data, time_t start, time_t stop);static void row_selected (Schedule * schedule, int row, time_t index);static void child_double_clicked (Schedule * schedule, char *text, gpointer data, time_t start, time_t stop);static void child_right_clicked (Schedule * schedule, char *text, gpointer data, time_t start, time_t stop);static gint schedule_motion_notify_event (GtkWidget * widget, GdkEventMotion * event);static void schedule_child_find_best (ScheduleChild * child);static void schedule_child_unmap (Schedule * schedule, ScheduleChild * child);static void schedule_child_unrealize (Schedule * schedule, ScheduleChild * child);static void schedule_remove_child (GtkContainer * container, GtkWidget * widget);static void schedule_forall (GtkContainer * container, gboolean include_internals, GtkCallback callback, gpointer callback_data);static void schedule_show_conflict (Schedule * schedule, time_t time);static int schedule_time_to_row (int first, Schedule * schedule, time_t start, time_t stop);guintschedule_get_type (void){ static guint schedule_type = 0; if (!schedule_type) { static const GtkTypeInfo schedule_info = { "Schedule", sizeof (Schedule), sizeof (ScheduleClass), (GtkClassInitFunc) schedule_class_init, (GtkObjectInitFunc) schedule_init, NULL, NULL, (GtkClassInitFunc) NULL }; schedule_type = gtk_type_unique (gtk_container_get_type (), &schedule_info); } return (schedule_type);}GtkWidget *schedule_new (void){ GtkWidget *widget = GTK_WIDGET (gtk_type_new (schedule_get_type ())); return (widget);}static voidschedule_class_init (ScheduleClass * schedule_class){ GtkWidgetClass *widget_class; GtkObjectClass *object_class; GtkContainerClass *container_class; parent_class = gtk_type_class (gtk_container_get_type ()); widget_class = (GtkWidgetClass *) schedule_class; object_class = (GtkObjectClass *) schedule_class; container_class = (GtkContainerClass *) schedule_class; schedule_signals[CHILD_CHANGED] = gtk_signal_new ("child_changed", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (ScheduleClass, child_changed), gtk_marshal_NONE__POINTER_POINTER_UINT_UINT, GTK_TYPE_NONE, 3, GTK_TYPE_POINTER, GTK_TYPE_POINTER, GTK_TYPE_UINT, GTK_TYPE_UINT); schedule_signals[CHILD_SELECTED] = gtk_signal_new ("child_selected", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (ScheduleClass, child_selected), gtk_marshal_NONE__POINTER_POINTER_UINT_UINT, GTK_TYPE_NONE, 3, GTK_TYPE_POINTER, GTK_TYPE_POINTER, GTK_TYPE_ULONG, GTK_TYPE_ULONG); schedule_signals[CHILD_DOUBLE_CLICKED] = gtk_signal_new ("child_double_clicked", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (ScheduleClass, child_double_clicked), gtk_marshal_NONE__POINTER_POINTER_UINT_UINT, GTK_TYPE_NONE, 3, GTK_TYPE_POINTER, GTK_TYPE_POINTER, GTK_TYPE_ULONG, GTK_TYPE_ULONG); schedule_signals[CHILD_RIGHT_CLICKED] = gtk_signal_new ("child_right_clicked", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (ScheduleClass, child_right_clicked), gtk_marshal_NONE__POINTER_POINTER_UINT_UINT, GTK_TYPE_NONE, 3, GTK_TYPE_POINTER, GTK_TYPE_POINTER, GTK_TYPE_ULONG, GTK_TYPE_ULONG); schedule_signals[ROW_SELECTED] = gtk_signal_new ("row_selected", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (ScheduleClass, row_selected), gtk_signal_default_marshaller, GTK_TYPE_NONE, 2, GTK_TYPE_UINT, GTK_TYPE_ULONG); schedule_signals[ROW_UNSELECTED] = gtk_signal_new ("row_unselected", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (ScheduleClass, row_unselected), gtk_signal_default_marshaller, GTK_TYPE_NONE, 2, GTK_TYPE_UINT, GTK_TYPE_ULONG); gtk_object_class_add_signals (object_class, schedule_signals, LAST_SIGNAL); widget_class = (GtkWidgetClass *) schedule_class; object_class = (GtkObjectClass *) schedule_class; widget_class->realize = schedule_realize; widget_class->draw = schedule_draw; widget_class->event = schedule_event; widget_class->button_press_event = schedule_button_press_event; widget_class->button_release_event = schedule_button_release_event; widget_class->key_press_event = schedule_key_press_event; widget_class->size_request = schedule_size_request; widget_class->size_allocate = schedule_size_allocate; widget_class->motion_notify_event = schedule_motion_notify_event; object_class->destroy = schedule_destroy; container_class->forall = schedule_forall; container_class->remove = schedule_remove_child; schedule_class->child_changed = child_changed; schedule_class->child_selected = child_selected; schedule_class->child_double_clicked = child_double_clicked; schedule_class->child_right_clicked = child_right_clicked; schedule_class->row_selected = row_selected;}static voidschedule_init (Schedule * schedule){ GTK_WIDGET_UNSET_FLAGS (schedule, GTK_NO_WINDOW); GTK_WIDGET_SET_FLAGS (schedule, GTK_CAN_FOCUS); schedule->depth_count = 0; schedule->child_count = 0; schedule->time_style = SCHEDULE_AMPM; schedule->granularity = SCHEDULE_30M; schedule->selected_row_start = -1; schedule->selected_row_stop = -1; schedule->row_height = 20; schedule->day_start_row = 15; schedule->day_end_row = 40; schedule->dark = NULL; schedule->light = NULL;}voidschedule_remove_child (GtkContainer * container, GtkWidget * widget){}static voidschedule_forall (GtkContainer * container, gboolean include_internals, GtkCallback callback, gpointer callback_data){}static voidschedule_realize (GtkWidget * widget){ Schedule *schedule; GdkWindowAttr attributes; guint attributes_mask; g_return_if_fail (widget != NULL); g_return_if_fail (SCHEDULE_IS_SCHEDULE (widget)); schedule = SCHEDULE (widget); GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); attributes.window_type = GDK_WINDOW_CHILD; attributes.x = widget->allocation.x; attributes.y = widget->allocation.y; attributes.width = widget->allocation.width; attributes.height = widget->allocation.height; attributes.wclass = GDK_INPUT_OUTPUT; attributes.visual = gtk_widget_get_visual (widget); attributes.colormap = gtk_widget_get_colormap (widget); attributes.event_mask = (GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); gdk_window_set_user_data (widget->window, widget); widget->style = gtk_style_attach (widget->style, widget->window); gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); SCHEDULE (widget)->up_down_cursor = gdk_cursor_new (GDK_DOUBLE_ARROW); schedule_send_configure (SCHEDULE (widget));}static voidschedule_destroy (GtkObject * object){ ScheduleClass *schedule_class; g_return_if_fail (object != NULL); g_return_if_fail (SCHEDULE_IS_SCHEDULE (object)); schedule_destroy_children (SCHEDULE (GTK_WIDGET (object))); schedule_class = gtk_type_class (gtk_widget_get_type ()); if (GTK_OBJECT_CLASS (schedule_class)->destroy) (*GTK_OBJECT_CLASS (schedule_class)->destroy) (object);}voidschedule_destroy_children (Schedule * schedule){ GList *seek; ScheduleChild *child; g_return_if_fail (schedule != NULL); seek = schedule->children; while (seek) { child = seek->data; schedule_child_unmap (schedule, child); schedule_child_unrealize (schedule, child); gtk_widget_destroy (child->widget); g_free (seek->data); seek = seek->next; } g_list_free (schedule->children); schedule->children = NULL;}static voidschedule_child_unmap (Schedule * schedule, ScheduleChild * child){ if (g_list_find (schedule->children, child)) { gdk_window_hide (child->window); if (GTK_WIDGET_MAPPED (child->widget)) gtk_widget_hide (child->widget); }}static voidschedule_child_unrealize (Schedule * schedule, ScheduleChild * child){ if (GTK_WIDGET_REALIZED (child->widget)) gtk_widget_unrealize (child->widget); gdk_window_set_user_data (child->window, NULL); gdk_window_destroy (child->window); child->window = NULL;}static voidschedule_draw (GtkWidget * widget, GdkRectangle * area){ g_return_if_fail (widget != NULL); g_return_if_fail (SCHEDULE_IS_SCHEDULE (widget)); schedule_paint (widget);}static gintschedule_event (GtkWidget * widget, GdkEvent * event){ Schedule *schedule; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (SCHEDULE_IS_SCHEDULE (widget), FALSE); schedule = SCHEDULE (widget); switch (event->type) { case GDK_EXPOSE: break; default: return FALSE; }#if 1 gtk_widget_queue_draw (widget);#else schedule_paint (widget);#endif return TRUE;}static gintschedule_button_press_event (GtkWidget * widget, GdkEventButton * event){ Schedule *schedule = SCHEDULE (widget); int row = (int) event->y / schedule->row_height; ScheduleChild *child = NULL; GList *seek; int gran; char *text = NULL; switch (schedule->granularity) { case SCHEDULE_15M: gran = 2.0; break; case SCHEDULE_30M: gran = 1.0; break; case SCHEDULE_60M: gran = 0.5; break; } if (SCHEDULE (widget)->selected_row_start == row) { SCHEDULE (widget)->selected_row_start = -1; } else { SCHEDULE (widget)->selected_row_start = row; } SCHEDULE (widget)->selected_row_stop = -1; if (event->window == widget->window) { gtk_widget_grab_focus (widget); } else { SCHEDULE (widget)->selected_row_start = -1; seek = schedule->children; for (seek = schedule->children; seek; seek = seek->next) { child = (ScheduleChild *) seek->data; if (child->window == event->window) { break; } if (event->window == child->widget->window) { break; } } if (!seek) { return TRUE; } if (info == NULL) { info = (ScheduleDragInfo *) g_malloc0 (sizeof (ScheduleDragInfo)); } info->child = child; info->start_x = event->x; info->start_y = event->y; if (event->y < HANDLE_SIZE) { info->type = DRAG_SIZEUP; } if (event->y > child->height - HANDLE_SIZE) { info->type = DRAG_SIZEDOWN; } if (event->x < HANDLE_SIZE) { info->type = DRAG_MOVE; } gdk_pointer_grab (widget->window, FALSE, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK, NULL, NULL, GDK_CURRENT_TIME); if (child) text = gtk_editable_get_chars (GTK_EDITABLE (child->widget), 0, -1); if (event->button == 1 && event->type == 4 && child) { if (!GTK_WIDGET_HAS_FOCUS (child->widget)) { gtk_widget_grab_focus (child->widget); } } if (event->button == 1 && event->type == 5 && child) { gtk_signal_emit (GTK_OBJECT (GTK_WIDGET (child->schedule)), schedule_signals[CHILD_DOUBLE_CLICKED], text, child->data, child->start, child->stop); } if (event->button == 3 && event->type == 4 && child) { gtk_signal_emit (GTK_OBJECT (GTK_WIDGET (child->schedule)), schedule_signals[CHILD_RIGHT_CLICKED], text, child->data, child->start, child->stop); } } schedule_paint (widget); return TRUE;}static gintschedule_button_release_event (GtkWidget * widget, GdkEventButton * event){ Schedule *schedule = SCHEDULE (widget); int row = (int) event->y / schedule->row_height; if (widget->window == event->window) { SCHEDULE (widget)->selected_row_stop = row; } else { SCHEDULE (widget)->selected_row_stop = -1; } gdk_pointer_ungrab (GDK_CURRENT_TIME);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -