/* * Copyright (C) 2004-2005 Vadim Berezniker * http://www.kryptolus.com * * 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, 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 GNU Make; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "stdafx.h" #include "common.h" #include "sabbu.h" #include "gui_time_entry.h" gboolean gui_time_entry_key_up_cb(GtkTextView *view, GdkEventKey *event, gpointer data) { if(event->keyval == GDK_Return) { GuiTimeEntryEnterCallback cb = (GuiTimeEntryEnterCallback) g_object_get_data(G_OBJECT(view), "enter_cb"); cb(); return FALSE; } if(event->keyval >= GDK_0 && event->keyval <= GDK_9) { GtkTextIter iter_insert; GtkTextBuffer *buffer = gtk_text_view_get_buffer(view); GtkTextMark *mark_insert = gtk_text_buffer_get_mark(buffer, "insert"); gtk_text_buffer_get_iter_at_mark(buffer, &iter_insert, mark_insert); int pos = gtk_text_iter_get_offset(&iter_insert); int len = (long) g_object_get_data(G_OBJECT(view), "num_digits"); int offset = 0; if(len == 12) offset = -1; if(pos + offset == 1 || pos + offset == 4 || pos + offset == 7) { gtk_text_iter_forward_char(&iter_insert); gtk_text_buffer_place_cursor(buffer, &iter_insert); } } return FALSE; } gboolean gui_time_entry_button_down_cb(GtkTextView *view, GdkEventButton *event, gpointer data) { if(event->button != 1) return TRUE; return FALSE; } void gui_time_entry_invoke_callback(GtkTextView *view, char *text) { GCallback callback = G_CALLBACK(g_object_get_data(G_OBJECT(view), "time_changed_cb")); gpointer callback_param = g_object_get_data(G_OBJECT(view), "time_changed_cb_param"); if(!callback) return; ((GuiTimeEntryCallback) callback) (text, callback_param); } gboolean gui_time_entry_key_down_cb(GtkTextView *view, GdkEventKey *event, gpointer data) { if(event->keyval == GDK_Tab || event->keyval == GDK_ISO_Left_Tab) return FALSE; if(event->state & GDK_CONTROL_MASK && (event->keyval == GDK_v || event->keyval == GDK_V)) return TRUE; if(event->state & GDK_CONTROL_MASK || event->keyval == GDK_Left || event->keyval == GDK_Right || event->keyval == GDK_Home || event->keyval == GDK_End) { return FALSE; } int offset = 0; long len = (long) g_object_get_data(G_OBJECT(view), "num_digits"); if(len == 12) offset = -1; gboolean text_changed = FALSE; GtkTextBuffer *buffer = gtk_text_view_get_buffer(view); GtkTextIter iter_insert, iter_selection; GtkTextMark *mark_insert, *mark_selection; int pos = 0; if(event->keyval == GDK_BackSpace || event->keyval >= GDK_0 && event->keyval <= GDK_9) { mark_insert = gtk_text_buffer_get_mark(buffer, "insert"); mark_selection = gtk_text_buffer_get_mark(buffer, "selection_bound"); gtk_text_buffer_get_iter_at_mark(buffer, &iter_insert, mark_insert); gtk_text_buffer_get_iter_at_mark(buffer, &iter_selection, mark_selection); if(gtk_text_iter_compare(&iter_insert, &iter_selection) < 0) gtk_text_buffer_place_cursor(buffer, &iter_insert); else gtk_text_buffer_place_cursor(buffer, &iter_selection); gtk_text_buffer_get_iter_at_mark(buffer, &iter_insert, mark_insert); pos = gtk_text_iter_get_offset(&iter_insert); } if(event->keyval == GDK_BackSpace) { if(pos == 0) return TRUE; if(pos + offset == 2 || pos + offset == 5 || pos + offset == 8) { gtk_text_iter_backward_char(&iter_insert); gtk_text_buffer_place_cursor(buffer, &iter_insert); } GtkTextIter *iter_end = gtk_text_iter_copy(&iter_insert); gtk_text_iter_backward_char(&iter_insert); gtk_text_buffer_delete(buffer, &iter_insert, iter_end); gtk_text_buffer_insert(buffer, &iter_insert, "0", -1); gtk_text_iter_free(iter_end); gtk_text_iter_backward_char(&iter_insert); gtk_text_buffer_place_cursor(buffer, &iter_insert); text_changed = TRUE; } if(event->keyval >= GDK_0 && event->keyval <= GDK_9) { if(len == 12 && pos == 12 || len != 12 && pos == 10) return TRUE; if(pos + offset == 1 || pos + offset == 4 || pos + offset == 7) { gtk_text_iter_forward_char(&iter_insert); gtk_text_buffer_place_cursor(buffer, &iter_insert); } GtkTextIter *iter_end = gtk_text_iter_copy(&iter_insert); gtk_text_iter_forward_char(iter_end); gtk_text_buffer_delete(buffer, &iter_insert, iter_end); char str[2] = { event->keyval, 0}; gtk_text_buffer_insert(buffer, &iter_insert, str, -1); gtk_text_iter_free(iter_end); text_changed = TRUE; } if(text_changed) { GtkTextIter iter_start, iter_end; gtk_text_buffer_get_start_iter(buffer, &iter_start); gtk_text_buffer_get_end_iter(buffer, &iter_end); char *text = gtk_text_buffer_get_text(buffer, &iter_start, &iter_end, FALSE); gui_time_entry_invoke_callback(view, text); g_free(text); } GtkTextIter iter_start, iter_end; gtk_text_buffer_get_start_iter(buffer, &iter_start); gtk_text_buffer_get_end_iter(buffer, &iter_end); char *text = gtk_text_buffer_get_text(buffer, &iter_start, &iter_end, FALSE); g_free(text); return TRUE; } char *gui_time_entry_get_text(GtkWidget *widget) { GtkTextView *view = GTK_TEXT_VIEW(g_object_get_data(G_OBJECT(widget), "text_view")); GtkTextBuffer *buffer = gtk_text_view_get_buffer(view); GtkTextIter iter_start, iter_end; gtk_text_buffer_get_start_iter(buffer, &iter_start); gtk_text_buffer_get_end_iter(buffer, &iter_end); return gtk_text_buffer_get_text(buffer, &iter_start, &iter_end, FALSE); } void gui_time_entry_set_text(GtkWidget *widget, char *text) { GtkTextView *view = GTK_TEXT_VIEW(g_object_get_data(G_OBJECT(widget), "text_view")); GtkTextBuffer *buffer = gtk_text_view_get_buffer(view); GtkTextIter iter_start, iter_end; gtk_text_buffer_get_start_iter(buffer, &iter_start); gtk_text_buffer_get_end_iter(buffer, &iter_end); g_object_set_data(G_OBJECT(view), "num_digits", (gpointer) strlen(text)); char *text_old = gtk_text_buffer_get_text(buffer, &iter_start, &iter_end, FALSE); if(strcmp(text_old, text)) { gtk_text_buffer_set_text(buffer, text, -1); gui_time_entry_invoke_callback(view, text); } g_free(text_old); } GtkTextView *gui_time_entry_get_view(GtkWidget *widget) { return GTK_TEXT_VIEW(g_object_get_data(G_OBJECT(widget), "text_view")); } GtkWidget *gui_time_entry_new(GCallback callback_changed, GCallback callback_enter, gpointer param) { GtkTextIter end_iter; GtkFrame *frame = GTK_FRAME(gtk_frame_new(NULL)); GtkTextBuffer *buffer = GTK_TEXT_BUFFER(gtk_text_buffer_new(NULL)); GtkTextView *view = GTK_TEXT_VIEW(gtk_text_view_new_with_buffer(buffer)); GtkTextTag *lock_tag = gtk_text_buffer_create_tag(buffer, "lock", "editable", FALSE, NULL); PangoFontDescription *font_desc = pango_font_description_from_string ("Courier"); gtk_widget_modify_font(GTK_WIDGET(view), font_desc); pango_font_description_free (font_desc); gtk_text_buffer_get_end_iter(buffer, &end_iter); gtk_text_buffer_insert_with_tags(buffer, &end_iter, "0", -1, NULL, NULL); gtk_text_buffer_insert_with_tags(buffer, &end_iter, ":", -1, lock_tag, NULL); gtk_text_buffer_insert_with_tags(buffer, &end_iter, "00", -1, NULL, NULL); gtk_text_buffer_insert_with_tags(buffer, &end_iter, ":", -1, lock_tag, NULL); gtk_text_buffer_insert_with_tags(buffer, &end_iter, "00", -1, NULL, NULL); gtk_text_buffer_insert_with_tags(buffer, &end_iter, ".", -1, lock_tag, NULL); gtk_text_buffer_insert_with_tags(buffer, &end_iter, "00", -1, NULL, NULL); gtk_text_view_set_overwrite(view, TRUE); gtk_text_view_set_left_margin(view, 2); gtk_text_view_set_right_margin(view, 2); gtk_frame_set_shadow_type(frame, GTK_SHADOW_IN); gtk_container_add(GTK_CONTAINER(frame), GTK_WIDGET(view)); g_signal_connect(G_OBJECT(view), "key-press-event", G_CALLBACK(gui_main_time_box_key_press_cb), NULL); g_signal_connect(G_OBJECT(view), "key-press-event", G_CALLBACK(gui_time_entry_key_down_cb), NULL); g_signal_connect(G_OBJECT(view), "key-release-event", G_CALLBACK(gui_time_entry_key_up_cb), NULL); g_signal_connect(G_OBJECT(view), "button-press-event", G_CALLBACK(gui_time_entry_button_down_cb), NULL); g_object_set_data(G_OBJECT(frame), "text_view", view); g_object_set_data(G_OBJECT(view), "time_changed_cb", (void *) callback_changed); g_object_set_data(G_OBJECT(view), "enter_cb", (void *) callback_enter); g_object_set_data(G_OBJECT(view), "time_changed_cb_param", param); return GTK_WIDGET(frame); }