r15691 - gnucash/branches/register-rewrite - Copy some GtkCalendar-in-a-GtkCellRenderer code from Planner.
Chris Shoemaker
chris at cvs.gnucash.org
Thu Mar 8 16:40:09 EST 2007
Author: chris
Date: 2007-03-08 16:40:06 -0500 (Thu, 08 Mar 2007)
New Revision: 15691
Trac: http://svn.gnucash.org/trac/changeset/15691
Added:
gnucash/branches/register-rewrite/src/gnome-utils/planner-cell-renderer-date.c
gnucash/branches/register-rewrite/src/gnome-utils/planner-cell-renderer-date.h
gnucash/branches/register-rewrite/src/gnome-utils/planner-cell-renderer-popup.c
gnucash/branches/register-rewrite/src/gnome-utils/planner-cell-renderer-popup.h
gnucash/branches/register-rewrite/src/gnome-utils/planner-marshal.list
gnucash/branches/register-rewrite/src/gnome-utils/planner-popup-entry.c
gnucash/branches/register-rewrite/src/gnome-utils/planner-popup-entry.h
Modified:
gnucash/branches/register-rewrite/configure.in
gnucash/branches/register-rewrite/src/gnome-utils/Makefile.am
Log:
Copy some GtkCalendar-in-a-GtkCellRenderer code from Planner.
Wholesale copy of some code from Planner that implements a GtkCalendar
in a custom GtkCellEditable popup from a GtkCellRenderer.
These files are unchanged except for one place that's commented.
Also, introduce a dependency on libplanner. This could be brought in-tree,
if needed.
Modified: gnucash/branches/register-rewrite/configure.in
===================================================================
--- gnucash/branches/register-rewrite/configure.in 2007-03-08 13:23:14 UTC (rev 15690)
+++ gnucash/branches/register-rewrite/configure.in 2007-03-08 21:40:06 UTC (rev 15691)
@@ -1822,6 +1822,9 @@
fi
### End of gui-only checks
+### CAS: I don't know what the real min is. This is just what I have.
+PKG_CHECK_MODULES(LIBPLANNER, libplanner-1 >= 0.14)
+
###-------------------------------------------------------------------------
### Selectively disable deprecated bits of glib/gdk/gtk/gnome
###-------------------------------------------------------------------------
Modified: gnucash/branches/register-rewrite/src/gnome-utils/Makefile.am
===================================================================
--- gnucash/branches/register-rewrite/src/gnome-utils/Makefile.am 2007-03-08 13:23:14 UTC (rev 15690)
+++ gnucash/branches/register-rewrite/src/gnome-utils/Makefile.am 2007-03-08 21:40:06 UTC (rev 15691)
@@ -22,9 +22,14 @@
${GUILE_INCS} \
${QOF_CFLAGS} \
${GOFFICE_CFLAGS} \
+ ${LIBPLANNER_CFLAGS} \
${GSF_CFLAGS}
libgncmod_gnome_utils_la_SOURCES = \
+ planner-marshal.c \
+ planner-popup-entry.c \
+ planner-cell-renderer-popup.c \
+ planner-cell-renderer-date.c \
QuickFill.c \
account-quickfill.c \
cursors.c \
@@ -101,6 +106,10 @@
gncincludedir = ${GNC_INCLUDE_DIR}
gncinclude_HEADERS = \
+ planner-marshal.h \
+ planner-popup-entry.h \
+ planner-cell-renderer-popup.h \
+ planner-cell-renderer-date.h \
QuickFill.h \
account-quickfill.h \
dialog-account.h \
@@ -198,6 +207,7 @@
${QOF_LIBS} \
${GOFFICE_LIBS} \
${REGEX_LIBS} \
+ ${LIBPLANNER_LIBS} \
${LIBXML2_LIBS}
if BUILDING_FROM_SVN
@@ -305,3 +315,14 @@
endif
INCLUDES = -DG_LOG_DOMAIN=\"gnc.gui\"
+
+planner-marshal.h: Makefile.am planner-marshal.list
+ $(GLIB_GENMARSHAL) --prefix=planner_marshal $(srcdir)/planner-marshal.list --header > xgen-gmh \
+ && (cmp -s xgen-gmh planner-marshal.h || cp xgen-gmh planner-marshal.h) \
+ && rm -f xgen-gmh xgen-gmh~
+
+planner-marshal.c: Makefile.am planner-marshal.list
+ (echo "#include \"planner-marshal.h\""; $(GLIB_GENMARSHAL) --prefix=planner_marshal $(srcdir)/planner-marshal.list --body) > xgen-gmc \
+ && cp xgen-gmc planner-marshal.c \
+ && rm -f xgen-gmc xgen-gmc~
+
Added: gnucash/branches/register-rewrite/src/gnome-utils/planner-cell-renderer-date.c
===================================================================
--- gnucash/branches/register-rewrite/src/gnome-utils/planner-cell-renderer-date.c 2007-03-08 13:23:14 UTC (rev 15690)
+++ gnucash/branches/register-rewrite/src/gnome-utils/planner-cell-renderer-date.c 2007-03-08 21:40:06 UTC (rev 15691)
@@ -0,0 +1,587 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2005 Imendio AB
+ * Copyright (C) 2001-2002 CodeFactory AB
+ * Copyright (C) 2001-2002 Richard Hult <richard at imendio.com>
+ * Copyright (C) 2001-2002 Mikael Hallendal <micke at imendio.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 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtkmain.h>
+#include <gtk/gtkcellrenderertext.h>
+#include <gtk/gtkeditable.h>
+#include <gtk/gtkhseparator.h>
+#include <gtk/gtkbutton.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkoptionmenu.h>
+#include <gtk/gtkmenuitem.h>
+#include <gtk/gtkarrow.h>
+#include <gtk/gtkwindow.h>
+#include <gtk/gtkframe.h>
+#include <gtk/gtkvbox.h>
+#include <gtk/gtkhbox.h>
+#include <gtk/gtkhbbox.h>
+#include <gtk/gtkstock.h>
+#include <gtk/gtkcalendar.h>
+#include <glib/gi18n.h>
+#include "planner-marshal.h"
+#include "planner-cell-renderer-date.h"
+#include "planner-popup-entry.h"
+/* CAS:
+ This one function came from planner-format.c and was the only reason
+planner-format.h was included. I've pasted it here with one modification -
+adding the year to the string.
+
+#include "planner-format.h"
+
+*/
+gchar * planner_format_date (mrptime date);
+gchar *
+planner_format_date (mrptime date)
+{
+ gchar *svalue;
+
+ if (date == MRP_TIME_INVALID) {
+ svalue = g_strdup ("");
+ } else {
+ /* i18n: this string is the date nr and month name, displayed
+ * e.g. in the date cells in the task tree. See
+ * libmrproject/docs/DateFormat.
+ */
+ svalue = mrp_time_format (_("%b %e %Y"), date);//CAS: added year
+ }
+
+ return svalue;
+}
+
+enum {
+ PROP_0,
+ PROP_USE_CONSTRAINT,
+};
+
+static void mcrd_init (PlannerCellRendererDate *date);
+static void mcrd_class_init (PlannerCellRendererDateClass *class);
+static void mcrd_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void mcrd_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void mcrd_today_clicked (GtkWidget *button,
+ PlannerCellRendererDate *cell);
+static void mcrd_selected_double_click (GtkWidget *calendar,
+ PlannerCellRendererDate *cell);
+static void mcrd_cancel_clicked (GtkWidget *popup_window,
+ PlannerCellRendererDate *cell);
+static void mcrd_ok_clicked (GtkWidget *popup_window,
+ PlannerCellRendererDate *cell);
+static void mcrd_day_selected (GtkWidget *popup_window,
+ PlannerCellRendererDate *cell);
+static void mcrd_constraint_activated_cb (GtkWidget *widget,
+ PlannerCellRendererDate *cell);
+GtkCellEditable *mcrd_start_editing (GtkCellRenderer *cell,
+ GdkEvent *event,
+ GtkWidget *widget,
+ const gchar *path,
+ GdkRectangle *background_area,
+ GdkRectangle *cell_area,
+ GtkCellRendererState flags);
+static void mcrd_show (PlannerCellRendererPopup *cell,
+ const gchar *path,
+ gint x1,
+ gint y1,
+ gint x2,
+ gint y2);
+static void mcrd_hide (PlannerCellRendererPopup *cell);
+static void mcrd_setup_option_menu (GtkWidget *option_menu,
+ GtkSignalFunc func,
+ gpointer user_data,
+ gpointer str1, ...);
+
+
+static PlannerCellRendererPopupClass *parent_class;
+
+GType
+planner_cell_renderer_date_get_type (void)
+{
+ static GType cell_text_type = 0;
+
+ if (!cell_text_type) {
+ static const GTypeInfo cell_text_info = {
+ sizeof (PlannerCellRendererDateClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) mcrd_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PlannerCellRendererDate),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) mcrd_init,
+ };
+
+ cell_text_type = g_type_register_static (PLANNER_TYPE_CELL_RENDERER_POPUP,
+ "PlannerCellRendererDate",
+ &cell_text_info,
+ 0);
+ }
+
+ return cell_text_type;
+}
+
+static void
+mcrd_init (PlannerCellRendererDate *date)
+{
+ PlannerCellRendererPopup *popup;
+ GtkWidget *frame;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *bbox;
+ GtkWidget *button;
+
+ popup = PLANNER_CELL_RENDERER_POPUP (date);
+
+ frame = gtk_frame_new (NULL);
+ gtk_container_add (GTK_CONTAINER (popup->popup_window), frame);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
+
+ vbox = gtk_vbox_new (FALSE, 6);
+ gtk_container_add (GTK_CONTAINER (frame), vbox);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
+
+ date->calendar = gtk_calendar_new ();
+ popup->focus_window = date->calendar;
+ gtk_box_pack_start (GTK_BOX (vbox), date->calendar, TRUE, TRUE, 0);
+
+ date->constraint_vbox = gtk_vbox_new (FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), date->constraint_vbox, FALSE, FALSE, 0);
+
+ hbox = gtk_hbox_new (FALSE, 6);
+ /* I18n: the verb "schedule" here. */
+ gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("Schedule:")),
+ FALSE, FALSE, 0);
+
+ date->option_menu = gtk_option_menu_new ();
+ mcrd_setup_option_menu (date->option_menu,
+ G_CALLBACK (mcrd_constraint_activated_cb),
+ date,
+ _("As soon as possible"), MRP_CONSTRAINT_ASAP,
+ _("No earlier than"), MRP_CONSTRAINT_SNET,
+ _("On fixed date"), MRP_CONSTRAINT_MSO,
+ NULL);
+ gtk_box_pack_end (GTK_BOX (hbox), date->option_menu, TRUE, TRUE, 0);
+
+ gtk_box_pack_start (GTK_BOX (date->constraint_vbox), hbox, TRUE, TRUE, 0);
+
+ hbox = gtk_hbox_new (FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (date->constraint_vbox), hbox, FALSE, FALSE, 0);
+
+ bbox = gtk_hbutton_box_new ();
+ gtk_box_set_spacing (GTK_BOX (bbox), 6);
+ gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, FALSE, 0);
+
+ date->today_button = gtk_button_new_with_label (_("Today"));
+ gtk_container_add (GTK_CONTAINER (bbox), date->today_button);
+ g_signal_connect (date->today_button, "clicked",
+ G_CALLBACK (mcrd_today_clicked),
+ date);
+
+ button = gtk_button_new_with_label (_("Cancel"));
+ gtk_container_add (GTK_CONTAINER (bbox), button);
+ g_signal_connect (button,
+ "clicked",
+ G_CALLBACK (mcrd_cancel_clicked),
+ date);
+
+ button = gtk_button_new_with_label (_("Select"));
+ gtk_container_add (GTK_CONTAINER (bbox), button);
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (mcrd_ok_clicked),
+ date);
+
+ g_signal_connect (date->calendar, "day-selected",
+ G_CALLBACK (mcrd_day_selected),
+ date);
+ g_signal_connect (date->calendar, "day-selected-double-click",
+ G_CALLBACK (mcrd_selected_double_click),
+ date);
+
+ gtk_widget_show_all (frame);
+}
+
+static void
+mcrd_class_init (PlannerCellRendererDateClass *class)
+{
+ PlannerCellRendererPopupClass *popup_class;
+ GtkCellRendererClass *cell_class;
+ GObjectClass *gobject_class;
+
+ popup_class = PLANNER_CELL_RENDERER_POPUP_CLASS (class);
+ cell_class = GTK_CELL_RENDERER_CLASS (class);
+ parent_class = PLANNER_CELL_RENDERER_POPUP_CLASS (g_type_class_peek_parent (class));
+ gobject_class = G_OBJECT_CLASS (class);
+
+ gobject_class->set_property = mcrd_set_property;
+ gobject_class->get_property = mcrd_get_property;
+
+ cell_class->start_editing = mcrd_start_editing;
+
+ popup_class->show_popup = mcrd_show;
+ popup_class->hide_popup = mcrd_hide;
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_USE_CONSTRAINT,
+ g_param_spec_boolean ("use-constraint",
+ NULL,
+ NULL,
+ TRUE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+mcrd_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ PlannerCellRendererDate *date;
+
+ date = PLANNER_CELL_RENDERER_DATE (object);
+
+ switch (param_id) {
+ case PROP_USE_CONSTRAINT:
+ date->use_constraint = g_value_get_boolean (value);
+
+ if (date->use_constraint) {
+ gtk_widget_show (date->constraint_vbox);
+ } else {
+ gtk_widget_hide (date->constraint_vbox);
+ }
+
+ gtk_widget_set_sensitive (date->calendar, date->use_constraint);
+ gtk_widget_set_sensitive (date->today_button, date->use_constraint);
+
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+mcrd_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ PlannerCellRendererDate *date;
+
+ date = PLANNER_CELL_RENDERER_DATE (object);
+
+ switch (param_id) {
+ case PROP_USE_CONSTRAINT:
+ g_value_set_boolean (value, date->use_constraint);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+GtkCellEditable *
+mcrd_start_editing (GtkCellRenderer *cell,
+ GdkEvent *event,
+ GtkWidget *widget,
+ const gchar *path,
+ GdkRectangle *background_area,
+ GdkRectangle *cell_area,
+ GtkCellRendererState flags)
+{
+ PLANNER_CELL_RENDERER_POPUP (cell)->editing_canceled = TRUE;
+
+ if (GTK_CELL_RENDERER_CLASS (parent_class)->start_editing) {
+ return GTK_CELL_RENDERER_CLASS (parent_class)->start_editing (
+ cell,
+ event,
+ widget,
+ path,
+ background_area,
+ cell_area,
+ flags);
+ }
+
+ return NULL;
+}
+
+
+static void
+mcrd_hide (PlannerCellRendererPopup *cell)
+{
+ if (parent_class->hide_popup) {
+ parent_class->hide_popup (cell);
+ }
+}
+
+static void
+mcrd_show (PlannerCellRendererPopup *cell,
+ const gchar *path,
+ gint x1,
+ gint y1,
+ gint x2,
+ gint y2)
+{
+ PlannerCellRendererDate *date;
+ gint year;
+ gint month;
+ gint day;
+ gint index;
+ gboolean sensitive;
+
+ if (parent_class->show_popup) {
+ parent_class->show_popup (cell,
+ path,
+ x1, y1,
+ x2, y2);
+ }
+
+ date = PLANNER_CELL_RENDERER_DATE (cell);
+
+ mrp_time_decompose (date->time, &year, &month, &day, NULL, NULL, NULL);
+
+ index = 0;
+
+ switch (date->type) {
+ case MRP_CONSTRAINT_ASAP:
+ index = 0;
+ break;
+ case MRP_CONSTRAINT_SNET:
+ index = 1;
+ break;
+ case MRP_CONSTRAINT_MSO:
+ index = 2;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ sensitive = (!date->use_constraint ||
+ (date->type != MRP_CONSTRAINT_ASAP &&
+ date->type != MRP_CONSTRAINT_ALAP));
+
+ gtk_widget_set_sensitive (date->calendar, sensitive);
+ gtk_widget_set_sensitive (date->today_button, sensitive);
+
+ gtk_calendar_clear_marks (GTK_CALENDAR (date->calendar));
+ gtk_calendar_select_month (GTK_CALENDAR (date->calendar),
+ month - 1, year);
+ gtk_calendar_select_day (GTK_CALENDAR (date->calendar), day);
+ gtk_calendar_mark_day (GTK_CALENDAR (date->calendar), day);
+
+ gtk_option_menu_set_history (GTK_OPTION_MENU (date->option_menu),
+ index);
+}
+
+GtkCellRenderer *
+planner_cell_renderer_date_new (gboolean use_constraint)
+{
+ GObject *cell;
+
+ cell = g_object_new (PLANNER_TYPE_CELL_RENDERER_DATE,
+ "use-constraint", use_constraint,
+ NULL);
+
+ return GTK_CELL_RENDERER (cell);
+}
+
+static void
+mcrd_today_clicked (GtkWidget *button,
+ PlannerCellRendererDate *cell)
+{
+ mrptime today;
+ gint year, month, day;
+
+ today = mrp_time_current_time ();
+
+ mrp_time_decompose (today, &year, &month, &day,
+ NULL, NULL, NULL);
+
+ gtk_calendar_clear_marks (GTK_CALENDAR (cell->calendar));
+ gtk_calendar_select_month (GTK_CALENDAR (cell->calendar),
+ month - 1, year);
+ gtk_calendar_select_day (GTK_CALENDAR (cell->calendar), day);
+ gtk_calendar_mark_day (GTK_CALENDAR (cell->calendar), day);
+}
+
+static void
+mcrd_selected_double_click (GtkWidget *calendar,
+ PlannerCellRendererDate *cell)
+{
+ PlannerCellRendererPopup *popup;
+
+ popup = PLANNER_CELL_RENDERER_POPUP (cell);
+
+ mcrd_ok_clicked (popup->popup_window, cell);
+}
+
+static void
+mcrd_cancel_clicked (GtkWidget *popup_window,
+ PlannerCellRendererDate *cell)
+{
+ PlannerCellRendererPopup *popup;
+
+ popup = PLANNER_CELL_RENDERER_POPUP (cell);
+
+ popup->editing_canceled = TRUE;
+ planner_cell_renderer_popup_hide (popup);
+}
+
+static void
+mcrd_ok_clicked (GtkWidget *popup_window,
+ PlannerCellRendererDate *cell)
+{
+ PlannerCellRendererPopup *popup;
+
+ popup = PLANNER_CELL_RENDERER_POPUP (cell);
+
+ mcrd_day_selected (popup_window, cell);
+
+ popup->editing_canceled = FALSE;
+ planner_cell_renderer_popup_hide (popup);
+}
+
+static void
+mcrd_day_selected (GtkWidget *popup_window,
+ PlannerCellRendererDate *cell)
+{
+ guint year;
+ guint month;
+ guint day;
+ mrptime t;
+ gchar *str;
+
+ gtk_calendar_get_date (GTK_CALENDAR (cell->calendar),
+ &year,
+ &month,
+ &day);
+
+ t = mrp_time_compose (year, month + 1, day, 0, 0, 0);
+
+ cell->time = t;
+
+ str = planner_format_date (t);
+ planner_popup_entry_set_text (
+ PLANNER_POPUP_ENTRY (PLANNER_CELL_RENDERER_POPUP (cell)->editable), str);
+ g_free (str);
+}
+
+static gboolean
+mcrd_grab_on_window (GdkWindow *window,
+ guint32 activate_time)
+{
+ if ((gdk_pointer_grab (window, TRUE,
+ GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+ GDK_POINTER_MOTION_MASK,
+ NULL, NULL, activate_time) == 0)) {
+ if (gdk_keyboard_grab (window, TRUE,
+ activate_time) == 0)
+ return TRUE;
+ else {
+ gdk_pointer_ungrab (activate_time);
+ return FALSE;
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+mcrd_constraint_activated_cb (GtkWidget *widget,
+ PlannerCellRendererDate *cell)
+{
+ gpointer data;
+ gboolean sensitive;
+
+ data = g_object_get_data (G_OBJECT (widget), "data");
+
+ cell->type = GPOINTER_TO_INT (data);
+
+ sensitive = (!cell->use_constraint ||
+ (cell->type != MRP_CONSTRAINT_ASAP &&
+ cell->type != MRP_CONSTRAINT_ALAP));
+
+ gtk_widget_set_sensitive (cell->calendar, sensitive);
+ gtk_widget_set_sensitive (cell->today_button, sensitive);
+
+ /* A bit hackish. Grab focus on the popup window again when the
+ * optionmenu is activated, since focus is transferred to the optionmenu
+ * when it's popped up.
+ */
+ mcrd_grab_on_window (PLANNER_CELL_RENDERER_POPUP (cell)->popup_window->window,
+ gtk_get_current_event_time ());
+}
+
+/* Utility function to use before optionmenus work with libglade again.
+ */
+
+static void
+mcrd_setup_option_menu (GtkWidget *option_menu,
+ GtkSignalFunc func,
+ gpointer user_data,
+ gpointer str1, ...)
+{
+ GtkWidget *menu, *menu_item;
+ gint i;
+ va_list args;
+ gpointer str;
+ gint type;
+
+ menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (option_menu));
+ if (menu) {
+ gtk_widget_destroy (menu);
+ }
+
+ menu = gtk_menu_new ();
+
+ va_start (args, str1);
+ for (str = str1, i = 0; str != NULL; str = va_arg (args, gpointer), i++) {
+ menu_item = gtk_menu_item_new_with_label (str);
+ gtk_widget_show (menu_item);
+ gtk_menu_append (GTK_MENU (menu), menu_item);
+
+ type = va_arg (args, gint);
+
+ g_object_set_data (G_OBJECT (menu_item),
+ "data",
+ GINT_TO_POINTER (type));
+ gtk_signal_connect (GTK_OBJECT (menu_item),
+ "activate",
+ func,
+ user_data);
+ }
+ va_end (args);
+
+ gtk_widget_show (menu);
+ gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu), menu);
+}
+
Added: gnucash/branches/register-rewrite/src/gnome-utils/planner-cell-renderer-date.h
===================================================================
--- gnucash/branches/register-rewrite/src/gnome-utils/planner-cell-renderer-date.h 2007-03-08 13:23:14 UTC (rev 15690)
+++ gnucash/branches/register-rewrite/src/gnome-utils/planner-cell-renderer-date.h 2007-03-08 21:40:06 UTC (rev 15691)
@@ -0,0 +1,65 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2005 Imendio AB
+ * Copyright (C) 2001-2002 CodeFactory AB
+ * Copyright (C) 2001-2002 Richard Hult <richard at imendio.com>
+ * Copyright (C) 2001-2002 Mikael Hallendal <micke at imendio.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 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PLANNER_CELL_RENDERER_DATE_H__
+#define __PLANNER_CELL_RENDERER_DATE_H__
+
+#include <glib-object.h>
+#include <gtk/gtkwidget.h>
+#include <libplanner/mrp-time.h>
+#include <libplanner/mrp-types.h>
+#include "planner-cell-renderer-popup.h"
+
+#define PLANNER_TYPE_CELL_RENDERER_DATE (planner_cell_renderer_date_get_type ())
+#define PLANNER_CELL_RENDERER_DATE(obj) (GTK_CHECK_CAST ((obj), PLANNER_TYPE_CELL_RENDERER_DATE, PlannerCellRendererDate))
+#define PLANNER_CELL_RENDERER_DATE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), PLANNER_TYPE_CELL_RENDERER_DATE, PlannerCellRendererDateClass))
+#define PLANNER_IS_CELL_RENDERER_DATE(obj) (GTK_CHECK_TYPE ((obj), PLANNER_TYPE_CELL_RENDERER_DATE))
+#define PLANNER_IS_CELL_RENDERER_DATE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), PLANNER_TYPE_CELL_RENDERER_DATE))
+#define PLANNER_CELL_RENDERER_DATE_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), PLANNER_TYPE_CELL_RENDERER_DATE, PlannerCellRendererDateClass))
+
+typedef struct _PlannerCellRendererDate PlannerCellRendererDate;
+typedef struct _PlannerCellRendererDateClass PlannerCellRendererDateClass;
+
+struct _PlannerCellRendererDate
+{
+ PlannerCellRendererPopup parent;
+ GtkWidget *calendar;
+ GtkWidget *option_menu;
+ GtkWidget *today_button;
+
+ gboolean use_constraint;
+ GtkWidget *constraint_vbox;
+ mrptime time;
+ MrpConstraintType type;
+};
+
+struct _PlannerCellRendererDateClass
+{
+ PlannerCellRendererPopupClass parent_class;
+};
+
+GType planner_cell_renderer_date_get_type (void) G_GNUC_CONST;
+GtkCellRenderer *planner_cell_renderer_date_new (gboolean use_constraint);
+
+
+#endif /* __PLANNER_CELL_RENDERER_DATE_H__ */
Added: gnucash/branches/register-rewrite/src/gnome-utils/planner-cell-renderer-popup.c
===================================================================
--- gnucash/branches/register-rewrite/src/gnome-utils/planner-cell-renderer-popup.c 2007-03-08 13:23:14 UTC (rev 15690)
+++ gnucash/branches/register-rewrite/src/gnome-utils/planner-cell-renderer-popup.c 2007-03-08 21:40:06 UTC (rev 15691)
@@ -0,0 +1,517 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2001-2002 CodeFactory AB
+ * Copyright (C) 2001-2002 Richard Hult <richard at imendio.com>
+ * Copyright (C) 2001-2002 Mikael Hallendal <micke at imendio.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 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtkcellrenderertext.h>
+#include <gtk/gtkwindow.h>
+#include <gtk/gtkmain.h>
+#include <gtk/gtkeditable.h>
+#include <gtk/gtksignal.h>
+#include <gtk/gtkbutton.h>
+#include "planner-marshal.h"
+#include "planner-cell-renderer-popup.h"
+#include "planner-popup-entry.h"
+
+
+enum {
+ SHOW_POPUP,
+ HIDE_POPUP,
+ LAST_SIGNAL
+};
+
+static void mcrp_init (PlannerCellRendererPopup *popup);
+static void mcrp_class_init (PlannerCellRendererPopupClass *class);
+
+static GtkCellEditable *
+mcrp_start_editing (GtkCellRenderer *cell,
+ GdkEvent *event,
+ GtkWidget *widget,
+ const gchar *path,
+ GdkRectangle *background_area,
+ GdkRectangle *cell_area,
+ GtkCellRendererState flags);
+static void mcrp_show_popup (PlannerCellRendererPopup *cell,
+ const gchar *path,
+ gint x1,
+ gint y1,
+ gint x2,
+ gint y2);
+static void mcrp_hide_popup (PlannerCellRendererPopup *cell);
+static void mcrp_get_size (GtkCellRenderer *cell,
+ GtkWidget *widget,
+ GdkRectangle *cell_area,
+ gint *x_offset,
+ gint *y_offset,
+ gint *width,
+ gint *height);
+static void mcrp_style_set (GtkWidget *widget,
+ GtkStyle *old_style,
+ PlannerCellRendererPopup *popup);
+static gboolean mcrp_key_press_event (GtkWidget *popup_window,
+ GdkEventKey *event,
+ PlannerCellRendererPopup *cell);
+static gboolean mcrp_button_press_event (GtkWidget *widget,
+ GdkEventButton *event,
+ PlannerCellRendererPopup *popup);
+
+
+static GtkCellRendererTextClass *parent_class;
+static guint signals[LAST_SIGNAL];
+
+#define PLANNER_CELL_RENDERER_POPUP_PATH "planner-cell-renderer-popup-path"
+
+GType
+planner_cell_renderer_popup_get_type (void)
+{
+ static GType cell_text_type = 0;
+
+ if (!cell_text_type) {
+ static const GTypeInfo cell_text_info = {
+ sizeof (PlannerCellRendererPopupClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) mcrp_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PlannerCellRendererPopup),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) mcrp_init,
+ };
+
+ cell_text_type = g_type_register_static (GTK_TYPE_CELL_RENDERER_TEXT,
+ "PlannerCellRendererPopup",
+ &cell_text_info,
+ 0);
+ }
+
+ return cell_text_type;
+}
+
+static void
+mcrp_init (PlannerCellRendererPopup *popup)
+{
+ popup->popup_window = gtk_window_new (GTK_WINDOW_POPUP);
+
+ popup->button_width = -1;
+
+ g_signal_connect (popup->popup_window,
+ "button-press-event",
+ G_CALLBACK (mcrp_button_press_event),
+ popup);
+
+ g_signal_connect (popup->popup_window,
+ "key-press-event",
+ G_CALLBACK (mcrp_key_press_event),
+ popup);
+
+ g_signal_connect (popup->popup_window,
+ "style-set",
+ G_CALLBACK (mcrp_style_set),
+ popup);
+}
+
+static void
+mcrp_class_init (PlannerCellRendererPopupClass *class)
+{
+ GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
+
+ parent_class = GTK_CELL_RENDERER_TEXT_CLASS (g_type_class_peek_parent (class));
+
+ cell_class->start_editing = mcrp_start_editing;
+ cell_class->get_size = mcrp_get_size;
+
+ class->show_popup = mcrp_show_popup;
+ class->hide_popup = mcrp_hide_popup;
+
+ signals[SHOW_POPUP] = g_signal_new (
+ "show-popup",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PlannerCellRendererPopupClass, show_popup),
+ NULL, NULL,
+ planner_marshal_VOID__STRING_INT_INT_INT_INT,
+ G_TYPE_NONE, 5,
+ G_TYPE_STRING,
+ G_TYPE_INT,
+ G_TYPE_INT,
+ G_TYPE_INT,
+ G_TYPE_INT);
+
+ signals[HIDE_POPUP] = g_signal_new (
+ "hide-popup",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PlannerCellRendererPopupClass, hide_popup),
+ NULL, NULL,
+ planner_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+mcrp_editing_done (GtkCellEditable *editable,
+ PlannerCellRendererPopup *cell)
+{
+ gchar *path;
+ const gchar *new_text;
+
+ if (PLANNER_POPUP_ENTRY (editable)->editing_canceled ||
+ cell->editing_canceled) {
+ return;
+ }
+
+ path = g_object_get_data (G_OBJECT (editable),
+ PLANNER_CELL_RENDERER_POPUP_PATH);
+ new_text = planner_popup_entry_get_text (PLANNER_POPUP_ENTRY (editable));
+
+ g_signal_emit_by_name (cell,
+ "edited",
+ path,
+ new_text);
+}
+
+static void
+mcrp_style_set (GtkWidget *widget,
+ GtkStyle *old_style,
+ PlannerCellRendererPopup *popup)
+{
+ /* Invalidate the cache. */
+ popup->button_width = -1;
+}
+
+static gboolean
+mcrp_grab_on_window (GdkWindow *window,
+ guint32 activate_time)
+{
+ if ((gdk_pointer_grab (window, TRUE,
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_POINTER_MOTION_MASK,
+ NULL, NULL, activate_time) == 0)) {
+ if (gdk_keyboard_grab (window, TRUE,
+ activate_time) == 0)
+ return TRUE;
+ else {
+ gdk_pointer_ungrab (activate_time);
+ return FALSE;
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+mcrp_show_popup (PlannerCellRendererPopup *cell,
+ const gchar *path,
+ gint x1,
+ gint y1,
+ gint x2,
+ gint y2)
+{
+ GtkAllocation alloc;
+ gint x, y;
+ gint screen_height, screen_width;
+ gint button_height;
+
+ cell->shown = TRUE;
+
+ gtk_widget_realize (cell->popup_window);
+
+ /* I'm not sure this is ok to do, but we need to show the window to be
+ * able to get the allocation right.
+ */
+ gtk_window_move (GTK_WINDOW (cell->popup_window), -500, -500);
+ gtk_widget_show (cell->popup_window);
+
+ alloc = cell->popup_window->allocation;
+
+ x = x2;
+ y = y2;
+
+ button_height = y2 - y1;
+
+ screen_height = gdk_screen_height () - y;
+ screen_width = gdk_screen_width ();
+
+ /* Check if it fits in the available height. */
+ if (alloc.height > screen_height) {
+ /* It doesn't fit, so we see if we have the minimum space needed. */
+ if (alloc.height > screen_height && y - button_height > screen_height) {
+ /* We don't, so we show the popup above the cell
+ instead of below it. */
+ screen_height = y - button_height;
+ y -= (alloc.height + button_height);
+ if (y < 0) {
+ y = 0;
+ }
+ }
+ }
+
+ /* We try to line it up with the right edge of the column, but we don't
+ * want it to go off the edges of the screen.
+ */
+ if (x > screen_width) {
+ x = screen_width;
+ }
+
+ x -= alloc.width;
+ if (x < 0) {
+ x = 0;
+ }
+
+ gtk_grab_add (cell->popup_window);
+
+ gtk_window_move (GTK_WINDOW (cell->popup_window), x, y);
+ gtk_widget_show (cell->popup_window);
+
+ gtk_widget_grab_focus (cell->focus_window);
+
+ mcrp_grab_on_window (cell->popup_window->window,
+ gtk_get_current_event_time ());
+}
+
+static void
+mcrp_hide_popup (PlannerCellRendererPopup *cell)
+{
+ gtk_grab_remove (cell->popup_window);
+ gtk_widget_hide (cell->popup_window);
+
+ if (cell->editable) {
+ gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (cell->editable));
+ }
+
+ /* This may look weird (the test), but the weak pointer will actually be
+ * nulled out for some cells, like the date cell.
+ */
+ if (cell->editable) {
+ gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (cell->editable));
+ }
+
+ cell->shown = FALSE;
+ cell->editing_canceled = FALSE;
+}
+
+static void
+mcrp_arrow_clicked (GtkCellEditable *entry,
+ PlannerCellRendererPopup *cell)
+{
+ GtkAllocation alloc;
+ gint x, y;
+ const gchar *path;
+
+ if (cell->shown) {
+ cell->editing_canceled = TRUE;
+ planner_cell_renderer_popup_hide (cell);
+ return;
+ }
+
+ path = g_object_get_data (G_OBJECT (entry),
+ PLANNER_CELL_RENDERER_POPUP_PATH);
+
+ /* Temporarily grab pointer and keyboard on a window we know exists; we
+ * do this so that the grab (with owner events == TRUE) affects
+ * events generated when the window is mapped, such as enter
+ * notify events on subwidgets. If the grab fails, bail out.
+ */
+ if (!mcrp_grab_on_window (GTK_WIDGET (entry)->window,
+ gtk_get_current_event_time ())) {
+ return;
+ }
+
+ gtk_editable_select_region (GTK_EDITABLE (PLANNER_POPUP_ENTRY (entry)->entry), 0, 0);
+
+ gdk_window_get_origin (GTK_WIDGET (entry)->window, &x, &y);
+
+ alloc = GTK_WIDGET (entry)->allocation;
+
+ g_signal_emit (cell, signals[SHOW_POPUP], 0,
+ path,
+ x,
+ y,
+ x + alloc.width,
+ y + alloc.height);
+}
+
+static GtkCellEditable *
+mcrp_start_editing (GtkCellRenderer *cell,
+ GdkEvent *event,
+ GtkWidget *widget,
+ const gchar *path,
+ GdkRectangle *background_area,
+ GdkRectangle *cell_area,
+ GtkCellRendererState flags)
+{
+ PlannerCellRendererPopup *popup;
+ GtkWidget *editable;
+ gchar *text;
+
+ popup = PLANNER_CELL_RENDERER_POPUP (cell);
+
+ /* If the cell isn't editable we return NULL. */
+ if (GTK_CELL_RENDERER_TEXT (popup)->editable == FALSE) {
+ return NULL;
+ }
+
+ editable = g_object_new (PLANNER_TYPE_POPUP_ENTRY, NULL);
+
+ text = GTK_CELL_RENDERER_TEXT (cell)->text;
+ planner_popup_entry_set_text (PLANNER_POPUP_ENTRY (editable), text ? text : "");
+
+ g_object_set_data_full (G_OBJECT (editable),
+ PLANNER_CELL_RENDERER_POPUP_PATH,
+ g_strdup (path),
+ g_free);
+
+ gtk_widget_show (editable);
+
+ g_signal_connect (editable,
+ "editing-done",
+ G_CALLBACK (mcrp_editing_done),
+ popup);
+
+ g_signal_connect (editable,
+ "arrow-clicked",
+ G_CALLBACK (mcrp_arrow_clicked),
+ popup);
+
+ popup->editable = editable;
+
+ g_object_add_weak_pointer (G_OBJECT (popup->editable),
+ (gpointer) &popup->editable);
+
+ return GTK_CELL_EDITABLE (editable);
+}
+
+GtkCellRenderer *
+planner_cell_renderer_popup_new (void)
+{
+ return GTK_CELL_RENDERER (
+ g_object_new (planner_cell_renderer_popup_get_type (), NULL));
+}
+
+void
+planner_cell_renderer_popup_hide (PlannerCellRendererPopup *cell)
+{
+ g_return_if_fail (PLANNER_IS_CELL_RENDERER_POPUP (cell));
+
+ g_signal_emit (cell, signals[HIDE_POPUP], 0);
+}
+
+static void
+mcrp_get_size (GtkCellRenderer *cell,
+ GtkWidget *widget,
+ GdkRectangle *cell_area,
+ gint *x_offset,
+ gint *y_offset,
+ gint *width,
+ gint *height)
+{
+ PlannerCellRendererPopup *popup;
+
+ popup = PLANNER_CELL_RENDERER_POPUP (cell);
+
+ if (GTK_CELL_RENDERER_CLASS (parent_class)->get_size) {
+ (* GTK_CELL_RENDERER_CLASS (parent_class)->get_size) (cell,
+ widget,
+ cell_area,
+ x_offset,
+ y_offset,
+ width,
+ height);
+ }
+
+ /* We cache this because it takes really long to get the width. */
+ if (popup->button_width == -1) {
+ popup->button_width = planner_popup_get_button_width ();
+ }
+
+ *width += popup->button_width;
+}
+
+static gboolean
+mcrp_key_press_event (GtkWidget *popup_window,
+ GdkEventKey *event,
+ PlannerCellRendererPopup *cell)
+{
+ if (event->keyval != GDK_Escape &&
+ event->keyval != GDK_Return &&
+ event->keyval != GDK_KP_Enter &&
+ event->keyval != GDK_ISO_Enter &&
+ event->keyval != GDK_3270_Enter) {
+ return FALSE;
+ }
+
+ if (event->keyval == GDK_Escape) {
+ cell->editing_canceled = TRUE;
+ } else {
+ cell->editing_canceled = FALSE;
+ }
+
+ planner_cell_renderer_popup_hide (cell);
+
+ return TRUE;
+}
+
+static gboolean
+mcrp_button_press_event (GtkWidget *widget,
+ GdkEventButton *event,
+ PlannerCellRendererPopup *popup)
+{
+ GtkAllocation alloc;
+ gdouble x, y;
+ gint xoffset, yoffset;
+ gint x1, y1;
+ gint x2, y2;
+
+ if (event->button != 1) {
+ return FALSE;
+ }
+
+ /* If the event happened outside the popup, cancel editing.
+ */
+
+ /*gdk_event_get_root_coords ((GdkEvent *) event, &x, &y);*/
+ x = event->x_root;
+ y = event->y_root;
+
+ gdk_window_get_root_origin (widget->window,
+ &xoffset,
+ &yoffset);
+
+ xoffset += widget->allocation.x;
+ yoffset += widget->allocation.y;
+
+ alloc = popup->popup_window->allocation;
+ x1 = alloc.x + xoffset;
+ y1 = alloc.y + yoffset;
+ x2 = x1 + alloc.width;
+ y2 = y1 + alloc.height;
+
+ if (x > x1 && x < x2 && y > y1 && y < y2) {
+ return FALSE;
+ }
+
+ popup->editing_canceled = TRUE;
+ planner_cell_renderer_popup_hide (popup);
+
+ return FALSE;
+}
Added: gnucash/branches/register-rewrite/src/gnome-utils/planner-cell-renderer-popup.h
===================================================================
--- gnucash/branches/register-rewrite/src/gnome-utils/planner-cell-renderer-popup.h 2007-03-08 13:23:14 UTC (rev 15690)
+++ gnucash/branches/register-rewrite/src/gnome-utils/planner-cell-renderer-popup.h 2007-03-08 21:40:06 UTC (rev 15691)
@@ -0,0 +1,64 @@
+#ifndef __PLANNER_CELL_RENDERER_POPUP_H__
+#define __PLANNER_CELL_RENDERER_POPUP_H__
+
+#include <pango/pango.h>
+#include <gtk/gtkcellrenderertext.h>
+
+#define PLANNER_TYPE_CELL_RENDERER_POPUP (planner_cell_renderer_popup_get_type ())
+#define PLANNER_CELL_RENDERER_POPUP(obj) (GTK_CHECK_CAST ((obj), PLANNER_TYPE_CELL_RENDERER_POPUP, PlannerCellRendererPopup))
+#define PLANNER_CELL_RENDERER_POPUP_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), PLANNER_TYPE_CELL_RENDERER_POPUP, PlannerCellRendererPopupClass))
+#define PLANNER_IS_CELL_RENDERER_POPUP(obj) (GTK_CHECK_TYPE ((obj), PLANNER_TYPE_CELL_RENDERER_POPUP))
+#define PLANNER_IS_CELL_RENDERER_POPUP_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), PLANNER_TYPE_CELL_RENDERER_POPUP))
+#define PLANNER_CELL_RENDERER_POPUP_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), PLANNER_TYPE_CELL_RENDERER_POPUP, PlannerCellRendererPopupClass))
+
+typedef struct _PlannerCellRendererPopup PlannerCellRendererPopup;
+typedef struct _PlannerCellRendererPopupClass PlannerCellRendererPopupClass;
+
+struct _PlannerCellRendererPopup
+{
+ GtkCellRendererText parent;
+
+ /* Cached width of the popup button. */
+ gint button_width;
+
+ /* The popup window. */
+ GtkWidget *popup_window;
+
+ /* The widget that should grab focus on popup. */
+ GtkWidget *focus_window;
+
+ /* The editable entry. */
+ GtkWidget *editable;
+
+ gboolean shown;
+ gboolean editing_canceled;
+};
+
+struct _PlannerCellRendererPopupClass
+{
+ GtkCellRendererTextClass parent_class;
+
+ void (* show_popup) (PlannerCellRendererPopup *cell,
+ const gchar *path,
+ gint x1,
+ gint y1,
+ gint x2,
+ gint y2);
+
+ void (* hide_popup) (PlannerCellRendererPopup *cell);
+};
+
+GtkType planner_cell_renderer_popup_get_type (void) G_GNUC_CONST;
+
+GtkCellRenderer *planner_cell_renderer_popup_new (void);
+
+void planner_cell_renderer_popup_show (PlannerCellRendererPopup *cell,
+ const gchar *path,
+ gint x1,
+ gint y1,
+ gint x2,
+ gint y2);
+
+void planner_cell_renderer_popup_hide (PlannerCellRendererPopup *cell);
+
+#endif /* __PLANNER_CELL_RENDERER_POPUP_H__ */
Added: gnucash/branches/register-rewrite/src/gnome-utils/planner-marshal.list
===================================================================
--- gnucash/branches/register-rewrite/src/gnome-utils/planner-marshal.list 2007-03-08 13:23:14 UTC (rev 15690)
+++ gnucash/branches/register-rewrite/src/gnome-utils/planner-marshal.list 2007-03-08 21:40:06 UTC (rev 15691)
@@ -0,0 +1,12 @@
+VOID:VOID
+VOID:BOOLEAN
+VOID:BOOLEAN,STRING
+VOID:POINTER
+VOID:OBJECT
+VOID:STRING
+VOID:OBJECT,OBJECT
+VOID:INT,INT,INT,INT
+VOID:STRING,INT,INT,INT,INT
+VOID:DOUBLE,DOUBLE,DOUBLE,DOUBLE
+VOID:OBJECT,BOOLEAN
+OBJECT:VOID
Added: gnucash/branches/register-rewrite/src/gnome-utils/planner-popup-entry.c
===================================================================
--- gnucash/branches/register-rewrite/src/gnome-utils/planner-popup-entry.c 2007-03-08 13:23:14 UTC (rev 15690)
+++ gnucash/branches/register-rewrite/src/gnome-utils/planner-popup-entry.c 2007-03-08 21:40:06 UTC (rev 15691)
@@ -0,0 +1,270 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2001-2002 CodeFactory AB
+ * Copyright (C) 2001-2002 Richard Hult <richard at imendio.com>
+ * Copyright (C) 2001-2002 Mikael Hallendal <micke at imendio.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 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <string.h>
+#include <gtk/gtkwindow.h>
+#include <gtk/gtkbutton.h>
+#include <gtk/gtkentry.h>
+#include <gtk/gtkarrow.h>
+#include <gtk/gtkhbox.h>
+#include <gtk/gtkeventbox.h>
+#include <gtk/gtkcelleditable.h>
+#include <gdk/gdkkeysyms.h>
+#include "planner-popup-entry.h"
+
+static void planner_popup_entry_init (PlannerPopupEntry *entry);
+static void planner_popup_entry_class_init (PlannerPopupEntryClass *class);
+static void mpw_cell_editable_init (GtkCellEditableIface *iface);
+static gboolean mpw_key_press_event (GtkWidget *box,
+ GdkEventKey *key_event);
+
+enum {
+ ARROW_CLICKED,
+ LAST_SIGNAL
+};
+
+static GtkEventBoxClass *parent_class;
+static guint signals[LAST_SIGNAL];
+
+GtkType
+planner_popup_entry_get_type (void)
+{
+ static GtkType widget_type = 0;
+
+ if (!widget_type) {
+ static const GTypeInfo widget_info = {
+ sizeof (PlannerPopupEntryClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) planner_popup_entry_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PlannerPopupEntry),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) planner_popup_entry_init,
+ };
+
+ static const GInterfaceInfo cell_editable_info = {
+ (GInterfaceInitFunc) mpw_cell_editable_init, /* interface_init */
+ NULL, /* interface_finalize */
+ NULL /* interface_data */
+ };
+
+ widget_type = g_type_register_static (GTK_TYPE_EVENT_BOX,
+ "PlannerPopupEntry",
+ &widget_info,
+ 0);
+
+ g_type_add_interface_static (widget_type,
+ GTK_TYPE_CELL_EDITABLE,
+ &cell_editable_info);
+ }
+
+ return widget_type;
+}
+
+static void
+planner_popup_entry_init (PlannerPopupEntry *widget)
+{
+ GtkWidget *arrow;
+
+ widget->hbox = gtk_hbox_new (FALSE, 0);
+ gtk_widget_show (widget->hbox);
+
+ widget->entry = g_object_new (GTK_TYPE_ENTRY, "has_frame", FALSE, NULL);
+ GTK_ENTRY (widget->entry)->is_cell_renderer = TRUE;
+ gtk_widget_show (widget->entry);
+
+ widget->button = gtk_button_new ();
+ gtk_widget_show (widget->button);
+
+ arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
+ gtk_widget_show (arrow);
+
+ gtk_container_add (GTK_CONTAINER (widget->button), arrow);
+
+ gtk_box_pack_start (GTK_BOX (widget->hbox), widget->entry, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (widget->hbox), widget->button, FALSE, TRUE, 0);
+
+ gtk_container_add (GTK_CONTAINER (widget), widget->hbox);
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
+ gtk_widget_add_events (GTK_WIDGET (widget), GDK_KEY_PRESS_MASK);
+ gtk_widget_add_events (GTK_WIDGET (widget), GDK_KEY_RELEASE_MASK);
+}
+
+static void
+planner_popup_entry_class_init (PlannerPopupEntryClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ widget_class->key_press_event = mpw_key_press_event;
+
+ parent_class = GTK_EVENT_BOX_CLASS (g_type_class_peek_parent (klass));
+
+ signals[ARROW_CLICKED] = g_signal_new
+ ("arrow-clicked",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+mpw_arrow_clicked (GtkWidget *button, PlannerPopupEntry *widget)
+{
+ g_signal_emit (widget, signals[ARROW_CLICKED], 0);
+}
+
+/* GtkCellEditable method implementations
+ */
+static void
+gtk_cell_editable_entry_activated (GtkEntry *entry, PlannerPopupEntry *widget)
+{
+ gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (widget));
+ gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (widget));
+}
+
+static gboolean
+gtk_cell_editable_key_press_event (GtkEntry *entry,
+ GdkEventKey *key_event,
+ PlannerPopupEntry *widget)
+{
+ if (key_event->keyval == GDK_Escape) {
+ widget->editing_canceled = TRUE;
+
+ gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (widget));
+ gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (widget));
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+mpw_key_press_event (GtkWidget *box,
+ GdkEventKey *key_event)
+{
+ PlannerPopupEntry *widget = PLANNER_POPUP_ENTRY (box);
+ GdkEvent tmp_event;
+
+ if (key_event->keyval == GDK_Escape) {
+ widget->editing_canceled = TRUE;
+
+ gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (widget));
+ gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (widget));
+
+ return TRUE;
+ }
+
+ gtk_widget_grab_focus (widget->entry);
+
+ /* Hackish :/ Synthesize a key press event for the entry. */
+ memcpy (&tmp_event, key_event, sizeof (GdkEventKey));
+
+ tmp_event.key.window = widget->entry->window;
+ tmp_event.key.send_event = TRUE;
+
+ gtk_widget_event (widget->entry, &tmp_event);
+
+ return GTK_WIDGET_CLASS (parent_class)->key_press_event (GTK_WIDGET (widget),
+ key_event);
+}
+
+static void
+mpw_start_editing (GtkCellEditable *cell_editable,
+ GdkEvent *event)
+{
+ PlannerPopupEntry *widget = PLANNER_POPUP_ENTRY (cell_editable);
+
+ gtk_editable_select_region (GTK_EDITABLE (widget->entry), 0, -1);
+
+ g_signal_connect (G_OBJECT (widget->entry),
+ "activate",
+ G_CALLBACK (gtk_cell_editable_entry_activated),
+ widget);
+ g_signal_connect (G_OBJECT (widget->entry),
+ "key_press_event",
+ G_CALLBACK (gtk_cell_editable_key_press_event),
+ widget);
+ g_signal_connect (G_OBJECT (widget->button),
+ "clicked",
+ (GCallback) mpw_arrow_clicked,
+ widget);
+}
+
+static void
+mpw_cell_editable_init (GtkCellEditableIface *iface)
+{
+ iface->start_editing = mpw_start_editing;
+}
+
+void
+planner_popup_entry_set_text (PlannerPopupEntry *popup, const gchar *text)
+{
+ g_return_if_fail (PLANNER_IS_POPUP_ENTRY (popup));
+
+ gtk_entry_set_text (GTK_ENTRY (popup->entry), text ? text : "");
+}
+
+const gchar *
+planner_popup_entry_get_text (PlannerPopupEntry *popup)
+{
+ g_return_val_if_fail (PLANNER_IS_POPUP_ENTRY (popup), NULL);
+
+ return gtk_entry_get_text (GTK_ENTRY (popup->entry));
+}
+
+gint
+planner_popup_get_button_width (void)
+{
+ GtkWidget *window, *button, *arrow;
+ gint width;
+
+ GtkRequisition req;
+
+ window = gtk_window_new (GTK_WINDOW_POPUP);
+
+ button = gtk_button_new ();
+ gtk_widget_show (button);
+ gtk_container_add (GTK_CONTAINER (window), button);
+
+ arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
+ gtk_widget_show (arrow);
+ gtk_container_add (GTK_CONTAINER (button), arrow);
+
+ gtk_window_move (GTK_WINDOW (window), -500, -500);
+ gtk_widget_show (window);
+
+ gtk_widget_size_request (window, &req);
+
+ width = req.width;
+
+ gtk_widget_destroy (window);
+
+ return width;
+}
+
Added: gnucash/branches/register-rewrite/src/gnome-utils/planner-popup-entry.h
===================================================================
--- gnucash/branches/register-rewrite/src/gnome-utils/planner-popup-entry.h 2007-03-08 13:23:14 UTC (rev 15690)
+++ gnucash/branches/register-rewrite/src/gnome-utils/planner-popup-entry.h 2007-03-08 21:40:06 UTC (rev 15691)
@@ -0,0 +1,67 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2001-2002 CodeFactory AB
+ * Copyright (C) 2001-2002 Richard Hult <richard at imendio.com>
+ * Copyright (C) 2001-2002 Mikael Hallendal <micke at imendio.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 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PLANNER_POPUP_ENTRY_H__
+#define __PLANNER_POPUP_ENTRY_H__
+
+#include <pango/pango.h>
+#include <gtk/gtkeventbox.h>
+
+#define PLANNER_TYPE_POPUP_ENTRY (planner_popup_entry_get_type ())
+#define PLANNER_POPUP_ENTRY(obj) (GTK_CHECK_CAST ((obj), PLANNER_TYPE_POPUP_ENTRY, PlannerPopupEntry))
+#define PLANNER_POPUP_ENTRY_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), PLANNER_TYPE_POPUP_ENTRY, PlannerPopupEntryClass))
+#define PLANNER_IS_POPUP_ENTRY(obj) (GTK_CHECK_TYPE ((obj), PLANNER_TYPE_POPUP_ENTRY))
+#define PLANNER_IS_POPUP_ENTRY_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), PLANNER_TYPE_POPUP_ENTRY))
+#define PLANNER_POPUP_ENTRY_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), PLANNER_TYPE_POPUP_ENTRY, PlannerPopupEntryClass))
+
+typedef struct _PlannerPopupEntry PlannerPopupEntry;
+typedef struct _PlannerPopupEntryClass PlannerPopupEntryClass;
+
+struct _PlannerPopupEntry
+{
+ GtkEventBox parent;
+
+ GtkWidget *hbox;
+ GtkWidget *button;
+ GtkWidget *entry;
+
+ gboolean editing_canceled;
+};
+
+struct _PlannerPopupEntryClass
+{
+ GtkEventBoxClass parent_class;
+};
+
+GtkType planner_popup_entry_get_type (void) G_GNUC_CONST;
+
+GtkWidget *planner_popup_entry_new (void);
+
+void planner_popup_entry_set_text (PlannerPopupEntry *popup,
+ const gchar *text);
+
+const gchar *planner_popup_entry_get_text (PlannerPopupEntry *popup);
+
+gint planner_popup_get_button_width (void);
+
+
+#endif /* __PLANNER_POPUP_ENTRY_H__ */
More information about the gnucash-changes
mailing list