From f6302d17784a0020efc9faef31b8d8c773b1ba44 Mon Sep 17 00:00:00 2001 From: Michael Dominic Kostrzewa Date: Tue, 14 Nov 2006 12:19:43 +0000 Subject: [PATCH] 2006-11-14 Michael Dominic Kostrzewa * ./: hildon-widgets => src . hildon-widgets-plugins => plugins. Changing dir names etc. --- ChangeLog | 5 + Makefile.am | 3 +- configure.ac | 11 +- hildon-widgets-plugins/Makefile.am | 27 - .../hildon-color-chooser-dialog-hsv.c | 1062 --------- hildon-widgets-plugins/hildon-color-chooser-hsv.c | 1099 --------- hildon-widgets/Makefile.am | 216 -- hildon-widgets/gtk-infoprint.c | 341 --- hildon-widgets/gtk-infoprint.h | 52 - hildon-widgets/hildon-add-home-dialog.c | 525 ----- hildon-widgets/hildon-add-home-dialog.h | 61 - hildon-widgets/hildon-app-private.h | 78 - hildon-widgets/hildon-app.c | 2270 ------------------- hildon-widgets/hildon-app.h | 158 -- hildon-widgets/hildon-appview.c | 1495 ------------- hildon-widgets/hildon-appview.h | 121 - hildon-widgets/hildon-banner.c | 913 -------- hildon-widgets/hildon-banner.h | 88 - hildon-widgets/hildon-calendar-popup.c | 439 ---- hildon-widgets/hildon-calendar-popup.h | 87 - hildon-widgets/hildon-caption.c | 1254 ----------- hildon-widgets/hildon-caption.h | 156 -- hildon-widgets/hildon-code-dialog.c | 480 ---- hildon-widgets/hildon-code-dialog.h | 71 - hildon-widgets/hildon-color-button.c | 491 ---- hildon-widgets/hildon-color-button.h | 82 - hildon-widgets/hildon-color-chooser-button.c | 409 ---- hildon-widgets/hildon-color-chooser-button.h | 82 - hildon-widgets/hildon-color-chooser-dialog.c | 172 -- hildon-widgets/hildon-color-chooser-dialog.h | 76 - hildon-widgets/hildon-color-chooser.c | 166 -- hildon-widgets/hildon-color-chooser.h | 73 - hildon-widgets/hildon-color-popup.c | 242 -- hildon-widgets/hildon-color-popup.h | 52 - hildon-widgets/hildon-color-selector.c | 845 ------- hildon-widgets/hildon-color-selector.h | 72 - hildon-widgets/hildon-composite-widget.c | 79 - hildon-widgets/hildon-composite-widget.h | 53 - hildon-widgets/hildon-controlbar.c | 799 ------- hildon-widgets/hildon-controlbar.h | 71 - hildon-widgets/hildon-date-editor.c | 1445 ------------ hildon-widgets/hildon-date-editor.h | 111 - hildon-widgets/hildon-defines.c | 268 --- hildon-widgets/hildon-defines.h | 143 -- hildon-widgets/hildon-dialoghelp.c | 190 -- hildon-widgets/hildon-dialoghelp.h | 37 - hildon-widgets/hildon-file-handling-note.c | 379 ---- hildon-widgets/hildon-file-handling-note.h | 77 - hildon-widgets/hildon-find-toolbar.c | 667 ------ hildon-widgets/hildon-find-toolbar.h | 80 - hildon-widgets/hildon-font-selection-dialog.c | 1998 ----------------- hildon-widgets/hildon-font-selection-dialog.h | 100 - hildon-widgets/hildon-get-password-dialog.c | 569 ----- hildon-widgets/hildon-get-password-dialog.h | 99 - hildon-widgets/hildon-grid-item-private.h | 71 - hildon-widgets/hildon-grid-item.c | 1020 --------- hildon-widgets/hildon-grid-item.h | 92 - hildon-widgets/hildon-grid.c | 2348 -------------------- hildon-widgets/hildon-grid.h | 107 - hildon-widgets/hildon-hvolumebar.c | 330 --- hildon-widgets/hildon-hvolumebar.h | 58 - hildon-widgets/hildon-input-mode-hint.h | 70 - hildon-widgets/hildon-marshalers.c | 134 -- hildon-widgets/hildon-marshalers.h | 31 - hildon-widgets/hildon-marshalers.list | 28 - hildon-widgets/hildon-name-password-dialog.c | 382 ---- hildon-widgets/hildon-name-password-dialog.h | 85 - hildon-widgets/hildon-note.c | 869 -------- hildon-widgets/hildon-note.h | 118 - hildon-widgets/hildon-number-editor.c | 964 -------- hildon-widgets/hildon-number-editor.h | 81 - hildon-widgets/hildon-plugin-widget.c | 260 --- hildon-widgets/hildon-plugin-widget.h | 56 - hildon-widgets/hildon-private.h | 38 - hildon-widgets/hildon-program.c | 630 ------ hildon-widgets/hildon-program.h | 100 - hildon-widgets/hildon-range-editor.c | 1023 --------- hildon-widgets/hildon-range-editor.h | 96 - hildon-widgets/hildon-scroll-area.c | 239 -- hildon-widgets/hildon-scroll-area.h | 40 - hildon-widgets/hildon-seekbar.c | 601 ----- hildon-widgets/hildon-seekbar.h | 65 - hildon-widgets/hildon-set-password-dialog.c | 666 ------ hildon-widgets/hildon-set-password-dialog.h | 102 - hildon-widgets/hildon-sort-dialog.c | 495 ----- hildon-widgets/hildon-sort-dialog.h | 68 - hildon-widgets/hildon-system-sound.c | 93 - hildon-widgets/hildon-system-sound.h | 32 - hildon-widgets/hildon-telephone-editor.c | 1436 ------------ hildon-widgets/hildon-telephone-editor.h | 133 -- hildon-widgets/hildon-time-editor.c | 1902 ---------------- hildon-widgets/hildon-time-editor.h | 121 - hildon-widgets/hildon-time-picker.c | 933 -------- hildon-widgets/hildon-time-picker.h | 74 - hildon-widgets/hildon-volumebar-private.h | 47 - hildon-widgets/hildon-volumebar-range.c | 293 --- hildon-widgets/hildon-volumebar-range.h | 78 - hildon-widgets/hildon-volumebar.c | 622 ------ hildon-widgets/hildon-volumebar.h | 74 - hildon-widgets/hildon-vvolumebar.c | 233 -- hildon-widgets/hildon-vvolumebar.h | 60 - hildon-widgets/hildon-weekday-picker.c | 502 ----- hildon-widgets/hildon-weekday-picker.h | 149 -- hildon-widgets/hildon-window-private.h | 54 - hildon-widgets/hildon-window.c | 1707 -------------- hildon-widgets/hildon-window.h | 112 - hildon-widgets/hildon-wizard-dialog.c | 487 ---- hildon-widgets/hildon-wizard-dialog.h | 86 - plugins/Makefile.am | 27 + plugins/hildon-color-chooser-dialog-hsv.c | 1062 +++++++++ plugins/hildon-color-chooser-hsv.c | 1099 +++++++++ src/Makefile.am | 216 ++ src/gtk-infoprint.c | 341 +++ src/gtk-infoprint.h | 52 + src/hildon-add-home-dialog.c | 525 +++++ src/hildon-add-home-dialog.h | 61 + src/hildon-app-private.h | 78 + src/hildon-app.c | 2270 +++++++++++++++++++ src/hildon-app.h | 158 ++ src/hildon-appview.c | 1495 +++++++++++++ src/hildon-appview.h | 121 + src/hildon-banner.c | 913 ++++++++ src/hildon-banner.h | 88 + src/hildon-calendar-popup.c | 439 ++++ src/hildon-calendar-popup.h | 87 + src/hildon-caption.c | 1254 +++++++++++ src/hildon-caption.h | 156 ++ src/hildon-code-dialog.c | 480 ++++ src/hildon-code-dialog.h | 71 + src/hildon-color-button.c | 491 ++++ src/hildon-color-button.h | 82 + src/hildon-color-chooser-button.c | 409 ++++ src/hildon-color-chooser-button.h | 82 + src/hildon-color-chooser-dialog.c | 172 ++ src/hildon-color-chooser-dialog.h | 76 + src/hildon-color-chooser.c | 166 ++ src/hildon-color-chooser.h | 73 + src/hildon-color-popup.c | 242 ++ src/hildon-color-popup.h | 52 + src/hildon-color-selector.c | 845 +++++++ src/hildon-color-selector.h | 72 + src/hildon-composite-widget.c | 79 + src/hildon-composite-widget.h | 53 + src/hildon-controlbar.c | 799 +++++++ src/hildon-controlbar.h | 71 + src/hildon-date-editor.c | 1445 ++++++++++++ src/hildon-date-editor.h | 111 + src/hildon-defines.c | 268 +++ src/hildon-defines.h | 143 ++ src/hildon-dialoghelp.c | 190 ++ src/hildon-dialoghelp.h | 37 + src/hildon-file-handling-note.c | 379 ++++ src/hildon-file-handling-note.h | 77 + src/hildon-find-toolbar.c | 667 ++++++ src/hildon-find-toolbar.h | 80 + src/hildon-font-selection-dialog.c | 1998 +++++++++++++++++ src/hildon-font-selection-dialog.h | 100 + src/hildon-get-password-dialog.c | 569 +++++ src/hildon-get-password-dialog.h | 99 + src/hildon-grid-item-private.h | 71 + src/hildon-grid-item.c | 1020 +++++++++ src/hildon-grid-item.h | 92 + src/hildon-grid.c | 2348 ++++++++++++++++++++ src/hildon-grid.h | 107 + src/hildon-hvolumebar.c | 330 +++ src/hildon-hvolumebar.h | 58 + src/hildon-input-mode-hint.h | 70 + src/hildon-marshalers.c | 134 ++ src/hildon-marshalers.h | 31 + src/hildon-marshalers.list | 28 + src/hildon-name-password-dialog.c | 382 ++++ src/hildon-name-password-dialog.h | 85 + src/hildon-note.c | 869 ++++++++ src/hildon-note.h | 118 + src/hildon-number-editor.c | 964 ++++++++ src/hildon-number-editor.h | 81 + src/hildon-plugin-widget.c | 260 +++ src/hildon-plugin-widget.h | 56 + src/hildon-private.h | 38 + src/hildon-program.c | 630 ++++++ src/hildon-program.h | 100 + src/hildon-range-editor.c | 1023 +++++++++ src/hildon-range-editor.h | 96 + src/hildon-scroll-area.c | 239 ++ src/hildon-scroll-area.h | 40 + src/hildon-seekbar.c | 601 +++++ src/hildon-seekbar.h | 65 + src/hildon-set-password-dialog.c | 666 ++++++ src/hildon-set-password-dialog.h | 102 + src/hildon-sort-dialog.c | 495 +++++ src/hildon-sort-dialog.h | 68 + src/hildon-system-sound.c | 93 + src/hildon-system-sound.h | 32 + src/hildon-telephone-editor.c | 1436 ++++++++++++ src/hildon-telephone-editor.h | 133 ++ src/hildon-time-editor.c | 1902 ++++++++++++++++ src/hildon-time-editor.h | 121 + src/hildon-time-picker.c | 933 ++++++++ src/hildon-time-picker.h | 74 + src/hildon-volumebar-private.h | 47 + src/hildon-volumebar-range.c | 293 +++ src/hildon-volumebar-range.h | 78 + src/hildon-volumebar.c | 622 ++++++ src/hildon-volumebar.h | 74 + src/hildon-vvolumebar.c | 233 ++ src/hildon-vvolumebar.h | 60 + src/hildon-weekday-picker.c | 502 +++++ src/hildon-weekday-picker.h | 149 ++ src/hildon-window-private.h | 54 + src/hildon-window.c | 1707 ++++++++++++++ src/hildon-window.h | 112 + src/hildon-wizard-dialog.c | 487 ++++ src/hildon-wizard-dialog.h | 86 + 213 files changed, 41424 insertions(+), 41425 deletions(-) delete mode 100644 hildon-widgets-plugins/Makefile.am delete mode 100644 hildon-widgets-plugins/hildon-color-chooser-dialog-hsv.c delete mode 100644 hildon-widgets-plugins/hildon-color-chooser-hsv.c delete mode 100644 hildon-widgets/Makefile.am delete mode 100644 hildon-widgets/gtk-infoprint.c delete mode 100644 hildon-widgets/gtk-infoprint.h delete mode 100644 hildon-widgets/hildon-add-home-dialog.c delete mode 100644 hildon-widgets/hildon-add-home-dialog.h delete mode 100644 hildon-widgets/hildon-app-private.h delete mode 100644 hildon-widgets/hildon-app.c delete mode 100644 hildon-widgets/hildon-app.h delete mode 100644 hildon-widgets/hildon-appview.c delete mode 100644 hildon-widgets/hildon-appview.h delete mode 100644 hildon-widgets/hildon-banner.c delete mode 100644 hildon-widgets/hildon-banner.h delete mode 100644 hildon-widgets/hildon-calendar-popup.c delete mode 100644 hildon-widgets/hildon-calendar-popup.h delete mode 100644 hildon-widgets/hildon-caption.c delete mode 100644 hildon-widgets/hildon-caption.h delete mode 100644 hildon-widgets/hildon-code-dialog.c delete mode 100644 hildon-widgets/hildon-code-dialog.h delete mode 100644 hildon-widgets/hildon-color-button.c delete mode 100644 hildon-widgets/hildon-color-button.h delete mode 100644 hildon-widgets/hildon-color-chooser-button.c delete mode 100644 hildon-widgets/hildon-color-chooser-button.h delete mode 100644 hildon-widgets/hildon-color-chooser-dialog.c delete mode 100644 hildon-widgets/hildon-color-chooser-dialog.h delete mode 100644 hildon-widgets/hildon-color-chooser.c delete mode 100644 hildon-widgets/hildon-color-chooser.h delete mode 100644 hildon-widgets/hildon-color-popup.c delete mode 100644 hildon-widgets/hildon-color-popup.h delete mode 100644 hildon-widgets/hildon-color-selector.c delete mode 100644 hildon-widgets/hildon-color-selector.h delete mode 100644 hildon-widgets/hildon-composite-widget.c delete mode 100644 hildon-widgets/hildon-composite-widget.h delete mode 100644 hildon-widgets/hildon-controlbar.c delete mode 100644 hildon-widgets/hildon-controlbar.h delete mode 100644 hildon-widgets/hildon-date-editor.c delete mode 100644 hildon-widgets/hildon-date-editor.h delete mode 100644 hildon-widgets/hildon-defines.c delete mode 100644 hildon-widgets/hildon-defines.h delete mode 100644 hildon-widgets/hildon-dialoghelp.c delete mode 100644 hildon-widgets/hildon-dialoghelp.h delete mode 100644 hildon-widgets/hildon-file-handling-note.c delete mode 100644 hildon-widgets/hildon-file-handling-note.h delete mode 100644 hildon-widgets/hildon-find-toolbar.c delete mode 100644 hildon-widgets/hildon-find-toolbar.h delete mode 100644 hildon-widgets/hildon-font-selection-dialog.c delete mode 100644 hildon-widgets/hildon-font-selection-dialog.h delete mode 100644 hildon-widgets/hildon-get-password-dialog.c delete mode 100644 hildon-widgets/hildon-get-password-dialog.h delete mode 100644 hildon-widgets/hildon-grid-item-private.h delete mode 100644 hildon-widgets/hildon-grid-item.c delete mode 100644 hildon-widgets/hildon-grid-item.h delete mode 100644 hildon-widgets/hildon-grid.c delete mode 100644 hildon-widgets/hildon-grid.h delete mode 100644 hildon-widgets/hildon-hvolumebar.c delete mode 100644 hildon-widgets/hildon-hvolumebar.h delete mode 100644 hildon-widgets/hildon-input-mode-hint.h delete mode 100644 hildon-widgets/hildon-marshalers.c delete mode 100644 hildon-widgets/hildon-marshalers.h delete mode 100644 hildon-widgets/hildon-marshalers.list delete mode 100644 hildon-widgets/hildon-name-password-dialog.c delete mode 100644 hildon-widgets/hildon-name-password-dialog.h delete mode 100644 hildon-widgets/hildon-note.c delete mode 100644 hildon-widgets/hildon-note.h delete mode 100644 hildon-widgets/hildon-number-editor.c delete mode 100644 hildon-widgets/hildon-number-editor.h delete mode 100644 hildon-widgets/hildon-plugin-widget.c delete mode 100644 hildon-widgets/hildon-plugin-widget.h delete mode 100644 hildon-widgets/hildon-private.h delete mode 100644 hildon-widgets/hildon-program.c delete mode 100644 hildon-widgets/hildon-program.h delete mode 100644 hildon-widgets/hildon-range-editor.c delete mode 100644 hildon-widgets/hildon-range-editor.h delete mode 100644 hildon-widgets/hildon-scroll-area.c delete mode 100644 hildon-widgets/hildon-scroll-area.h delete mode 100644 hildon-widgets/hildon-seekbar.c delete mode 100644 hildon-widgets/hildon-seekbar.h delete mode 100644 hildon-widgets/hildon-set-password-dialog.c delete mode 100644 hildon-widgets/hildon-set-password-dialog.h delete mode 100644 hildon-widgets/hildon-sort-dialog.c delete mode 100644 hildon-widgets/hildon-sort-dialog.h delete mode 100644 hildon-widgets/hildon-system-sound.c delete mode 100644 hildon-widgets/hildon-system-sound.h delete mode 100644 hildon-widgets/hildon-telephone-editor.c delete mode 100644 hildon-widgets/hildon-telephone-editor.h delete mode 100644 hildon-widgets/hildon-time-editor.c delete mode 100644 hildon-widgets/hildon-time-editor.h delete mode 100644 hildon-widgets/hildon-time-picker.c delete mode 100644 hildon-widgets/hildon-time-picker.h delete mode 100644 hildon-widgets/hildon-volumebar-private.h delete mode 100644 hildon-widgets/hildon-volumebar-range.c delete mode 100644 hildon-widgets/hildon-volumebar-range.h delete mode 100644 hildon-widgets/hildon-volumebar.c delete mode 100644 hildon-widgets/hildon-volumebar.h delete mode 100644 hildon-widgets/hildon-vvolumebar.c delete mode 100644 hildon-widgets/hildon-vvolumebar.h delete mode 100644 hildon-widgets/hildon-weekday-picker.c delete mode 100644 hildon-widgets/hildon-weekday-picker.h delete mode 100644 hildon-widgets/hildon-window-private.h delete mode 100644 hildon-widgets/hildon-window.c delete mode 100644 hildon-widgets/hildon-window.h delete mode 100644 hildon-widgets/hildon-wizard-dialog.c delete mode 100644 hildon-widgets/hildon-wizard-dialog.h create mode 100644 plugins/Makefile.am create mode 100644 plugins/hildon-color-chooser-dialog-hsv.c create mode 100644 plugins/hildon-color-chooser-hsv.c create mode 100644 src/Makefile.am create mode 100644 src/gtk-infoprint.c create mode 100644 src/gtk-infoprint.h create mode 100644 src/hildon-add-home-dialog.c create mode 100644 src/hildon-add-home-dialog.h create mode 100644 src/hildon-app-private.h create mode 100644 src/hildon-app.c create mode 100644 src/hildon-app.h create mode 100644 src/hildon-appview.c create mode 100644 src/hildon-appview.h create mode 100644 src/hildon-banner.c create mode 100644 src/hildon-banner.h create mode 100644 src/hildon-calendar-popup.c create mode 100644 src/hildon-calendar-popup.h create mode 100644 src/hildon-caption.c create mode 100644 src/hildon-caption.h create mode 100644 src/hildon-code-dialog.c create mode 100644 src/hildon-code-dialog.h create mode 100644 src/hildon-color-button.c create mode 100644 src/hildon-color-button.h create mode 100644 src/hildon-color-chooser-button.c create mode 100644 src/hildon-color-chooser-button.h create mode 100644 src/hildon-color-chooser-dialog.c create mode 100644 src/hildon-color-chooser-dialog.h create mode 100644 src/hildon-color-chooser.c create mode 100644 src/hildon-color-chooser.h create mode 100644 src/hildon-color-popup.c create mode 100644 src/hildon-color-popup.h create mode 100644 src/hildon-color-selector.c create mode 100644 src/hildon-color-selector.h create mode 100644 src/hildon-composite-widget.c create mode 100644 src/hildon-composite-widget.h create mode 100644 src/hildon-controlbar.c create mode 100644 src/hildon-controlbar.h create mode 100644 src/hildon-date-editor.c create mode 100644 src/hildon-date-editor.h create mode 100644 src/hildon-defines.c create mode 100644 src/hildon-defines.h create mode 100644 src/hildon-dialoghelp.c create mode 100644 src/hildon-dialoghelp.h create mode 100644 src/hildon-file-handling-note.c create mode 100644 src/hildon-file-handling-note.h create mode 100644 src/hildon-find-toolbar.c create mode 100644 src/hildon-find-toolbar.h create mode 100644 src/hildon-font-selection-dialog.c create mode 100644 src/hildon-font-selection-dialog.h create mode 100644 src/hildon-get-password-dialog.c create mode 100644 src/hildon-get-password-dialog.h create mode 100644 src/hildon-grid-item-private.h create mode 100644 src/hildon-grid-item.c create mode 100644 src/hildon-grid-item.h create mode 100644 src/hildon-grid.c create mode 100644 src/hildon-grid.h create mode 100644 src/hildon-hvolumebar.c create mode 100644 src/hildon-hvolumebar.h create mode 100644 src/hildon-input-mode-hint.h create mode 100644 src/hildon-marshalers.c create mode 100644 src/hildon-marshalers.h create mode 100644 src/hildon-marshalers.list create mode 100644 src/hildon-name-password-dialog.c create mode 100644 src/hildon-name-password-dialog.h create mode 100644 src/hildon-note.c create mode 100644 src/hildon-note.h create mode 100644 src/hildon-number-editor.c create mode 100644 src/hildon-number-editor.h create mode 100644 src/hildon-plugin-widget.c create mode 100644 src/hildon-plugin-widget.h create mode 100644 src/hildon-private.h create mode 100644 src/hildon-program.c create mode 100644 src/hildon-program.h create mode 100644 src/hildon-range-editor.c create mode 100644 src/hildon-range-editor.h create mode 100644 src/hildon-scroll-area.c create mode 100644 src/hildon-scroll-area.h create mode 100644 src/hildon-seekbar.c create mode 100644 src/hildon-seekbar.h create mode 100644 src/hildon-set-password-dialog.c create mode 100644 src/hildon-set-password-dialog.h create mode 100644 src/hildon-sort-dialog.c create mode 100644 src/hildon-sort-dialog.h create mode 100644 src/hildon-system-sound.c create mode 100644 src/hildon-system-sound.h create mode 100644 src/hildon-telephone-editor.c create mode 100644 src/hildon-telephone-editor.h create mode 100644 src/hildon-time-editor.c create mode 100644 src/hildon-time-editor.h create mode 100644 src/hildon-time-picker.c create mode 100644 src/hildon-time-picker.h create mode 100644 src/hildon-volumebar-private.h create mode 100644 src/hildon-volumebar-range.c create mode 100644 src/hildon-volumebar-range.h create mode 100644 src/hildon-volumebar.c create mode 100644 src/hildon-volumebar.h create mode 100644 src/hildon-vvolumebar.c create mode 100644 src/hildon-vvolumebar.h create mode 100644 src/hildon-weekday-picker.c create mode 100644 src/hildon-weekday-picker.h create mode 100644 src/hildon-window-private.h create mode 100644 src/hildon-window.c create mode 100644 src/hildon-window.h create mode 100644 src/hildon-wizard-dialog.c create mode 100644 src/hildon-wizard-dialog.h diff --git a/ChangeLog b/ChangeLog index e072a67..427ce84 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2006-11-14 Michael Dominic Kostrzewa + + * ./: hildon-widgets => src . hildon-widgets-plugins => plugins. + Changing dir names etc. + 2006-11-08 Michael Dominic Kostrzewa * hildon-widgets/hildon-libs.c: diff --git a/Makefile.am b/Makefile.am index d64987e..dbc2ae8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,5 @@ -SUBDIRS = hildon-widgets hildon-widgets-plugins timer doc po +SUBDIRS = src plugins timer doc po + EXTRA_DIST = \ debian/changelog \ debian/control \ diff --git a/configure.ac b/configure.ac index aceb3bf..7ddfaa3 100644 --- a/configure.ac +++ b/configure.ac @@ -13,9 +13,6 @@ AC_PROG_LIBTOOL AC_HEADER_STDC -#PKG_CHECK_MODULES(OUTO, outo >= 0.1.1) -#AC_SUBST(OUTO_CFLAGS) - CFLAGS="$CFLAGS -std=c99 -Wall -pedantic -Wmissing-prototypes -Wmissing-declarations" # -Werror disabled due to the flaw in glib-2.0 # See http://bugzilla.gnome.org/show_bug.cgi?id=310175 and @@ -56,13 +53,9 @@ AC_CHECK_PROG(DOXYGEN_FOUND, doxygen, yes, no) AM_CONDITIONAL(HAVE_DOXYGEN, [test "$DOXYGEN_FOUND" = "yes"]) localedir=${datadir}/locale -#outomoduledir=${libdir}/outo AC_SUBST(localedir) -#AC_SUBST(outomoduledir) - - # Disable rebuild of glib-mkenum -generated source code: AC_ARG_ENABLE(rebuilds, [ --disable-rebuilds disable all source autogeneration rules],,enable_rebuilds=yes) @@ -80,8 +73,8 @@ AC_SUBST(REBUILD) AC_OUTPUT(Makefile \ - hildon-widgets/Makefile \ - hildon-widgets-plugins/Makefile \ + src/Makefile \ + plugins/Makefile \ timer/Makefile \ po/Makefile \ po/porules.mk \ diff --git a/hildon-widgets-plugins/Makefile.am b/hildon-widgets-plugins/Makefile.am deleted file mode 100644 index f2b45ee..0000000 --- a/hildon-widgets-plugins/Makefile.am +++ /dev/null @@ -1,27 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -INCLUDES = $(GTK_CFLAGS) $(GCONF_CFLAGS) -DLOCALEDIR=\"$(localedir)\" \ - -I$(srcdir)/.. - -LDFLAGS = -module -avoid-version -LIBADD = -L$(srcdir)/../hildon-widgets/.libs -lhildonwidgets $(GTK_LIBS) - -pluginwidgetdir = $(libdir)/hildon-widgets -pluginwidget_LTLIBRARIES = hildoncolorchooser_hsv.la \ - hildoncolorchooserdialog_hsv.la - -hildoncolorchooser_hsv_la_SOURCES = hildon-color-chooser-hsv.c - -hildoncolorchooserdialog_hsv_la_SOURCES = hildon-color-chooser-dialog-hsv.c -hildoncolorchooserdialog_hsv_la_LIBADD = $(GCONF_LIBS) - -install-exec-local: installdirs - @echo "Creating default symlink for color chooser..." - @ln -f -s 'hildoncolorchooser_hsv.so' '$(DESTDIR)/$(libdir)/hildon-widgets/hildoncolorchooser_default.so' - @echo "Creating default symlink for color chooser dialog..." - @ln -f -s 'hildoncolorchooserdialog_hsv.so' '$(DESTDIR)/$(libdir)/hildon-widgets/hildoncolorchooserdialog_default.so' - - - - - diff --git a/hildon-widgets-plugins/hildon-color-chooser-dialog-hsv.c b/hildon-widgets-plugins/hildon-color-chooser-dialog-hsv.c deleted file mode 100644 index 3f57eb3..0000000 --- a/hildon-widgets-plugins/hildon-color-chooser-dialog-hsv.c +++ /dev/null @@ -1,1062 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Author: Kuisma Salonen - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - - -#include -#include - -#include - -#include -#include - -#include - -#include - - -#include -#include - -#include - -#include - -#include - - -#define _(String) dgettext("hildon-libs", String) - - -const char *parent_name = "HildonColorChooserDialog"; -const char *plugin_name = "HSV color chooser dialog"; - -GType export_type(void); - - -static HildonPluginWidgetInfo *chooser_plugin = NULL; - -static HildonColorChooserDialogClass *parent_klass = NULL; - - -/* darkened EGA palette to be used as predefined colors if style doesn't - define anything else (darker colors are darkened 0x8000 -> 0x6666) */ -static GdkColor hardcoded_colors[16] = {{0, 0x0000, 0x0000, 0x0000}, - {0, 0x6666, 0x6666, 0x6666}, - {0, 0x6666, 0x0000, 0x0000}, - {0, 0x0000, 0x6666, 0x0000}, - {0, 0x0000, 0x0000, 0x6666}, - {0, 0x6666, 0x6666, 0x0000}, - {0, 0x6666, 0x0000, 0x6666}, - {0, 0x0000, 0x6666, 0x6666}, - {0, 0xffff, 0xffff, 0xffff}, - {0, 0xc000, 0xc000, 0xc000}, - {0, 0xffff, 0x0000, 0x0000}, - {0, 0x0000, 0xffff, 0x0000}, - {0, 0x0000, 0x0000, 0xffff}, - {0, 0xffff, 0xffff, 0x0000}, - {0, 0xffff, 0x0000, 0xffff}, - {0, 0x0000, 0xffff, 0xffff}}; - - -typedef struct { - GtkBorder radio_sizes; - GtkBorder cont_sizes; - GtkBorder num_buttons; - GtkBorder last_num_buttons; - - GdkColor default_color; -} HildonColorChooserStyleInfo; - - -typedef struct _HildonColorChooserDialogHSV HildonColorChooserDialogHSV; -typedef struct _HildonColorChooserDialogHSVClass HildonColorChooserDialogHSVClass; - - -struct _HildonColorChooserDialogHSV { - HildonColorChooserDialog parent; - - GtkWidget *hbox; - GtkWidget *vbox; - - GtkWidget *align_custom, *align_defined; - GtkWidget *area_custom, *area_defined; - GtkWidget *separator; - - GtkWidget *chooser; - - GdkColor *colors_custom, *colors_defined; - GdkGC **gc_array; - - gint selected; - - HildonColorChooserStyleInfo style_info; - - - gint has_style; - - GdkColor pending_color; - - - struct { - GConfClient *client; - } gconf_data; -}; - -struct _HildonColorChooserDialogHSVClass { - HildonColorChooserDialogClass parent_klass; -}; - - -#define HILDON_COLOR_CHOOSER_DIALOG_HSV(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), export_type(), HildonColorChooserDialogHSV)) -#define HILDON_COLOR_CHOOSER_DIALOG_HSV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), export_type(), HildonColorChooserDialogHSVClass)) - - -GtkType export_type(void); - - -static void hildon_color_chooser_dialog_hsv_init(HildonColorChooserDialogHSV *object); -static void hildon_color_chooser_dialog_hsv_class_init(HildonColorChooserDialogHSVClass *klass); - -static void hildon_color_chooser_dialog_hsv_size_request(GtkWidget *widget, GtkRequisition *req); -static void hildon_color_chooser_dialog_hsv_size_allocate(GtkWidget *widget, GtkAllocation *alloc); - -static void hildon_color_chooser_dialog_hsv_realize(GtkWidget *widget); -static void hildon_color_chooser_dialog_hsv_unrealize(GtkWidget *widget); - -static void hildon_color_chooser_dialog_hsv_style_set(GtkWidget *widget, GtkStyle *previous_style); - -static void hildon_color_chooser_dialog_hsv_show(GtkWidget *widget); -static void hildon_color_chooser_dialog_hsv_show_all(GtkWidget *widget); - -static gboolean hildon_color_chooser_dialog_hsv_key_press_event(GtkWidget *widget, GdkEventKey *event); -static gboolean hildon_color_chooser_dialog_hsv_key_release_event(GtkWidget *widget, GdkEventKey *event); - - -static void hildon_color_chooser_dialog_hsv_destroy(GtkObject *object); - - -static void hildon_color_chooser_dialog_hsv_set_color(HildonColorChooserDialog *dialog, GdkColor *color); - - -static gboolean hildon_color_chooser_dialog_hsv_area_expose(GtkWidget *widget, GdkEventExpose *event, gpointer data); - -static gboolean hildon_color_chooser_dialog_hsv_area_button_press(GtkWidget *widget, GdkEventButton *event, gpointer data); - - -static void hildon_color_chooser_dialog_hsv_chooser_color_changed(HildonColorChooser *chooser, GdkColor *color, gpointer data); - -static void hildon_color_chooser_dialog_hsv_chooser_insensitive_press(GtkWidget *widget, gpointer data); - - -static void hildon_color_chooser_dialog_hsv_refresh_style_info(HildonColorChooserDialogHSV *dialog); - -static void hildon_color_chooser_dialog_hsv_set_color_num(HildonColorChooserDialogHSV *dialog, gint num); - -static void hildon_color_chooser_dialog_hsv_ascii_hex_to_color(gchar *s, GdkColor *color); -static void hildon_color_chooser_dialog_hsv_color_to_ascii_hex(gchar *s, GdkColor *color); - - -GType export_type() -{ - static GType dialog_type = 0; - - if (!dialog_type) { - static const GTypeInfo dialog_info = - { - sizeof (HildonColorChooserDialogHSVClass), - NULL, - NULL, - (GClassInitFunc) hildon_color_chooser_dialog_hsv_class_init, - NULL, - NULL, - sizeof (HildonColorChooserDialogHSV), - 0, - (GInstanceInitFunc) hildon_color_chooser_dialog_hsv_init, - NULL - }; - - dialog_type = g_type_register_static (HILDON_TYPE_COLOR_CHOOSER_DIALOG, "HildonColorChooserDialogHSV", &dialog_info, 0); - } - - return dialog_type; -} - - -static void hildon_color_chooser_dialog_hsv_init(HildonColorChooserDialogHSV *object) -{ - if(!chooser_plugin) { - chooser_plugin = hildon_plugin_info_initialize(HILDON_TYPE_COLOR_CHOOSER, "hsv"); - } - - - gtk_dialog_set_has_separator(GTK_DIALOG(object), FALSE); - - gtk_window_set_title(GTK_WINDOW(object), _("ecdg_ti_colour_selector")); - - - object->chooser = hildon_plugin_info_construct_widget(chooser_plugin); - - object->hbox = gtk_hbox_new(FALSE, 0); - object->vbox = gtk_vbox_new(FALSE, 0); - - gtk_box_pack_start(GTK_BOX(object->hbox), object->chooser, TRUE, TRUE, 0); - gtk_box_pack_end(GTK_BOX(object->hbox), object->vbox, FALSE, FALSE, 0); - - - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(object)->vbox), object->hbox, TRUE, TRUE, 0); - - - object->align_custom = gtk_alignment_new(0.5, 1.0, 0.0, 0.0); - object->align_defined = gtk_alignment_new(0.5, 1.0, 0.0, 0.0); - - object->area_custom = gtk_drawing_area_new(); - object->area_defined = gtk_drawing_area_new(); - - - gtk_container_add(GTK_CONTAINER(object->align_custom), object->area_custom); - gtk_container_add(GTK_CONTAINER(object->align_defined), object->area_defined); - - - object->separator = gtk_hseparator_new(); - - - gtk_box_pack_start(GTK_BOX(object->vbox), object->align_defined, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(object->vbox), object->separator, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(object->vbox), object->align_custom, FALSE, FALSE, 0); - - - gtk_dialog_add_button(GTK_DIALOG(object), _("ecdg_bd_colour_selector_ok"), GTK_RESPONSE_OK); - gtk_dialog_add_button(GTK_DIALOG(object), _("ecdg_bd_colour_selector_cancel"), GTK_RESPONSE_CANCEL); - gtk_dialog_set_default_response (GTK_DIALOG (object), GTK_RESPONSE_OK); - - - g_signal_connect(G_OBJECT(object->chooser), "insensitive-press", G_CALLBACK(hildon_color_chooser_dialog_hsv_chooser_insensitive_press), object); - - - g_signal_connect(G_OBJECT(object->area_custom), "expose-event", G_CALLBACK(hildon_color_chooser_dialog_hsv_area_expose), object); - g_signal_connect(G_OBJECT(object->area_defined), "expose-event", G_CALLBACK(hildon_color_chooser_dialog_hsv_area_expose), object); - - g_signal_connect(G_OBJECT(object->area_custom), "button-press-event", G_CALLBACK(hildon_color_chooser_dialog_hsv_area_button_press), object); - g_signal_connect(G_OBJECT(object->area_defined), "button-press-event", G_CALLBACK(hildon_color_chooser_dialog_hsv_area_button_press), object); - - gtk_widget_add_events(object->area_custom, GDK_BUTTON_PRESS_MASK); - gtk_widget_add_events(object->area_defined, GDK_BUTTON_PRESS_MASK); - - - object->selected = 0; - - - g_signal_connect(G_OBJECT(object->chooser), "color-changed", G_CALLBACK(hildon_color_chooser_dialog_hsv_chooser_color_changed), object); - - - object->gconf_data.client = gconf_client_get_default(); - - - memset(&object->style_info, 0, sizeof(HildonColorChooserStyleInfo)); - - - object->colors_custom = NULL; - object->colors_defined = NULL; - - object->gc_array = NULL; - - - object->has_style = 0; -} - -static void hildon_color_chooser_dialog_hsv_class_init(HildonColorChooserDialogHSVClass *klass) -{ - GtkWidgetClass *widget_klass = GTK_WIDGET_CLASS(klass); - GtkObjectClass *object_klass = GTK_OBJECT_CLASS(klass); - HildonColorChooserDialogClass *dialog_klass = HILDON_COLOR_CHOOSER_DIALOG_CLASS(klass); - gchar tmp[32]; - gint i; - - - widget_klass->size_request = hildon_color_chooser_dialog_hsv_size_request; - widget_klass->size_allocate = hildon_color_chooser_dialog_hsv_size_allocate; - - widget_klass->realize = hildon_color_chooser_dialog_hsv_realize; - widget_klass->unrealize = hildon_color_chooser_dialog_hsv_unrealize; - - widget_klass->style_set = hildon_color_chooser_dialog_hsv_style_set; - - widget_klass->show = hildon_color_chooser_dialog_hsv_show; - widget_klass->show_all = hildon_color_chooser_dialog_hsv_show_all; - - widget_klass->key_press_event = hildon_color_chooser_dialog_hsv_key_press_event; - widget_klass->key_release_event = hildon_color_chooser_dialog_hsv_key_release_event; - - - object_klass->destroy = hildon_color_chooser_dialog_hsv_destroy; - - - dialog_klass->set_color = hildon_color_chooser_dialog_hsv_set_color; - - - parent_klass = g_type_class_peek_parent(klass); - - - gtk_widget_class_install_style_property(widget_klass, - g_param_spec_boxed("container_sizes", - "Container sizes", - "Container specific sizes", - GTK_TYPE_BORDER, - G_PARAM_READABLE)); - - gtk_widget_class_install_style_property(widget_klass, - g_param_spec_boxed("radio_sizes", - "Color radio sizes", - "Color radio specific sizes", - GTK_TYPE_BORDER, - G_PARAM_READABLE)); - - gtk_widget_class_install_style_property(widget_klass, - g_param_spec_boxed("num_buttons", - "Number of buttons", - "Number of color store buttons", - GTK_TYPE_BORDER, - G_PARAM_READABLE)); - - - gtk_widget_class_install_style_property(widget_klass, - g_param_spec_boxed("default_color", "Default color", - "Default color for nonpainted custom colors", - GDK_TYPE_COLOR, - G_PARAM_READABLE)); - - - for(i = 0; i < 32; i++) { - memset(tmp, 0, 32); - g_snprintf(tmp, 32, "defined_color%d", i); - - gtk_widget_class_install_style_property(widget_klass, - g_param_spec_boxed(tmp, "Defined color", - "Pre-defined colors for the dialog", - GDK_TYPE_COLOR, - G_PARAM_READABLE)); - } -} - - -static void hildon_color_chooser_dialog_hsv_size_request(GtkWidget *widget, GtkRequisition *req) -{ - HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(widget); - - - gtk_container_set_border_width(GTK_CONTAINER(dialog->hbox), dialog->style_info.cont_sizes.left); - - gtk_box_set_spacing(GTK_BOX(dialog->hbox), dialog->style_info.cont_sizes.right); - gtk_box_set_spacing(GTK_BOX(dialog->vbox), dialog->style_info.cont_sizes.top); - gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(widget)->vbox), dialog->style_info.cont_sizes.bottom); - - - gtk_widget_set_size_request(dialog->area_custom, - (dialog->style_info.radio_sizes.left + 2*dialog->style_info.radio_sizes.bottom)*(dialog->style_info.num_buttons.top) + - (dialog->style_info.num_buttons.top-1)*dialog->style_info.radio_sizes.top, - (dialog->style_info.radio_sizes.right + 2*dialog->style_info.radio_sizes.bottom)*(dialog->style_info.num_buttons.bottom) + - (dialog->style_info.num_buttons.bottom-1)*dialog->style_info.radio_sizes.top); - gtk_widget_set_size_request(dialog->area_defined, - (dialog->style_info.radio_sizes.left + 2*dialog->style_info.radio_sizes.bottom)*(dialog->style_info.num_buttons.left) + - (dialog->style_info.num_buttons.left-1)*dialog->style_info.radio_sizes.top, - (dialog->style_info.radio_sizes.right + 2*dialog->style_info.radio_sizes.bottom)*(dialog->style_info.num_buttons.right) + - (dialog->style_info.num_buttons.right-1)*dialog->style_info.radio_sizes.top); - - - GTK_WIDGET_CLASS(parent_klass)->size_request(widget, req); -} - -static void hildon_color_chooser_dialog_hsv_size_allocate(GtkWidget *widget, GtkAllocation *alloc) -{ - HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(widget); - GdkRectangle rect; - int i, tmp, tmp2; - - - GTK_WIDGET_CLASS(parent_klass)->size_allocate(widget, alloc); - - - if(GTK_WIDGET_REALIZED(widget)) { - tmp = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right); - tmp2 = (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom); - - for(i = 0; i < tmp; i++) { - rect.x = ((i % dialog->style_info.num_buttons.left) * (dialog->style_info.radio_sizes.left + dialog->style_info.radio_sizes.top + - 2*dialog->style_info.radio_sizes.bottom)) + dialog->style_info.radio_sizes.bottom; - rect.y = ((i / dialog->style_info.num_buttons.left) * (dialog->style_info.radio_sizes.right + dialog->style_info.radio_sizes.top + - 2*dialog->style_info.radio_sizes.bottom)) + dialog->style_info.radio_sizes.bottom; - rect.width = dialog->style_info.radio_sizes.left; - rect.height = dialog->style_info.radio_sizes.right; - - gdk_gc_set_clip_rectangle(dialog->gc_array[i], &rect); - } - - for(i = 0; i < tmp2; i++) { - rect.x = ((i % dialog->style_info.num_buttons.top) * (dialog->style_info.radio_sizes.left + dialog->style_info.radio_sizes.top + - 2*dialog->style_info.radio_sizes.bottom)) + dialog->style_info.radio_sizes.bottom; - rect.y = ((i / dialog->style_info.num_buttons.top) * (dialog->style_info.radio_sizes.right + dialog->style_info.radio_sizes.top + - 2*dialog->style_info.radio_sizes.bottom)) + dialog->style_info.radio_sizes.bottom; - rect.width = dialog->style_info.radio_sizes.left; - rect.height = dialog->style_info.radio_sizes.right; - - gdk_gc_set_clip_rectangle(dialog->gc_array[i + tmp], &rect); - } - } -} - - -static void hildon_color_chooser_dialog_hsv_realize(GtkWidget *widget) -{ - HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(widget); - GdkRectangle rect; - int i, tmp, tmp2; - - - GTK_WIDGET_CLASS(parent_klass)->realize(widget); - - - tmp = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right) + - (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom); - - for(i = 0; i < tmp; i++) { - dialog->gc_array[i] = gdk_gc_new(widget->window); - } - - - - tmp = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right); - tmp2 = (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom); - - for(i = 0; i < tmp; i++) { - gdk_gc_set_rgb_fg_color(dialog->gc_array[i], &dialog->colors_defined[i]); - - rect.x = ((i % dialog->style_info.num_buttons.left) * (dialog->style_info.radio_sizes.left + dialog->style_info.radio_sizes.top + - 2*dialog->style_info.radio_sizes.bottom)) + dialog->style_info.radio_sizes.bottom; - rect.y = ((i / dialog->style_info.num_buttons.left) * (dialog->style_info.radio_sizes.right + dialog->style_info.radio_sizes.top + - 2*dialog->style_info.radio_sizes.bottom)) + dialog->style_info.radio_sizes.bottom; - rect.width = dialog->style_info.radio_sizes.left; - rect.height = dialog->style_info.radio_sizes.right; - - gdk_gc_set_clip_rectangle(dialog->gc_array[i], &rect); - } - - for(i = 0; i < tmp2; i++) { - gdk_gc_set_rgb_fg_color(dialog->gc_array[i + tmp], &dialog->colors_custom[i]); - - rect.x = ((i % dialog->style_info.num_buttons.top) * (dialog->style_info.radio_sizes.left + dialog->style_info.radio_sizes.top + - 2*dialog->style_info.radio_sizes.bottom)) + dialog->style_info.radio_sizes.bottom; - rect.y = ((i / dialog->style_info.num_buttons.top) * (dialog->style_info.radio_sizes.right + dialog->style_info.radio_sizes.top + - 2*dialog->style_info.radio_sizes.bottom)) + dialog->style_info.radio_sizes.bottom; - rect.width = dialog->style_info.radio_sizes.left; - rect.height = dialog->style_info.radio_sizes.right; - - gdk_gc_set_clip_rectangle(dialog->gc_array[i + tmp], &rect); - } -} - -static void hildon_color_chooser_dialog_hsv_unrealize(GtkWidget *widget) -{ - HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(widget); - int i, tmp; - - - tmp = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right) + - (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom); - - for(i = 0; i < tmp; i++) { - g_object_unref(dialog->gc_array[i]); - } - - - GTK_WIDGET_CLASS(parent_klass)->unrealize(widget); -} - - -static void hildon_color_chooser_dialog_hsv_style_set(GtkWidget *widget, GtkStyle *previous_style) -{ - HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(widget); - GdkColor *tmpcolor; - gchar tmp[32], key[128], *val; - int i, tmpn, setcolor = 0; - - - if(!dialog->has_style) - setcolor = 1; - - dialog->has_style = 1; - - - gtk_widget_style_get(widget, "default_color", &tmpcolor, NULL); - if(tmpcolor) { - dialog->style_info.default_color = *tmpcolor; - } else { - dialog->style_info.default_color.red = 0x0000; - dialog->style_info.default_color.green = 0x0000; - dialog->style_info.default_color.blue = 0x0000; - dialog->style_info.default_color.pixel = 0x00000000; - } - - - hildon_color_chooser_dialog_hsv_refresh_style_info(dialog); - - - if(memcmp(&dialog->style_info.num_buttons, &dialog->style_info.last_num_buttons, sizeof(GtkBorder))) { - if(dialog->colors_custom) { - g_free(dialog->colors_custom); - } if(dialog->colors_defined) { - g_free(dialog->colors_defined); - } if(dialog->gc_array) { - if(GTK_WIDGET_REALIZED(widget)) { - tmpn = (dialog->style_info.last_num_buttons.left * dialog->style_info.last_num_buttons.right) + - (dialog->style_info.last_num_buttons.top * dialog->style_info.last_num_buttons.bottom); - - for(i = 0; i < tmpn; i++) { - g_object_unref(dialog->gc_array[i]); - } - } - - g_free(dialog->gc_array); - } - - dialog->colors_custom = (GdkColor *)g_malloc0(sizeof(GdkColor) * (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom)); - dialog->colors_defined = (GdkColor *)g_malloc0(sizeof(GdkColor) * (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right)); - - - tmpn = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right) + - (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom); - dialog->gc_array = (GdkGC **)g_malloc0(sizeof(GdkGC *) * tmpn); - - - if(dialog->gconf_data.client) { - for(i = 0; i < (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom); i++) { - memset(key, 0, 128); - g_snprintf(key, 128, "/system/osso/af/color_chooser/custom_color%d", i); - val = gconf_client_get_string(dialog->gconf_data.client, key, NULL); - if(val) { - hildon_color_chooser_dialog_hsv_ascii_hex_to_color(val, &dialog->colors_custom[i]); - g_free(val); - } else { - dialog->colors_custom[i] = dialog->style_info.default_color; - } - } - } else { - for(i = 0; i < (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom); i++) { - dialog->colors_custom[i] = dialog->style_info.default_color; - } - } - } - - - tmpn = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right); - - hildon_color_chooser_set_color(HILDON_COLOR_CHOOSER(dialog->chooser), - (dialog->selected < tmpn) ? &dialog->colors_defined[dialog->selected] : &dialog->colors_custom[dialog->selected - tmpn]); - - - for(i = 0; i < (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right); i++) { - memset(tmp, 0, 32); - g_snprintf(tmp, 32, "defined_color%d", i); - - gtk_widget_style_get(widget, tmp, &tmpcolor, NULL); - - if(tmpcolor) { - dialog->colors_defined[i] = *tmpcolor; - } else { - if(i < 16) { - dialog->colors_defined[i] = hardcoded_colors[i]; - } else { /* fallback to prevent segfault */ - dialog->colors_defined[i].red = 0x0000; - dialog->colors_defined[i].green = 0x0000; - dialog->colors_defined[i].blue = 0x0000; - dialog->colors_defined[i].pixel = 0x00000000; - } - } - } - - - if(GTK_WIDGET_REALIZED(widget)) { - for(i = 0; i < (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right); i++) { - gdk_gc_set_rgb_fg_color(dialog->gc_array[i], &dialog->colors_defined[i]); - } - } - - - if(setcolor) - hildon_color_chooser_dialog_hsv_set_color(HILDON_COLOR_CHOOSER_DIALOG(dialog), &dialog->pending_color); - - - gtk_widget_queue_resize(widget); - - - GTK_WIDGET_CLASS(parent_klass)->style_set(widget, previous_style); -} - - -static void hildon_color_chooser_dialog_hsv_show(GtkWidget *widget) -{ - HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(widget); - - - gtk_widget_show(dialog->hbox); - gtk_widget_show(dialog->vbox); - - gtk_widget_show(dialog->chooser); - - gtk_widget_show(dialog->align_custom); - gtk_widget_show(dialog->align_defined); - - gtk_widget_show(dialog->separator); - - gtk_widget_show(dialog->area_custom); - gtk_widget_show(dialog->area_defined); - - - GTK_WIDGET_CLASS(parent_klass)->show(widget); -} - -static void hildon_color_chooser_dialog_hsv_show_all(GtkWidget *widget) -{ - hildon_color_chooser_dialog_hsv_show(widget); -} - - -static gboolean hildon_color_chooser_dialog_hsv_key_press_event(GtkWidget *widget, GdkEventKey *event) -{ - HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(widget); - int tmp, tot, sel; - - - if(event->keyval == HILDON_HARDKEY_UP || event->keyval == HILDON_HARDKEY_DOWN || - event->keyval == HILDON_HARDKEY_LEFT || event->keyval == HILDON_HARDKEY_RIGHT) { - tmp = (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom); - tot = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right) + tmp; - - switch(event->keyval) { - case HILDON_HARDKEY_UP: - if(dialog->selected >= dialog->style_info.num_buttons.top) { - if(dialog->selected - dialog->style_info.num_buttons.left >= tmp) { - sel = dialog->selected - dialog->style_info.num_buttons.left; - } else { - sel = dialog->selected - dialog->style_info.num_buttons.top; - } - - hildon_color_chooser_dialog_hsv_set_color_num(dialog, sel); - } - break; - case HILDON_HARDKEY_DOWN: - if(dialog->selected < tot - dialog->style_info.num_buttons.left) { - if(dialog->selected < tmp) { - sel = dialog->selected + dialog->style_info.num_buttons.top; - } else { - sel = dialog->selected + dialog->style_info.num_buttons.left; - } - - hildon_color_chooser_dialog_hsv_set_color_num(dialog, sel); - } - break; - case HILDON_HARDKEY_LEFT: - if((dialog->selected < tmp ? (dialog->selected % dialog->style_info.num_buttons.top) : ((dialog->selected - tmp) % dialog->style_info.num_buttons.left)) > 0) { - sel = dialog->selected - 1; - - hildon_color_chooser_dialog_hsv_set_color_num(dialog, sel); - } - break; - case HILDON_HARDKEY_RIGHT: - if((dialog->selected < tmp) ? (dialog->selected % dialog->style_info.num_buttons.top < dialog->style_info.num_buttons.top - 1) : - ((dialog->selected - tmp) % dialog->style_info.num_buttons.left < dialog->style_info.num_buttons.left - 1)) { - sel = dialog->selected + 1; - - hildon_color_chooser_dialog_hsv_set_color_num(dialog, sel); - } - break; - default: - break; - } - - return FALSE; - } - - return GTK_WIDGET_CLASS(parent_klass)->key_press_event(widget, event); -} - -static gboolean hildon_color_chooser_dialog_hsv_key_release_event(GtkWidget *widget, GdkEventKey *event) -{ - if(event->keyval == HILDON_HARDKEY_UP || event->keyval == HILDON_HARDKEY_DOWN || - event->keyval == HILDON_HARDKEY_LEFT || event->keyval == HILDON_HARDKEY_RIGHT) { - return FALSE; - } - - return GTK_WIDGET_CLASS(parent_klass)->key_press_event(widget, event); -} - - -static void hildon_color_chooser_dialog_hsv_destroy(GtkObject *object) -{ - HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(object); - gchar key[128], color[13]; - int i, tmp; - - - if(dialog->gconf_data.client) { - memset(color, 0, 13); - - tmp = (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom); - - for(i = 0; i < tmp; i++) { - memset(key, 0, 128); - g_snprintf(key, 128, "/system/osso/af/color_chooser/custom_color%d", i); - hildon_color_chooser_dialog_hsv_color_to_ascii_hex(color, &dialog->colors_custom[i]); - gconf_client_set_string(dialog->gconf_data.client, key, color, NULL); - } - - g_object_unref(dialog->gconf_data.client); - dialog->gconf_data.client = NULL; - } - - - if(dialog->gc_array) { - g_free(dialog->gc_array); - dialog->gc_array = NULL; - } if(dialog->colors_defined) { - g_free(dialog->colors_defined); - dialog->colors_defined = NULL; - } if(dialog->colors_custom) { - g_free(dialog->colors_custom); - dialog->colors_custom = NULL; - } - - - GTK_OBJECT_CLASS(parent_klass)->destroy(object); -} - - -static void hildon_color_chooser_dialog_hsv_set_color(HildonColorChooserDialog *dialog, GdkColor *color) -{ - HildonColorChooserDialogHSV *dialog_hsv = HILDON_COLOR_CHOOSER_DIALOG_HSV(dialog); - int i, found = -1, tmp, tmp2; - - - if(!dialog_hsv->has_style) { - dialog_hsv->pending_color = *color; - return; - } - - - tmp = (dialog_hsv->style_info.num_buttons.left * dialog_hsv->style_info.num_buttons.right); - tmp2 = (dialog_hsv->style_info.num_buttons.top * dialog_hsv->style_info.num_buttons.bottom); - - for(i = 0; i < tmp; i++) { - if(dialog_hsv->colors_defined[i].red == color->red && - dialog_hsv->colors_defined[i].green == color->green && - dialog_hsv->colors_defined[i].blue == color->blue) { - found = i; - break; - } - } - - if(found == -1) { - for(i = 0; i < tmp2; i++) { - if(dialog_hsv->colors_custom[i].red == color->red && - dialog_hsv->colors_custom[i].green == color->green && - dialog_hsv->colors_custom[i].blue == color->blue) { - found = i + tmp; - break; - } - } - } - - - if(found == -1) { - dialog_hsv->colors_custom[tmp2-1] = *color; - if(GTK_WIDGET_REALIZED(GTK_WIDGET(dialog))) { - gdk_gc_set_rgb_fg_color(dialog_hsv->gc_array[tmp2-1], color); - } - hildon_color_chooser_dialog_hsv_set_color_num(dialog_hsv, tmp2-1); - } else { - hildon_color_chooser_dialog_hsv_set_color_num(dialog_hsv, found); - } -} - - -static gboolean hildon_color_chooser_dialog_hsv_area_expose(GtkWidget *widget, GdkEventExpose *event, gpointer data) -{ - HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(data); - int i, num_selected, tot_w, tot_h, spacing, brd, x, y; - GdkGC **start_gc; - int tmp, w, h; - - - tmp = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right); - - if(widget == dialog->area_custom) { - num_selected = dialog->selected - tmp; - start_gc = dialog->gc_array + tmp; - tmp = (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom); - w = dialog->style_info.num_buttons.top; h = dialog->style_info.num_buttons.bottom; - } else { /* widget == dialog->area_defined */ - num_selected = dialog->selected; - start_gc = dialog->gc_array; - w = dialog->style_info.num_buttons.left; h = dialog->style_info.num_buttons.right; - } - - spacing = dialog->style_info.radio_sizes.top; - brd = dialog->style_info.radio_sizes.bottom; - tot_w = dialog->style_info.radio_sizes.left + 2*brd; - tot_h = dialog->style_info.radio_sizes.right + 2*brd; - - - for(i = 0; i < tmp; i++) { - x = ((i % w) * (tot_w + spacing)); - y = ((i / w) * (tot_h + spacing)); - - gdk_draw_rectangle(widget->window, - widget->style->black_gc, - TRUE, - (i == num_selected) ? x : x + 2, - (i == num_selected) ? y : y + 2, - (i == num_selected) ? tot_w : tot_w - 4, - (i == num_selected) ? tot_h : tot_h - 4); - - gdk_draw_rectangle(widget->window, - widget->style->white_gc, - TRUE, - x + 3, - y + 3, - tot_w - 6, - tot_h - 6); - - gdk_draw_rectangle(widget->window, - start_gc [i], - TRUE, - x + 3 + 1, - y + 3 + 1, - tot_w - 6 - 2, - tot_h - 6 - 2); - -// gtk_paint_box(gtk_widget_get_style(GTK_WIDGET(dialog)), widget->window, (i == num_selected) ? GTK_STATE_SELECTED : GTK_STATE_NORMAL, -// (i == num_selected) ? GTK_SHADOW_IN : GTK_SHADOW_OUT, &event->area, GTK_WIDGET(dialog), "color-radio", x, y, tot_w, tot_h); - //} - - //gdk_draw_rectangle(widget->window, start_gc[i], TRUE, event->area.x, event->area.y, event->area.width, event->area.height); - } - - - return FALSE; -} - - -static gboolean hildon_color_chooser_dialog_hsv_area_button_press(GtkWidget *widget, GdkEventButton *event, gpointer data) -{ - HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(data); - int i, hskip, vskip, brd, selection = -1; - int x, y, tmp, tmp2, w; - - - x = event->x; - y = event->y; - - - brd = dialog->style_info.radio_sizes.bottom; - hskip = dialog->style_info.radio_sizes.left + dialog->style_info.radio_sizes.top + 2*brd; - vskip = dialog->style_info.radio_sizes.right + dialog->style_info.radio_sizes.top + 2*brd; - - - tmp = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right); - tmp2 = (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom); - - - if(widget == dialog->area_defined) { - w = dialog->style_info.num_buttons.left; - - for(i = 0; i < tmp; i++) { - if(x >= hskip*(i % w) + brd && x < hskip*(i % w) + brd + dialog->style_info.radio_sizes.left && - y >= vskip*(i / w) + brd && y < hskip*(i / w) + brd + dialog->style_info.radio_sizes.right) { - selection = i; - break; - } - } - } else { - w = dialog->style_info.num_buttons.top; - for(i = 0; i < tmp2; i++) { - if(x >= hskip*(i % w) + brd && x < hskip*(i % w) + brd + dialog->style_info.radio_sizes.left && - y >= vskip*(i / w) + brd && y < hskip*(i / w) + brd + dialog->style_info.radio_sizes.right) { - selection = i + tmp; - break; - } - } - } - - - if(selection != -1) { - hildon_color_chooser_dialog_hsv_set_color_num(dialog, selection); - } - - - return FALSE; -} - - -static void hildon_color_chooser_dialog_hsv_chooser_color_changed(HildonColorChooser *chooser, GdkColor *color, gpointer data) -{ - HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(data); - HildonColorChooserDialog *dia = HILDON_COLOR_CHOOSER_DIALOG(data); - char key[128], color_str[13]; - int tmp; - - - dia->color = *color; - - - tmp = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right); - - - if(dialog->selected >= tmp) { - dialog->colors_custom[dialog->selected - tmp] = *color; - - gdk_gc_set_rgb_fg_color(dialog->gc_array[dialog->selected], &dialog->colors_custom[dialog->selected - tmp]); - - gtk_widget_queue_draw(dialog->area_custom); - - - if(dialog->gconf_data.client) { - memset(key, 0, 128); - memset(color_str, 0, 13); - g_snprintf(key, 128, "/system/osso/af/color_chooser/custom_color%d", dialog->selected - tmp); - hildon_color_chooser_dialog_hsv_color_to_ascii_hex(color_str, &dialog->colors_custom[dialog->selected - tmp]); - gconf_client_set_string(dialog->gconf_data.client, key, color_str, NULL); - } - } -} - - -static void hildon_color_chooser_dialog_hsv_chooser_insensitive_press(GtkWidget *widget, gpointer data) -{ - hildon_banner_show_information(widget, NULL, _("ecdg_ib_colour_selector_predefined")); -} - - /* function has size defaults */ -static void hildon_color_chooser_dialog_hsv_refresh_style_info(HildonColorChooserDialogHSV *dialog) -{ - GtkBorder *tmp1, *tmp2, *tmp3; - - - gtk_widget_style_get(GTK_WIDGET(dialog), "container_sizes", &tmp1, - "radio_sizes", &tmp2, "num_buttons", &tmp3, NULL); - - - dialog->style_info.last_num_buttons = dialog->style_info.num_buttons; - - - if(tmp1) { - dialog->style_info.cont_sizes = *tmp1; - g_free(tmp1); - } else { - dialog->style_info.cont_sizes.left = 0; - dialog->style_info.cont_sizes.right = 8; - dialog->style_info.cont_sizes.top = 4; - dialog->style_info.cont_sizes.bottom = 0; - } - - if(tmp2) { - dialog->style_info.radio_sizes = *tmp2; - g_free(tmp2); - } else { - dialog->style_info.radio_sizes.left = 16; - dialog->style_info.radio_sizes.right = 16; - dialog->style_info.radio_sizes.top = 4; - dialog->style_info.radio_sizes.bottom = 2; - } - - if(tmp3) { - dialog->style_info.num_buttons = *tmp3; - g_free(tmp3); - } else { - dialog->style_info.num_buttons.left = 8; - dialog->style_info.num_buttons.right = 2; - dialog->style_info.num_buttons.top = 8; - dialog->style_info.num_buttons.bottom = 2; - } -} - - -static void hildon_color_chooser_dialog_hsv_set_color_num(HildonColorChooserDialogHSV *dialog, gint num) -{ - HildonColorChooserDialog *dia = HILDON_COLOR_CHOOSER_DIALOG(dialog); - int tmp; - - - tmp = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right); - - - if(num < tmp) { - gtk_widget_set_sensitive(dialog->chooser, FALSE); - } else { - gtk_widget_set_sensitive(dialog->chooser, TRUE); - } - - - dialog->selected = num; - - gtk_widget_queue_draw(dialog->area_custom); - gtk_widget_queue_draw(dialog->area_defined); - - dia->color = (num < tmp) ? dialog->colors_defined[num] : dialog->colors_custom[num - tmp]; - - hildon_color_chooser_set_color(HILDON_COLOR_CHOOSER(dialog->chooser), (num < tmp) ? &dialog->colors_defined[num] : &dialog->colors_custom[num - tmp]); -} - - -static void hildon_color_chooser_dialog_hsv_ascii_hex_to_color(gchar *s, GdkColor *color) -{ - int vals[12], i; - - - for(i = 0; i < 12; i++) { - if(s[i] >= '0' && s[i] <= '9') { - vals[i] = s[i] - 0x30; - } else if(s[i] >= 'a' && s[i] <= 'f') { - vals[i] = s[i] - 0x57; - } else { - vals[i] = 0; - } - } - - - color->red = (vals[0] << 12) | (vals[1] << 8) | (vals[2 ] << 4) | (vals[3 ] ); - color->green = (vals[4] << 12) | (vals[5] << 8) | (vals[6 ] << 4) | (vals[7 ] ); - color->blue = (vals[8] << 12) | (vals[9] << 8) | (vals[10] << 4) | (vals[11] ); -} - -static void hildon_color_chooser_dialog_hsv_color_to_ascii_hex(gchar *s, GdkColor *color) -{ - g_snprintf(s, 13, "%x%x%x%x%x%x%x%x%x%x%x%x", - (color->red >> 12) & 0xf, (color->red >> 8) & 0xf, - (color->red >> 4) & 0xf, (color->red ) & 0xf, - (color->green >> 12) & 0xf, (color->green >> 8) & 0xf, - (color->green >> 4) & 0xf, (color->green ) & 0xf, - (color->blue >> 12) & 0xf, (color->blue >> 8) & 0xf, - (color->blue >> 4) & 0xf, (color->blue ) & 0xf); -} diff --git a/hildon-widgets-plugins/hildon-color-chooser-hsv.c b/hildon-widgets-plugins/hildon-color-chooser-hsv.c deleted file mode 100644 index 9804f73..0000000 --- a/hildon-widgets-plugins/hildon-color-chooser-hsv.c +++ /dev/null @@ -1,1099 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Author: Kuisma Salonen - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include - -#include - - -const char *parent_name = "HildonColorChooser"; -const char *plugin_name = "HSV color chooser"; - -GType export_type(void); - - -typedef struct { - HildonColorChooser parent; - - GtkAllocation hba; - GtkAllocation spa; - - unsigned short currhue; - unsigned short currsat; - unsigned short currval; - - int mousestate; - gboolean mousein; - - - GdkWindow *event_window; - - GdkPixbuf *dimmed_plane; - GdkPixbuf *dimmed_bar; - - struct { - unsigned short last_expose_hue; - - GTimeVal last_expose_time; - - int expose_queued; - } expose_info; -} HildonColorChooserHSV; - -typedef struct { - HildonColorChooserClass parent; -} HildonColorChooserHSVClass; - - -#define HILDON_COLOR_CHOOSER_HSV(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), export_type(), HildonColorChooserHSV)) -#define HILDON_COLOR_CHOOSER_HSV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), export_type(), HildonColorChooserHSVClass)) - - -static HildonColorChooserClass *parent_class = NULL; - - - /* "crosshair" is hardcoded for now */ -static gchar crosshair[64] = { 0, 0, 0, 2, 2, 0, 0, 0, - 0, 2, 2, 3, 3, 2, 2, 0, - 0, 2, 3, 0, 0, 3, 2, 0, - 2, 3, 0, 0, 0, 0, 3, 2, - 2, 3, 0, 0, 0, 0, 3, 2, - 0, 2, 3, 0, 0, 3, 2, 0, - 0, 2, 2, 3, 3, 2, 2, 0, - 0, 0, 0, 2, 2, 0, 0, 0}; - - -static void hildon_color_chooser_hsv_init(HildonColorChooserHSV *sel); -static void hildon_color_chooser_hsv_class_init(HildonColorChooserHSVClass *klass); - -static void hildon_color_chooser_hsv_dispose(HildonColorChooserHSV *sel); - -static void hildon_color_chooser_hsv_size_request(GtkWidget *widget, GtkRequisition *req); -static void hildon_color_chooser_hsv_size_allocate(GtkWidget *widget, GtkAllocation *alloc); - -static void hildon_color_chooser_hsv_realize(GtkWidget *widget); - -static void hildon_color_chooser_hsv_map(GtkWidget *widget); -static void hildon_color_chooser_hsv_unmap(GtkWidget *widget); - -static gboolean hildon_color_chooser_hsv_expose(GtkWidget *widget, GdkEventExpose *event); - -static gboolean hildon_color_chooser_button_press(GtkWidget *widget, GdkEventButton *event); -static gboolean hildon_color_chooser_button_release(GtkWidget *widget, GdkEventButton *event); -static gboolean hildon_color_chooser_pointer_motion(GtkWidget *widget, GdkEventMotion *event); - -static void hildon_color_chooser_hsv_set_color(HildonColorChooser *sel, GdkColor *color); - - -static void internal_get_border(GtkWidget *w, char *name, GtkBorder *b); -static void _internal_init_borders(GtkWidget *w, GtkBorder *inner, GtkBorder *outer); - -static void internal_invoke_color_changed(HildonColorChooserHSV *sel); - - -inline void inline_clip_to_alloc(void *s, GtkAllocation *a); - -inline void inline_sub_times(GTimeVal *result, GTimeVal *greater, GTimeVal *lesser); - -inline void inline_limited_expose(HildonColorChooserHSV *sel); - -inline void inline_draw_hue_bar(GtkWidget *widget, int x, int y, int w, int h, int sy, int sh); -inline void inline_draw_hue_bar_dimmed(GtkWidget *widget, int x, int y, int w, int h, int sy, int sh); - -inline void inline_draw_sv_plane(HildonColorChooserHSV *sel, int x, int y, int w, int h); -inline void inline_draw_sv_plane_dimmed(HildonColorChooserHSV *sel, int x, int y, int w, int h); - -inline void inline_draw_crosshair(unsigned char *buf, int x, int y, int w, int h); - - -inline void inline_h2rgb(unsigned short hue, unsigned long *rgb); - - -static gboolean hildon_color_chooser_hsv_expose_timer(gpointer data); - - -GType export_type() -{ - static GType chooser_type = 0; - - if (!chooser_type) { - static const GTypeInfo chooser_info = - { - sizeof (HildonColorChooserHSVClass), - NULL, - NULL, - (GClassInitFunc) hildon_color_chooser_hsv_class_init, - NULL, - NULL, - sizeof (HildonColorChooserHSV), - 0, - (GInstanceInitFunc) hildon_color_chooser_hsv_init, - NULL - }; - - chooser_type = g_type_register_static (HILDON_TYPE_COLOR_CHOOSER, - "HildonColorChooserHSV", - &chooser_info, 0); - } - - return chooser_type; -} - -static void hildon_color_chooser_hsv_init(HildonColorChooserHSV *sel) -{ - GTK_WIDGET_SET_FLAGS (sel, GTK_NO_WINDOW); - - - sel->currhue = 0; - sel->currsat = 0; - sel->currval = 0; - - sel->mousestate = 0; - sel->mousein = FALSE; - - - g_get_current_time(&sel->expose_info.last_expose_time); - - sel->expose_info.last_expose_hue = sel->currhue; - sel->expose_info.expose_queued = 0; - - sel->dimmed_plane = NULL; - sel->dimmed_bar = NULL; -} - -static void hildon_color_chooser_hsv_class_init(HildonColorChooserHSVClass *klass) -{ - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); - GObjectClass *object_class = G_OBJECT_CLASS(klass); - - HildonColorChooserClass *selection_class = HILDON_COLOR_CHOOSER_CLASS(klass); - - - parent_class = g_type_class_peek_parent(klass); - - - object_class->dispose = (gpointer) hildon_color_chooser_hsv_dispose; - - widget_class->size_request = hildon_color_chooser_hsv_size_request; - widget_class->size_allocate = hildon_color_chooser_hsv_size_allocate; - - widget_class->realize = hildon_color_chooser_hsv_realize; - - widget_class->map = hildon_color_chooser_hsv_map; - widget_class->unmap = hildon_color_chooser_hsv_unmap; - - widget_class->expose_event = hildon_color_chooser_hsv_expose; - - widget_class->button_press_event = hildon_color_chooser_button_press; - widget_class->button_release_event = hildon_color_chooser_button_release; - widget_class->motion_notify_event = hildon_color_chooser_pointer_motion; - - - selection_class->set_color = hildon_color_chooser_hsv_set_color; - - - gtk_widget_class_install_style_property(widget_class, - g_param_spec_boxed("inner_size", - "Inner sizes", - "Sizes of SV plane, H bar and spacing", - GTK_TYPE_BORDER, - G_PARAM_READABLE)); - gtk_widget_class_install_style_property(widget_class, - g_param_spec_boxed("graphic_border", - "Graphical borders", - "Size of graphical border", - GTK_TYPE_BORDER, - G_PARAM_READABLE)); -} - - -static void hildon_color_chooser_hsv_dispose(HildonColorChooserHSV *sel) -{ - if (sel->dimmed_bar != NULL) { - g_object_unref (sel->dimmed_bar); - sel->dimmed_bar = NULL; - } - - if (sel->dimmed_plane != NULL) { - g_object_unref (sel->dimmed_plane); - sel->dimmed_plane = NULL; - } - - G_OBJECT_CLASS(parent_class)->dispose(sel); -} - -static void hildon_color_chooser_hsv_size_request(GtkWidget *widget, GtkRequisition *req) -{ - GtkBorder inner, outer; - - - _internal_init_borders(widget, &inner, &outer); - - - req->width = inner.left + inner.top + inner.bottom + outer.left + outer.right; - req->height = inner.right + outer.top + outer.bottom; -} - -static void hildon_color_chooser_hsv_size_allocate(GtkWidget *widget, GtkAllocation *alloc) -{ - HildonColorChooserHSV *sel = HILDON_COLOR_CHOOSER_HSV(widget); - GtkBorder outer, inner; - - - widget->allocation = *alloc; - - - _internal_init_borders(widget, &inner, &outer); - - - sel->hba.height = alloc->height - outer.top - outer.bottom; - sel->hba.y = alloc->y + outer.top; - sel->hba.width = inner.top; - sel->hba.x = alloc->x + alloc->width - outer.right - inner.top; - - sel->spa.x = alloc->x + outer.left; - sel->spa.y = alloc->y + outer.top; - sel->spa.height = alloc->height - outer.top - outer.bottom; - sel->spa.width = alloc->width - outer.left - outer.right - inner.top - inner.bottom; - - if(GTK_WIDGET_REALIZED(widget)) { - gdk_window_move_resize(sel->event_window, widget->allocation.x, widget->allocation.y, widget->allocation.width, widget->allocation.height); - } -} - - -static void hildon_color_chooser_hsv_realize(GtkWidget *widget) -{ - HildonColorChooserHSV *sel = HILDON_COLOR_CHOOSER_HSV(widget); - GdkWindowAttr attributes; - gint attributes_mask; - - attributes.x = widget->allocation.x; - attributes.y = widget->allocation.y; - attributes.width = widget->allocation.width; - attributes.height = widget->allocation.height; - attributes.wclass = GDK_INPUT_ONLY; - attributes.window_type = GDK_WINDOW_CHILD; - attributes.event_mask = gtk_widget_get_events(widget) | GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | - GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_MOTION_MASK | - GDK_BUTTON1_MOTION_MASK; - attributes.visual = gtk_widget_get_visual(widget); - attributes.colormap = gtk_widget_get_colormap(widget); - - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_WMCLASS; - sel->event_window = gdk_window_new (widget->parent->window, &attributes, attributes_mask); - - - gdk_window_set_user_data(sel->event_window, widget); - - - widget->window = gtk_widget_get_parent_window(widget); - - - widget->style = gtk_style_attach(widget->style, widget->window); - - - GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED); -} - - -static void hildon_color_chooser_hsv_map(GtkWidget *widget) -{ - HildonColorChooserHSV *sel = HILDON_COLOR_CHOOSER_HSV(widget); - - - GTK_WIDGET_CLASS(parent_class)->map(widget); - - if(sel->event_window) { - gdk_window_show(sel->event_window); - } -} - -static void hildon_color_chooser_hsv_unmap(GtkWidget *widget) -{ - HildonColorChooserHSV *sel = HILDON_COLOR_CHOOSER_HSV(widget); - - - if(sel->event_window) { - gdk_window_hide(sel->event_window); - } - - GTK_WIDGET_CLASS(parent_class)->unmap(widget); -} - - -inline void inline_clip_to_alloc(void *s, GtkAllocation *a) -{ - struct { - int x, y, w, h; - } *area = s; - - - if(area->x < a->x) { - area->w -= a->x - area->x; - area->x = a->x; - } if(area->y < a->y) { - area->h -= a->y - area->y; - area->y = a->y; - } - if(area->x + area->w > a->x + a->width) area->w = a->width - (area->x - a->x); - if(area->y + area->h > a->y + a->height) area->h = a->height - (area->y - a->y); -} - -static gboolean hildon_color_chooser_hsv_expose(GtkWidget *widget, GdkEventExpose *event) -{ - HildonColorChooserHSV *sel = HILDON_COLOR_CHOOSER_HSV(widget); - GtkBorder graphical_border; - struct { - int x, y, w, h; - } area; - - - if(!GTK_WIDGET_REALIZED(widget)) { - return FALSE; - } - - - internal_get_border(widget, "graphic_border", &graphical_border); - - - if(event->area.width || event->area.height) { - gdk_draw_rectangle(widget->window, - widget->style->black_gc, - FALSE, - sel->hba.x - 2, - sel->hba.y - 2, - sel->hba.width + 3, - sel->hba.height + 3); - - gdk_draw_rectangle(widget->window, - widget->style->black_gc, - FALSE, - sel->spa.x - 2, - sel->spa.y - 2, - sel->spa.width + 3, - sel->spa.height + 3); - } - - if(sel->expose_info.expose_queued) { - if(GTK_WIDGET_SENSITIVE(widget)) { - inline_draw_hue_bar(widget, sel->hba.x, sel->hba.y, sel->hba.width, sel->hba.height, sel->hba.y, sel->hba.height); - - inline_draw_sv_plane(sel, sel->spa.x, sel->spa.y, sel->spa.width, sel->spa.height); - } else { - inline_draw_hue_bar_dimmed(widget, sel->hba.x, sel->hba.y, sel->hba.width, sel->hba.height, sel->hba.y, sel->hba.height); - - inline_draw_sv_plane_dimmed(sel, sel->spa.x, sel->spa.y, sel->spa.width, sel->spa.height); - } - - - sel->expose_info.expose_queued = 0; - - g_get_current_time(&sel->expose_info.last_expose_time); - } else { - /* clip hue bar region */ - area.x = event->area.x; - area.y = event->area.y; - area.w = event->area.width; - area.h = event->area.height; - - inline_clip_to_alloc(&area, &sel->hba); - - if(GTK_WIDGET_SENSITIVE(widget)) { - inline_draw_hue_bar(widget, area.x, area.y, area.w, area.h, sel->hba.y, sel->hba.height); - } else { - inline_draw_hue_bar_dimmed(widget, area.x, area.y, area.w, area.h, sel->hba.y, sel->hba.height); - } - - - area.x = event->area.x; - area.y = event->area.y; - area.w = event->area.width; - area.h = event->area.height; - - inline_clip_to_alloc(&area, &sel->spa); - - if(GTK_WIDGET_SENSITIVE(widget)) { - inline_draw_sv_plane(sel, area.x, area.y, area.w, area.h); - } else { - inline_draw_sv_plane_dimmed(sel, area.x, area.y, area.w, area.h); - } - } - - - return FALSE; -} - - -inline void inline_sub_times(GTimeVal *result, GTimeVal *greater, GTimeVal *lesser) -{ - result->tv_sec = greater->tv_sec - lesser->tv_sec; - result->tv_usec = greater->tv_usec - lesser->tv_usec; - - if(result->tv_usec < 0) { - result->tv_sec--; - result->tv_usec += 1000000; - } -} - -#define EXPOSE_INTERVAL 50000 -inline void inline_limited_expose(HildonColorChooserHSV *sel) -{ - GTimeVal curr_time, result; - GdkEventExpose event; - - - if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sel))) { - return; - } - - - if(sel->currhue == sel->expose_info.last_expose_hue) { - return; /* no need to redraw */ - } - - - sel->expose_info.last_expose_hue = sel->currhue; - - - g_get_current_time(&curr_time); - - inline_sub_times(&result, &curr_time, &sel->expose_info.last_expose_time); - - if(result.tv_sec != 0 || result.tv_usec >= EXPOSE_INTERVAL) { - sel->expose_info.expose_queued = 1; - -#if 1 - event.type = GDK_EXPOSE; - event.area.width = 0; - event.area.height = 0; - event.window = GTK_WIDGET(sel)->window; - - gtk_widget_send_expose(GTK_WIDGET(sel), (GdkEvent *)&event); -#else - gtk_widget_queue_draw(GTK_WIDGET(sel)); -#endif - } else if(!sel->expose_info.expose_queued) { - sel->expose_info.expose_queued = 1; - - - g_timeout_add((EXPOSE_INTERVAL - result.tv_usec)/1000, hildon_color_chooser_hsv_expose_timer, sel); - } -} - -static gboolean hildon_color_chooser_button_press(GtkWidget *widget, GdkEventButton *event) -{ - HildonColorChooserHSV *sel = HILDON_COLOR_CHOOSER_HSV(widget); - int x, y, tmp; - - - x = (int)event->x + widget->allocation.x; - y = (int)event->y + widget->allocation.y; - - - if(x >= sel->spa.x && x <= sel->spa.x + sel->spa.width && - y >= sel->spa.y && y <= sel->spa.y + sel->spa.height) { - tmp = y - sel->spa.y; - sel->currsat = tmp * 0xffff / sel->spa.height; - tmp = x - sel->spa.x; - sel->currval = tmp * 0xffff / sel->spa.width; - - internal_invoke_color_changed(sel); - gtk_widget_queue_draw(widget); - - sel->mousestate = 1; - sel->mousein = TRUE; - - gtk_grab_add(widget); - } else if(x >= sel->hba.x && x <= sel->hba.x + sel->hba.width && - y >= sel->hba.y && y <= sel->hba.y + sel->hba.height) { - tmp = y - sel->hba.y; - sel->currhue = tmp * 0xffff / sel->hba.height; - - internal_invoke_color_changed(sel); - inline_limited_expose(sel); - - sel->mousestate = 2; - sel->mousein = TRUE; - - gtk_grab_add(widget); - } - - - return FALSE; -} - -static gboolean hildon_color_chooser_button_release(GtkWidget *widget, GdkEventButton *event) -{ - HildonColorChooserHSV *sel = HILDON_COLOR_CHOOSER_HSV(widget); - - - if(sel->mousestate) { - gtk_grab_remove(widget); - } - - - sel->mousestate = 0; - sel->mousein = FALSE; - - - return FALSE; -} - -static gboolean hildon_color_chooser_pointer_motion(GtkWidget *widget, GdkEventMotion *event) -{ - HildonColorChooserHSV *sel = HILDON_COLOR_CHOOSER_HSV(widget); - GdkModifierType mods; - gint x, y, tmp; - - - if (event->is_hint || (event->window != widget->window)) - gdk_window_get_pointer (widget->window, &x, &y, &mods); - - - if(sel->mousestate == 1) { - if(x >= sel->spa.x && x <= sel->spa.x + sel->spa.width && - y >= sel->spa.y && y <= sel->spa.y + sel->spa.height) { - sel->currsat = (((long)(y - sel->spa.y)) * 0xffff)/sel->spa.height; - sel->currval = (((long)(x - sel->spa.x)) * 0xffff)/sel->spa.width; - - internal_invoke_color_changed(sel); - gtk_widget_queue_draw(widget); - } else if(sel->mousein == TRUE) { - } - } else if(sel->mousestate == 2) { - if(x >= sel->hba.x && x <= sel->hba.x + sel->hba.width && - y >= sel->hba.y && y <= sel->hba.y + sel->hba.height) { - tmp = y - sel->hba.y; - tmp *= 0xffff; - tmp /= sel->hba.height; - - if(tmp != sel->currhue) { - sel->currhue = tmp; - - internal_invoke_color_changed(sel); - inline_limited_expose(sel); - } - } else if(sel->mousein == TRUE) { - } - } - - return FALSE; -} - - -static void internal_get_border(GtkWidget *w, char *name, GtkBorder *b) -{ - GtkBorder *tb; - - gtk_widget_style_get(w, name, &tb, NULL); - - if(tb) { - *b = *tb; - g_free(tb); - } else { - b->left = 0; - b->right = 0; - b->top = 0; - b->bottom = 0; - } -} - - -static void _internal_init_borders(GtkWidget *w, GtkBorder *inner, GtkBorder *outer) -{ - GtkBorder *tb; - - - internal_get_border(w, "outer_border", outer); - - - gtk_widget_style_get(w, "inner_size", &tb, NULL); - - if(tb) { - *inner = *tb; - g_free(tb); - } else { - inner->left = 64; - inner->right = 64; - inner->top = 12; - inner->bottom = 2; - } - - if(inner->left < 2) inner->left = 2; - if(inner->right < 2) inner->right = 2; - if(inner->top < 2) inner->top = 2; -} - - /* calculate RGB color & emit signal */ -static void internal_invoke_color_changed(HildonColorChooserHSV *sel) -{ - HildonColorChooser *parent_sel = HILDON_COLOR_CHOOSER(sel); - GdkVisual *system_visual = gdk_visual_get_system(); - unsigned long rgb[3], rgb2[3]; - - - inline_h2rgb(sel->currhue, rgb); - - rgb2[0] = 0xffffff - rgb[0]; - rgb2[1] = 0xffffff - rgb[1]; - rgb2[2] = 0xffffff - rgb[2]; - - - parent_sel->color.red = ((rgb[0] >> 8) + ((rgb2[0] >> 8) * (0xffff - sel->currsat) / 0xffff)) * sel->currval / 0xffff; - parent_sel->color.green = ((rgb[1] >> 8) + ((rgb2[1] >> 8) * (0xffff - sel->currsat) / 0xffff)) * sel->currval / 0xffff; - parent_sel->color.blue = ((rgb[2] >> 8) + ((rgb2[2] >> 8) * (0xffff - sel->currsat) / 0xffff)) * sel->currval / 0xffff; - - parent_sel->color.pixel = ((parent_sel->color.red >> (16 - system_visual->red_prec)) << system_visual->red_shift) | - ((parent_sel->color.green >> (16 - system_visual->green_prec)) << system_visual->green_shift) | - ((parent_sel->color.blue >> (16 - system_visual->blue_prec)) << system_visual->blue_shift); - - - hildon_color_chooser_emit_color_changed(HILDON_COLOR_CHOOSER(sel)); -} - - /* do the RGB -> HSV conversion here, not so time critical */ -static void hildon_color_chooser_hsv_set_color(HildonColorChooser *sel, GdkColor *color) -{ - HildonColorChooserHSV *sel_hsv = HILDON_COLOR_CHOOSER_HSV(sel); - unsigned short hue, sat, val; - unsigned long min, max; - signed long tmp, diff; - - /* ugly nesting */ - min = MIN(MIN(color->red, color->green), color->blue); - max = MAX(MAX(color->red, color->green), color->blue); - diff = max - min; - - - val = max; - - if(val > 0 && diff != 0) { - sat = (diff * 0x0000ffff) / max; - - if(color->red == max) { - tmp = (signed)color->green - (signed)color->blue; - tmp *= 10922; - tmp /= diff; - if(tmp < 0) { - tmp += 65532; - } - hue = tmp; - } else if(color->green == max) { - hue = (((signed long)color->blue - (signed long)color->red)*10922 / diff) + 21844; - } else { - hue = (((signed long)color->red - (signed long)color->green)*10922 / diff) + 43688; - } - } else { - hue = 0; - sat = 0; - } - - - sel_hsv->currhue = hue; - sel_hsv->currsat = sat; - sel_hsv->currval = val; - - - inline_limited_expose(sel_hsv); -} - - -#define FULL_COLOR 0x00ffffff -inline void inline_h2rgb(unsigned short hue, unsigned long *rgb) -{ - unsigned short hue_rotation, hue_value; - - hue_rotation = hue / 10922; - hue_value = hue % 10922; - - - switch(hue_rotation) { - case 0: - case 6: - rgb[0] = FULL_COLOR; - rgb[1] = hue_value * 6*256; - rgb[2] = 0; - break; - case 1: - rgb[0] = FULL_COLOR - (hue_value * 6*256); - rgb[1] = FULL_COLOR; - rgb[2] = 0; - break; - case 2: - rgb[0] = 0; - rgb[1] = FULL_COLOR; - rgb[2] = hue_value * 6*256; - break; - case 3: - rgb[0] = 0; - rgb[1] = FULL_COLOR - (hue_value * 6*256); - rgb[2] = FULL_COLOR; - break; - case 4: - rgb[0] = hue_value * 6*256; - rgb[1] = 0; - rgb[2] = FULL_COLOR; - break; - case 5: - rgb[0] = FULL_COLOR; - rgb[1] = 0; - rgb[2] = FULL_COLOR - (hue_value * 6*256); - break; - default: - rgb[0] = 0; - rgb[1] = 0; - rgb[2] = 0; - break; - } -} - -#define FULL_COLOR8 0xff -static void intern_h2rgb8(unsigned short hue, unsigned char *rgb) -{ - unsigned short hue_rotation, hue_value; - - hue >>= 8; - hue_rotation = hue / 42; - hue_value = hue % 42; - - - switch(hue_rotation) { - case 0: - case 6: - rgb[0] = FULL_COLOR8; - rgb[1] = hue_value * 6; - rgb[2] = 0; - break; - case 1: - rgb[0] = FULL_COLOR8 - (hue_value * 6); - rgb[1] = FULL_COLOR8; - rgb[2] = 0; - break; - case 2: - rgb[0] = 0; - rgb[1] = FULL_COLOR8; - rgb[2] = hue_value * 6; - break; - case 3: - rgb[0] = 0; - rgb[1] = FULL_COLOR8 - (hue_value * 6); - rgb[2] = FULL_COLOR8; - break; - case 4: - rgb[0] = hue_value * 6; - rgb[1] = 0; - rgb[2] = FULL_COLOR8; - break; - case 5: - rgb[0] = FULL_COLOR8; - rgb[1] = 0; - rgb[2] = FULL_COLOR8 - (hue_value * 6); - break; - default: - rgb[0] = 0; - rgb[1] = 0; - rgb[2] = 0; - break; - } -} - - - /* optimization: do not ask hue for each round but have bilinear vectors */ - /* rethink: benefits from handling data 8 bit? (no shift round) */ -inline void inline_draw_hue_bar(GtkWidget *widget, int x, int y, int w, int h, int sy, int sh) -{ - HildonColorChooserHSV *sel = HILDON_COLOR_CHOOSER_HSV(widget); - unsigned short hvec, hcurr; - unsigned char *buf, *ptr, tmp[3]; - int i, j, tmpy; - - - if(w <= 0 || h <= 0) { - return; - } - - buf = (unsigned char *)g_malloc(w*h*3); - - hvec = 65535/sh; - hcurr = hvec * (y - sy); - - ptr = buf; - - - for(i = 0; i < h; i++) { - intern_h2rgb8(hcurr, tmp); - - for(j = 0; j < w; j++) { - ptr[0] = tmp[0]; - ptr[1] = tmp[1]; - ptr[2] = tmp[2]; - ptr += 3; - } - - hcurr += hvec; - } - - - gdk_draw_rgb_image(widget->parent->window, widget->style->fg_gc[0], x, y, w, h, GDK_RGB_DITHER_NONE, buf, w*3); - - tmpy = sel->hba.y + (sel->currhue * sel->hba.height / 0xffff); - gdk_draw_line(widget->parent->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], sel->hba.x, tmpy, sel->hba.x + sel->hba.width - 1, tmpy); - - if((((sel->currhue * sel->hba.height) & 0xffff) > 0x8000) && (tmpy < (sel->hba.y + sel->hba.height))) { - gdk_draw_line(widget->parent->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], sel->hba.x, tmpy+1, sel->hba.x + sel->hba.width - 1, tmpy+1); - } else if(tmpy > sel->hba.y) { - gdk_draw_line(widget->parent->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], sel->hba.x, tmpy-1, sel->hba.x + sel->hba.width - 1, tmpy-1); - } - - - g_free(buf); -} - -inline void inline_draw_hue_bar_dimmed(GtkWidget *widget, int x, int y, int w, int h, int sy, int sh) -{ - HildonColorChooserHSV *sel = HILDON_COLOR_CHOOSER_HSV(widget); - - - if(w <= 0 || h <= 0) { - return; - } - - /* We need to create (and cache) the pixbuf if we don't - * have it yet */ - if (sel->dimmed_bar == NULL) { - int i, j; - unsigned short hvec, hcurr, avg; - unsigned char *buf, *ptr, tmp[3]; - buf = (unsigned char *)g_malloc(w*h*3); - - hvec = 65535/sh; - hcurr = hvec * (y - sy); - - ptr = buf; - - - for(i = 0; i < h; i++) { - intern_h2rgb8(hcurr, tmp); - - for(j = 0; j < w; j++) { - avg = ((unsigned short)tmp[0]*3 + (unsigned short)tmp[1]*2 + (unsigned short)tmp[2])/6; - ptr[0] = ((((i % 2) + j) % 2) == 0) ? MIN ((avg * 0.7) + 180, 255) : MIN ((avg * 0.7) + 120, 255); - ptr[1] = ((((i % 2) + j) % 2) == 0) ? MIN ((avg * 0.7) + 180, 255) : MIN ((avg * 0.7) + 120, 255); - ptr[2] = ((((i % 2) + j) % 2) == 0) ? MIN ((avg * 0.7) + 180, 255) : MIN ((avg * 0.7) + 120, 255); - ptr += 3; - } - - hcurr += hvec; - } - - sel->dimmed_bar = gdk_pixbuf_new_from_data (buf, GDK_COLORSPACE_RGB, FALSE, 8, w, h, w * 3, g_free, buf); - } - - gdk_draw_pixbuf (widget->parent->window, widget->style->fg_gc [0], sel->dimmed_bar, 0, 0, x, y, w, h, GDK_RGB_DITHER_NONE, 0, 0); -} - - -inline void inline_draw_crosshair(unsigned char *buf, int x, int y, int w, int h) -{ - int i, j, sx, sy; - - /* bad "clipping", clip the loop to save cpu */ - for(i = 0; i < 8; i++) { - for(j = 0; j < 8; j++) { - sx = j + x; sy = i + y; - - if(sx >= 0 && sx < w && sy >= 0 && sy < h) { - if(crosshair[j + 8*i]) { - if(crosshair[j + 8*i] & 0x1) { - buf[(sx)*3+(sy)*w*3+0] = 255; - buf[(sx)*3+(sy)*w*3+1] = 255; - buf[(sx)*3+(sy)*w*3+2] = 255; - } else { - buf[(sx)*3+(sy)*w*3+0] = 0; - buf[(sx)*3+(sy)*w*3+1] = 0; - buf[(sx)*3+(sy)*w*3+2] = 0; - } - } - } - } - } -} - - -inline void inline_draw_sv_plane(HildonColorChooserHSV *sel, int x, int y, int w, int h) -{ - GtkWidget *widget = GTK_WIDGET(sel); - unsigned char *buf, *ptr; - unsigned long rgbx[3] = { 0x00ffffff, 0x00ffffff, 0x00ffffff }, rgbtmp[3]; - signed long rgby[3]; - int tmp = sel->spa.width*sel->spa.height, i, j; - - - if(w <= 0 || h <= 0) { - return; - } - - - buf = (unsigned char *)g_malloc(w*h*3); - - ptr = buf; - - - inline_h2rgb(sel->currhue, rgbtmp); - - rgby[0] = rgbtmp[0] - rgbx[0]; - rgby[1] = rgbtmp[1] - rgbx[1]; - rgby[2] = rgbtmp[2] - rgbx[2]; - - rgbx[0] /= sel->spa.width; - rgbx[1] /= sel->spa.width; - rgbx[2] /= sel->spa.width; - - rgby[0] /= tmp; - rgby[1] /= tmp; - rgby[2] /= tmp; - - - rgbx[0] += (y - sel->spa.y)*rgby[0]; - rgbx[1] += (y - sel->spa.y)*rgby[1]; - rgbx[2] += (y - sel->spa.y)*rgby[2]; - - - for(i = 0; i < h; i++) { - rgbtmp[0] = rgbx[0] * (x - sel->spa.x); - rgbtmp[1] = rgbx[1] * (x - sel->spa.x); - rgbtmp[2] = rgbx[2] * (x - sel->spa.x); - - for(j = 0; j < w; j++) { - ptr[0] = rgbtmp[0] >> 16; - ptr[1] = rgbtmp[1] >> 16; - ptr[2] = rgbtmp[2] >> 16; - rgbtmp[0] += rgbx[0]; - rgbtmp[1] += rgbx[1]; - rgbtmp[2] += rgbx[2]; - ptr += 3; - } - - rgbx[0] += rgby[0]; - rgbx[1] += rgby[1]; - rgbx[2] += rgby[2]; - } - - - inline_draw_crosshair(buf, (sel->spa.width * sel->currval / 0xffff) - x + sel->spa.x - 4, (sel->spa.height * sel->currsat / 0xffff) - y + sel->spa.y - 4, w, h); - - - gdk_draw_rgb_image(widget->parent->window, widget->style->fg_gc[0], x, y, w, h, GDK_RGB_DITHER_NONE, buf, w*3); - - - g_free(buf); -} - -inline void inline_draw_sv_plane_dimmed(HildonColorChooserHSV *sel, int x, int y, int w, int h) -{ - GtkWidget *widget = GTK_WIDGET(sel); - - if(w <= 0 || h <= 0) { - return; - } - - /* We need to create (and cache) the pixbuf if we don't - * have it yet */ - if (sel->dimmed_plane == NULL) { - unsigned char *buf, *ptr; - unsigned long rgbx[3] = { 0x00ffffff, 0x00ffffff, 0x00ffffff }, rgbtmp[3]; - unsigned long avg; - signed long rgby[3]; - int tmp = sel->spa.width*sel->spa.height, i, j; - - buf = (unsigned char *)g_malloc(w*h*3); - - ptr = buf; - - /* possibe optimization: as we are drawing grayscale plane, there might - be some simpler algorithm to do this*/ - rgbtmp[0] = 0x00ffffff; - rgbtmp[1] = 0x00000000; - rgbtmp[2] = 0x00000000; - - rgby[0] = rgbtmp[0] - rgbx[0]; - rgby[1] = rgbtmp[1] - rgbx[1]; - rgby[2] = rgbtmp[2] - rgbx[2]; - - rgbx[0] /= sel->spa.width; - rgbx[1] /= sel->spa.width; - rgbx[2] /= sel->spa.width; - - rgby[0] /= tmp; - rgby[1] /= tmp; - rgby[2] /= tmp; - - rgbx[0] += (y - sel->spa.y)*rgby[0]; - rgbx[1] += (y - sel->spa.y)*rgby[1]; - rgbx[2] += (y - sel->spa.y)*rgby[2]; - - for(i = 0; i < h; i++) { - rgbtmp[0] = rgbx[0] * (x - sel->spa.x); - rgbtmp[1] = rgbx[1] * (x - sel->spa.x); - rgbtmp[2] = rgbx[2] * (x - sel->spa.x); - - for(j = 0; j < w; j++) { - avg = (rgbtmp[0] + rgbtmp[1] + rgbtmp[2])/3; - avg >>= 16; - ptr[0] = ((((i % 2) + j) % 2) == 0) ? MIN ((avg * 0.7) + 180, 255) : MIN ((avg * 0.7) + 120, 255); - ptr[1] = ((((i % 2) + j) % 2) == 0) ? MIN ((avg * 0.7) + 180, 255) : MIN ((avg * 0.7) + 120, 255); - ptr[2] = ((((i % 2) + j) % 2) == 0) ? MIN ((avg * 0.7) + 180, 255) : MIN ((avg * 0.7) + 120, 255); - rgbtmp[0] += rgbx[0]; - rgbtmp[1] += rgbx[1]; - rgbtmp[2] += rgbx[2]; - ptr += 3; - } - - rgbx[0] += rgby[0]; - rgbx[1] += rgby[1]; - rgbx[2] += rgby[2]; - } - - sel->dimmed_plane = gdk_pixbuf_new_from_data (buf, GDK_COLORSPACE_RGB, FALSE, 8, w, h, w * 3, g_free, buf); - } - - gdk_draw_pixbuf (widget->parent->window, widget->style->fg_gc [0], sel->dimmed_plane, 0, 0, x, y, w, h, GDK_RGB_DITHER_NONE, 0, 0); -} - - -static gboolean hildon_color_chooser_hsv_expose_timer(gpointer data) -{ - HildonColorChooserHSV *sel = HILDON_COLOR_CHOOSER_HSV(data); - - - if(sel->expose_info.expose_queued) { - gtk_widget_queue_draw(GTK_WIDGET(data)); - } - - - return FALSE; -} diff --git a/hildon-widgets/Makefile.am b/hildon-widgets/Makefile.am deleted file mode 100644 index badc28b..0000000 --- a/hildon-widgets/Makefile.am +++ /dev/null @@ -1,216 +0,0 @@ -INCLUDES = $(GTK_CFLAGS) $(GCONF_CFLAGS) \ - $(ESD_CFLAGS) $(LIBMB_CFLAGS) -DLOCALEDIR=\"$(localedir)\" -I$(srcdir)/.. - -lib_LTLIBRARIES = libhildonwidgets.la - -MAINTAINERCLEANFILES = \ - Makefile.in hildon-libs-enum-types.c hildon-libs-enum-types.h - -EXTRA_DIST = hildon-marshalers.list - -libhildonwidgets_la_LDFLAGS = -version-info 5:0:5 - -libhildonwidgets_la_LIBADD = $(GTK_LIBS) $(GCONF_LIBS) \ - $(ESD_LIBS) $(LIBMB_LIBS) - -libhildonwidgets_la_SOURCES = \ - hildon-marshalers.c \ - hildon-marshalers.h \ - hildon-composite-widget.c \ - hildon-composite-widget.h \ - hildon-controlbar.c \ - hildon-controlbar.h \ - hildon-seekbar.c \ - hildon-seekbar.h \ - hildon-color-selector.c \ - hildon-color-selector.h \ - hildon-note.c \ - hildon-note.h \ - hildon-volumebar.c \ - hildon-volumebar.h \ - hildon-volumebar-range.c \ - hildon-volumebar-range.h \ - hildon-volumebar-private.h \ - hildon-hvolumebar.c \ - hildon-hvolumebar.h \ - hildon-vvolumebar.c \ - hildon-vvolumebar.h \ - hildon-dialoghelp.c \ - hildon-dialoghelp.h \ - hildon-calendar-popup.c \ - hildon-calendar-popup.h \ - hildon-date-editor.c \ - hildon-date-editor.h \ - hildon-time-editor.c \ - hildon-time-editor.h \ - hildon-private.h \ - hildon-time-picker.c \ - hildon-time-picker.h \ - hildon-weekday-picker.c \ - hildon-weekday-picker.h \ - hildon-telephone-editor.c \ - hildon-telephone-editor.h \ - hildon-number-editor.c \ - hildon-number-editor.h \ - hildon-range-editor.c \ - hildon-range-editor.h \ - hildon-get-password-dialog.c \ - hildon-get-password-dialog.h \ - hildon-set-password-dialog.c \ - hildon-set-password-dialog.h \ - hildon-sort-dialog.c \ - hildon-sort-dialog.h \ - hildon-add-home-dialog.c \ - hildon-add-home-dialog.h \ - hildon-font-selection-dialog.c \ - hildon-font-selection-dialog.h \ - hildon-grid.c \ - hildon-grid.h \ - hildon-grid-item.c \ - hildon-grid-item.h \ - hildon-grid-item-private.h \ - hildon-file-handling-note.c \ - hildon-file-handling-note.h \ - hildon-name-password-dialog.c \ - hildon-name-password-dialog.h \ - hildon-scroll-area.c \ - hildon-scroll-area.h \ - hildon-wizard-dialog.c \ - hildon-wizard-dialog.h \ - hildon-color-popup.c \ - hildon-color-popup.h \ - hildon-color-button.c \ - hildon-color-button.h \ - hildon-system-sound.c \ - hildon-system-sound.h \ - hildon-app.c \ - hildon-app.h \ - hildon-defines.c \ - hildon-defines.h \ - hildon-appview.c \ - hildon-appview.h \ - hildon-find-toolbar.c \ - hildon-find-toolbar.h \ - gtk-infoprint.c \ - gtk-infoprint.h \ - hildon-banner.c \ - hildon-banner.h \ - hildon-input-mode-hint.h \ - hildon-app-private.h \ - hildon-caption.c \ - hildon-caption.h \ - hildon-window.c \ - hildon-window.h \ - hildon-window-private.h \ - hildon-program.c \ - hildon-program.h \ - hildon-code-dialog.c \ - hildon-code-dialog.h \ - hildon-plugin-widget.c \ - hildon-plugin-widget.h \ - hildon-color-chooser.c \ - hildon-color-chooser.h \ - hildon-color-chooser-dialog.c \ - hildon-color-chooser-dialog.h \ - hildon-color-chooser-button.c \ - hildon-color-chooser-button.h \ - $(hildonlibs_built_headers) \ - $(hildonlibs_built_cfiles) - - -hildon-marshalers.h: hildon-marshalers.list - glib-genmarshal --prefix _hildon_marshal --header \ - hildon-marshalers.list >hildon-marshalers.h - -hildon-marshalers.c: hildon-marshalers.list hildon-marshalers.h - echo '#include ' >hildon-marshalers.c - glib-genmarshal --prefix _hildon_marshal --body \ - hildon-marshalers.list >>hildon-marshalers.c - -hildonwidgetsincludeinstdir=$(includedir)/hildon-widgets -hildonwidgetsincludeinst_DATA = \ - hildon-controlbar.h \ - hildon-note.h \ - hildon-seekbar.h \ - hildon-color-selector.h \ - hildon-volumebar.h \ - hildon-hvolumebar.h \ - hildon-vvolumebar.h \ - hildon-dialoghelp.h \ - hildon-calendar-popup.h \ - hildon-date-editor.h \ - hildon-time-editor.h \ - hildon-time-picker.h \ - hildon-weekday-picker.h \ - hildon-telephone-editor.h \ - hildon-number-editor.h \ - hildon-range-editor.h \ - hildon-get-password-dialog.h \ - hildon-set-password-dialog.h \ - hildon-sort-dialog.h \ - hildon-add-home-dialog.h \ - hildon-font-selection-dialog.h \ - hildon-grid.h \ - hildon-grid-item.h \ - hildon-file-handling-note.h \ - hildon-name-password-dialog.h \ - hildon-scroll-area.h \ - hildon-wizard-dialog.h \ - hildon-color-popup.h \ - hildon-color-button.h \ - hildon-system-sound.h \ - hildon-app.h \ - hildon-defines.h \ - hildon-appview.h \ - hildon-find-toolbar.h \ - gtk-infoprint.h \ - hildon-banner.h \ - hildon-input-mode-hint.h \ - hildon-app-private.h \ - hildon-caption.h \ - hildon-window.h \ - hildon-program.h \ - hildon-window-private.h \ - hildon-code-dialog.h \ - hildon-plugin-widget.h \ - hildon-color-chooser.h \ - hildon-color-chooser-dialog.h \ - hildon-color-chooser-button.h - -headers_to_scan_for_enums = $(hildonwidgetsincludeinst_DATA) - -# Generate the enums source code, with glib-mkenums: -# This is based on the same Makefile.am stuff in pango: -hildonlibs_built_headers = hildon-libs-enum-types.h -hildonlibs_built_cfiles = hildon-libs-enum-types.c - -# Don't build the library until we have built the header that it needs: -$(OBJECTS) $(libhildonwidgets_la_OBJECTS): $(hildonlibs_built_headers) - -hildon-libs-enum-types.h: @REBUILD@ $(headers_to_scan_for_enums) Makefile - (cd $(srcdir) && glib-mkenums \ - --fhead "#ifndef __HILDON_LIBS_ENUM_TYPES_H__\n#define __HILDON_LIBS_ENUM_TYPES_H__\n\n#include \n\nG_BEGIN_DECLS\n" \ - --fprod "/* enumerations from \"@filename@\" */\n" \ - --vhead "GType @enum_name@_get_type (void);\n#define HILDON_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \ - --ftail "G_END_DECLS\n\n#endif /* __HILDON_LIBS_ENUM_TYPES_H__ */" \ - $(headers_to_scan_for_enums)) > $@ - -#FIXME: This would be shorter if there was a hildon-libs.h file: -hildon-libs-enum-types.c: @REBUILD@ $(headers_to_scan_for_enums) Makefile - (cd $(srcdir) && glib-mkenums \ - --fhead "#include \n" \ - --fhead "#include \n" \ - --fhead "#include \n" \ - --fhead "#include \n" \ - --fhead "#include \n" \ - --fhead "#include \n" \ - --fhead "#include \n" \ - --fhead "#include \n" \ - --fhead "#include \n" \ - --fhead '#include "hildon-libs-enum-types.h"\n' \ - --fhead "#include " \ - --fprod "\n/* enumerations from \"@filename@\" */" \ - --vhead "GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {" \ - --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \ - --vtail " { 0, NULL, NULL }\n };\n etype = g_@type@_register_static (\"@EnumName@\", values);\n }\n return etype;\n}\n" \ - $(headers_to_scan_for_enums)) > $@ diff --git a/hildon-widgets/gtk-infoprint.c b/hildon-widgets/gtk-infoprint.c deleted file mode 100644 index 0f9be2a..0000000 --- a/hildon-widgets/gtk-infoprint.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:gtk-infoprint - * @short_description: deprecated widget. Use #HildonBanner instead - * - * This widget is deprecated. Use #HildonBanner instead - */ - -#include "gtk-infoprint.h" -#include "hildon-banner.h" - -/* This is a helper function that searches the banner for - given window. This is needed to provide backwards - compatibility. */ -static GtkWidget *find_banner_for_parent(GtkWindow *parent) -{ - GList *toplevels, *iter; - GtkWidget *result = NULL; - gboolean is_timed; - - toplevels = gtk_window_list_toplevels(); - for (iter = toplevels; iter; iter = iter->next) - if (HILDON_IS_BANNER(iter->data) && - gtk_window_get_transient_for(GTK_WINDOW(iter->data)) == parent) - { - g_object_get(iter->data, "is-timed", &is_timed, NULL); - - /* We do not want to touch timed infoprints */ - if (!is_timed) { - result = iter->data; - break; - } - } - - g_list_free(toplevels); - return result; -} - -/**************************************************/ -/** Public **/ -/**************************************************/ - -/** - * gtk_infoprint: - * @parent: The transient window for the infoprint. - * @text: The text in infoprint - * - * Opens a new infoprint with @text content. - * - * If parent is %NULL, the infoprint is a system infoprint. - * Normally you should use your application window - * or dialog as a transient parent and avoid passing %NULL. - * - * Deprecated: Use #hildon_banner_show_information instead. - */ -void gtk_infoprint(GtkWindow * parent, const gchar * text) -{ - hildon_banner_show_information((GtkWidget *) parent, NULL, text); -} - -/** - * gtk_infoprint_with_icon_stock: - * @parent: The transient window for the infoprint. - * @text: The text in infoprint - * @stock_id: The stock id of the custom icon - * - * Opens a new infoprint with @text content. - * With this function you can also set a custom icon - * by giving a stock id as last parameter. - * - * If parent is %NULL, the infoprint is a system infoprint. - * Normally you should use your application window - * or dialog as a transient parent and avoid passing %NULL. - * - * Deprecated: Use #hildon_banner_show_information instead. - */ -void -gtk_infoprint_with_icon_stock(GtkWindow * parent, - const gchar * text, const gchar * stock_id) -{ - hildon_banner_show_information((GtkWidget *) parent, NULL, text); -} - -/** - * gtk_infoprint_with_icon_name: - * @parent: The transient window for the infoprint. - * @text: The text in infoprint - * @icon_name: The name of the icon - * - * Opens a new infoprint with @text content. - * With this function you can also set a custom icon - * by giving a icon name as last parameter. - * - * If parent is %NULL, the infoprint is a system infoprint. - * Normally you should use your application window - * or dialog as a transient parent and avoid passing %NULL. - * - * Deprecated: Use #hildon_banner_show_information instead. - */ -void -gtk_infoprint_with_icon_name(GtkWindow * parent, - const gchar * text, const gchar * icon_name) -{ - hildon_banner_show_information((GtkWidget *) parent, icon_name, text); -} - -/** - * gtk_infoprintf: - * @parent: The transient window for the infoprint. - * @format: Format of the text. - * @Varargs: List of parameters. - * - * Opens a new infoprint with @text printf-style formatting - * string and comma-separated list of parameters. - * - * If parent is %NULL, the infoprint is a system infoprint. - * This version of infoprint allow you to make printf-like formatting - * easily. - * - * Deprecated: Use #hildon_banner_show_information instead. - */ -void gtk_infoprintf(GtkWindow * parent, const gchar * format, ...) -{ - gchar *message; - va_list args; - - va_start(args, format); - message = g_strdup_vprintf(format, args); - va_end(args); - - gtk_infoprint(parent, message); - - g_free(message); -} - -/** - * gtk_infoprint_temporarily_disable_wrap: - * - * Will disable wrapping for the next shown infoprint. This only - * affects next infoprint shown in this application. - * - * Currently it does nothing. - * - * Deprecated: - */ -void gtk_infoprint_temporarily_disable_wrap(void) -{ -} - -/** - * gtk_confirmation_banner: - * @parent: The transient window for the confirmation banner. - * @text: The text in confirmation banner - * @stock_id: The stock id of the custom icon - * - * Opens a new confirmation banner with @text content. - * With this function you can also set a custom icon - * by giving a stock id as last parameter. - * - * If parent is %NULL, the banner is a system banner. - * Normally you should use your application window - * or dialog as a transient parent and avoid passing %NULL. - * - * This function is otherwise similar to - * gtk_infoprint_with_icon_stock except in always restricts - * the text to one line and the font is emphasized. - * - * Deprecated: Use #hildon_banner_show_information instead. - */ -void -gtk_confirmation_banner(GtkWindow * parent, const gchar * text, - const gchar * stock_id) -{ - gchar *s; - s = g_strdup_printf("%s", text); - - hildon_banner_show_information_with_markup((GtkWidget *) parent, NULL, s); - - g_free(s); -} - -/** - * gtk_confirmation_banner_with_icon_name: - * @parent: The transient window for the confirmation banner. - * @text: The text in confirmation banner - * @icon_name: The name of the custom icon in icon theme - * - * Opens a new confirmation banner with @text content. - * With this function you can also set a custom icon - * by giving a icon theme's icon name as last parameter. - * - * If parent is %NULL, the banner is a system banner. - * Normally you should use your application window - * or dialog as a transient parent and avoid passing %NULL. - * - * This function is otherwise similar to - * gtk_infoprint_with_icon_name except in always restricts - * the text to one line and the font is emphasized. - * - * Deprecated: Use #hildon_banner_show_information instead. - */ -void -gtk_confirmation_banner_with_icon_name(GtkWindow * parent, const gchar * text, - const gchar * icon_name) -{ - gchar *s; - s = g_strdup_printf("%s", text); - - hildon_banner_show_information_with_markup((GtkWidget *) parent, icon_name, s); - - g_free(s); -} - -/** - * gtk_banner_show_animation: - * @parent: #GtkWindow - * @text: #const gchar * - * - * The @text is the text shown in banner. - * Creates a new banner with the animation. - * - * Deprecated: Use #hildon_banner_show_animation instead. - */ -void gtk_banner_show_animation(GtkWindow * parent, const gchar * text) -{ - (void) hildon_banner_show_animation((GtkWidget *) parent, NULL, text); -} - -/** - * gtk_banner_show_bar - * @parent: #GtkWindow - * @text: #const gchar * - * - * The @text is the text shown in banner. - * Creates a new banner with the progressbar. - * - * Deprecated: Use #hildon_banner_show_progress instead. - */ -void gtk_banner_show_bar(GtkWindow * parent, const gchar * text) -{ - (void) hildon_banner_show_progress((GtkWidget *) parent, NULL, text); -} - -/** - * gtk_banner_set_text - * @parent: #GtkWindow - * @text: #const gchar * - * - * The @text is the text shown in banner. - * Sets the banner text. - * - * Deprecated: Use #hildon_banner_set_text instead. - */ -void gtk_banner_set_text(GtkWindow * parent, const gchar * text) -{ - GtkWidget *banner; - - g_return_if_fail(GTK_IS_WINDOW(parent) || parent == NULL); - - banner = find_banner_for_parent(parent); - if (banner) - hildon_banner_set_text(HILDON_BANNER(banner), text); -} - -/** - * gtk_banner_set_fraction: - * @parent: #GtkWindow - * @fraction: #gdouble - * - * The fraction is the completion of progressbar, - * the scale is from 0.0 to 1.0. - * Sets the amount of fraction the progressbar has. - * - * Deprecated: Use #hildon_banner_set_fraction instead. - */ -void gtk_banner_set_fraction(GtkWindow * parent, gdouble fraction) -{ - GtkWidget *banner; - - g_return_if_fail(GTK_IS_WINDOW(parent) || parent == NULL); - - banner = find_banner_for_parent(parent); - if (banner) - hildon_banner_set_fraction(HILDON_BANNER(banner), fraction); -} - -/** - * gtk_banner_close: - * @parent: #GtkWindow - * - * Destroys the banner - * - * Deprecated: - */ -void gtk_banner_close(GtkWindow * parent) -{ - GtkWidget *banner; - - g_return_if_fail(GTK_IS_WINDOW(parent) || parent == NULL); - - banner = find_banner_for_parent(parent); - if (banner) - gtk_widget_destroy(banner); -} - -/** - * gtk_banner_temporarily_disable_wrap - * - * Will disable wrapping for the next shown banner. This only - * affects next banner shown in this application. - * - * Currently it does nothing. - * - * Deprecated: - **/ -void gtk_banner_temporarily_disable_wrap(void) -{ -} diff --git a/hildon-widgets/gtk-infoprint.h b/hildon-widgets/gtk-infoprint.h deleted file mode 100644 index d97b212..0000000 --- a/hildon-widgets/gtk-infoprint.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __GTK_INFOPRINT_H__ -#define __GTK_INFOPRINT_H__ - -#include - -G_BEGIN_DECLS void gtk_infoprint(GtkWindow * parent, const gchar * text); -void gtk_infoprint_with_icon_stock(GtkWindow * parent, const gchar * text, - const gchar * stock_id); -void gtk_infoprint_with_icon_name(GtkWindow * parent, const gchar * text, - const gchar * icon_name); - -void gtk_infoprintf(GtkWindow * parent, const gchar * format, ...); -void gtk_infoprint_temporarily_disable_wrap(void); - -void gtk_confirmation_banner_with_icon_name(GtkWindow * parent, const gchar * text, - const gchar * icon_name); -void gtk_confirmation_banner(GtkWindow * parent, const gchar * text, - const gchar * stock_id); - -void gtk_banner_show_animation(GtkWindow * parent, const gchar * text); -void gtk_banner_show_bar(GtkWindow * parent, const gchar * text); -void gtk_banner_set_text(GtkWindow * parent, const gchar * text); -void gtk_banner_set_fraction(GtkWindow * parent, gdouble fraction); -void gtk_banner_close(GtkWindow * parent); -void gtk_banner_temporarily_disable_wrap(void); - -G_END_DECLS -#endif /* __GTK_INFOPRINT_H__ */ diff --git a/hildon-widgets/hildon-add-home-dialog.c b/hildon-widgets/hildon-add-home-dialog.c deleted file mode 100644 index 9824677..0000000 --- a/hildon-widgets/hildon-add-home-dialog.c +++ /dev/null @@ -1,525 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "hildon-add-home-dialog.h" -#include - -#define _(String) dgettext(PACKAGE, String) -#define MAX_ERR_MSG 256 -#define HILDON_ADD_HOME_DIALOG_WIDTH 370 -#define HILDON_ADD_HOME_DIALOG_HEIGHT 100 -#define HILDON_MAX_TITLE_LENGTH 256 -#define HILDON_HOME_MAX_SHORTCUT_LEN 255 - -#define HILDON_ADD_HOME_DIALOG_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_ADD_HOME_DIALOG, \ - HildonAddHomeDialogPrivate)); - -typedef struct _HildonAddHomeDialogPrivate HildonAddHomeDialogPrivate; - -static GtkDialogClass *parent_class; - -static const gchar *hildon_add_home_dialog_get_old_name(HildonAddHomeDialog * dialog); -static void hildon_add_home_dialog_set_old_name(HildonAddHomeDialog * dialog, const gchar* name); -static void hildon_add_home_dialog_set_new_name(HildonAddHomeDialog * dialog, const gchar* name); -static void hildon_add_home_dialog_create_widgets(HildonAddHomeDialog * dialog, gboolean new_isrename); - -static void -hildon_add_home_dialog_get_property(GObject * object, - guint prop_id, - GValue * value, - GParamSpec * pspec); -static void -hildon_add_home_dialog_set_property(GObject * object, - guint prop_id, - const GValue * value, - GParamSpec * pspec); -static void -hildon_add_home_dialog_class_init(HildonAddHomeDialogClass * class); -static void hildon_add_home_dialog_init(HildonAddHomeDialog * dialog); - -/* private struct */ - -struct _HildonAddHomeDialogPrivate { - GtkWidget *desc_label; - GtkWidget *name_entry; /* Used when isrename */ - GtkWidget *name_label; /* Used when !isrename */ - GtkWidget *caption_name_entry; /* Used when isrename */ - GtkWidget *new_name_entry; - GtkWidget *caption_new_name_entry; - GtkSizeGroup *size_group; - GtkWidget *okButton; - GtkWidget *cancelButton; - gboolean isrename; -}; - -enum -{ - PROP_0, - - PROP_NAME, - PROP_NEW_NAME, -}; - -/* Private functions */ - -static void -hildon_add_home_dialog_class_init(HildonAddHomeDialogClass * klass) -{ - GObjectClass * gobject_class = G_OBJECT_CLASS(klass); - parent_class = g_type_class_peek_parent(klass); - - gobject_class->set_property = hildon_add_home_dialog_set_property; - gobject_class->get_property = hildon_add_home_dialog_get_property; - - /** - * HildonAddHomeDialog:name - * - * The name - */ - g_object_class_install_property(gobject_class, - PROP_NAME, - g_param_spec_string ("name", - ("Name"), - ("The name."), - NULL, - G_PARAM_READWRITE)); - - /** - * HildonAddHomeDialog:new_name - * - * The new name - */ - g_object_class_install_property(gobject_class, - PROP_NEW_NAME, - g_param_spec_string ("new_name", - ("New Name"), - ("The new name."), - NULL, - G_PARAM_READWRITE)); - - g_type_class_add_private(klass, sizeof(HildonAddHomeDialogPrivate)); -} - -static void hildon_add_home_dialog_init(HildonAddHomeDialog * dialog) -{ - HildonAddHomeDialogPrivate *priv; - - gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); - - priv = HILDON_ADD_HOME_DIALOG_GET_PRIVATE(dialog); - priv->name_entry = NULL; - priv->name_label = NULL; - priv->caption_name_entry = NULL; - priv->new_name_entry = NULL; - priv->isrename = FALSE; - - priv->okButton = gtk_dialog_add_button(GTK_DIALOG(dialog), - "addtoHome_button_ok", - GTK_RESPONSE_OK); - priv->cancelButton = gtk_dialog_add_button(GTK_DIALOG(dialog), - "addtoHome_button_cancel", - GTK_RESPONSE_CANCEL); - - gtk_window_resize(GTK_WINDOW(dialog), - HILDON_ADD_HOME_DIALOG_WIDTH, - HILDON_ADD_HOME_DIALOG_HEIGHT); - - gtk_widget_show_all(GTK_DIALOG(dialog)->vbox); - gtk_widget_show_all(GTK_DIALOG(dialog)->action_area); - - priv->size_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); - - - /* add description text (only shown when isrename==true */ - priv->desc_label = gtk_label_new(_("ckdg_ib_link_exists")); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), - priv->desc_label, FALSE, FALSE, 0); - - /* We don't use the hildon_caption_new() C convenience function, because it demands a non-NULL child widget (via gtk_container_add()). */ - priv->caption_name_entry = GTK_WIDGET( g_object_new( HILDON_TYPE_CAPTION, "size_group", priv->size_group, "label", "addtoHome_editor_caption", "status", HILDON_CAPTION_OPTIONAL, NULL) ); - gtk_widget_show(priv->caption_name_entry); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), priv->caption_name_entry, - FALSE, FALSE, 0); - - - gtk_widget_show_all(GTK_DIALOG(dialog)->action_area); -} - -/* Public functions */ - -GType hildon_add_home_dialog_get_type(void) -{ - static GType dialog_type = 0; - - if (!dialog_type) { - static const GTypeInfo dialog_info = { - sizeof(HildonAddHomeDialogClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_add_home_dialog_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonAddHomeDialog), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_add_home_dialog_init - }; - - dialog_type = g_type_register_static(GTK_TYPE_DIALOG, - "HildonAddHomeDialog", - &dialog_info, 0); - } - return dialog_type; -} - -static void -hildon_add_home_dialog_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - HildonAddHomeDialog * dialog = HILDON_ADD_HOME_DIALOG(object); - HildonAddHomeDialogPrivate *priv = HILDON_ADD_HOME_DIALOG_GET_PRIVATE(dialog); - - switch(prop_id) - { - case PROP_NAME: - { - const gchar* name = NULL; - if(priv->isrename && priv->name_label) - name = gtk_entry_get_text(GTK_ENTRY(priv->name_label)); - else if(!(priv->isrename) && priv->name_entry) - name = gtk_entry_get_text(GTK_ENTRY(priv->name_entry)); - - g_value_set_string (value, name); - break; - } - case PROP_NEW_NAME: - { - const gchar* new_name = NULL; - if(priv->isrename && priv->new_name_entry) - new_name = gtk_entry_get_text(GTK_ENTRY(priv->new_name_entry)); - - g_value_set_string (value, new_name); - break; - } - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -hildon_add_home_dialog_set_window_title (HildonAddHomeDialog * dialog) -{ - HildonAddHomeDialogPrivate *priv; - - g_return_if_fail(HILDON_IS_ADD_HOME_DIALOG(dialog)); - priv = HILDON_ADD_HOME_DIALOG_GET_PRIVATE(dialog); - - /* Set up the window title */ - if (priv->isrename) - gtk_window_set_title(GTK_WINDOW(dialog), _("ckdg_ti_rename_link")); - else - gtk_window_set_title(GTK_WINDOW(dialog), "addtoHome_dialog_title"); -} - - -static void -hildon_add_home_dialog_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - HildonAddHomeDialog * dialog = HILDON_ADD_HOME_DIALOG(object); - HildonAddHomeDialogPrivate *priv; - - g_return_if_fail(HILDON_IS_ADD_HOME_DIALOG(dialog)); - priv = HILDON_ADD_HOME_DIALOG_GET_PRIVATE(dialog); - - switch (prop_id) - { - case PROP_NAME: - hildon_add_home_dialog_set_old_name (dialog, g_value_get_string (value)); - break; - case PROP_NEW_NAME: - hildon_add_home_dialog_set_new_name (dialog, g_value_get_string (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -/** - * hildon_add_home_dialog_new: - * @parent: parent window for the dialog - * @name: name to show in the entry (or label, if @new_name is not NULL) - * @new_name: name to show in the new name entry. If this is not NULL - * the widget acts as a RenameShortcutDialog. - * - * Creates a new Add to Home dialog or Rename Shortcut dialog. - * - * Returns: the new dialog. - */ -GtkWidget *hildon_add_home_dialog_new(GtkWindow * parent, - const gchar * name, - const gchar * new_name) -{ - HildonAddHomeDialog *dialog = - HILDON_ADD_HOME_DIALOG(g_object_new - (HILDON_TYPE_ADD_HOME_DIALOG, "name", name, "new_name", new_name, NULL)); - - if (parent) - gtk_window_set_transient_for(GTK_WINDOW(dialog), parent); - - return GTK_WIDGET(dialog); -} - -/** - * hildon_add_home_dialog_get_name: - * @dialog: the dialog - * - * Returns: the string the user has entered in the entry - */ -const gchar *hildon_add_home_dialog_get_name(HildonAddHomeDialog * dialog) -{ - HildonAddHomeDialogPrivate *priv; - - g_return_val_if_fail(HILDON_IS_ADD_HOME_DIALOG(dialog), NULL); - priv = HILDON_ADD_HOME_DIALOG_GET_PRIVATE(dialog); - - if (priv->isrename && priv->new_name_entry) - return gtk_entry_get_text(GTK_ENTRY(priv->new_name_entry)); - else if(priv->name_entry) - return gtk_entry_get_text(GTK_ENTRY(priv->name_entry)); - else - return NULL; -} - -static const gchar *hildon_add_home_dialog_get_old_name(HildonAddHomeDialog * dialog) -{ - HildonAddHomeDialogPrivate *priv; - - g_return_val_if_fail(HILDON_IS_ADD_HOME_DIALOG(dialog), NULL); - priv = HILDON_ADD_HOME_DIALOG_GET_PRIVATE(dialog); - - if (priv->isrename && priv->name_label) - return gtk_label_get_text(GTK_LABEL(priv->name_label)); - else if(!priv->isrename && priv->name_entry) - return gtk_entry_get_text(GTK_ENTRY(priv->name_entry)); - else - return NULL; -} - -static void hildon_add_home_dialog_set_old_name(HildonAddHomeDialog * dialog, const gchar* name) -{ - HildonAddHomeDialogPrivate *priv; - - g_return_if_fail(HILDON_IS_ADD_HOME_DIALOG(dialog)); - priv = HILDON_ADD_HOME_DIALOG_GET_PRIVATE(dialog); - - hildon_add_home_dialog_create_widgets(dialog, priv->isrename); - - /* Set text in the widgets: */ - if (priv->isrename) - gtk_label_set_text(GTK_LABEL(priv->name_label), name); - else - gtk_entry_set_text(GTK_ENTRY(priv->name_entry), name); -} - -static void hildon_add_home_dialog_set_new_name(HildonAddHomeDialog * dialog, const gchar* new_name) -{ - HildonAddHomeDialogPrivate *priv; - gchar* name = NULL; - gboolean new_isrename = FALSE; - - g_return_if_fail(HILDON_IS_ADD_HOME_DIALOG(dialog)); - priv = HILDON_ADD_HOME_DIALOG_GET_PRIVATE(dialog); - - /* We get the old name, in case we need to set it again in a new widget. */ - name = g_strdup( hildon_add_home_dialog_get_old_name(dialog) ); - new_isrename = (new_name != NULL); - - hildon_add_home_dialog_create_widgets(dialog, new_isrename); - - - /* Set text in the widgets: */ - if(priv->isrename) - { - gtk_entry_set_text(GTK_ENTRY(priv->new_name_entry), new_name); - gtk_label_set_text(GTK_LABEL(priv->name_label), (name) ? name : ""); - } - else - { - gtk_entry_set_text(GTK_ENTRY(priv->name_entry), (name) ? name : ""); - } - - if(name) - g_free(name); -} - -static void hildon_add_home_dialog_create_widgets(HildonAddHomeDialog * dialog, gboolean new_isrename) -{ - HildonAddHomeDialogPrivate *priv; - - g_return_if_fail(HILDON_IS_ADD_HOME_DIALOG(dialog)); - priv = HILDON_ADD_HOME_DIALOG_GET_PRIVATE(dialog); - - /* Create and destroy widgets, depending on the mode. - * Note that we are making a small speed sacrifice (recreating the widgets) - * in exchange for memory (creating all widgets and just hiding the ones we don't use.) - */ - - if(priv->isrename && !new_isrename) - { - /* Remove widgets that were used for isrename mode, - because we don't need them anymore. */ - if(priv->new_name_entry) - { - gtk_widget_destroy(priv->new_name_entry); - priv->new_name_entry = NULL; - } - - if(priv->caption_new_name_entry) - { - gtk_widget_destroy(priv->caption_new_name_entry); - priv->caption_new_name_entry = NULL; - } - - if(priv->name_label) /* A label */ - { - gtk_widget_destroy(priv->name_label); - priv->name_label = NULL; - } - - if(priv->name_entry) /* A box with label inside */ - { - gtk_widget_destroy(priv->name_entry); - priv->name_entry = NULL; - } - } - else if(!priv->isrename && new_isrename) - { - /* Remove widgets that were used only for !isrename mode, - because we don't need them anymore. */ - if(priv->name_entry) /* An entry. */ - { - gtk_widget_destroy(priv->name_entry); - priv->name_entry = NULL; - } - } - - priv->isrename = new_isrename; - - if(priv->isrename) - { - /* Create widgets needed for isrename mode: */ - - /* Create Entry (in a Caption) for the new name, and pack it into the dialog: */ - if(!priv->new_name_entry) - { - priv->new_name_entry = gtk_entry_new(); - gtk_widget_show(priv->new_name_entry); - } - - if(!priv->caption_new_name_entry) - { - priv->caption_new_name_entry = hildon_caption_new(priv->size_group, _("ckdg_fi_rename_name"), - priv->new_name_entry, NULL, - HILDON_CAPTION_OPTIONAL); - gtk_widget_show(priv->caption_new_name_entry); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), GTK_WIDGET(priv->caption_new_name_entry), - FALSE, FALSE, 0); - } - - /* add description text */ - if(priv->desc_label) - gtk_widget_show(priv->desc_label); - - /* Create Label (in a Box) for the existing name: */ - if(!priv->name_entry) - { - priv->name_label = gtk_label_new(NULL); - gtk_widget_show(priv->name_label); - - priv->name_entry = gtk_hbox_new(FALSE, 0); - gtk_widget_show(priv->name_entry); - gtk_box_pack_start(GTK_BOX(priv->name_entry), priv->name_label, FALSE, FALSE, - 0); - gtk_container_add(GTK_CONTAINER(priv->caption_name_entry), GTK_WIDGET(priv->name_entry)); - } - } - else - { - if(priv->desc_label) - gtk_widget_hide(priv->desc_label); - - /* Create widgets needed for !isrename mode: */ - if(!priv->name_entry) - { - priv->name_entry = gtk_entry_new(); - gtk_widget_show(priv->name_entry); - gtk_container_add(GTK_CONTAINER(priv->caption_name_entry), GTK_WIDGET(priv->name_entry)); - } - } - - hildon_add_home_dialog_set_window_title(dialog); - - priv->isrename = new_isrename; -} - -void hildon_add_home_dialog_set_name(HildonAddHomeDialog * dialog, const gchar* name) -{ - HildonAddHomeDialogPrivate *priv; - - g_return_if_fail(HILDON_IS_ADD_HOME_DIALOG(dialog)); - priv = HILDON_ADD_HOME_DIALOG_GET_PRIVATE(dialog); - - hildon_add_home_dialog_create_widgets(dialog, priv->isrename); - - /* Set text in the widgets: */ - if (priv->isrename) - gtk_entry_set_text(GTK_ENTRY(priv->new_name_entry), name); - else - gtk_label_set_text(GTK_LABEL(priv->name_entry), name); -} - diff --git a/hildon-widgets/hildon-add-home-dialog.h b/hildon-widgets/hildon-add-home-dialog.h deleted file mode 100644 index bd3e1c2..0000000 --- a/hildon-widgets/hildon-add-home-dialog.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_ADD_HOME_DIALOG_H__ -#define __HILDON_ADD_HOME_DIALOG_H__ - -#include - -G_BEGIN_DECLS -#define HILDON_TYPE_ADD_HOME_DIALOG \ - ( hildon_add_home_dialog_get_type() ) -#define HILDON_ADD_HOME_DIALOG(obj) \ - (GTK_CHECK_CAST (obj, HILDON_TYPE_ADD_HOME_DIALOG, HildonAddHomeDialog)) -#define HILDON_ADD_HOME_DIALOG_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), HILDON_TYPE_ADD_HOME_DIALOG, \ - HildonAddHomeDialogClass)) -#define HILDON_IS_ADD_HOME_DIALOG(obj) \ - (GTK_CHECK_TYPE (obj, HILDON_TYPE_ADD_HOME_DIALOG)) -#define HILDON_IS_ADD_HOME_DIALOG_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_ADD_HOME_DIALOG)) -typedef struct _HildonAddHomeDialog HildonAddHomeDialog; -typedef struct _HildonAddHomeDialogClass HildonAddHomeDialogClass; - -struct _HildonAddHomeDialog { - GtkDialog parent; -}; - -struct _HildonAddHomeDialogClass { - GtkDialogClass parent_class; -}; - -GType hildon_add_home_dialog_get_type(void); - -GtkWidget *hildon_add_home_dialog_new(GtkWindow * parent, - const gchar * name, - const gchar * new_name); -const gchar *hildon_add_home_dialog_get_name(HildonAddHomeDialog * dialog); - -G_END_DECLS -#endif /* __HILDON_ADD_HOME_DIALOG_H__ */ diff --git a/hildon-widgets/hildon-app-private.h b/hildon-widgets/hildon-app-private.h deleted file mode 100644 index 1441a0b..0000000 --- a/hildon-widgets/hildon-app-private.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - - -#ifndef HILDON_APP_PRIVATE_H -#define HILDON_APP_PRIVATE_H - -G_BEGIN_DECLS - -enum { - TOPMOST_STATUS_ACQUIRE, - TOPMOST_STATUS_LOSE, - SWITCH_TO, - IM_CLOSE, - CLIPBOARD_COPY, - CLIPBOARD_CUT, - CLIPBOARD_PASTE, - - HILDON_APP_LAST_SIGNAL -}; - -struct _HildonAppPrivate { - GList *children; - gchar *title; -#ifndef HILDON_DISABLE_DEPRECATED - HildonZoomLevel zoom; -#endif - - /* Used to keep track of menu key press/release */ - gint lastmenuclick; - - gulong curr_view_id; - gulong view_id_counter; - GSList *view_ids; - gboolean scroll_control; - - guint twoparttitle: 1; - guint is_topmost: 1; - gboolean killable; - gboolean autoregistration; - - guint escape_timeout; - guint key_snooper; - - GtkUIManager *uim; - - guint active_menu_id; -}; - -typedef struct { - gpointer view_ptr; - unsigned long view_id; -} view_item; - -G_END_DECLS - -#endif /* HILDON_APP_PRIVATE_H */ diff --git a/hildon-widgets/hildon-app.c b/hildon-widgets/hildon-app.c deleted file mode 100644 index b7a24a7..0000000 --- a/hildon-widgets/hildon-app.c +++ /dev/null @@ -1,2270 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-app - * @short_description: A base widget to present application. Deprecated, use #HildonProgram instead. - * @see_also: #HildonAppView - * - * #HildonApp is the base for any hildon application. - * It controls basic looks and functionality of an application, like a title. - * - * This widget is deprecated use #HildonProgram instead. - */ - -#include -#include "hildon-app.h" -#include "hildon-app-private.h" -#include "hildon-appview.h" -#include "gtk-infoprint.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#ifdef HAVE_CONFIG_H -#include -#endif - -#define TITLE_DELIMITER " - " - -/* - * 'Magic' values for the titlebar menu area limits - */ -#define MENUAREA_LEFT_LIMIT 80 -#define MENUAREA_RIGHT_LIMIT MENUAREA_LEFT_LIMIT + 307 -#define MENUAREA_TOP_LIMIT 0 -#define MENUAREA_BOTTOM_LIMIT 39 - -#define KILLABLE "CANKILL" - -#define _(String) dgettext(PACKAGE, String) - -#define HILDON_APP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_APP, HildonAppPrivate)); - -static GtkWindowClass *parent_class; -static guint app_signals[HILDON_APP_LAST_SIGNAL] = { 0 }; - -typedef struct _HildonAppPrivate HildonAppPrivate; - -static gboolean -hildon_app_key_press (GtkWidget *widget, GdkEventKey *keyevent); -static gboolean -hildon_app_key_release (GtkWidget *widget, GdkEventKey *keyevent); -static gboolean -hildon_app_key_snooper (GtkWidget *widget, GdkEventKey *keyevent, HildonApp *app); -static GdkFilterReturn -hildon_app_event_filter (GdkXEvent *xevent, GdkEvent *event, gpointer data); -static void -hildon_app_construct_title (HildonApp *self); -static void -hildon_app_finalize (GObject *obj_self); -static void -hildon_app_destroy (GtkObject *obj); -static void -hildon_app_init (HildonApp *self); -static void -hildon_app_class_init (HildonAppClass *app_class); -static void -hildon_app_real_topmost_status_acquire (HildonApp *self); -static void -hildon_app_real_topmost_status_lose (HildonApp *self); -static void -hildon_app_real_switch_to (HildonApp *self); -static gboolean -hildon_app_button (GtkWidget *widget, GdkEventButton *event); -static GdkWindow * -find_window (GdkWindow *window, gint by, gint co); -static void -hildon_app_clipboard_copy(HildonApp *self, GtkWidget *widget); -static void -hildon_app_clipboard_cut(HildonApp *self, GtkWidget *widget); -static void -hildon_app_clipboard_paste(HildonApp *self, GtkWidget *widget); -static gboolean hildon_app_escape_timeout(gpointer data); - -static void hildon_app_set_property(GObject * object, guint property_id, - const GValue * value, GParamSpec * pspec); -static void hildon_app_get_property(GObject * object, guint property_id, - GValue * value, GParamSpec * pspec); - -static void hildon_app_add (GtkContainer *container, GtkWidget *child); -static void hildon_app_remove (GtkContainer *container, GtkWidget *child); -static void hildon_app_forall (GtkContainer *container, gboolean include_internals, - GtkCallback callback, gpointer callback_data); - -enum { - PROP_0, - PROP_SCROLL_CONTROL, - /* FIXME: Zoom is deprecated, should be removed */ - PROP_ZOOM, - PROP_TWO_PART_TITLE, - PROP_APP_TITLE, - PROP_KILLABLE, - PROP_AUTOREGISTRATION, - PROP_APPVIEW, - PROP_UI_MANAGER -}; - -static gpointer find_view(HildonApp *self, unsigned long view_id); - -/* FIXME: Zoom level is deprecated, should be removed */ -/** - * hildon_zoom_level_get_type: - * - * Initialises, and returns the type of a hildon zoom level - * - * Returns: GType of #HildonZoomLevel - */ - -GType -hildon_zoom_level_get_type (void) -{ - static GType etype = 0; - if (etype == 0) { - static const GEnumValue values[] = { - { HILDON_ZOOM_SMALL, "HILDON_ZOOM_SMALL", "small" }, - { HILDON_ZOOM_MEDIUM, "HILDON_ZOOM_MEDIUM", "medium" }, - { HILDON_ZOOM_LARGE, "HILDON_ZOOM_LARGE", "large" }, - { 0, NULL, NULL } - }; - etype = g_enum_register_static ("HildonZoomLevel", values); - } - return etype; -} - -GType hildon_app_get_type(void) -{ - static GType app_type = 0; - - if (!app_type) - { - static const GTypeInfo app_info = - { - sizeof(HildonAppClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_app_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonApp), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_app_init, - }; - app_type = g_type_register_static(GTK_TYPE_WINDOW, - "HildonApp", &app_info, 0); - } - return app_type; -} - -/* - * Sets or delete a custom property into the XServer, according - * to the boolean value of HildonAppPrivate::killable - */ -static void hildon_app_apply_killable(HildonApp *self) -{ - HildonAppPrivate *priv; - Atom killability_atom = XInternAtom (GDK_DISPLAY(), - "_HILDON_APP_KILLABLE", False); - priv = HILDON_APP_GET_PRIVATE (self); - - g_assert (HILDON_IS_APP (self) ); - g_assert(GTK_WIDGET_REALIZED(self)); - - if (priv->killable) - { - /* Set the atom to specific value, because perhaps in the future, - there may be other possible values? */ - XChangeProperty(GDK_DISPLAY(), - GDK_WINDOW_XID(GTK_WIDGET(self)->window), - killability_atom, XA_STRING, 8, - PropModeReplace, (unsigned char *)KILLABLE, - strlen(KILLABLE)); - } - else - { - XDeleteProperty(GDK_DISPLAY(), - GDK_WINDOW_XID(GTK_WIDGET(self)->window), - killability_atom); - } -} - -/* - * Updates the _NET_CLIENT_LIST property into the XServer. - * It is the list of the views associated to the HildonApp. - * It will be used by the Task Navigator in order to be able to show a list - * of all the views, and let the user switch and navigate them. - */ -static void hildon_app_apply_client_list(HildonApp *self) -{ - HildonAppPrivate *priv; - Window *win_array; - GSList *list_ptr; - int loopctr = 0; - Atom clientlist; - - g_assert (HILDON_IS_APP (self) ); - g_assert(GTK_WIDGET_REALIZED(self)); - - /* Get the client list handle */ - clientlist = XInternAtom (GDK_DISPLAY(), - "_NET_CLIENT_LIST", False); - - /* Allocate a new array for window IDs */ - priv = HILDON_APP_GET_PRIVATE(self); - win_array = g_new(Window, g_slist_length(priv->view_ids)); - - /* Fill the contents of the window array with current view IDs */ - for (list_ptr = priv->view_ids; list_ptr; list_ptr = list_ptr->next) - { - win_array[loopctr] = - (unsigned long)(((view_item *)(list_ptr->data))->view_id); - loopctr++; - } - - /* Update the details of current view IDs to our X property */ - XChangeProperty(GDK_DISPLAY(), GDK_WINDOW_XID(GTK_WIDGET(self)->window), - clientlist, XA_WINDOW, 32, PropModeReplace, - (unsigned char *)win_array, - g_slist_length(priv->view_ids)); - - XFlush(GDK_DISPLAY()); - g_free(win_array); -} - -/* - * Performs the standard gtk realize function. - */ -static void hildon_app_realize(GtkWidget *widget) -{ - HildonApp *self; - HildonAppPrivate *priv; - GdkWindow *window; - Atom *old_atoms, *new_atoms; - gint atom_count; - Display *disp; - - g_assert(widget != NULL); - - self = HILDON_APP(widget); - priv = HILDON_APP_GET_PRIVATE(self); - - /* - * Of course we need to realize the parent. - * parent_class got already initialised in the hildon_app_init function - */ - GTK_WIDGET_CLASS(parent_class)->realize(widget); - - /* some initialisation code */ - hildon_app_apply_killable(self); - hildon_app_construct_title(self); - hildon_app_apply_client_list(self); - hildon_app_notify_view_changed(self, hildon_app_get_appview(self)); - window = widget->window; - disp = GDK_WINDOW_XDISPLAY(window); - - /* Install a key snooper for the Home button - so that it works everywhere */ - priv->key_snooper = gtk_key_snooper_install - ((GtkKeySnoopFunc) hildon_app_key_snooper, widget); - - /* Get the list of Atoms for the WM_PROTOCOLS property... */ - XGetWMProtocols(disp, GDK_WINDOW_XID(window), &old_atoms, &atom_count); - new_atoms = g_new(Atom, atom_count + 1); - - memcpy(new_atoms, old_atoms, sizeof(Atom) * atom_count); - - /* ... creates a new Atom... */ - new_atoms[atom_count++] = - XInternAtom(disp, "_NET_WM_CONTEXT_CUSTOM", False); - - /* ... and finally update the property within the XServer */ - XSetWMProtocols(disp, GDK_WINDOW_XID(window), new_atoms, atom_count); - - XFree(old_atoms); - g_free(new_atoms); - - /* Add the GDK_SUBSTRUCTURE_MASK (receive events about window configuration - * changes of child windows) to the window. - */ - gdk_window_set_events(window, gdk_window_get_events(window) | GDK_SUBSTRUCTURE_MASK); -} - -/* - * Performs the standard gtk unrealize function. - */ -static void hildon_app_unrealize(GtkWidget *widget) -{ - HildonAppPrivate *priv = HILDON_APP_GET_PRIVATE(widget); - - if (priv->key_snooper) - { - /* removing the snooper that handles MENU key presses */ - gtk_key_snooper_remove(priv->key_snooper); - priv->key_snooper = 0; - } - - gdk_window_remove_filter(NULL, hildon_app_event_filter, widget); - GTK_WIDGET_CLASS(parent_class)->unrealize(widget); -} - -/* - * Class initialisation. - */ -static void hildon_app_class_init (HildonAppClass *app_class) -{ - /* get convenience variables */ - GObjectClass *object_class = G_OBJECT_CLASS(app_class); - GtkContainerClass *container_class = GTK_CONTAINER_CLASS (app_class); - GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS(app_class); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(app_class); - - /* set the global parent_class here */ - parent_class = g_type_class_peek_parent(app_class); - - g_type_class_add_private(app_class, sizeof(HildonAppPrivate)); - - /* now the object stuff */ - object_class->finalize = hildon_app_finalize; - object_class->set_property = hildon_app_set_property; - object_class->get_property = hildon_app_get_property; - - gtkobject_class->destroy = hildon_app_destroy; - - widget_class->key_press_event = hildon_app_key_press; - widget_class->key_release_event = hildon_app_key_release; - widget_class->button_press_event = hildon_app_button; - widget_class->button_release_event = hildon_app_button; - widget_class->realize = hildon_app_realize; - widget_class->unrealize = hildon_app_unrealize; - - container_class->add = hildon_app_add; - container_class->remove = hildon_app_remove; - container_class->forall = hildon_app_forall; - - app_class->topmost_status_acquire = - hildon_app_real_topmost_status_acquire; - app_class->topmost_status_lose = hildon_app_real_topmost_status_lose; - app_class->switch_to = hildon_app_real_switch_to; - - /* create the signals */ - app_signals[TOPMOST_STATUS_ACQUIRE] = - g_signal_new("topmost_status_acquire", - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(HildonAppClass, - topmost_status_acquire), NULL, NULL, - g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - - app_signals[TOPMOST_STATUS_LOSE] = - g_signal_new("topmost_status_lose", - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(HildonAppClass, topmost_status_lose), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - - app_signals[SWITCH_TO] = - g_signal_new("switch_to", - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(HildonAppClass, switch_to), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - - app_signals[IM_CLOSE] = - g_signal_new("im_close", - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(HildonAppClass, im_close), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - - app_signals[CLIPBOARD_COPY] = - g_signal_new("clipboard_copy", - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(HildonAppClass, clipboard_copy), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, - GTK_TYPE_WIDGET); - app_signals[CLIPBOARD_CUT] = - g_signal_new("clipboard_cut", - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(HildonAppClass, clipboard_cut), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, - GTK_TYPE_WIDGET); - app_signals[CLIPBOARD_PASTE] = - g_signal_new("clipboard_paste", - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(HildonAppClass, clipboard_paste), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, - GTK_TYPE_WIDGET); - - /* properties */ - g_object_class_install_property(object_class, PROP_SCROLL_CONTROL, - g_param_spec_boolean("scroll-control", - "Scroll control", - "Set the scroll control ON/OFF", - TRUE, G_PARAM_READWRITE)); - - g_object_class_install_property(object_class, PROP_TWO_PART_TITLE, - g_param_spec_boolean("two-part-title", - "Two part title", - "Use two part title or not", - FALSE, G_PARAM_READWRITE)); -#ifndef HILDON_DISABLE_DEPRECATED - g_object_class_install_property(object_class, PROP_ZOOM, - g_param_spec_enum ("zoom", - "Zoom level", - "Set the zoom level", - HILDON_TYPE_ZOOM_LEVEL, - HILDON_ZOOM_MEDIUM, - G_PARAM_READWRITE)); -#endif - g_object_class_install_property(object_class, PROP_APP_TITLE, - g_param_spec_string ("app-title", - "Application title", - "Set the application title", - "", - G_PARAM_READWRITE)); - - g_object_class_install_property(object_class, PROP_KILLABLE, - g_param_spec_boolean("killable", - "Killable", - "Whether the application is killable or not", - FALSE, - G_PARAM_READWRITE)); - g_object_class_install_property(object_class, PROP_AUTOREGISTRATION, - g_param_spec_boolean("autoregistration", - "Autoregistration", - "Whether the application views should be registered automatically", - TRUE, - G_PARAM_READWRITE)); - g_object_class_install_property(object_class, PROP_APPVIEW, - g_param_spec_object("appview", - "Appplication View", - "The currently active application view", - HILDON_TYPE_APPVIEW, - G_PARAM_READWRITE)); - g_object_class_install_property(object_class, PROP_UI_MANAGER, - g_param_spec_object("ui-manager", - "UIManager", - "The associated GtkUIManager for this app", - GTK_TYPE_UI_MANAGER, - G_PARAM_READWRITE)); -} - -/* - * Performs the standard gtk finalize function, freeing allocated - * memory and propagating the finalization to the parent. - */ -static void -hildon_app_finalize (GObject *obj) -{ - HildonAppPrivate *priv = NULL; - - g_assert (obj != NULL); - - priv = HILDON_APP_GET_PRIVATE (obj); - - g_free (priv->title); - - if (G_OBJECT_CLASS(parent_class)->finalize) - G_OBJECT_CLASS(parent_class)->finalize(obj); - - /* FIXME: This is legacy code, but cannot be removed - without changing functionality */ - gtk_main_quit (); -} - -/* - * Removes the long escape ("cancel" hw key) press timeout. - */ -static void -hildon_app_remove_timeout(HildonAppPrivate *priv) -{ - g_assert(priv != NULL); - - if (priv->escape_timeout > 0) - { - g_source_remove (priv->escape_timeout); - priv->escape_timeout = 0; - } -} - -/* - * Frees all the resources and propagates the destroy call to the parent. - */ -static void -hildon_app_destroy (GtkObject *obj) -{ - HildonAppPrivate *priv = NULL; - - g_assert (obj != NULL); - - priv = HILDON_APP_GET_PRIVATE (obj); - - /* Just in case a GDK_Escape key was pressed shortly before the propagation - * of this event, it is safer to remove the timeout that will generate a - * GDK_DELETE key press. We are destroying the app, so we're not interested - * anymore in processing key presses. - */ - hildon_app_remove_timeout(priv); - - if (priv->uim != NULL) - { - g_object_unref (G_OBJECT (priv->uim)); - priv->uim = NULL; - } - - /* Free all the views */ - if (priv->view_ids) - { - g_slist_foreach (priv->view_ids, (GFunc)g_free, NULL); - g_slist_free (priv->view_ids); - priv->view_ids = NULL; - } - - if (GTK_OBJECT_CLASS (parent_class)->destroy) - GTK_OBJECT_CLASS (parent_class)->destroy(obj); -} - -/* - * Overrides gtk_container_forall, calling the callback function for each of - * the children of HildonAppPrivate. - */ -static void hildon_app_forall (GtkContainer *container, gboolean include_internals, - GtkCallback callback, gpointer callback_data) -{ - HildonAppPrivate *priv = NULL; - - g_return_if_fail (container != NULL); - g_return_if_fail (callback != NULL); - - priv = HILDON_APP_GET_PRIVATE (container); - - /* Note! we only have user added children, no internals */ - g_list_foreach (priv->children, (GFunc)callback, callback_data); -} - -/* - * An accessor to set private properties of HildonAppPrivate. - */ -static void hildon_app_set_property(GObject * object, guint property_id, - const GValue * value, GParamSpec * pspec) -{ - HildonAppPrivate *priv = HILDON_APP_GET_PRIVATE(object); - - switch (property_id) { - case PROP_SCROLL_CONTROL: - priv->scroll_control = g_value_get_boolean(value); - break; -#ifndef HILDON_DISABLE_DEPRECATED - case PROP_ZOOM: - hildon_app_set_zoom( HILDON_APP (object), g_value_get_enum (value) ); - break; -#endif - case PROP_TWO_PART_TITLE: - hildon_app_set_two_part_title( HILDON_APP (object), - g_value_get_boolean (value) ); - break; - case PROP_APP_TITLE: - hildon_app_set_title( HILDON_APP (object), g_value_get_string (value)); - break; - case PROP_KILLABLE: - hildon_app_set_killable( HILDON_APP (object), - g_value_get_boolean (value)); - break; - case PROP_AUTOREGISTRATION: - hildon_app_set_autoregistration( HILDON_APP (object), - g_value_get_boolean (value)); - break; - case PROP_APPVIEW: - hildon_app_set_appview( HILDON_APP (object), - HILDON_APPVIEW (g_value_get_object (value))); - break; - case PROP_UI_MANAGER: - hildon_app_set_ui_manager( HILDON_APP (object), - GTK_UI_MANAGER (g_value_get_object (value))); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; - } -} - -/* - * An accessor to get private properties of HildonAppPrivate. - */ -static void hildon_app_get_property(GObject * object, guint property_id, - GValue * value, GParamSpec * pspec) -{ - HildonAppPrivate *priv = HILDON_APP_GET_PRIVATE(object); - - switch (property_id) { - case PROP_SCROLL_CONTROL: - g_value_set_boolean( value, priv->scroll_control ); - break; -#ifndef HILDON_DISABLE_DEPRECATED - case PROP_ZOOM: - g_value_set_enum( value, priv->zoom); - break; -#endif - case PROP_TWO_PART_TITLE: - g_value_set_boolean( value, priv->twoparttitle); - break; - case PROP_APP_TITLE: - g_value_set_string (value, priv->title); - break; - case PROP_KILLABLE: - g_value_set_boolean (value, priv->killable); - break; - case PROP_AUTOREGISTRATION: - g_value_set_boolean (value, priv->autoregistration); - break; - case PROP_APPVIEW: - g_value_set_object (value, hildon_app_get_appview (HILDON_APP (object))); - break; - case PROP_UI_MANAGER: - g_value_set_object (value, hildon_app_get_ui_manager (HILDON_APP (object))); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; - } -} - -/* - * Adds a child widget to HildonApp. - */ -static void hildon_app_add (GtkContainer *container, GtkWidget *child) -{ - HildonApp *app = NULL; - HildonAppPrivate *priv = NULL; - - g_return_if_fail (container != NULL); - g_return_if_fail (GTK_IS_WIDGET (child)); - - app = HILDON_APP (container); - priv = HILDON_APP_GET_PRIVATE (app); - - /* Check if child is already added here */ - if (g_list_find (priv->children, child) != NULL) - return; - - priv->children = g_list_append (priv->children, child); - GTK_BIN (container)->child = child; - gtk_widget_set_parent (child, GTK_WIDGET (app)); - - /* If the default direction (RTL/LTR) is different from the real - default, change it This happens if the locale has been changed - but this appview was orphaned and thus never got to know about - it. "default_direction" could be RTL, but the widget direction - of the view might still be LTR. Thats what we're fixing here. */ - - /* FIXME: This is legacy stuff */ - if (gtk_widget_get_default_direction () != - gtk_widget_get_direction (GTK_WIDGET (child))) - { - gtk_widget_set_direction (GTK_WIDGET (child), - gtk_widget_get_default_direction ()); - } - - if (HILDON_IS_APPVIEW (child)) - { - g_signal_connect_swapped (G_OBJECT (child), "title_change", - G_CALLBACK (hildon_app_construct_title), app); - if (priv->autoregistration) - hildon_app_register_view (app, child); - } -} - -/* - * Removes a child widget from HildonApp. - */ -static void hildon_app_remove (GtkContainer *container, GtkWidget *child) -{ - HildonAppPrivate *priv; - GtkBin *bin; - HildonApp *app; - - g_return_if_fail (container != NULL); - g_return_if_fail (GTK_IS_WIDGET (child)); - - priv = HILDON_APP_GET_PRIVATE (container); - bin = GTK_BIN (container); - app = HILDON_APP (bin); - - /* Make sure that child is found in the list */ - if (g_list_find (priv->children, child) == NULL) - return; - - priv->children = g_list_remove (priv->children, child); - - if (HILDON_IS_APPVIEW (child)) - { - /* FIXME: This is a compilation workaround for gcc > 3.3, since glib-2 API is buggy. - * see http://bugzilla.gnome.org/show_bug.cgi?id=310175 */ - -G_GNUC_EXTENSION - - g_signal_handlers_disconnect_by_func (G_OBJECT (child), - (gpointer)hildon_app_construct_title, app); - - if (priv->autoregistration) - hildon_app_unregister_view (app, HILDON_APPVIEW (child)); - } - - /* If that was our visible child, we need to recalculate size. - We could chain up to parent as well... */ - gtk_widget_unparent (child); - - if (bin->child == child) - { - bin->child = NULL; - gtk_widget_queue_resize (GTK_WIDGET (bin)); - } -} - - -/* - * Long escape keypress handler. - * Long press of the escape key means "close this window", so we fake a delete-event - * for our GdkWindow to make it act the same as if the user had closed the window the - * usual way. This allows any application code to gracefully exit. - * - * It returns FALSE in order to get called only once. - */ -static gboolean -hildon_app_escape_timeout(gpointer app) -{ - HildonAppPrivate *priv; - GdkEvent *event; - - GDK_THREADS_ENTER (); - - g_assert(GTK_WIDGET_REALIZED(app)); - - priv = HILDON_APP_GET_PRIVATE(app); - - /* Send fake event, simulation a situation that user - pressed 'x' from the corner */ - event = gdk_event_new(GDK_DELETE); - ((GdkEventAny *)event)->window = GTK_WIDGET(app)->window; - gtk_main_do_event(event); - gdk_event_free(event); - - priv->escape_timeout = 0; - - GDK_THREADS_LEAVE (); - - return FALSE; -} - -/* - * Looks for the visible window to whom the point of coordinates (co,by) - * belongs. Search recursively all the children of the window. - * - * This functionality is only needed for scrollbar remote control. - */ -static GdkWindow *find_window (GdkWindow *window, gint by, gint co) -{ - GdkWindow *child; - GList *children = gdk_window_peek_children (window); - - /* If the window has no children, then the coordinates must match it */ - if (!children) - return window; - - if (!(child = (GdkWindow *)children->data)) - return window; - - do - { - /* It makes sense to process a child window only if it's visible and it's - * capable to get the GDK_BUTTON_PRESS_MASK event. */ - if (gdk_window_is_visible (child) && - gdk_window_get_events (child) & GDK_BUTTON_PRESS_MASK) - { - gint x, width, y, height; - - gdk_window_get_geometry (child, &x, &y, &width, &height, NULL); - /* This checks that the the point of coordinates (co,by) is in the rectangle - * made by (x,y,x+width,y+height). If so, then we spotted which child of the - * original window is in the point (co,by). We can now recursively search - * its own children. - */ - if (x < co && x + width > co && y < by && y + height > by) - return find_window (child, by, co); - } - - /* If the window has no more children, then it's the one we're looking for */ - if (!(children = g_list_next (children))) - return window; - - } while ( (child = children->data)); - - return NULL; -} - -/* - * This is the callback function that gets called on a mouse button press - * event. If the press is happens in a "sensitive border" area in the right side of - * the window, the event is translated to the left edge of that border (which - * usually will contain a scrollbar). - * - * This functionality is used for right-hand side scroll control feature (dragging on the - * right edge of the window controls the rightmost scrollbar if present). - */ -static gboolean -hildon_app_button (GtkWidget *widget, GdkEventButton *event) -{ - HildonAppPrivate *priv = NULL; - - /* FIXME: This is an estimate, but the AppView does not expose the - width of it's borders so we default to something */ - gint sensitive_border = 31; - - if (!GTK_WIDGET_REALIZED(widget)) - { - return FALSE; - } - - priv = HILDON_APP_GET_PRIVATE (widget); - - if (!priv->scroll_control) - { - return FALSE; - } - - /* We can easily get the location of the vertical scrollbar and get the exact - * area for the scroll_control *if* the setup is such that the HildonAppview - * contains a GtkScrolledWindow, so we check for it before defaulting to - * the previous guess. More complex situations are not feasible to autodetect. - * Applications should provide the GtkAdjustment to be changed for this to work - * flawlessly. - */ - if (HILDON_IS_APPVIEW(GTK_BIN(widget)->child)) - { - GtkBin *avbin = GTK_BIN(GTK_BIN(widget)->child); - if (GTK_IS_SCROLLED_WINDOW(avbin->child)) - { - GtkScrolledWindow *win; - win = GTK_SCROLLED_WINDOW(avbin->child); - - if (GTK_WIDGET_VISIBLE(win->vscrollbar)) - { - /* Calculate the distance between the AppView's right border and - * the scrollbars center - */ - sensitive_border = (GTK_WIDGET(avbin)->allocation.x + - GTK_WIDGET(avbin)->allocation.width) - - (win->vscrollbar->allocation.x + - win->vscrollbar->allocation.width / 2); - } - } - } - - /* If the press event comes to the sensitive area, we send a fake event to the - * area we think the scrollbar is in to make it think the button press happened on it - */ - if (event->x > widget->allocation.width - sensitive_border) - { - GdkWindow *window = NULL; - gint co = widget->allocation.width - sensitive_border; - - /* We now need to know in which window the _modified_ coordinates are */ - if ((window = find_window (widget->window, event->y, co))) - { - GdkEventButton nevent; - - if (window == widget->window) - return FALSE; - - /* Build a new event and associate the proper window to it */ - nevent = *event; - nevent.x = 8; - nevent.window = window; - g_object_ref (nevent.window); - gtk_main_do_event ((GdkEvent*)&nevent); - } - } - return FALSE; -} - -/* - * Performs the initialisation of the widget. - */ -static void -hildon_app_init (HildonApp *self) -{ - HildonAppPrivate *priv; - - priv = HILDON_APP_GET_PRIVATE(self); - - /* init private */ - priv->title = g_strdup(""); -#ifndef HILDON_DISABLE_DEPRECATED - priv->zoom = HILDON_ZOOM_MEDIUM; -#endif - priv->twoparttitle = FALSE; - priv->lastmenuclick = 0; - priv->is_topmost = FALSE; - priv->curr_view_id = 0; - priv->view_id_counter = 1; - priv->view_ids = NULL; - priv->killable = FALSE; - priv->autoregistration = TRUE; - priv->scroll_control = TRUE; - priv->uim = NULL; - priv->active_menu_id = 0; - - /* grab the events here since HildonApp isn't necessarily ever shown */ - gdk_window_set_events(gdk_get_default_root_window(), - gdk_window_get_events(gdk_get_default_root_window()) | - GDK_PROPERTY_CHANGE_MASK); - - /* For some reason, the titlebar menu has problems with the grab - (bugzilla bug 1527). This is part of somewhat ugly fix for it to - get it to work until a more satisfactory solution is found */ - gdk_window_add_filter(NULL, hildon_app_event_filter, self); - - gtk_widget_set_events (GTK_WIDGET(self), GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK | - GDK_POINTER_MOTION_MASK); -} - -/*public functions */ - -/** - * hildon_app_new: - * - * Creates a new #HildonApp - * - * Returns: pointer to a new #HildonApp structure - */ -GtkWidget * -hildon_app_new (void) -{ - return GTK_WIDGET(g_object_new(HILDON_TYPE_APP, NULL)); -} - -/** - * hildon_app_new_with_appview: - * @appview : a #HildonAppView - * - * Creates an app, and sets it's initial appview. - * - * Returns: pointer to a new #HildonApp structure - */ -GtkWidget * -hildon_app_new_with_appview (HildonAppView *appview) -{ - GtkWidget *app; - - g_return_val_if_fail (HILDON_IS_APPVIEW (appview), NULL); - - app = hildon_app_new (); - - hildon_app_set_appview(HILDON_APP(app), appview); - - return app; -} - -/** - * hildon_app_get_appview: - * @self : a #HildonApp - * - * Gets the currently shown appview. - * - * Returns: the currently shown appview in this HildonApp. - * If no appview is currently set for this HildonApp, - * returns NULL. - */ -HildonAppView * -hildon_app_get_appview (HildonApp *self) -{ - GtkBin *bin; - - g_return_val_if_fail (HILDON_IS_APP (self), NULL); - bin = GTK_BIN (self); - if (HILDON_IS_APPVIEW (bin->child)) - { - return HILDON_APPVIEW (bin->child); - } - - return NULL; -} - -/** - * hildon_app_set_appview: - * @self : a #HildonApp - * @appview : a #HildonAppView - * - * Sets (switches to) appview. - */ -void -hildon_app_set_appview (HildonApp *app, HildonAppView *view) -{ - HildonAppPrivate *priv; - GtkBin *bin; - GtkWidget *widget; /*(view to be set)*/ - gchar *menu_ui; - - g_return_if_fail (HILDON_IS_APP (app)); - g_return_if_fail (HILDON_IS_APPVIEW (view)); - - bin = GTK_BIN (app); - priv = HILDON_APP_GET_PRIVATE (app); - widget = GTK_WIDGET (view); - - if (widget == bin->child) - return; - - /* Make old appview dissapear */ - if (bin->child) - { - gtk_widget_hide (bin->child); - g_signal_emit_by_name (bin->child, "switched_from", NULL); - - if (priv->active_menu_id > 0) - { - if (priv->uim != NULL) - { - gtk_ui_manager_remove_ui (priv->uim, - priv->active_menu_id); - } - priv->active_menu_id = 0; - } - - bin->child = NULL; - } - - /* Ensure that new view is in our child list */ - if (!g_list_find (priv->children, widget)) - gtk_container_add (GTK_CONTAINER (app), widget); - - bin->child = widget; - - gtk_widget_show (widget); - - /* UI manager support, merge menu for activated view */ - g_object_get (G_OBJECT (view), - "menu-ui", &menu_ui, - NULL); - - if (menu_ui && priv->uim) - { - - priv->active_menu_id = - gtk_ui_manager_add_ui_from_string (priv->uim, menu_ui, -1, NULL); - - gtk_ui_manager_ensure_update (priv->uim); - - } - - g_free (menu_ui); - - g_signal_emit_by_name (widget, "switched_to", NULL); - - /* Inform task navigator about changed view */ - hildon_app_notify_view_changed (app, view); - - /* Update title to show currently activated view */ - hildon_app_construct_title (app); - gtk_widget_child_focus (widget, GTK_DIR_TAB_FORWARD); -} - -/** - * hildon_app_set_title: - * @self : a #HildonApp - * @newtitle : the new title assigned to the application - * - * Sets title of the application. - */ -void -hildon_app_set_title (HildonApp *self, const gchar *newtitle) -{ - HildonAppPrivate *priv; - gchar *oldstr; - - g_return_if_fail(HILDON_IS_APP(self)); - - priv = HILDON_APP_GET_PRIVATE(self); - oldstr = priv->title; - - if (newtitle) - { - priv->title = g_strdup(newtitle); - g_strstrip(priv->title); - } - else - priv->title = g_strdup(""); - - if (oldstr) - g_free(oldstr); - - hildon_app_construct_title(self); -} - -/** - * hildon_app_get_title: - * @self : a #HildonApp - * - * Gets the title of the application. - * - * Returns: the title currently assigned to the application. This - * value is not to be freed or modified by the calling application - */ -const gchar * -hildon_app_get_title (HildonApp *self) -{ - HildonAppPrivate *priv; - - g_return_val_if_fail (HILDON_IS_APP(self), NULL); - priv = HILDON_APP_GET_PRIVATE(self); - return priv->title; -} - -/* FIXME: Zoom is deprecated, remove */ -/** - * hildon_app_set_zoom: - * @self : a #HildonApp - * @newzoom: the zoom level of type #HildonZoomLevel to be assigned to an - * application - * - * Sets the zoom level. Warning! This function is deprecated and - * should not be used. It's lecacy stuff from ancient specs. - */ -void -hildon_app_set_zoom (HildonApp *self, HildonZoomLevel newzoom) -{ - HildonAppPrivate *priv; - - g_return_if_fail(HILDON_IS_APP(self)); - - priv = HILDON_APP_GET_PRIVATE(self); - - if (newzoom != priv->zoom) - { - if (newzoom < HILDON_ZOOM_SMALL) - { - newzoom = HILDON_ZOOM_SMALL; - gtk_infoprint(GTK_WINDOW(self), _("ckct_ib_min_zoom_level_reached")); - } - else if (newzoom > HILDON_ZOOM_LARGE) { - newzoom = HILDON_ZOOM_LARGE; - gtk_infoprint(GTK_WINDOW(self), _("ckct_ib_max_zoom_level_reached")); - } - priv->zoom = newzoom; - } -} - -/** - * hildon_app_get_zoom: - * @self : a #HildonApp - * - * Gets the zoom level. Warning! This function is deprecated and - * should not be used. It's lecacy stuff from ancient specifications. - * - * Returns: the zoom level of the Hildon application. The - * returned zoom level is of type #HildonZoomLevel. - */ -HildonZoomLevel -hildon_app_get_zoom (HildonApp *self) -{ - HildonAppPrivate *priv; - - g_return_val_if_fail(HILDON_IS_APP(self), HILDON_ZOOM_MEDIUM); - priv = HILDON_APP_GET_PRIVATE(self); - return priv->zoom; -} - -/** - * hildon_app_get_default_font: - * @self : a #HildonApp - * - * Gets default font. Warning! This function is deprecated and should - * not be used. It's legacy stuff from ancient version of specification. - * - * Returns: pointer to PangoFontDescription for the default, - * normal size font - */ -PangoFontDescription * -hildon_app_get_default_font (HildonApp *self) -{ - PangoFontDescription *font_desc = NULL; - GtkStyle *fontstyle = NULL; - - g_return_val_if_fail(HILDON_IS_APP(self), NULL); - - fontstyle = - gtk_rc_get_style_by_paths (gtk_widget_get_settings - (GTK_WIDGET(self)), NULL, NULL, - gtk_widget_get_type()); - - if (!fontstyle) - { - g_print("WARNING : default font not found. " - "Defaulting to swissa 19\n"); - font_desc = pango_font_description_from_string("swissa 19"); - - } - else - font_desc = pango_font_description_copy(fontstyle->font_desc); - - return font_desc; -} - -/** - * hildon_app_get_zoom_font: - * @self : a #HildonApp - * - * Gets the description of the default font. Warning! This function - * is deprecated and should not be used. It's legacy stuff from - * ancient specs. - * - * Returns: pointer to PangoFontDescription for the default, - * normal size font - */ -PangoFontDescription * -hildon_app_get_zoom_font (HildonApp *self) -{ - HildonAppPrivate *priv; - PangoFontDescription *font_desc = NULL; - gchar *style_name = 0; - GtkStyle *fontstyle = NULL; - - g_return_val_if_fail(HILDON_IS_APP(self), NULL); - - priv = HILDON_APP_GET_PRIVATE(self); - if (priv->zoom == HILDON_ZOOM_SMALL) - style_name = g_strdup("hildon-zoom-small"); - else if (priv->zoom == HILDON_ZOOM_MEDIUM) - style_name = g_strdup("hildon-zoom-medium"); - else if (priv->zoom == HILDON_ZOOM_LARGE) - style_name = g_strdup("hildon-zoom-large"); - else - { - g_warning("Invalid Zoom Value\n"); - style_name = g_strdup(""); - } - - fontstyle = - gtk_rc_get_style_by_paths (gtk_widget_get_settings - (GTK_WIDGET(self)), style_name, NULL, - G_TYPE_NONE); - g_free (style_name); - - if (!fontstyle) - { - g_print("WARNING : theme specific zoomed font not found. " - "Defaulting to preset zoom-specific fonts\n"); - if (priv->zoom == HILDON_ZOOM_SMALL) - font_desc = pango_font_description_from_string("swissa 16"); - else if (priv->zoom == HILDON_ZOOM_MEDIUM) - font_desc = pango_font_description_from_string("swissa 19"); - else if (priv->zoom == HILDON_ZOOM_LARGE) - font_desc = pango_font_description_from_string("swissa 23"); - } - else - font_desc = pango_font_description_copy(fontstyle->font_desc); - - return font_desc; -} - - /* FIXME: Zoom is deprecated, remove the code above */ - -/** - * hildon_app_set_two_part_title: - * @self : a #HildonApp - * @istwoparttitle : a gboolean indicating wheter to activate - * a title that has both the application title and application - * view title separated by a triangle - * - * Sets the two part title. - */ -void -hildon_app_set_two_part_title (HildonApp *self, gboolean istwoparttitle) -{ - HildonAppPrivate *priv; - g_return_if_fail(HILDON_IS_APP(self)); - priv = HILDON_APP_GET_PRIVATE(self); - - if (istwoparttitle != priv->twoparttitle) - { - priv->twoparttitle = istwoparttitle; - hildon_app_construct_title(self); - } -} - -/** - * hildon_app_get_two_part_title: - * @self : a #HildonApp - * - * Gets the 'twopart' represention of the title inside #HildonApp. - * - * Returns: a boolean indicating wheter title shown has both - * application, and application view title separated by a triangle. - */ -gboolean -hildon_app_get_two_part_title (HildonApp *self) -{ - HildonAppPrivate *priv; - - g_return_val_if_fail(HILDON_IS_APP(self), FALSE); - priv = HILDON_APP_GET_PRIVATE(self); - return priv->twoparttitle; -} - - -/* private functions */ - - -/* - * Handles the key press of the Escape, Increase and Decrease keys. Other keys - * are handled by the parent GtkWidgetClass. - */ -static gboolean -hildon_app_key_press (GtkWidget *widget, GdkEventKey *keyevent) -{ - HildonApp *app = HILDON_APP (widget); - HildonAppView *appview; - HildonAppPrivate *priv = HILDON_APP_GET_PRIVATE(app); - - if (HILDON_IS_APPVIEW(GTK_BIN (app)->child)) - { - appview = HILDON_APPVIEW (GTK_BIN (app)->child); - } - else - { - return FALSE; - } - - if (keyevent->keyval == GDK_Escape && priv->escape_timeout == 0) - { - /* Call hildon_app_escape_timeout every 1500ms until it returns FALSE - * and store the relative GSource id. Since hildon_app_escape_timeout - * can only return FALSE, the call will occurr only once. - */ - priv->escape_timeout = g_timeout_add(1500, hildon_app_escape_timeout, app); - } - - /* FIXME: Handling +/- keys here is not usefull. Applications - can equally easily handle the keypress themselves. */ - else if (HILDON_KEYEVENT_IS_INCREASE_KEY (keyevent)) - { - _hildon_appview_increase_button_state_changed (appview, - keyevent->type); - } - else if (HILDON_KEYEVENT_IS_DECREASE_KEY (keyevent)) - { - _hildon_appview_decrease_button_state_changed (appview, - keyevent->type); - } - - /* Activate default bindings and let the widget with focus to handle key */ - return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, keyevent); -} - -/* - * Handles the key release event for the Escape, Toolbar and Fullscreen keys. - */ -static gboolean -hildon_app_key_release (GtkWidget *widget, GdkEventKey *keyevent) -{ - HildonApp *app = HILDON_APP (widget); - HildonAppView *appview; - HildonAppPrivate *priv = HILDON_APP_GET_PRIVATE(app); - - if (HILDON_IS_APPVIEW(GTK_BIN (app)->child)) - { - appview = HILDON_APPVIEW (GTK_BIN (app)->child); - } - else - { - return FALSE; - } - - if (keyevent->keyval == GDK_Escape) - { - /* - * This will prevent the hildon_app_escape_timeout from being called. - * See hildon_app_escape_timeout and hildon_app_remove_timeout for more. - */ - hildon_app_remove_timeout(priv); - } - else if (HILDON_KEYEVENT_IS_TOOLBAR_KEY (keyevent)) - { - g_signal_emit_by_name(G_OBJECT(appview), - "toolbar-toggle-request"); - } - else if (HILDON_KEYEVENT_IS_FULLSCREEN_KEY (keyevent)) - { - /* Emit the fullscreen_state_change directly, it'll save one step */ - if (hildon_appview_get_fullscreen_key_allowed (appview)) - { - gboolean fullscreen; - - fullscreen = hildon_appview_get_fullscreen(appview); - g_signal_emit_by_name(G_OBJECT(appview), - "fullscreen_state_change", - !fullscreen); - } - } - - /* FIXME: Should the event be marked as handled if any of the three - above cases took an action */ - - /* Activate default bindings and let the widget with focus to handle key */ - return GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, keyevent); -} - -/* - * Handles the MENU key presses. - */ -static gboolean -hildon_app_key_snooper (GtkWidget *widget, GdkEventKey *keyevent, HildonApp *app) -{ - /* FIXME: Using normal keypress handler would be better choise. All - keyevents come to window anyway, so we would get the same - keys in that way as well, but we wouldn't need to struggle - with grabs (modal dialogs etc). */ - - /* Menu key handling is done here */ - if ( HILDON_KEYEVENT_IS_MENU_KEY (keyevent) ) { - HildonAppView *appview; - HildonAppPrivate *priv; - GtkWidget *toplevel; - GtkWidget *focus = NULL; - - /* Don't act on modal dialogs */ - toplevel = gtk_widget_get_toplevel (widget); - focus = gtk_window_get_focus(GTK_WINDOW(app)); - - /* Don't act when comboboxes are active, if a togglebutton - (combobox) has the focus and it is active, we deactivate the - combobox and do nothing */ - if (GTK_IS_TOGGLE_BUTTON (focus)) - { - GtkWidget *parent = gtk_widget_get_parent (focus); - - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (focus)) && - GTK_IS_COMBO_BOX (parent)) - { - gtk_combo_box_popdown (GTK_COMBO_BOX (parent)); - return TRUE; - } - } - - /* Don't act when a GtkWindow of a combobox is selected, this - can happen in some applications that change the properties of - the widget focus attribute, WARNING: we are using the name of - the hildon combobox widget to identify the window - (gtkcombobox.c, HILDON_COMBO_BOX_POPUP), if it changes we - must change this name */ - if (GTK_IS_WINDOW (widget) && - !g_ascii_strcasecmp("hildon-combobox-window", gtk_widget_get_name (widget))) - { - return TRUE; - } - - if (GTK_IS_DIALOG (toplevel) - && gtk_window_get_modal (GTK_WINDOW (toplevel))) - { - return TRUE; - } - - appview = HILDON_APPVIEW (GTK_BIN(app)->child); - priv = HILDON_APP_GET_PRIVATE(app); - - if ( keyevent->type == GDK_KEY_PRESS ) { - /* Toggle menu on press, avoid key repeat */ - if ( priv->lastmenuclick == 0 ){ - priv->lastmenuclick = 1; - if (_hildon_appview_toggle_menu(appview, - gtk_get_current_event_time())) - { - return TRUE; - } - } - } else if ( keyevent->type == GDK_KEY_RELEASE ) { - /* We got release, so next press is really a new press, - not a repeat */ - if ( priv->lastmenuclick == 1 ) { - priv->lastmenuclick = 0; - } - - } else { - /* Unknown key event */ - return FALSE; - } - - /* don't stop the key event so that it reaches GTK where it - closes all existing menus that might be open */ - return FALSE; - } - - return FALSE; -} - -/* - * Returns the message_type of the Atom registered with a certain name. - */ -static int -xclient_message_type_check(XClientMessageEvent *cm, const gchar *name) -{ - return cm->message_type == XInternAtom(GDK_DISPLAY(), name, FALSE); -} - -/* - * Returns the GtkWidget associated to a certain Window. - */ -static GtkWidget * -hildon_app_xwindow_lookup_widget(Window xwindow) -{ - GdkWindow *window; - gpointer widget; - - window = gdk_xid_table_lookup(xwindow); - if (window == NULL) - return NULL; - - gdk_window_get_user_data(window, &widget); - return widget; -} - -/* - * Let's search a actual main window using tranciency hints. - * Note that there can be several levels of menus/dialogs above - * the actual main window. - */ -static Window get_active_main_window(Window window) -{ - Window parent_window; - gint limit = 0; - - gdk_error_trap_push (); - - while (XGetTransientForHint(GDK_DISPLAY(), window, &parent_window)) - { - /* The limit > TRANSIENCY_MAXITER ensures that we can't be stuck - here forever if we have circular transiencies for some reason. - Use of _MB_CURRENT_APP_WINDOW might be more elegant... */ - - if (!parent_window || parent_window == GDK_ROOT_WINDOW() || - parent_window == window || limit > TRANSIENCY_MAXITER) - { - break; - } - - limit++; - window = parent_window; - } - - gdk_flush (); - - if (gdk_error_trap_pop ()) - return 0; - - return window; -} - -/* - * Filters every GDK event first. - */ -static GdkFilterReturn -hildon_app_event_filter (GdkXEvent *xevent, GdkEvent *event, gpointer data) -{ - gint x,y; - HildonApp *app = data; - HildonAppPrivate *priv; - HildonAppView *appview = NULL; - - XAnyEvent *eventti = xevent; - - if (HILDON_IS_APPVIEW (GTK_BIN (app)->child)) - { - appview = HILDON_APPVIEW (GTK_BIN (app)->child); - } - - g_return_val_if_fail (app, GDK_FILTER_CONTINUE); - g_return_val_if_fail (HILDON_IS_APP(app), GDK_FILTER_CONTINUE); - - priv = HILDON_APP_GET_PRIVATE(app); - if (eventti->type == ClientMessage) - { - XClientMessageEvent *cm = xevent; - - /* Check if a message indicating a click on titlebar has been - received. Don't open it if mouse is grabbed (eg. modal dialog - was just opened). - _MB_GRAB_TRANSFER is emitted by MatchBox, and signals that a button - has just been released. */ - if (xclient_message_type_check(cm, "_MB_GRAB_TRANSFER") && - HILDON_IS_APPVIEW(appview) && - gtk_grab_get_current() == NULL && - !_hildon_appview_menu_visible(appview)) - { - _hildon_appview_toggle_menu(appview, cm->data.l[0]); - return GDK_FILTER_REMOVE; - } - /* IM_CLOSE is input method specific hack that is really questionable */ - else if (xclient_message_type_check(cm, "_HILDON_IM_CLOSE")) - { - g_signal_emit_by_name(app, "im_close", NULL); - return GDK_FILTER_REMOVE; - } - /* Task user changed the view through task navigator? */ - else if (xclient_message_type_check(cm, "_NET_ACTIVE_WINDOW")) - { - unsigned long view_id = cm->window; - gpointer view_ptr = find_view(app, view_id); - - /* When getting a _NET_ACTIVE_WINDOW signal from the WM we need - * to bring the application to the front */ - if (!priv->is_topmost) - g_signal_emit_by_name (G_OBJECT(app), "topmost_status_acquire"); - - if (HILDON_IS_APPVIEW(view_ptr)) - /* Sets the current view to the "window" that the _NET_ACTIVE_WINDOW - * specified */ - hildon_app_set_appview(app, (HILDON_APPVIEW(view_ptr))); - else - /* there was no view, so we have to switch to an actual application */ - g_signal_emit_by_name (G_OBJECT(app), "switch_to", view_ptr); - - /* FIXME: This is a hack. This was once just gtk_window_present, but - was changed into this at some day!! */ - if (GTK_WIDGET(app)->window) - { - mb_util_window_activate(GDK_DISPLAY(), - GDK_WINDOW_XID(GTK_WIDGET(app)->window)); - } - } - /* FIXME: IM hack */ - else if (xclient_message_type_check(cm, "_HILDON_IM_CLIPBOARD_COPY")) - { - Window xwindow = cm->data.l[0]; - GtkWidget *widget = hildon_app_xwindow_lookup_widget(xwindow); - - g_signal_emit_by_name (G_OBJECT(app), "clipboard_copy", widget); - } - /* FIXME: IM hack */ - else if (xclient_message_type_check(cm, "_HILDON_IM_CLIPBOARD_CUT")) - { - Window xwindow = cm->data.l[0]; - GtkWidget *widget = hildon_app_xwindow_lookup_widget(xwindow); - - g_signal_emit_by_name (G_OBJECT(app), "clipboard_cut", widget); - } - /* FIXME: IM hack */ - else if (xclient_message_type_check(cm, "_HILDON_IM_CLIPBOARD_PASTE")) - { - Window xwindow = cm->data.l[0]; - GtkWidget *widget = hildon_app_xwindow_lookup_widget(xwindow); - - g_signal_emit_by_name (G_OBJECT(app), "clipboard_paste", widget); - } - } - - if (eventti->type == ButtonPress) - { - - /* FIXME: This is mysterious bugfix related to problems to open the - application menu (bugzilla N#3204) */ - XButtonEvent *bev = (XButtonEvent *)xevent; - - if (HILDON_IS_APPVIEW(appview) && - _hildon_appview_menu_visible(appview) && - !hildon_appview_get_fullscreen(appview)) - { - x = bev->x_root; - y = bev->y_root; - if ( (x >= MENUAREA_LEFT_LIMIT) && (x <= MENUAREA_RIGHT_LIMIT) && - (y >= MENUAREA_TOP_LIMIT) && (y <= MENUAREA_BOTTOM_LIMIT)) - { - _hildon_appview_toggle_menu(appview, bev->time); - return GDK_FILTER_CONTINUE; - } - } - } - - /* FIXME: as above */ - if (eventti->type == ButtonRelease) - { - if (HILDON_IS_APPVIEW(appview) && - _hildon_appview_menu_visible(appview) && - !hildon_appview_get_fullscreen(appview)) - { - XButtonEvent *bev = (XButtonEvent *)xevent; - x = bev->x_root; - y = bev->y_root; - if ( (x >= MENUAREA_LEFT_LIMIT) && (x < MENUAREA_RIGHT_LIMIT) && - (y >= MENUAREA_TOP_LIMIT) && (y <= MENUAREA_BOTTOM_LIMIT)) - { - return GDK_FILTER_REMOVE; - } - } - return GDK_FILTER_CONTINUE; - } - - /* Application stacking order changed */ - if (eventti->type == PropertyNotify) - { - Atom active_app_atom = - XInternAtom (GDK_DISPLAY(), "_MB_CURRENT_APP_WINDOW", False); - XPropertyEvent *prop = xevent; - - if ((prop->atom == active_app_atom) - && (prop->window == GDK_ROOT_WINDOW())) - { - Atom realtype; - int format; - int status; - unsigned long n; - unsigned long extra; - Window my_window; - union - { - Window *win; - unsigned char *char_pointer; - } win; - - win.win = NULL; - - status = XGetWindowProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(), - active_app_atom, 0L, 16L, - 0, XA_WINDOW, &realtype, &format, - &n, &extra, &win.char_pointer); - if (!(status == Success && realtype == XA_WINDOW && format == 32 - && n == 1 && win.win != NULL)) - { - if (win.win != NULL) - XFree(win.char_pointer); - return GDK_FILTER_CONTINUE; - } - - my_window = GDK_WINDOW_XID(GTK_WIDGET(app)->window); - - /* Are we the topmost one? */ - if (win.win[0] == my_window || - get_active_main_window(win.win[0]) == my_window) - { - if (!priv->is_topmost) - g_signal_emit_by_name (G_OBJECT(app), - "topmost_status_acquire"); - } - else if (priv->is_topmost) - { - GtkWidget *focus = gtk_window_get_focus(GTK_WINDOW(app)); - - /* FIXME: IM hack, IM-module should do this in response to - topmost_status_lose (emission hook?) */ - if (GTK_IS_ENTRY(focus)) - gtk_im_context_focus_out(GTK_ENTRY(focus)->im_context); - if (GTK_IS_TEXT_VIEW(focus)) - gtk_im_context_focus_out(GTK_TEXT_VIEW(focus)->im_context); - - g_signal_emit_by_name (app, "topmost_status_lose"); - } - - if (win.win != NULL) - XFree(win.char_pointer); - } - } - - return GDK_FILTER_CONTINUE; - } - -/* - * Sets the GTK Window title to the application's title, or - * combined appview/app title, if two part title is asked. - */ -static void -hildon_app_construct_title (HildonApp *self) -{ - g_return_if_fail (HILDON_IS_APP (self)); - - if (GTK_WIDGET_REALIZED(self)) - { - HildonAppPrivate *priv; - GdkAtom subname; - gchar *concatenated_title = NULL; - HildonAppView *appview; - - priv = HILDON_APP_GET_PRIVATE (self); - appview = hildon_app_get_appview(self); - - /* FIXME: The subname property is legacy stuff no longer supported by - Matchbox. However, it is still set for the convenience of - the Task Navigator. */ - subname = gdk_atom_intern("_MB_WIN_SUB_NAME", FALSE); - - if (!appview || !hildon_app_get_two_part_title(self) || - g_utf8_strlen(hildon_appview_get_title(appview), -1) < 1 ) - { - /* Set an invisible dummy value if there is no appview title */ - gdk_property_change (GTK_WIDGET(self)->window, subname, - gdk_atom_intern ("UTF8_STRING", FALSE), - 8, GDK_PROP_MODE_REPLACE, (guchar *) " \0", 1); - gtk_window_set_title (GTK_WINDOW(self), priv->title); - } - else - { - gdk_property_change (GTK_WIDGET(self)->window, subname, - gdk_atom_intern ("UTF8_STRING", FALSE), - 8, GDK_PROP_MODE_REPLACE, - (guchar *)hildon_appview_get_title(appview), - strlen(hildon_appview_get_title (appview))); - concatenated_title = g_strjoin(TITLE_DELIMITER, priv->title, - hildon_appview_get_title(appview), NULL); - /* priv->title should always be non-null, but check anyway */ - if (concatenated_title != NULL) - { - gtk_window_set_title (GTK_WINDOW(self), concatenated_title); - g_free(concatenated_title); - } - } - } -} - -/* - * Callback function to the topmost_status_acquire signal emitted by - * hildon_app_event_filter function. See it for more details. - */ -void -hildon_app_real_topmost_status_acquire (HildonApp *self) -{ - HildonAppPrivate *priv; - g_return_if_fail (HILDON_IS_APP (self)); - priv = HILDON_APP_GET_PRIVATE (self); - - /* FIXME: What is the logic not to update topmost status now? */ - if (!GTK_BIN (self)->child) - return; - - priv->is_topmost = TRUE; -} - -/* - * Callback function to the topmost_status_lose signal emitted by - * hildon_app_event_filter function. See it for more details. - */ -void -hildon_app_real_topmost_status_lose (HildonApp *self) -{ - HildonAppPrivate *priv; - g_return_if_fail (HILDON_IS_APP (self)); - priv = HILDON_APP_GET_PRIVATE (self); - - /* FIXME: What is the logic not to update topmost status now? */ - if (!GTK_BIN (self)->child) - return; - - priv->is_topmost = FALSE; -} - -void -hildon_app_real_switch_to (HildonApp *self) -{ - g_return_if_fail (HILDON_IS_APP (self)); - /* Do we have to do anything here? */ -} - - -/** - * hildon_app_set_autoregistration - * @self : a #HildonApp - * @auto_reg : whether the (app)view autoregistration should be active - * - * Controls the autoregistration/unregistration of (app)views. - */ - -void hildon_app_set_autoregistration(HildonApp *self, gboolean auto_reg) -{ - HildonAppPrivate *priv; - g_return_if_fail (HILDON_IS_APP (self)); - - priv = HILDON_APP_GET_PRIVATE (self); - priv->autoregistration = auto_reg; -} - - -/** - * hildon_app_register_view: - * @self : a #HildonApp - * @view_ptr : pointer to the view instance to be registered - * - * Registers a new view. For appviews, this can be done automatically - * if autoregistration is set. - */ - -void hildon_app_register_view(HildonApp *self, gpointer view_ptr) -{ - HildonAppPrivate *priv; - view_item *view_item_inst; - - g_return_if_fail (HILDON_IS_APP (self) || view_ptr != NULL); - - priv = HILDON_APP_GET_PRIVATE (self); - - if (hildon_app_find_view_id(self, view_ptr) == 0) - { - /* The pointer to the view was unique, so add it to the list */ - view_item_inst = g_malloc(sizeof(view_item)); - view_item_inst->view_id = priv->view_id_counter; - view_item_inst->view_ptr = view_ptr; - - priv->view_id_counter++; - - priv->view_ids = - g_slist_append(priv->view_ids, view_item_inst); - - /* Update the list of views */ - if (GTK_WIDGET_REALIZED(self)) - hildon_app_apply_client_list(self); - } -} - - -/** - * hildon_app_register_view_with_id: - * @self : a #HildonApp - * @view_ptr : pointer to the view instance to be registered - * @view_id : the ID of the view - * - * Registers a new view. Allows the application to specify any ID. - * - * Returns: TRUE if the view registration succeeded, FALSE otherwise. - * The probable cause of failure is that view with that ID - * already existed. - */ - -gboolean hildon_app_register_view_with_id(HildonApp *self, - gpointer view_ptr, - unsigned long view_id) -{ - view_item *view_item_inst; - HildonAppPrivate *priv; - GSList *list_ptr = NULL; - - g_return_val_if_fail (HILDON_IS_APP (self), FALSE); - g_return_val_if_fail (view_ptr, FALSE); - - priv = HILDON_APP_GET_PRIVATE (self); - - list_ptr = priv->view_ids; - - /* Check that the view is not already registered */ - while (list_ptr) - { - if ( (gpointer)((view_item *)list_ptr->data)->view_ptr == view_ptr - && (unsigned long)((view_item *)list_ptr->data)->view_id == view_id) - { - return FALSE; - } - list_ptr = list_ptr->next; - } - - /* The pointer to the view was unique, so add it to the list */ - view_item_inst = g_malloc(sizeof(view_item)); - view_item_inst->view_id = view_id; - view_item_inst->view_ptr = view_ptr; - - priv->view_ids = - g_slist_append(priv->view_ids, view_item_inst); - - priv->view_id_counter++; - - /* Finally, update the _NET_CLIENT_LIST property */ - if (GTK_WIDGET_REALIZED(self)) - hildon_app_apply_client_list(self); - - return TRUE; -} - -/** - * hildon_app_unregister_view: - * @self : a #HildonApp - * @view_ptr : pointer to the view instance to be unregistered - * - * Unregisters a view from HildonApp. Done usually when a view is - * destroyed. For appviews, this is can be automatically - * if autoregistration is set. - */ -void hildon_app_unregister_view(HildonApp *self, gpointer view_ptr) -{ - HildonAppPrivate *priv = NULL; - GSList *list_ptr = NULL; - - g_return_if_fail (HILDON_IS_APP (self)); - g_return_if_fail (view_ptr != NULL); - - priv = HILDON_APP_GET_PRIVATE (self); - - /* Search the view from the list */ - list_ptr = priv->view_ids; - - while (list_ptr) - { - if ( (gpointer)((view_item *)list_ptr->data)->view_ptr == view_ptr) - { - /* Found the view, kick it off */ - g_free (list_ptr->data); - priv->view_ids = g_slist_delete_link(priv->view_ids, list_ptr); - break; - } - list_ptr = list_ptr->next; - } - - if (GTK_WIDGET_REALIZED(self)) - hildon_app_apply_client_list(self); -} - - -/** - * hildon_app_unregister_view_with_id: - * @self: a #HildonApp - * @view_id: the ID of the view that should be unregistered - * - * Unregisters a view with specified ID, if it exists. - */ -void hildon_app_unregister_view_with_id(HildonApp *self, - unsigned long view_id) -{ - HildonAppPrivate *priv; - GSList *list_ptr = NULL; - - g_return_if_fail (HILDON_IS_APP (self)); - - priv = HILDON_APP_GET_PRIVATE (self); - - /* Search the view from the list */ - list_ptr = priv->view_ids; - - while (list_ptr) - { - if ( (unsigned long)((view_item *)list_ptr->data)->view_id == view_id) - { - /* Found view with given id, kick it off */ - g_free (list_ptr->data); - priv->view_ids = g_slist_delete_link(priv->view_ids, list_ptr); - break; - } - list_ptr = list_ptr->next; - } - - /* Update client list to reflect new situation. If we are not - realized, then nobody knows about us anyway... */ - if (GTK_WIDGET_REALIZED(self)) - hildon_app_apply_client_list(self); -} - - -/** - * hildon_app_notify_view_changed: - * @self : a #HildonApp - * @view_ptr : pointer to the view that is switched to - * - * Updates the X property that contains the currently active view - */ -void hildon_app_notify_view_changed(HildonApp *self, gpointer view_ptr) -{ - g_return_if_fail (HILDON_IS_APP (self)); - g_return_if_fail (view_ptr != NULL); - - /* We need GdkWindow before we can send X messages */ - if (GTK_WIDGET_REALIZED(self)) - { - gulong id = hildon_app_find_view_id(self, view_ptr); - Atom active_view = XInternAtom (GDK_DISPLAY(), - "_NET_ACTIVE_WINDOW", False); - - if (id) { - /* Set _NET_ACTIVE_WINDOW for our own toplevel to contain view id */ - XChangeProperty(GDK_DISPLAY(), GDK_WINDOW_XID(GTK_WIDGET(self)->window), - active_view, XA_WINDOW, 32, PropModeReplace, - (unsigned char *)&id, 1); - XFlush(GDK_DISPLAY()); - } - } -} - - -/** - * hildon_app_find_view_id: - * @self : a #HildonApp - * @view_ptr : pointer to the view whose ID we want to acquire - * - * Returns: the ID of the view, or 0 if not found - * - * Allows mapping of view pointer to its view ID. If NULL is passed - * as the view pointer, returns the ID of the current view. - */ -unsigned long hildon_app_find_view_id(HildonApp *self, gpointer view_ptr) -{ - HildonAppPrivate *priv; - GSList *iter; - - priv = HILDON_APP_GET_PRIVATE (self); - - /* If no view is given, find the ID for the currently visible view */ - if (!view_ptr) - view_ptr = GTK_BIN (self)->child; - if (!view_ptr) - return 0; - - /* Iterate through list and search for given view pointer */ - for (iter = priv->view_ids; iter; iter = iter->next) - { - if ( (gpointer)((view_item *)iter->data)->view_ptr == view_ptr) - return (unsigned long)((view_item *)iter->data)->view_id; - } - - return 0; -} - -/** - * hildon_app_set_killable: - * @self : a #HildonApp - * @killability : truth value indicating whether the app can be killed - * - * Updates information about whether the application can be killed or not by - * Task Navigator (i.e. whether its statesave is up to date) - */ -void hildon_app_set_killable(HildonApp *self, gboolean killability) -{ - HildonAppPrivate *priv = HILDON_APP_GET_PRIVATE (self); - g_return_if_fail (HILDON_IS_APP (self) ); - - if (killability != priv->killable) - { - priv->killable = killability; - - /* If we have a window, then we can actually set this - property. Otherwise we wait until we are realized */ - if (GTK_WIDGET_REALIZED(self)) - hildon_app_apply_killable(self); - } -} - - -/** - * hildon_app_set_ui_manager: - * @self : #HildonApp - * @uim : #GtkUIManager to be set - * - * Sets the #GtkUIManager assigned to the #HildonApp. - * If @uim is NULL, unsets the current ui manager. - * The @HildonApp holds a reference to the ui manager until - * the @HildonApp is destroyed or unset. - */ -void hildon_app_set_ui_manager(HildonApp *self, GtkUIManager *uim) -{ - HildonAppPrivate *priv; - - g_return_if_fail(self && HILDON_IS_APP(self)); - - priv = HILDON_APP_GET_PRIVATE (self); - - /* Release old ui-manager object if such exists */ - if (priv->uim != NULL) - { - g_object_unref (G_OBJECT (priv->uim)); - } - - priv->uim = uim; - - /* If we got new ui-manager (it's perfectly valid not - to give one), acquire reference to it */ - if (priv->uim != NULL) - { - g_object_ref (G_OBJECT (uim)); - } - - g_object_notify (G_OBJECT(self), "ui-manager"); -} - -/** - * hildon_app_get_ui_manager: - * @self : #HildonApp - * - * Gets the #GtkUIManager assigned to the #HildonApp. - * - * Returns: the #GtkUIManager assigned to this application - * or null if no manager is assigned - */ -GtkUIManager *hildon_app_get_ui_manager(HildonApp *self) -{ - HildonAppPrivate *priv; - - g_return_val_if_fail(self && HILDON_IS_APP(self), NULL); - - priv = HILDON_APP_GET_PRIVATE (self); - - return (priv->uim); -} - -/* - * Search for a view with the given id within HildonApp. - * Returns a pointer to the found view, or NULL if not found. - */ -static gpointer find_view(HildonApp *self, unsigned long view_id) -{ - HildonAppPrivate *priv; - GSList *iter; - - priv = HILDON_APP_GET_PRIVATE (self); - - /* Iterate through the list of view ids and search given id */ - for (iter = priv->view_ids; iter; iter = iter->next) - { - if ( (unsigned long)((view_item *)iter->data)->view_id == view_id) - return (gpointer)((view_item *)iter->data)->view_ptr; - } - - return NULL; -} diff --git a/hildon-widgets/hildon-app.h b/hildon-widgets/hildon-app.h deleted file mode 100644 index bf41d04..0000000 --- a/hildon-widgets/hildon-app.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_APP_H__ -#define __HILDON_APP_H__ - -#include -#include -#include "hildon-appview.h" - -G_BEGIN_DECLS -/** - * HildonApp: - * - * Contains only private data not to be touched by outsiders. - */ -typedef struct _HildonApp HildonApp; -typedef struct _HildonAppClass HildonAppClass; - -#define HILDON_TYPE_APP ( hildon_app_get_type() ) - -#define HILDON_APP(obj) (GTK_CHECK_CAST (obj, HILDON_TYPE_APP, \ - HildonApp)) - -#define HILDON_APP_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), \ - HILDON_TYPE_APP, HildonAppClass)) - -#define HILDON_IS_APP(obj) (GTK_CHECK_TYPE (obj, HILDON_TYPE_APP)) - -#define HILDON_IS_APP_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), \ - HILDON_TYPE_APP)) - - -struct _HildonApp { - GtkWindow parent; -}; - -struct _HildonAppClass { - GtkWindowClass parent_class; - void (*topmost_status_acquire) (HildonApp *self); - void (*topmost_status_lose) (HildonApp *self); - void (*switch_to) (HildonApp *self); /* FIXME: Possible browser hack?? */ - void (*im_close) (HildonApp *self); - void (*clipboard_copy) (HildonApp *self, GtkWidget *widget); - void (*clipboard_cut) (HildonApp *self, GtkWidget *widget); - void (*clipboard_paste) (HildonApp *self, GtkWidget *widget); -}; - -#ifndef HILDON_DISABLE_DEPRECATED -/* Make these values >0 so that we can detect when someone sets SMALL-1 - * zoom level (enum seems to be unsigned int) - */ - -/** - * HildonZoomLevel: - * @HILDON_ZOOM_SMALL: Smallest font. - * @HILDON_ZOOM_MEDIUM: Middle size font. - * @HILDON_ZOOM_LARGE: Largest font. - * - * The Hildon zoom levels. Small meaning small font. Large meaning - * large font. These font are specified in the gtkrc files. - * This enum is deprecated and should not be used. It's just - * lecagy stuff from ancient specs. - */ -typedef enum /*< skip >*/ -{ - HILDON_ZOOM_SMALL = 1, - HILDON_ZOOM_MEDIUM = 2, - HILDON_ZOOM_LARGE = 3 -} HildonZoomLevel; - -#define HILDON_TYPE_ZOOM_LEVEL (hildon_zoom_level_get_type ()) - -GType hildon_zoom_level_get_type (void); -#endif /* deprecated */ - - -/* You should use the correct ones from hildon-defines.h - * - * FIXME: These should be removed when API changes are allowed, - * they are not used in hildon code anymore (but might be in external). - */ -#define HILDON_MENU_KEY GDK_F4 -#define HILDON_HOME_KEY GDK_F5 -#define HILDON_TOOLBAR_KEY GDK_T -#define HILDON_FULLSCREEN_KEY GDK_F6 -#define HILDON_INCREASE_KEY GDK_F7 -#define HILDON_DECREASE_KEY GDK_F8 -#define HILDON_TOOLBAR_MODIFIERS (GDK_SHIFT_MASK | GDK_CONTROL_MASK) - -#define HILDON_KEYEVENT_IS_MENU_KEY(keyevent) (keyevent->keyval == HILDON_MENU_KEY) -#define HILDON_KEYEVENT_IS_HOME_KEY(keyevent) (keyevent->keyval == HILDON_HOME_KEY) -#define HILDON_KEYEVENT_IS_TOOLBAR_KEY(keyevent) ((keyevent->keyval == HILDON_TOOLBAR_KEY) && \ - (keyevent->state == HILDON_TOOLBAR_MODIFIERS)) -#define HILDON_KEYEVENT_IS_FULLSCREEN_KEY(keyevent) (keyevent->keyval == HILDON_FULLSCREEN_KEY) -#define HILDON_KEYEVENT_IS_INCREASE_KEY(keyevent) (keyevent->keyval == HILDON_INCREASE_KEY) -#define HILDON_KEYEVENT_IS_DECREASE_KEY(keyevent) (keyevent->keyval == HILDON_DECREASE_KEY) - -#define TRANSIENCY_MAXITER 50 - -GType hildon_app_get_type(void) G_GNUC_CONST; -GtkWidget *hildon_app_new(void); -GtkWidget *hildon_app_new_with_appview(HildonAppView * appview); -void hildon_app_set_appview(HildonApp * self, HildonAppView * appview); -HildonAppView *hildon_app_get_appview(HildonApp * self); -void hildon_app_set_title(HildonApp * self, const gchar * newtitle); -const gchar *hildon_app_get_title(HildonApp * self); - -#ifndef HILDON_DISABLE_DEPRECATED -void hildon_app_set_zoom(HildonApp * self, HildonZoomLevel newzoom); -HildonZoomLevel hildon_app_get_zoom(HildonApp * self); -PangoFontDescription *hildon_app_get_default_font(HildonApp * self); -PangoFontDescription *hildon_app_get_zoom_font(HildonApp * self); -#endif - -void hildon_app_set_two_part_title(HildonApp * self, - gboolean istwoparttitle); -gboolean hildon_app_get_two_part_title(HildonApp * self); - -void hildon_app_set_autoregistration(HildonApp *self, gboolean auto_reg); -void hildon_app_register_view(HildonApp *self, gpointer view_ptr); -gboolean hildon_app_register_view_with_id(HildonApp *self, - gpointer view_ptr, - unsigned long view_id); -void hildon_app_unregister_view(HildonApp *self, gpointer view_ptr); -void hildon_app_unregister_view_with_id(HildonApp *self, - unsigned long view_id); -unsigned long hildon_app_find_view_id(HildonApp *self, gpointer view_ptr); -void hildon_app_notify_view_changed(HildonApp *self, gpointer view_ptr); - -void hildon_app_set_killable(HildonApp *self, gboolean killability); - -void hildon_app_set_ui_manager(HildonApp *self, GtkUIManager *uim); -GtkUIManager *hildon_app_get_ui_manager(HildonApp *self); - -G_END_DECLS -#endif /* __HILDON_APP_H__ */ diff --git a/hildon-widgets/hildon-appview.c b/hildon-widgets/hildon-appview.c deleted file mode 100644 index 631eb1e..0000000 --- a/hildon-widgets/hildon-appview.c +++ /dev/null @@ -1,1495 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-appview - * @short_description: A widget which present one view of an application - * @see_also: #HildonApp - * - * #HildonAppView is a widget which presents one view of an application. - * Application can have many different views and the appview helps to organize. - * It has automatic fullscreen and menu handling. It also helps to handle - * components like a toolbar. - */ - -#include -#include -#include -#include -#include "hildon-app.h" -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - -#include -#define _(String) gettext(String) - -enum { - PROP_0, - PROP_CONNECTED_ADJUSTMENT, - PROP_FULLSCREEN_KEY_ALLOWED, - PROP_FULLSCREEN, - PROP_TITLE, - PROP_MENU_UI -}; - -/*The size of screen*/ -#define WINDOW_HEIGHT 480 -#define WINDOW_WIDTH 800 - -#define NAVIGATOR_HEIGHT WINDOW_HEIGHT - -#define APPVIEW_HEIGHT 396 -#define APPVIEW_WIDTH 672 - -#define TOOLBAR_HEIGHT 40 -#define TOOLBAR_UP 9 -#define TOOLBAR_DOWN 9 -#define TOOLBAR_MIDDLE 10 -#define TOOLBAR_RIGHT 24 -#define TOOLBAR_LEFT 24 -#define TOOLBAR_WIDTH APPVIEW_WIDTH - -#define WORKAREA_ATOM "_NET_WORKAREA" - -/* Non atom defines */ -#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */ -#define _NET_WM_STATE_ADD 1 /* add/set property */ - -/*Margins - * These margins are set to be 5pixels smaller than in the specs - * Inner things are allocation that extra space - * */ -/* -#define MARGIN_TOOLBAR_TOP 2 -#define MARGIN_TOOLBAR_BOTTOM 6 -#define MARGIN_TOOLBAR_LEFT 22 -#define MARGIN_TOOLBAR_RIGHT 23 -*/ -#define MARGIN_APPVIEW_TOP 0 -#define MARGIN_APPVIEW_BOTTOM 24 -#define MARGIN_APPVIEW_LEFT 24 -#define MARGIN_APPVIEW_RIGHT 24 - - -#define HILDON_APPVIEW_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ - HILDON_TYPE_APPVIEW, HildonAppViewPrivate)) - -/*Progressbar*/ -#define DEFAULT_WIDTH 20 -#define DEFAULT_HEIGHT 28 -#define BANNER_WIDTH DEFAULT_WIDTH -#define BANNER_HEIGHT DEFAULT_HEIGHT - -static GtkBinClass *parent_class; - -static void hildon_appview_init(HildonAppView * self); -static void hildon_appview_class_init(HildonAppViewClass * appview_class); - -static void hildon_appview_menupopupfunc(GtkMenu *menu, gint *x, gint *y, - gboolean *push_in, - GtkWidget *widget); -static void hildon_appview_menupopupfuncfull(GtkMenu *menu, gint *x, gint *y, - gboolean *push_in, - GtkWidget *widget); -static gboolean hildon_appview_expose(GtkWidget * widget, - GdkEventExpose * event); -static void hildon_appview_forall(GtkContainer * container, - gboolean include_internals, - GtkCallback callback, - gpointer callback_data); -static void hildon_appview_show_all(GtkWidget *widget); - -static void hildon_appview_size_allocate(GtkWidget * widget, - GtkAllocation * allocation); -static void hildon_appview_size_request(GtkWidget * widget, - GtkRequisition * requisition); -static void hildon_appview_finalize(GObject * obj_self); -static void hildon_appview_set_property(GObject * object, guint property_id, - const GValue * value, GParamSpec * pspec); -static void hildon_appview_get_property(GObject * object, guint property_id, - GValue * value, GParamSpec * pspec); -static void hildon_appview_destroy(GtkObject *obj); -static void hildon_appview_real_fullscreen_state_change(HildonAppView * - self, - gboolean - fullscreen); -static void hildon_appview_switched_to(HildonAppView * self); -static void get_client_area(GtkWidget * widget, - GtkAllocation * allocation); - -typedef void (*HildonAppViewSignal) (HildonAppView *, gint, gpointer); - -/* signals */ -enum { - TOOLBAR_CHANGED, - TOOLBAR_TOGGLE_REQUEST, - FULLSCREEN_STATE_CHANGE, - TITLE_CHANGE, - SWITCHED_TO, - SWITCHED_FROM, - INCREASE_BUTTON_EVENT, - DECREASE_BUTTON_EVENT, - HILDON_APPVIEW_LAST_SIGNAL -}; - -static guint appview_signals[HILDON_APPVIEW_LAST_SIGNAL] = { 0 }; - -enum { - WIN_TYPE = 0, - WIN_TYPE_MESSAGE, - MAX_WIN_MESSAGES -}; - -struct _HildonAppViewPrivate { - GtkWidget *menu; - gchar *title; - - GtkAllocation allocation; - - guint fullscreen : 1; - guint fullscreenshortcutallowed : 1; - - /* For future expansion. - * We might use the below variables for disabling keyrepeat if we need it someday. */ - guint increase_button_pressed_down : 1; - guint decrease_button_pressed_down : 1; - gint visible_toolbars; - GtkAdjustment * connected_adjustment; - - gchar *menu_ui; -}; - -/* FIXME: Extremely old Legacy code. I wonder why we need - a custom marshaller in the first place. */ -static void hildon_appview_signal_marshal(GClosure * closure, - GValue * return_value, - guint n_param_values, - const GValue * param_values, - gpointer invocation_hint, - gpointer marshal_data) -{ - register HildonAppViewSignal callback; - register GCClosure *cc = (GCClosure *) closure; - register gpointer data1, data2; - - g_assert(n_param_values == 2); - - if (G_CCLOSURE_SWAP_DATA(closure)) { - data1 = closure->data; - data2 = g_value_peek_pointer(param_values + 0); - } else { - data1 = g_value_peek_pointer(param_values + 0); - data2 = closure->data; - } - - callback = - /* FIXME: This is a compilation workaround for gcc > 3.3 since glib is buggy */ - /* see http://bugzilla.gnome.org/show_bug.cgi?id=310175 */ - -#ifdef __GNUC__ - __extension__ -#endif - (HildonAppViewSignal) (marshal_data != - NULL ? marshal_data : cc->callback); - - callback((HildonAppView *) data1, - (gint) g_value_get_int(param_values + 1), data2); -} - -GType hildon_appview_get_type(void) -{ - static GType appview_type = 0; - - if (!appview_type) { - static const GTypeInfo appview_info = { - sizeof(HildonAppViewClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_appview_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonAppView), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_appview_init, - }; - appview_type = g_type_register_static(GTK_TYPE_BIN, - "HildonAppView", - &appview_info, 0); - } - return appview_type; -} - -/* - * Class initialisation. - */ -static void hildon_appview_class_init(HildonAppViewClass * appview_class) -{ - /* Get convenience variables */ - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(appview_class); - GObjectClass *object_class = G_OBJECT_CLASS(appview_class); - GtkContainerClass *container_class = - GTK_CONTAINER_CLASS(appview_class); - - /* Set the global parent_class here */ - parent_class = g_type_class_peek_parent(appview_class); - - object_class->set_property = hildon_appview_set_property; - object_class->get_property = hildon_appview_get_property; - - /* Set the widgets virtual functions */ - widget_class->size_allocate = hildon_appview_size_allocate; - widget_class->size_request = hildon_appview_size_request; - widget_class->expose_event = hildon_appview_expose; - widget_class->show_all = hildon_appview_show_all; - /* widget_class->realize = hildon_appview_realize; */ - - /* now the object stuff */ - object_class->finalize = hildon_appview_finalize; - - /* To the container */ - container_class->forall = hildon_appview_forall; - - /* gtkobject stuff*/ - GTK_OBJECT_CLASS(appview_class)->destroy = hildon_appview_destroy; - - /* And own virtual functions */ - appview_class->fullscreen_state_change = - hildon_appview_real_fullscreen_state_change; - appview_class->switched_to = hildon_appview_switched_to; - - g_type_class_add_private(appview_class, - sizeof(struct _HildonAppViewPrivate)); - - /* New signals */ - appview_signals[TOOLBAR_CHANGED] = - g_signal_new("toolbar-changed", - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(HildonAppViewClass, toolbar_changed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - - appview_signals[TOOLBAR_TOGGLE_REQUEST] = - g_signal_new("toolbar-toggle-request", - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(HildonAppViewClass, - toolbar_toggle_request), NULL, NULL, - g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - - appview_signals[FULLSCREEN_STATE_CHANGE] = - g_signal_new("fullscreen_state_change", - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(HildonAppViewClass, - fullscreen_state_change), NULL, NULL, - hildon_appview_signal_marshal, G_TYPE_NONE, 1, - G_TYPE_INT); - - appview_signals[TITLE_CHANGE] = - g_signal_new("title_change", - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(HildonAppViewClass, title_change), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - - appview_signals[SWITCHED_TO] = - g_signal_new("switched_to", - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(HildonAppViewClass, switched_to), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - - appview_signals[SWITCHED_FROM] = - g_signal_new("switched_from", - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(HildonAppViewClass, switched_from), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - - appview_signals[INCREASE_BUTTON_EVENT] = - g_signal_new("increase_button_event", - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(HildonAppViewClass, increase_button_event), - NULL, NULL, - g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, - G_TYPE_UINT); - - appview_signals[DECREASE_BUTTON_EVENT] = - g_signal_new("decrease_button_event", - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(HildonAppViewClass, decrease_button_event), - NULL, NULL, - g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, - G_TYPE_UINT); - - /* New properties */ - g_object_class_install_property(object_class, PROP_CONNECTED_ADJUSTMENT, - g_param_spec_object("connected-adjustment", - "Connected GtkAdjustment", - "The GtkAdjustment. The increase and decrease hardware buttons are mapped to this.", - GTK_TYPE_ADJUSTMENT, - G_PARAM_READWRITE)); - - g_object_class_install_property(object_class, PROP_FULLSCREEN_KEY_ALLOWED, - g_param_spec_boolean("fullscreen-key-allowed", - "Fullscreen key allowed", - "Whether the fullscreen key is allowed or not", - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property(object_class, PROP_FULLSCREEN, - g_param_spec_boolean("fullscreen", - "Fullscreen", - "Whether the appview should be fullscreen or not", - FALSE, - G_PARAM_READWRITE)); - g_object_class_install_property(object_class, PROP_TITLE, - g_param_spec_string("title", - "Title", - "Appview title", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property(object_class, PROP_MENU_UI, - g_param_spec_string("menu-ui", - "Menu UI string", - "UI string for application view menu", - NULL, - G_PARAM_READWRITE)); - widget_class = (GtkWidgetClass*) appview_class; -} - -/* - * Performs the initialisation of the widget. - */ -static void hildon_appview_init(HildonAppView * self) -{ - HildonAppViewPrivate *priv = self->priv = - HILDON_APPVIEW_GET_PRIVATE(self); - - /* the vbox is used to handle both the view's main body and how many - * toolbars as the user wants */ - - self->vbox = gtk_vbox_new(TRUE, TOOLBAR_MIDDLE); - /* TOOLBAR_MIDDLE is here properly used, as originally meant. In order to - * be free to use whatever distance between toolbars, it's crucial to mind - * that the relevant gtkrc file must contain the following border property - * for the "toolbar-frame-middle" property: border = {24, 24, 5, 4} - */ - - gtk_widget_set_parent(self->vbox, GTK_WIDGET(self)); - priv->menu = NULL; - priv->visible_toolbars = 0; - - priv->title = g_strdup(""); - - priv->fullscreen = FALSE; - priv->fullscreenshortcutallowed = FALSE; - priv->increase_button_pressed_down = FALSE; - priv->decrease_button_pressed_down = FALSE; - - priv->connected_adjustment = NULL; -} - -/* - * Performs the standard gtk finalize function, freeing allocated - * memory and propagating the finalization to the parent. - */ -static void hildon_appview_finalize(GObject * obj_self) -{ - HildonAppView *self; - g_assert(HILDON_APPVIEW(obj_self)); - self = HILDON_APPVIEW(obj_self); - - if (self->priv->menu_ui) - g_free (self->priv->menu_ui); - - if (self->priv->connected_adjustment != NULL) - g_object_remove_weak_pointer (G_OBJECT (self->priv->connected_adjustment), - (gpointer) &self->priv->connected_adjustment); - - if (G_OBJECT_CLASS(parent_class)->finalize) - G_OBJECT_CLASS(parent_class)->finalize(obj_self); - - g_free(self->priv->title); -} - -/* - * An accessor to set private properties of HildonAppView. - */ -static void hildon_appview_set_property(GObject * object, guint property_id, - const GValue * value, GParamSpec * pspec) -{ - HildonAppView *appview = HILDON_APPVIEW (object); - - switch (property_id) { - case PROP_CONNECTED_ADJUSTMENT: - hildon_appview_set_connected_adjustment (appview, g_value_get_object (value)); - break; - - case PROP_FULLSCREEN_KEY_ALLOWED: - hildon_appview_set_fullscreen_key_allowed (appview, g_value_get_boolean (value)); - break; - - case PROP_FULLSCREEN: - hildon_appview_set_fullscreen (appview, g_value_get_boolean (value)); - break; - - case PROP_TITLE: - hildon_appview_set_title (appview, g_value_get_string (value)); - break; - - case PROP_MENU_UI: - hildon_appview_set_menu_ui (appview, g_value_get_string (value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; - } -} - -/* - * An accessor to get private properties of HildonAppView. - */ -static void hildon_appview_get_property(GObject * object, guint property_id, - GValue * value, GParamSpec * pspec) -{ - HildonAppViewPrivate *priv = HILDON_APPVIEW_GET_PRIVATE(object); - - switch (property_id) { - case PROP_CONNECTED_ADJUSTMENT: - g_value_set_object (value, priv->connected_adjustment); - break; - - case PROP_FULLSCREEN_KEY_ALLOWED: - g_value_set_boolean (value, priv->fullscreenshortcutallowed); - break; - - case PROP_FULLSCREEN: - g_value_set_boolean (value, priv->fullscreen); - break; - - case PROP_TITLE: - g_value_set_string (value, priv->title); - break; - - case PROP_MENU_UI: - g_value_set_string (value, priv->menu_ui); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; - } -} - -/* - * Used when the HildonAppView is exposed, this function gets a GtkBoxChild - * as first argument, and a pointer to a gint as second argument. If such - * GtkBoxChild is visible, the function increments the gint. It is used - * in a loop, to compute the number of visible toolbars. - */ -static void visible_toolbar(gpointer child, gpointer number_of_visible_toolbars) -{ - if(GTK_WIDGET_VISIBLE(((GtkBoxChild *)child)->widget)) - (*((gint *)number_of_visible_toolbars))++; -} - -/* - * Used in the paint_toolbar function to discover how many toolbars are - * above the find toolbar. It's called in a loop that iterates through - * all the children of the GtkVBox of the HildonAppView. - */ -static void find_findtoolbar_index(gpointer child, gpointer number_of_visible_toolbars) -{ - gint *pass_bundle = (gint *)number_of_visible_toolbars; - - if(((GtkBoxChild *)child)->widget->allocation.y < pass_bundle[0] - && GTK_WIDGET_VISIBLE(((GtkBoxChild *)child)->widget)) - pass_bundle[1]++; -} - -/* - * Used in the paint_toolbar function, it's get a GtkBoxChild as first argument - * and a pointer to a GtkWidget as the second one, which will be addressed to - * the find toolbar widget, if it is contained in the given GtkBoxChild. - */ -static void find_findtoolbar(gpointer child, gpointer widget) -{ - if(HILDON_IS_FIND_TOOLBAR(((GtkBoxChild *)child)->widget) - && GTK_WIDGET_VISIBLE(((GtkBoxChild *)child)->widget)) - (*((GtkWidget **)widget)) = ((GtkBoxChild *)child)->widget; -} - -/* - * Paints all the toolbar children of the GtkVBox of the HildonAppView. - */ -static void paint_toolbar(GtkWidget *widget, GtkBox *box, - GdkEventExpose * event, - gboolean fullscreen) -{ - gint toolbar_num = 0; - gint ftb_index = 0; - gint count; - GtkWidget *findtoolbar = NULL; - gchar toolbar_mode[40]; - - /* Iterate through all the children of the vbox of the HildonAppView. - * The visible_toolbar function increments toolbar_num if the toolbar - * is visible. After this loop, toobar_num will contain the number - * of the visible toolbars. */ - g_list_foreach(box->children, visible_toolbar, - (gpointer) &toolbar_num); - if(toolbar_num <= 0) - return; - - /* Loop through all the children of the GtkVBox of the HildonAppView. - * The find_findtoolbar function will assign a pointer to the find toolbar - * to "findtoolbar" argument. If the findtoolbar is not found, i.e. it - * isn't in the GtkVBox, then the "findtoolbar" argument will stay NULL */ - g_list_foreach(box->children, find_findtoolbar, - (gpointer) &findtoolbar); - if(findtoolbar != NULL){ - gint pass_bundle[2]; - - /* an array for convient data passing - * the first member contains the y allocation - * of the find toolbar, and the second allocation - * contains the index(how many toolbars are above - * find toolbar) */ - pass_bundle[0] = findtoolbar->allocation.y; - pass_bundle[1] = ftb_index; - - /* computes how many toolbars are above the find toolbar, and the - * value is stored in pass_bundle[1] */ - g_list_foreach(box->children, find_findtoolbar_index, - (gpointer) pass_bundle); - ftb_index = pass_bundle[1]; - } - /*upper border*/ - sprintf(toolbar_mode, "toolbar%sframe-top", - fullscreen ? "-fullscreen-" : "-"); - gtk_paint_box(widget->style, widget->window, - GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, - &event->area, widget, toolbar_mode, - widget->allocation.x, - GTK_WIDGET(box)->allocation.y -TOOLBAR_UP, - widget->allocation.width, TOOLBAR_UP); - - /*top most toolbar painting*/ - if(findtoolbar != NULL && ftb_index == 0 ) - { - sprintf(toolbar_mode, "findtoolbar%s", - fullscreen ? "-fullscreen" : ""); - - gtk_paint_box(widget->style, widget->window, - GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, - &event->area, widget, toolbar_mode, - widget->allocation.x, - GTK_WIDGET(box)->allocation.y, - widget->allocation.width, - TOOLBAR_HEIGHT); - }else{ - sprintf(toolbar_mode, "toolbar%s", - fullscreen ? "-fullscreen" : ""); - gtk_paint_box(widget->style, widget->window, - GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, - &event->area, widget, toolbar_mode, - widget->allocation.x, - GTK_WIDGET(box)->allocation.y, - widget->allocation.width, - TOOLBAR_HEIGHT); - } - /*multi toolbar painting*/ - for(count = 0; count < toolbar_num - 1; count++) - { - sprintf(toolbar_mode, "toolbar%sframe-middle", - fullscreen ? "-fullscreen-" : "-"); - - gtk_paint_box(widget->style, widget->window, - GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, - &event->area, widget, toolbar_mode, - widget->allocation.x, - GTK_WIDGET(box)->allocation.y + - (1 + count) * TOOLBAR_HEIGHT + - count * TOOLBAR_MIDDLE, - widget->allocation.width, - TOOLBAR_MIDDLE); - - if(findtoolbar != NULL && count + 1 == ftb_index){ - sprintf(toolbar_mode, "findtoolbar%s", - fullscreen ? "-fullscreen" : ""); - - gtk_paint_box(widget->style, widget->window, - GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, - &event->area, widget, toolbar_mode, - widget->allocation.x, - GTK_WIDGET(box)->allocation.y + - (1 + count) * (TOOLBAR_HEIGHT + TOOLBAR_MIDDLE), - widget->allocation.width, - TOOLBAR_HEIGHT); - }else{ - sprintf(toolbar_mode, "toolbar%s", - fullscreen ? "-fullscreen" : ""); - - gtk_paint_box(widget->style, widget->window, - GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, - &event->area, widget, toolbar_mode, - widget->allocation.x, - GTK_WIDGET(box)->allocation.y + - (1 + count) * (TOOLBAR_HEIGHT + TOOLBAR_MIDDLE), - widget->allocation.width, - TOOLBAR_HEIGHT); - } - } - sprintf(toolbar_mode, "toolbar%sframe-bottom", - fullscreen ? "-fullscreen-" : "-"); - - gtk_paint_box(widget->style, widget->window, - GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, - &event->area, widget, toolbar_mode, - widget->allocation.x, - GTK_WIDGET(box)->allocation.y + - GTK_WIDGET(box)->allocation.height, - widget->allocation.width, TOOLBAR_DOWN); -} - -/* - * Callback function to an expose event. - */ -static gboolean hildon_appview_expose(GtkWidget * widget, - GdkEventExpose * event) -{ - gint toolbar_num = 0; - GtkBox *box = GTK_BOX(HILDON_APPVIEW(widget)->vbox); - - if(GTK_WIDGET_VISIBLE(box) && box->children != NULL) - { - HildonAppViewPrivate *priv = HILDON_APPVIEW_GET_PRIVATE(widget); - - /* Iterate through all the children of the vbox of the HildonAppView. - * The visible_toolbar function increments toolbar_num if the toolbar - * is visible. After this loop, toobar_num will contain the number - * of the visible toolbars. */ - g_list_foreach(box->children, visible_toolbar, - (gpointer) &toolbar_num); - - if( priv->visible_toolbars != toolbar_num) - { - /* If the code reaches this block, it means that a toolbar as - * been added or removed since last time the view was drawn. - * Let's then compute the new height of the toolbars areas */ - gint y_pos = 0; - /* the height difference */ - gint change = (priv->visible_toolbars - toolbar_num) * - (TOOLBAR_HEIGHT+TOOLBAR_MIDDLE+TOOLBAR_UP); - if( change < 0 ) - change = TOOLBAR_MIDDLE + TOOLBAR_UP; - /* the new y-coordinate for the toolbars area */ - y_pos = HILDON_APPVIEW(widget)->vbox->allocation.y - change; - - gtk_widget_queue_draw_area(widget, 0, y_pos, widget->allocation.width, - change + HILDON_APPVIEW(widget)->vbox->allocation.height + - TOOLBAR_DOWN); - priv->visible_toolbars = toolbar_num; - } - } - - - if (HILDON_APPVIEW(widget)->priv->fullscreen) - { - if (toolbar_num > 0) - paint_toolbar(widget, box, event, TRUE); - } - else - { - gint appview_height_decrement = 0; - if (toolbar_num > 0) - { - appview_height_decrement = toolbar_num * TOOLBAR_HEIGHT + - (toolbar_num - 1) * TOOLBAR_MIDDLE - + TOOLBAR_UP + TOOLBAR_DOWN; - - paint_toolbar(widget, box, event, FALSE); - } - else - { - appview_height_decrement = MARGIN_APPVIEW_BOTTOM; - - gtk_paint_box(widget->style, widget->window, - GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, - &event->area, widget, "bottom-border", - widget->allocation.x, - widget->allocation.y + - (widget->allocation.height - MARGIN_APPVIEW_BOTTOM), - widget->allocation.width, MARGIN_APPVIEW_BOTTOM); - } - gtk_paint_box( widget->style, widget->window, - GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, - &event->area, - widget, "left-border", widget->allocation.x, - widget->allocation.y, MARGIN_APPVIEW_LEFT, - widget->allocation.height - appview_height_decrement ); - gtk_paint_box( widget->style, widget->window, - GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, - &event->area, - widget, "right-border", - (widget->allocation.x + - widget->allocation.width) - - MARGIN_APPVIEW_RIGHT, widget->allocation.y, - MARGIN_APPVIEW_RIGHT, - widget->allocation.height - appview_height_decrement ); - } - - GTK_WIDGET_CLASS(parent_class)->expose_event(widget, event); - - return FALSE; -} - -/* - * Responds to the usual size_request signal. - */ -static void hildon_appview_size_request(GtkWidget * widget, - GtkRequisition * requisition) -{ - HildonAppViewPrivate *priv = HILDON_APPVIEW(widget)->priv; - GtkWidget *child = GTK_BIN(widget)->child; - - /* forward the size_request to the eventual child of the main container */ - if (child) - gtk_widget_size_request(child, requisition); - - /* forward the size_request to the eventual vbox (which may contain - * toolbars) */ - if (HILDON_APPVIEW(widget)->vbox != NULL) - gtk_widget_size_request(HILDON_APPVIEW(widget)->vbox, requisition); - - /* express the size_request for the view */ - if (priv->fullscreen) { - requisition->height = WINDOW_HEIGHT; - requisition->width = WINDOW_WIDTH; - } else { - requisition->height = APPVIEW_HEIGHT; - requisition->width = APPVIEW_WIDTH; - } -} - -/* - * Computes size and position for the children of the view. - */ -static void hildon_appview_size_allocate(GtkWidget * widget, - GtkAllocation * allocation) -{ - GtkAllocation box_allocation; - GtkAllocation alloc = *allocation; - gint border_width = GTK_CONTAINER(widget)->border_width; - GtkBin *bin = GTK_BIN(widget); - GtkBox *box = GTK_BOX(HILDON_APPVIEW(widget)->vbox); - gboolean at_least_one_visible_toolbar = FALSE; - - if(!GTK_IS_WIDGET(bin->child)) return; - - widget->allocation = *allocation; - - if (bin->child != NULL && GTK_IS_WIDGET(bin->child)) { - if (HILDON_APPVIEW(widget)->priv->fullscreen) { - alloc.x += border_width; - alloc.y += border_width; - alloc.width -= (border_width * 2); - alloc.height -= (border_width * 2); - } else { - alloc.x += border_width + MARGIN_APPVIEW_LEFT; - alloc.y += border_width + MARGIN_APPVIEW_TOP; - alloc.width -= (border_width * 2) + (MARGIN_APPVIEW_LEFT + - MARGIN_APPVIEW_RIGHT); - alloc.height -= (border_width * 2) + MARGIN_APPVIEW_TOP; - } - } - - if (box->children != NULL) { - gint length = 0; - gint box_height = 0; - /* Iterate through all the children of the vbox of the HildonAppView. - * The visible_toolbar function increments toolbar_num if the toolbar - * is visible. After this loop, toobar_num will contain the number - * of the visible toolbars. */ - g_list_foreach(box->children, visible_toolbar, - (gpointer) &length); - if(length > 0){ - box_height = length * TOOLBAR_HEIGHT + - (length - 1) * TOOLBAR_MIDDLE; - - if(bin->child != NULL) { - alloc.height = alloc.height - box_height - TOOLBAR_UP - - TOOLBAR_DOWN; - at_least_one_visible_toolbar = TRUE; - } - - box_allocation.y = allocation->height - box_height - TOOLBAR_DOWN; - box_allocation.height = box_height; - box_allocation.x = allocation->x + TOOLBAR_LEFT; - box_allocation.width = allocation->width - TOOLBAR_LEFT - - TOOLBAR_RIGHT; - gtk_widget_size_allocate(GTK_WIDGET(box), &box_allocation); - } - } - - /* The bottom skin graphics is visible only when there are no toolbars */ - if ((HILDON_APPVIEW(widget)->priv->fullscreen == FALSE) && - (at_least_one_visible_toolbar == FALSE)) - alloc.height -= MARGIN_APPVIEW_BOTTOM; - - gtk_widget_size_allocate(GTK_WIDGET(bin->child), &alloc); -} - -/* - * Overrides gtk_container_forall, calling the callback function for each of - * the children of HildonAppPrivate. - */ -static void hildon_appview_forall(GtkContainer * container, - gboolean include_internals, - GtkCallback callback, - gpointer callback_data) -{ - HildonAppView *self = HILDON_APPVIEW(container); - - g_assert(callback != NULL); - - GTK_CONTAINER_CLASS(parent_class)->forall(container, include_internals, - callback, callback_data); - if(include_internals && self->vbox != NULL) - (* callback)(GTK_WIDGET(self->vbox), callback_data); -} - -/** - * Shows all the widgets in the container. - */ -static void hildon_appview_show_all(GtkWidget *widget) -{ - HildonAppView *self = HILDON_APPVIEW(widget); - - /* Toolbar items */ - gtk_widget_show_all(self->vbox); - - /* Parent handless stuff inside appview */ - GTK_WIDGET_CLASS(parent_class)->show_all(widget); -} - -/* - * Frees all the resources and propagates the destroy call to the parent. - */ -static void hildon_appview_destroy(GtkObject *obj) -{ - HildonAppView *self = HILDON_APPVIEW(obj); - - if(self->vbox != NULL){ - gtk_widget_unparent(self->vbox); - self->vbox = NULL; - } - - GTK_OBJECT_CLASS(parent_class)->destroy(obj); -} - -/*******************/ -/* Signals */ -/*******************/ - -/*Signal - When is changed to this appview, this is called*/ -static void hildon_appview_switched_to(HildonAppView * self) -{ - GtkWidget *parent; - - g_assert(self && HILDON_IS_APPVIEW(self)); - - parent = gtk_widget_get_parent(GTK_WIDGET(self)); - hildon_appview_set_fullscreen( self, self->priv->fullscreen ); -} - -/*Signal - When the fullscreen state is changed, this is called*/ -static void hildon_appview_real_fullscreen_state_change(HildonAppView * - self, - gboolean - fullscreen) -{ - HildonAppViewPrivate *priv; - g_assert(self && HILDON_IS_APPVIEW(self)); - priv = self->priv; - - /* Ensure that state is really changed */ - if( priv->fullscreen == fullscreen ) - return; - - if( fullscreen ) - gtk_window_fullscreen( GTK_WINDOW( - gtk_widget_get_parent(GTK_WIDGET(self))) ); - else - gtk_window_unfullscreen( GTK_WINDOW( - gtk_widget_get_parent(GTK_WIDGET(self))) ); - - priv->fullscreen = fullscreen; -} - -/*******************/ -/* General */ -/*******************/ - - -/* - * queries a window for the root window coordinates and size of its - * client area (i.e. minus the title borders etc.) - */ -static void get_client_area(GtkWidget * widget, GtkAllocation * allocation) -{ - GdkWindow *window = widget->window; - - if (window) - gdk_window_get_origin(window, &allocation->x, &allocation->y); - else - memset( allocation, 0, sizeof(GtkAllocation) ); -} - -/*The menu popuping needs a menu popup-function*/ -static void hildon_appview_menupopupfunc( GtkMenu *menu, gint *x, gint *y, - gboolean *push_in, GtkWidget *widget ) -{ - GtkAllocation client_area = { 0, 0, 0, 0 }; - - get_client_area( GTK_WIDGET(widget), &client_area ); - - gtk_widget_style_get (GTK_WIDGET (menu), "horizontal-offset", x, - "vertical-offset", y, NULL); - - *x += client_area.x; - *y += client_area.y; - -} - -/* Similar to above, but used in fullscreen mode */ -static void hildon_appview_menupopupfuncfull( GtkMenu *menu, gint *x, gint *y, - gboolean *push_in, - GtkWidget *widget ) -{ - gtk_widget_style_get (GTK_WIDGET (menu), "horizontal-offset", x, - "vertical-offset", y, NULL); - - *x = MAX (0, *x); - *y = MAX (0, *y); -} - -/*******************/ -/*public functions*/ -/*******************/ - - -/** - * hildon_appview_new: - * @title:the application view title of the new @HildonAppView - * - * Use this function to create a new application view. The title will - * be set only if two-part-title is enabled on the @HildonApp. - * - * Returns: A #HildonAppView. - **/ -GtkWidget *hildon_appview_new(const gchar * title) -{ - HildonAppView *newappview = g_object_new(HILDON_TYPE_APPVIEW, NULL); - - hildon_appview_set_title(newappview, title); - return GTK_WIDGET(newappview); -} - -/** - * hildon_appview_add_with_scrollbar - * @self : a @HildonAppView - * @child : a @GtkWidget - * - * Adds the @child to the @self(HildonAppView) and creates a vertical - * scrollbar to it. Similar as adding first a #GtkScrolledWindow - * and then the @child to it. - */ -void hildon_appview_add_with_scrollbar(HildonAppView * self, - GtkWidget * child) -{ - GtkScrolledWindow *scrolledw; - - g_return_if_fail(HILDON_IS_APPVIEW(self)); - g_return_if_fail(GTK_IS_WIDGET(child)); - g_return_if_fail(child->parent == NULL); - - scrolledw = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL)); - gtk_scrolled_window_set_policy(scrolledw, GTK_POLICY_NEVER, - GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type(scrolledw, GTK_SHADOW_NONE); - - /* Check whether child widget supports adjustments */ - if (GTK_WIDGET_GET_CLASS (child)->set_scroll_adjustments_signal) - gtk_container_add(GTK_CONTAINER(scrolledw), child); - else - { - if( GTK_IS_CONTAINER(child) ) - gtk_container_set_focus_vadjustment( GTK_CONTAINER(child), - gtk_scrolled_window_get_vadjustment(scrolledw) ); - gtk_scrolled_window_add_with_viewport(scrolledw, child); - } - - gtk_container_add(GTK_CONTAINER(self), GTK_WIDGET(scrolledw)); -} - -/** - * hildon_appview_get_title: - * @self : a #HildonAppView - * - * Gets the title of given #HildonAppView. - * - * Returns: the title of the application view - */ -const gchar *hildon_appview_get_title(HildonAppView * self) -{ - g_return_val_if_fail(self && HILDON_IS_APPVIEW(self), ""); - return self->priv->title; -} - -/** - * hildon_appview_set_title: - * @self : a #HildonAppView - * @newname : the new title of the application view. - * - * Sets an title of an application view. The title is visible only if - * two-part-title is enabled on the #HildonApp. - * - */ -void hildon_appview_set_title(HildonAppView * self, const gchar * newname) -{ - gchar *oldtitle; - - g_return_if_fail(self && HILDON_IS_APPVIEW(self)); - oldtitle = self->priv->title; - - if (newname != NULL) - self->priv->title = g_strdup(newname); - else - self->priv->title = g_strdup(""); - - g_free(oldtitle); - g_signal_emit_by_name(G_OBJECT(self), "title_change"); -} - -/** - * hildon_appview_set_toolbar: - * @self: a #HildonAppView - * @toolbar: a #GtkToolbar - * - * Sets the #GtkToolbar to given #HildonAppView. This is, however, not a - * recommended way to set your toolbars. When you have multi toolbars, calling - * this function more than once will just replace the bottom most toolbar. - * There is a #GtkVBox in #HildonAppView's public structure, the programmer - * is responsible to pack his toolbars in the #GtkVBox, and #HildonAppView will - * take care of putting them at the right place. - * - */ -#ifndef HILDON_DISABLE_DEPRECATED -void hildon_appview_set_toolbar(HildonAppView * self, GtkToolbar * toolbar) -{ - GtkBox *box = GTK_BOX(HILDON_APPVIEW(self)->vbox); - g_return_if_fail(self && HILDON_IS_APPVIEW(self)); - if(toolbar != NULL)/*for failure checking*/ - g_return_if_fail(GTK_IS_TOOLBAR(toolbar)); - - /*if it is NULL, it unsets the last one, - * if it is not null, it unsets the last one anyway*/ - if(box->children != NULL){ - GtkWidget *last_widget; - - last_widget = ((GtkBoxChild *)g_list_last - (box->children)->data)->widget; - gtk_container_remove(GTK_CONTAINER(box), - last_widget); - } - - gtk_box_pack_end(box, GTK_WIDGET(toolbar), TRUE, TRUE, 0); - gtk_widget_queue_resize(GTK_WIDGET(self)); - /*deprecated signal*/ - g_signal_emit_by_name(G_OBJECT(self), "toolbar-changed"); -} -#endif -/** - * hildon_appview_get_toolbar: - * @self: a #HildonAppView - * - * This function will only - * return the last widget that has been packed into the #GtkVBox in the public - * structure. Note this does not, however, mean that it is the bottom most - * toolbar. - * - * Return value: the #GtkToolbar assigned to this application view. - **/ -#ifndef HILDON_DISABLE_DEPRECATED -GtkToolbar *hildon_appview_get_toolbar(HildonAppView * self) -{ - GtkBox *box = GTK_BOX(HILDON_APPVIEW(self)->vbox); - g_return_val_if_fail(self != NULL && HILDON_IS_APPVIEW(self), FALSE); - if(box != NULL && box->children != NULL) - return GTK_TOOLBAR(((GtkBoxChild*) - g_list_last(box->children)->data)->widget); - else - return NULL; -} -#endif -/** - * hildon_appview_set_fullscreen: - * @self: a #HildonAppView - * @fullscreen: the new state of fullscreen mode. TRUE means fullscreen - * will be set. FALSE the opposite. - * - * Set the fullscreen state of given #HildonAppView class. - */ -void hildon_appview_set_fullscreen(HildonAppView * self, - gboolean fullscreen) -{ - g_return_if_fail(self && HILDON_IS_APPVIEW(self)); - g_signal_emit_by_name(G_OBJECT(self), "fullscreen_state_change", - fullscreen); -} - -/** - * hildon_appview_get_fullscreen: - * @self: a #HildonAppView - * - * Gets the current state of fullscreen mode. - * - * Returns: the current state of fullscreen mode - */ -gboolean hildon_appview_get_fullscreen(HildonAppView * self) -{ - g_return_val_if_fail(self && HILDON_IS_APPVIEW(self), FALSE); - return self->priv->fullscreen; -} - -/** - * hildon_appview_get_fullscreen_key_allowed: - * @self: a #HildonAppView - * - * Check if fullscreening with a shortcut is allowed for given - * #HildonAppView. - * - * Returns: wheter it's possible to swith fullscreen on/off with - * a shortcut key - */ -gboolean hildon_appview_get_fullscreen_key_allowed(HildonAppView * self) -{ - g_return_val_if_fail(self && HILDON_IS_APPVIEW(self), FALSE); - return self->priv->fullscreenshortcutallowed; -} - -/** - * hildon_appview_set_fullscreen_key_allowed: - * @self: a #HildonAppView - * @allow: wheter it's possible to swith fullscreen on/off with - * a shortcut key - * - * Sets given #HildonAppView whether to allow toggling fullscreen mode - * with a shortcut key. - */ -void hildon_appview_set_fullscreen_key_allowed(HildonAppView * self, - gboolean allow) -{ - g_return_if_fail(self && HILDON_IS_APPVIEW(self)); - self->priv->fullscreenshortcutallowed = allow; -} - -/** - * hildon_appview_get_menu: - * @self : #HildonAppView - * - * Gets the #GtMenu assigned to the #HildonAppview. - * - * Returns: the #GtkMenu assigned to this application view - */ -GtkMenu *hildon_appview_get_menu(HildonAppView * self) -{ - g_return_val_if_fail(self && HILDON_IS_APPVIEW(self), NULL); - - if (self->priv->menu == NULL) { - /* Create hildonlike menu */ - - GtkUIManager *uim; - GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (self)); - - /* Try to get appview menu from ui manager */ - if (parent && HILDON_IS_APP (parent)) - { - uim = hildon_app_get_ui_manager (HILDON_APP (parent)); - if (uim) - { - self->priv->menu = - gtk_ui_manager_get_widget (uim, "/HildonApp"); - } - } - - - if (self->priv->menu == NULL) - { - /* Fall back to oldskool menus */ - self->priv->menu = GTK_WIDGET (g_object_new (GTK_TYPE_MENU, NULL)); - } - - gtk_widget_set_name(GTK_WIDGET(self->priv->menu), - "menu_force_with_corners"); - gtk_widget_show_all (self->priv->menu); - } - - return GTK_MENU(self->priv->menu); -} - -/** - * _hildon_appview_toggle_menu: - * @self : a #HildonAppView - * @button_event_time : - * - * This function should be only called from @HildonApp. - * Should be renamed to popup menu. Just the first parameter is used. - * - * Returns: Whether or not something was done (whether or not we had - * a menu) - */ -gboolean _hildon_appview_toggle_menu(HildonAppView * self, - Time button_event_time) -{ - GList *children; - - g_return_val_if_fail(self && HILDON_IS_APPVIEW(self), FALSE); - - if (!self->priv->menu) - return FALSE; - - if (GTK_WIDGET_VISIBLE(self->priv->menu)) { - gtk_menu_popdown(GTK_MENU(self->priv->menu)); - gtk_menu_shell_deactivate(GTK_MENU_SHELL(self->priv->menu)); - return TRUE; - } - - /* Avoid opening an empty menu */ - children = gtk_container_get_children( - GTK_CONTAINER(hildon_appview_get_menu(self))); - if (children != NULL) { - GtkWidget *menu; - - g_list_free(children); - menu = GTK_WIDGET(hildon_appview_get_menu(self)); - if (self->priv->fullscreen) { - gtk_menu_popup(GTK_MENU(menu), NULL, NULL, - (GtkMenuPositionFunc) - hildon_appview_menupopupfuncfull, - self, 0, button_event_time); - } else { - gtk_menu_popup(GTK_MENU(menu), NULL, NULL, - (GtkMenuPositionFunc) - hildon_appview_menupopupfunc, - self, 0, button_event_time); - } - gtk_menu_shell_select_first(GTK_MENU_SHELL(menu), TRUE); - return TRUE; - } - return FALSE; - -} - -/** - * _hildon_appview_menu_visible - * @self: a #HildonAppView - * - * Checks whether the titlebar menu is currently visible - * Returns: TRUE if the menu is visible, FALSE if not - */ - -gboolean _hildon_appview_menu_visible(HildonAppView * self) -{ - g_return_val_if_fail (HILDON_IS_APPVIEW (self), FALSE); - - return GTK_WIDGET_VISIBLE(GTK_WIDGET(hildon_appview_get_menu(self))); -} - -/** - * hildon_appview_set_connected_adjustment - * @self : #HildonAppView - * @adjustment : a new #GtkAdjustment set to reach to increase - * / decrease hardware keys or NULL to unset - * - * Sets a #GtkAdjustment which will change when increase/decrease buttons - * are pressed. - */ -void hildon_appview_set_connected_adjustment (HildonAppView * self, - GtkAdjustment * adjustment) -{ - g_return_if_fail (HILDON_IS_APPVIEW (self)); - - /* Disconnect old adjustment */ - if (self->priv->connected_adjustment != NULL) - g_object_remove_weak_pointer (G_OBJECT (self->priv->connected_adjustment), - (gpointer) &self->priv->connected_adjustment); - - /* Start using the new one */ - self->priv->connected_adjustment = adjustment; - if (self->priv->connected_adjustment != NULL) - g_object_add_weak_pointer (G_OBJECT (self->priv->connected_adjustment), - (gpointer) &self->priv->connected_adjustment); -} - -/** - * hildon_appview_get_connected_adjustment - * @self : a #HildonAppView - * - * Retrieves the #GtkAdjustment which is connected to this application view - * and is changed with increase / decrease hardware buttons. - * - * Returns: currently connectd #GtkAdjustment assigned to this - * application view or NULL if it's not set - */ -GtkAdjustment * hildon_appview_get_connected_adjustment (HildonAppView * self) -{ - g_return_val_if_fail (HILDON_IS_APPVIEW (self), NULL); - - return self->priv->connected_adjustment; -} - - -/** - * hildon_appview_set_menu_ui - * @self : a #HildonAppView - * @ui_string : a #GtkUIManager ui description string - * - * Sets the ui description (xml) from which the UIManager creates menus - * (see @GtkUIManager for details on how to use it) - */ -void hildon_appview_set_menu_ui(HildonAppView *self, const gchar *ui_string) -{ - g_return_if_fail (HILDON_IS_APPVIEW (self)); - - if (ui_string) - { - if (self->priv->menu_ui) - g_free (self->priv->menu_ui); - - self->priv->menu_ui = g_strdup (ui_string); - - /* FIXME: We should update the menu here, preferrably by a - * hildon_app_ensure_menu_update() which re-installs the menu ui - * and calls gtk_ui_manager_ensure_update() - */ - } - else - { - /* Reset the UI */ - if (self->priv->menu_ui) - { - g_free (self->priv->menu_ui); - self->priv->menu_ui = NULL; - } - } - - g_object_notify (G_OBJECT(self), "menu-ui"); -} - -/** - * hildon_appview_get_menu_ui - * @self : a #HildonAppView - * - * Sets the ui description (xml) from which the UIManager creates menus - * (see #GtkUIManager for details on how to use it) - * - * Returns: currently set ui description - */ -const gchar *hildon_appview_get_menu_ui(HildonAppView *self) -{ - g_return_val_if_fail (HILDON_IS_APPVIEW (self), NULL); - - return (self->priv->menu_ui); - -} - -/* Called when '+' hardkey is pressed/released */ -void _hildon_appview_increase_button_state_changed (HildonAppView * self, - guint newkeytype) -{ - self->priv->increase_button_pressed_down = newkeytype; - - /* Transform '+' press into adjustment update (usually scrollbar move) */ - if ((self->priv->connected_adjustment != NULL) && (newkeytype == GDK_KEY_PRESS)) - { - gfloat clampedvalue = CLAMP (gtk_adjustment_get_value (self->priv->connected_adjustment) + self->priv->connected_adjustment->step_increment, - self->priv->connected_adjustment->lower, - self->priv->connected_adjustment->upper - self->priv->connected_adjustment->page_size); - gtk_adjustment_set_value (self->priv->connected_adjustment, clampedvalue); - } - - g_signal_emit (G_OBJECT (self), appview_signals[INCREASE_BUTTON_EVENT], 0, newkeytype); -} - -/* Called when '-' hardkey is pressed/released */ -void _hildon_appview_decrease_button_state_changed (HildonAppView * self, - guint newkeytype) -{ - self->priv->decrease_button_pressed_down = newkeytype; - - /* Transform '-' press into adjustment update (usually scrollbar move) */ - if ((self->priv->connected_adjustment != NULL) && (newkeytype == GDK_KEY_PRESS)) - { - gfloat clampedvalue = CLAMP (gtk_adjustment_get_value (self->priv->connected_adjustment) - self->priv->connected_adjustment->step_increment, - self->priv->connected_adjustment->lower, - self->priv->connected_adjustment->upper - self->priv->connected_adjustment->page_size); - gtk_adjustment_set_value (self->priv->connected_adjustment, clampedvalue); - } - - g_signal_emit (G_OBJECT (self), appview_signals[DECREASE_BUTTON_EVENT], 0, newkeytype); -} diff --git a/hildon-widgets/hildon-appview.h b/hildon-widgets/hildon-appview.h deleted file mode 100644 index bc802ab..0000000 --- a/hildon-widgets/hildon-appview.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - - -#ifndef __HILDON_APPVIEW_H__ -#define __HILDON_APPVIEW_H__ - -#include -#include -#include -#include -#include -#include - - -G_BEGIN_DECLS -#define HILDON_TYPE_APPVIEW ( hildon_appview_get_type() ) -#define HILDON_APPVIEW(obj) \ - (GTK_CHECK_CAST (obj, HILDON_TYPE_APPVIEW, HildonAppView)) -#define HILDON_APPVIEW_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass),\ - HILDON_TYPE_APPVIEW, HildonAppViewClass)) -#define HILDON_IS_APPVIEW(obj) (GTK_CHECK_TYPE (obj, HILDON_TYPE_APPVIEW)) -#define HILDON_IS_APPVIEW_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_APPVIEW)) -typedef struct _HildonAppView HildonAppView; -typedef struct _HildonAppViewClass HildonAppViewClass; - -/** - * HildonAppViewPrivate: - * - * This structure contains just internal data. It should not - * be accessed directly. - */ -typedef struct _HildonAppViewPrivate HildonAppViewPrivate; - -struct _HildonAppView { - GtkBin parent; - - /*public*/ - GtkWidget *vbox; - - /*private*/ - HildonAppViewPrivate *priv; -}; - -struct _HildonAppViewClass { - GtkBinClass parent_class; - void (*toolbar_changed) (HildonAppView * self); - void (*toolbar_toggle_request) (HildonAppView * self); - void (*fullscreen_state_change) (HildonAppView * self, - gboolean is_fullscreen); - void (*title_change) (HildonAppView * self); - void (*switched_to) (HildonAppView * self); - void (*switched_from) (HildonAppView * self); - void (*increase_button_event) (HildonAppView * self, - guint newkeytype); - void (*decrease_button_event) (HildonAppView * self, - guint newkeytype); -}; - - -GType hildon_appview_get_type(void) G_GNUC_CONST; -GtkWidget *hildon_appview_new(const gchar * title); -void hildon_appview_add_with_scrollbar(HildonAppView * self, - GtkWidget * child); -void hildon_appview_set_fullscreen_key_allowed(HildonAppView * self, - gboolean allow); -gboolean hildon_appview_get_fullscreen_key_allowed(HildonAppView * self); - -gboolean hildon_appview_get_fullscreen(HildonAppView * self); -void hildon_appview_set_fullscreen(HildonAppView * self, - gboolean fullscreen); -GtkMenu *hildon_appview_get_menu(HildonAppView * self); -#ifndef HILDON_DISABLE_DEPRECATED -void hildon_appview_set_toolbar(HildonAppView * self, - GtkToolbar * toolbar); -GtkToolbar *hildon_appview_get_toolbar(HildonAppView * self); -#endif -void hildon_appview_set_title(HildonAppView * self, const gchar * newname); -const gchar *hildon_appview_get_title(HildonAppView * self); - -gboolean _hildon_appview_toggle_menu(HildonAppView * self, - Time button_event_time); -gboolean _hildon_appview_menu_visible(HildonAppView * self); - -void hildon_appview_set_connected_adjustment (HildonAppView * self, - GtkAdjustment * adjustment); -GtkAdjustment * hildon_appview_get_connected_adjustment (HildonAppView * self); - -void _hildon_appview_increase_button_state_changed (HildonAppView * self, - guint newkeytype); -void _hildon_appview_decrease_button_state_changed (HildonAppView * self, - guint newkeytype); - -void hildon_appview_set_menu_ui(HildonAppView *self, const gchar *ui_string); -const gchar *hildon_appview_get_menu_ui(HildonAppView *self); - -G_END_DECLS -#endif /* HILDON_APPVIEW_H */ diff --git a/hildon-widgets/hildon-banner.c b/hildon-widgets/hildon-banner.c deleted file mode 100644 index 1b267d8..0000000 --- a/hildon-widgets/hildon-banner.c +++ /dev/null @@ -1,913 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include - -#include "hildon-defines.h" -#include "hildon-banner.h" - -/* position relative to the screen */ -#define HILDON_BANNER_WINDOW_X 30 -#define HILDON_BANNER_WINDOW_Y 73 -#define HILDON_BANNER_WINDOW_FULLSCREEN_Y 20 - -/* max widths */ -#define HILDON_BANNER_PROGRESS_WIDTH 104 -#define HILDON_BANNER_LABEL_MAX_TIMED 375 -#define HILDON_BANNER_LABEL_MAX_PROGRESS 375 /*265*/ - -/* default timeout */ -#define HILDON_BANNER_TIMEOUT 3000 - -/* default icons */ -#define HILDON_BANNER_DEFAULT_ICON "qgn_note_infoprint" -#define HILDON_BANNER_DEFAULT_PROGRESS_ANIMATION "qgn_indi_pball_a" - -enum { - PROP_PARENT_WINDOW = 1, - PROP_IS_TIMED -}; - -struct _HildonBannerPrivate -{ - GtkWidget *main_item; - GtkWidget *label; - GtkWidget *layout; - guint timeout_id; - gboolean is_timed; -}; - -static GtkWidget *global_timed_banner = NULL; - -G_DEFINE_TYPE(HildonBanner, hildon_banner, GTK_TYPE_WINDOW) - -/* copy/paste from old infoprint implementation: Use matchbox - properties to find the topmost application window */ -static Window get_current_app_window(void) -{ - unsigned long n; - unsigned long extra; - int format; - int status; - - Atom atom_current_app_window = gdk_x11_get_xatom_by_name ("_MB_CURRENT_APP_WINDOW"); - Atom realType; - Window win_result = None; - guchar *data_return = NULL; - - status = XGetWindowProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(), - atom_current_app_window, 0L, 16L, - 0, XA_WINDOW, &realType, &format, - &n, &extra, - &data_return); - - if ( status == Success && realType == XA_WINDOW - && format == 32 && n == 1 && data_return != NULL ) - { - win_result = ((Window*) data_return)[0]; - } - - if ( data_return ) - XFree(data_return); - - return win_result; -} - -/* Checks if a window is in fullscreen state or not. This - information is needed when banners are positioned on screen. - copy/paste from old infoprint implementation. */ -static gboolean check_fullscreen_state( Window window ) -{ - unsigned long n; - unsigned long extra; - int format, status, i; - guchar *data_return = NULL; - - Atom realType; - Atom atom_window_state = gdk_x11_get_xatom_by_name ("_NET_WM_STATE"); - Atom atom_fullscreen = gdk_x11_get_xatom_by_name ("_NET_WM_STATE_FULLSCREEN"); - - if ( window == None ) - return FALSE; - - /* in some cases XGetWindowProperty seems to generate BadWindow, - so at the moment this function does not always work perfectly */ - gdk_error_trap_push(); - status = XGetWindowProperty(GDK_DISPLAY(), window, - atom_window_state, 0L, 1000000L, - 0, XA_ATOM, &realType, &format, - &n, &extra, &data_return); - gdk_flush(); - if (gdk_error_trap_pop()) - return FALSE; - - if (status == Success && realType == XA_ATOM && format == 32 && n > 0) - { - for(i=0; i < n; i++) - if ( ((Atom*)data_return)[i] && - ((Atom*)data_return)[i] == atom_fullscreen) - { - if (data_return) XFree(data_return); - return TRUE; - } - } - - if (data_return) - XFree(data_return); - - return FALSE; -} - -static GQuark hildon_banner_timed_quark(void) -{ - static GQuark quark = 0; - - if (G_UNLIKELY(quark == 0)) - quark = g_quark_from_static_string("hildon-banner-timed"); - - return quark; -} - -/* Set the label name to make the correct rc-style attached into it */ -static void hildon_banner_bind_label_style(HildonBanner *self, - const gchar *name) -{ - GtkWidget *label = self->priv->label; - - /* Too bad that we cannot really reset the widget name */ - gtk_widget_set_name(label, name ? name : g_type_name(GTK_WIDGET_TYPE(label))); -} - -/* In timeout function we automatically destroy timed banners */ -static gboolean hildon_banner_timeout(gpointer data) -{ - GtkWidget *widget; - GdkEvent *event; - gboolean continue_timeout = FALSE; - - GDK_THREADS_ENTER (); - - g_assert(HILDON_IS_BANNER(data)); - - widget = GTK_WIDGET(data); - g_object_ref(widget); - - /* If the banner is currently visible (it normally should), - we simulate clicking the close button of the window. - This allows applications to reuse the banner by prevent - closing it etc */ - if (GTK_WIDGET_DRAWABLE(widget)) - { - event = gdk_event_new (GDK_DELETE); - event->any.window = g_object_ref(widget->window); - event->any.send_event = FALSE; - continue_timeout = gtk_widget_event (widget, event); - gdk_event_free(event); - } - - if (!continue_timeout) - gtk_widget_destroy (widget); - - g_object_unref(widget); - - GDK_THREADS_LEAVE (); - - return continue_timeout; -} - -static gboolean hildon_banner_clear_timeout(HildonBanner *self) -{ - g_assert(HILDON_IS_BANNER(self)); - - if (self->priv->timeout_id != 0) { - g_source_remove(self->priv->timeout_id); - self->priv->timeout_id = 0; - return TRUE; - } - - return FALSE; -} - -static void hildon_banner_ensure_timeout(HildonBanner *self) -{ - g_assert(HILDON_IS_BANNER(self)); - - if (self->priv->timeout_id == 0 && self->priv->is_timed) - self->priv->timeout_id = g_timeout_add(HILDON_BANNER_TIMEOUT, - hildon_banner_timeout, self); -} - -static void hildon_banner_set_property(GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GtkWidget *window; - GdkGeometry geom; - HildonBannerPrivate *priv = HILDON_BANNER(object)->priv; - - switch (prop_id) { - case PROP_IS_TIMED: - priv->is_timed = g_value_get_boolean(value); - - /* Timed and progress notifications have different - pixel size values for text. - We force to use requisition size for timed banners - in order to avoid resize problems when reusing the - window (see bug #24339) */ - geom.max_width = priv->is_timed ? -1 - : HILDON_BANNER_LABEL_MAX_PROGRESS; - geom.max_height = -1; - gtk_window_set_geometry_hints(GTK_WINDOW(object), - priv->label, &geom, GDK_HINT_MAX_SIZE); - break; - - case PROP_PARENT_WINDOW: - window = g_value_get_object(value); - - gtk_window_set_transient_for(GTK_WINDOW(object), (GtkWindow *) window); - - if (window) - gtk_window_set_destroy_with_parent(GTK_WINDOW(object), TRUE); - - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void hildon_banner_get_property(GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - HildonBanner *self = HILDON_BANNER(object); - - switch (prop_id) - { - case PROP_IS_TIMED: - g_value_set_boolean(value, self->priv->is_timed); - break; - - case PROP_PARENT_WINDOW: - g_value_set_object(value, gtk_window_get_transient_for(GTK_WINDOW(object))); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void hildon_banner_destroy(GtkObject *object) -{ - HildonBanner *self; - GObject *parent_window; - - g_assert(HILDON_IS_BANNER(object)); - self = HILDON_BANNER(object); - - /* Drop possible global pointer. That can hold reference to us */ - if ((gpointer) object == (gpointer) global_timed_banner) { - global_timed_banner = NULL; - g_object_unref(object); - } - - /* Remove the data from parent window for timed banners. Those hold reference */ - if (self->priv->is_timed && - (parent_window = (GObject *) gtk_window_get_transient_for( - GTK_WINDOW(object))) != NULL) - g_object_set_qdata(parent_window, hildon_banner_timed_quark(), NULL); - - (void) hildon_banner_clear_timeout(self); - - if (GTK_OBJECT_CLASS(hildon_banner_parent_class)->destroy) - GTK_OBJECT_CLASS(hildon_banner_parent_class)->destroy(object); -} - -/* Search a previous banner instance */ -static GObject *hildon_banner_real_get_instance(GObject *window, gboolean timed) -{ - g_assert(window == NULL || GTK_IS_WINDOW(window)); - - if (timed) { - /* If we have a parent window, the previous instance is stored there */ - if (window) - return g_object_get_qdata(window, hildon_banner_timed_quark()); - - /* System notification instance is stored into global pointer */ - return (GObject *) global_timed_banner; - } - - /* Non-timed banners are normal (non-singleton) objects */ - return NULL; -} - -/* By overriding constructor we force timed banners to be - singletons for each window */ -static GObject* hildon_banner_constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) -{ - GObject *banner, *window = NULL; - gboolean timed = FALSE; - guint i; - - /* Search banner type information from parameters in order - to locate the possible previous banner instance. */ - for (i = 0; i < n_construct_params; i++) - { - if (strcmp(construct_params[i].pspec->name, "parent-window") == 0) - window = g_value_get_object(construct_params[i].value); - else if (strcmp(construct_params[i].pspec->name, "is-timed") == 0) - timed = g_value_get_boolean(construct_params[i].value); - } - - /* Try to get a previous instance if such exists */ - banner = hildon_banner_real_get_instance(window, timed); - if (!banner) - { - /* We have to create a new banner */ - banner = G_OBJECT_CLASS(hildon_banner_parent_class)->constructor( - type, n_construct_params, construct_params); - - /* Store the newly created singleton instance either into parent - window data or into global variables. */ - if (timed) { - if (window) { - g_object_set_qdata_full(G_OBJECT(window), hildon_banner_timed_quark(), - g_object_ref(banner), g_object_unref); - } else { - g_assert(global_timed_banner == NULL); - global_timed_banner = g_object_ref(banner); - } - } - } - else { - /* FIXME: This is a hack! We have to manually freeze - notifications. This is normally done by g_object_init, but we - are not going to call that. g_object_newv will otherwise give - a critical like this: - - GLIB CRITICAL ** GLib-GObject - g_object_notify_queue_thaw: - assertion `nqueue->freeze_count > 0' failed */ - - g_object_freeze_notify(banner); - } - - /* We restart possible timeouts for each new timed banner request */ - if (timed && hildon_banner_clear_timeout(HILDON_BANNER(banner))) - hildon_banner_ensure_timeout(HILDON_BANNER(banner)); - - return banner; -} - -/* We start the timer for timed notifications after the window appears on screen */ -static gboolean hildon_banner_map_event(GtkWidget *widget, GdkEventAny *event) -{ - gboolean result = FALSE; - - if (GTK_WIDGET_CLASS(hildon_banner_parent_class)->map_event) - result = GTK_WIDGET_CLASS(hildon_banner_parent_class)->map_event(widget, event); - - hildon_banner_ensure_timeout(HILDON_BANNER(widget)); - - return result; -} - - -/* force to wrap truncated label by setting explicit size request - * see N#27000 and G#329646 */ -static void force_to_wrap_truncated(HildonBanner *banner){ - GtkLabel *label; - PangoLayout *layout; - int width_text, width_max; - int width = -1; - - label = GTK_LABEL(banner->priv->label); - - layout = gtk_label_get_layout(label); - width_text = PANGO_PIXELS(pango_layout_get_width(layout)); - /* = width to which the lines of the PangoLayout should be wrapped */ - - width_max = banner->priv->is_timed ? HILDON_BANNER_LABEL_MAX_TIMED - : HILDON_BANNER_LABEL_MAX_PROGRESS; - - if(width_text >= width_max){ - /* explicitly request maximum size to force wrapping */ - PangoRectangle logical; - - pango_layout_set_width (layout, width_max * PANGO_SCALE); - pango_layout_get_extents (layout, NULL, &logical); - - width = PANGO_PIXELS (logical.width); - } - - /* use fixed width when wrapping or natural one otherwise */ - gtk_widget_set_size_request (GTK_WIDGET (label), - width, -1); -} - - -static void hildon_banner_check_position(GtkWidget *widget) -{ - gint x, y; - GtkRequisition req; - - force_to_wrap_truncated(HILDON_BANNER(widget)); /* see N#27000 and G#329646 */ - - gtk_widget_size_request(widget, &req); - - if (req.width == 0) - { - return; - } - - x = gdk_screen_width() - HILDON_BANNER_WINDOW_X - req.width; - y = check_fullscreen_state(get_current_app_window()) ? - HILDON_BANNER_WINDOW_FULLSCREEN_Y : HILDON_BANNER_WINDOW_Y; - - gtk_window_move(GTK_WINDOW(widget), x, y); -} - -static void hildon_banner_realize(GtkWidget *widget) -{ - /* We let the parent to init widget->window before we need it */ - if (GTK_WIDGET_CLASS(hildon_banner_parent_class)->realize) - GTK_WIDGET_CLASS(hildon_banner_parent_class)->realize(widget); - - /* We use special hint to turn the banner into information notification. */ - gdk_window_set_type_hint(widget->window, GDK_WINDOW_TYPE_HINT_MESSAGE); - - hildon_banner_check_position(widget); -} - -static void hildon_banner_class_init(HildonBannerClass *klass) -{ - GObjectClass *object_class; - GtkWidgetClass *widget_class; - - object_class = G_OBJECT_CLASS(klass); - widget_class = GTK_WIDGET_CLASS(klass); - - /* Append private structure to class. This is more elegant than - on g_new based approach */ - g_type_class_add_private(klass, sizeof(HildonBannerPrivate)); - - /* Override virtual methods */ - object_class->constructor = hildon_banner_constructor; - object_class->set_property = hildon_banner_set_property; - object_class->get_property = hildon_banner_get_property; - GTK_OBJECT_CLASS(klass)->destroy = hildon_banner_destroy; - widget_class->map_event = hildon_banner_map_event; - widget_class->realize = hildon_banner_realize; - - /* Install properties. - We need construct properties for singleton purposes */ - g_object_class_install_property(object_class, PROP_PARENT_WINDOW, - g_param_spec_object("parent-window", - "Parent window", - "The window for which the banner will be singleton", - GTK_TYPE_WINDOW, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property(object_class, PROP_IS_TIMED, - g_param_spec_boolean("is-timed", - "Is timed", - "Whether or not the notification goes away automatically " - "after the specified time has passed", - FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); -} - -static void hildon_banner_init(HildonBanner *self) -{ - HildonBannerPrivate *priv; - - /* Make private data available through cached pointer */ - self->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE(self, - HILDON_TYPE_BANNER, - HildonBannerPrivate); - - /* Initialize the common layout inside banner */ - self->priv->layout = gtk_hbox_new(FALSE, HILDON_MARGIN_DEFAULT); - - priv->label = g_object_new(GTK_TYPE_LABEL, NULL); - gtk_label_set_line_wrap(GTK_LABEL(priv->label), TRUE); - - gtk_container_set_border_width(GTK_CONTAINER(self->priv->layout), HILDON_MARGIN_DEFAULT); - gtk_container_add(GTK_CONTAINER(self), self->priv->layout); - gtk_box_pack_start(GTK_BOX(self->priv->layout), priv->label, TRUE, TRUE, 0); - - gtk_window_set_accept_focus(GTK_WINDOW(self), FALSE); -} - -/* Makes sure that icon/progress item contains the desired type - of item. If possible, tries to avoid creating a new widget but - reuses the existing one */ -static void hildon_banner_ensure_child(HildonBanner *self, - GtkWidget *user_widget, - guint pos, - GType type, - const gchar *first_property, ...) -{ - GtkWidget *widget; - va_list args; - - g_assert(HILDON_IS_BANNER(self)); - g_assert(user_widget == NULL || GTK_IS_WIDGET(user_widget)); - - widget = self->priv->main_item; - va_start(args, first_property); - - /* Reuse existing widget if possible */ - if (!user_widget && G_TYPE_CHECK_INSTANCE_TYPE(widget, type)) - { - g_object_set_valist(G_OBJECT(widget), first_property, args); - } - else - { - /* We have to abandon old content widget */ - if (widget) - gtk_container_remove(GTK_CONTAINER(self->priv->layout), widget); - - /* Use user provided widget or create a new one */ - self->priv->main_item = widget = user_widget ? - user_widget : GTK_WIDGET(g_object_new_valist(type, first_property, args)); - gtk_box_pack_start(GTK_BOX(self->priv->layout), widget, TRUE, TRUE, 0); - } - - /* We make sure that the widget exists in desired position. Different - banners place this child widget to different places */ - gtk_box_reorder_child(GTK_BOX(self->priv->layout), widget, pos); - va_end(args); -} - -/* Creates a new banner instance or uses an existing one */ -static HildonBanner *hildon_banner_get_instance_for_widget(GtkWidget *widget, gboolean timed) -{ - GtkWidget *window; - - g_return_val_if_fail(widget == NULL || GTK_IS_WIDGET(widget), NULL); - window = widget ? gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW) : NULL; - return g_object_new(HILDON_TYPE_BANNER, "parent-window", window, "is-timed", timed, NULL); -} - - - - - -/* Public functions **************************************************************/ - -/** - * hildon_banner_show_information: - * @widget: the #GtkWidget that wants to display banner - * @icon_name: the name of icon to use. Can be %NULL for default icon. - * @text: Text to display - * - * This function creates and displays an information banner that - * automatically goes away after certain time period. For each window - * in your application there can only be one timed banner, so if you - * spawn a new banner before the earlier one has timed out, the - * previous one will be replaced. - * - * Since: 0.12.2 - */ -void hildon_banner_show_information(GtkWidget *widget, - const gchar *icon_name, - const gchar *text) -{ - HildonBanner *banner; - - g_return_if_fail(widget == NULL || GTK_IS_WIDGET(widget)); - g_return_if_fail(icon_name == NULL || icon_name[0] != 0); - g_return_if_fail(text != NULL); - - /* Prepare banner */ - banner = hildon_banner_get_instance_for_widget(widget, TRUE); - hildon_banner_ensure_child(banner, NULL, 0, GTK_TYPE_IMAGE, - "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE, - "icon-name", icon_name ? icon_name : HILDON_BANNER_DEFAULT_ICON, - "yalign", 0.0, - NULL); - hildon_banner_set_text(banner, text); - hildon_banner_bind_label_style(banner, NULL); - - /* Show the banner, since caller cannot do that */ - gtk_widget_show_all(GTK_WIDGET(banner)); -} - -/** - * hildon_banner_show_information_with_markup: - * @widget: the #GtkWidget that wants to display banner - * @icon_name: the name of icon to use. Can be %NULL for default icon. - * @markup: a markup string to display (see Pango markup format) - * - * This function creates and displays an information banner that - * automatically goes away after certain time period. For each window - * in your application there can only be one timed banner, so if you - * spawn a new banner before the earlier one has timed out, the - * previous one will be replaced. - * - * Since: 0.12.8 - */ -void hildon_banner_show_information_with_markup(GtkWidget *widget, - const gchar *icon_name, const gchar *markup) -{ - HildonBanner *banner; - - g_return_if_fail(widget == NULL || GTK_IS_WIDGET(widget)); - g_return_if_fail(icon_name == NULL || icon_name[0] != 0); - g_return_if_fail(markup != NULL); - - /* Prepare banner */ - banner = hildon_banner_get_instance_for_widget(widget, TRUE); - - hildon_banner_ensure_child(banner, NULL, 0, GTK_TYPE_IMAGE, - "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE, - "icon-name", icon_name ? icon_name : HILDON_BANNER_DEFAULT_ICON, - "yalign", 0.0, - NULL); - hildon_banner_set_markup(banner, markup); - hildon_banner_bind_label_style(banner, NULL); - - /* Show the banner, since caller cannot do that */ - gtk_widget_show_all(GTK_WIDGET(banner)); -} - -/** - * hildon_banner_show_animation: - * @widget: the #GtkWidget that wants to display banner - * @animation_name: The progress animation to use. You usually can just - * pass %NULL for the default animation. - * @text: the text to display. - * - * Shows an animated progress notification. It's recommended not to try - * to show more than one progress notification at a time, since - * they will appear on top of each other. You can use progress - * notifications with timed banners. In this case the banners are - * located so that you can somehow see both. - * - * Please note that banners are destroyed automatically once the - * window they are attached to is closed. The pointer that you - * receive with this function do not contain additional references, - * so it can become invalid without warning (this is true for - * all toplevel windows in gtk). To make sure that the banner do not disapear - * automatically, you can separately ref the return value (this - * doesn't prevent the banner from disappearing, but the object it just - * not finalized). In this case you have to call both #gtk_widget_destroy - * followed by #g_object_unref (in this order). - * - * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy - * once you are ready with the banner. - * - * Since: 0.12.2 - */ -GtkWidget *hildon_banner_show_animation(GtkWidget *widget, - const gchar *animation_name, const gchar *text) -{ - HildonBanner *banner; - GtkIconTheme *theme; - GtkIconInfo *info; - GtkWidget *image_widget; - const gchar *filename; - - g_return_val_if_fail(widget == NULL || GTK_IS_WIDGET(widget), NULL); - g_return_val_if_fail(animation_name == NULL || animation_name[0] != 0, NULL); - g_return_val_if_fail(text != NULL, NULL); - - /* Find out which animation to use */ - theme = gtk_icon_theme_get_default(); - info = gtk_icon_theme_lookup_icon(theme, animation_name ? /* TODO: consider using: gtk_icon_theme_load_icon() */ - animation_name : HILDON_BANNER_DEFAULT_PROGRESS_ANIMATION, - HILDON_ICON_SIZE_NOTE, 0); - - /* Try to load animation. One could try to optimize this - to avoid loading the default animation during each call */ - if (info) { - filename = gtk_icon_info_get_filename(info); - image_widget = gtk_image_new_from_file(filename); - gtk_icon_info_free(info); - } else { - g_warning("icon theme lookup for icon failed!"); - image_widget = NULL; - } - - /* Prepare banner */ - banner = hildon_banner_get_instance_for_widget(widget, FALSE); - hildon_banner_ensure_child(banner, image_widget, 0, - GTK_TYPE_IMAGE, "yalign", 0.0, NULL); - hildon_banner_set_text(banner, text); - hildon_banner_bind_label_style(banner, NULL); - - /* And show it */ - gtk_widget_show_all(GTK_WIDGET(banner)); - - return GTK_WIDGET(banner); -} - -/** - * hildon_banner_show_progress: - * @widget: the #GtkWidget that wants to display banner - * @bar: Progressbar to use. You usually can just pass %NULL, unless - * you want somehow customized progress bar. - * @text: text to display. - * - * Shows progress notification. See #hildon_banner_show_animation - * for more information. - * - * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy - * once you are ready with the banner. - * - * Since: 0.12.2 - */ -GtkWidget *hildon_banner_show_progress(GtkWidget *widget, - GtkProgressBar *bar, const gchar *text) -{ - HildonBanner *banner; - - g_return_val_if_fail(widget == NULL || GTK_IS_WIDGET(widget), NULL); - g_return_val_if_fail(bar == NULL || GTK_IS_PROGRESS_BAR(bar), NULL); - g_return_val_if_fail(text != NULL, NULL); - - /* Prepare banner */ - banner = hildon_banner_get_instance_for_widget(widget, FALSE); - hildon_banner_ensure_child(banner, (GtkWidget *) bar, -1, GTK_TYPE_PROGRESS_BAR, NULL); - gtk_widget_set_size_request(banner->priv->main_item, - HILDON_BANNER_PROGRESS_WIDTH, -1); - hildon_banner_set_text(banner, text); - hildon_banner_bind_label_style(banner, NULL); - - /* Show the banner */ - gtk_widget_show_all(GTK_WIDGET(banner)); - - return GTK_WIDGET(banner); -} - -/** - * hildon_banner_set_text: - * @self: a #HildonBanner widget - * @text: a new text to display in banner - * - * Sets the text that is displayed in the banner. - * - * Since: 0.12.2 - */ -void hildon_banner_set_text(HildonBanner *self, const gchar *text) -{ - GtkLabel *label; - - g_return_if_fail(HILDON_IS_BANNER(self)); - - label = GTK_LABEL(self->priv->label); - gtk_label_set_text(label, text); - - hildon_banner_check_position(GTK_WIDGET(self)); -} - -/** - * hildon_banner_set_markup: - * @self: a #HildonBanner widget - * @markup: a new text with Pango markup to display in the banner - * - * Sets the text with markup that is displayed in the banner. - * - * Since: 0.12.8 - */ -void hildon_banner_set_markup(HildonBanner *self, const gchar *markup) -{ - GtkLabel *label; - - g_return_if_fail(HILDON_IS_BANNER(self)); - - label = GTK_LABEL(self->priv->label); - gtk_label_set_markup(label, markup); - - hildon_banner_check_position(GTK_WIDGET(self)); -} - -/** - * hildon_banner_set_fraction: - * @self: a #HildonBanner widget - * @fraction: #gdouble - * - * The fraction is the completion of progressbar, - * the scale is from 0.0 to 1.0. - * Sets the amount of fraction the progressbar has. - * - * Since: 0.12.2 - */ -void hildon_banner_set_fraction(HildonBanner *self, gdouble fraction) -{ - g_return_if_fail(HILDON_IS_BANNER(self)); - g_return_if_fail(GTK_IS_PROGRESS_BAR(self->priv->main_item)); - gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(self->priv->main_item), fraction); -} - - - - - -/** - * Deprecated: really, do NOT use. - */ -void _hildon_gtk_label_set_text_n_lines(GtkLabel *label, const gchar *text, gint max_lines) -{ -/* Forces the wrapping of text into several lines and ellipsizes the rest. - Similar to combination of gtk_label_set_wrap and pango ellipzation. - We cannot just use those directly, since ellipzation always wins wrapping. - - This means that we have to: - * First wrap the text - * Insert forced linebreaks into text - * Truncate the result - - NOTE! This will not work with pango markup! - - FIXME: luc: DO NOT TRUNCATE the text. Use as many lines as needed. - Lenth of the text is under applications' responsibility. - Widget does not have to enforce this. -*/ - PangoLayout *layout; - PangoLayoutLine *line; - GtkRequisition req; - GString *wrapped_text; - gchar *line_data; - gint lines, i; - - g_return_if_fail(GTK_IS_LABEL(label)); - g_return_if_fail(max_lines >= 1); - - /* Setup the label to contain the new data */ - gtk_label_set_text(label, text); - gtk_label_set_line_wrap(label, TRUE); - gtk_label_set_ellipsize(label, PANGO_ELLIPSIZE_NONE); - - /* We really want to recalculate the size, not use some old values */ - gtk_widget_size_request(GTK_WIDGET(label), &req); - layout = gtk_label_get_layout(label); - lines = pango_layout_get_line_count(layout); - - /* Now collect the wrapped text. */ - wrapped_text = g_string_new(NULL); - - for (i = 0; i < lines; i++) - { - /* Append the next line into wrapping buffer, but - avoid adding extra whitespaces at the end, since those - can cause other lines to be ellipsized as well. */ - line = pango_layout_get_line(layout, i); - line_data = g_strndup(pango_layout_get_text(layout) + line->start_index, - line->length); - g_strchomp(line_data); - g_string_append(wrapped_text, line_data); - - /* Append forced linebreaks, until we have the desired - amount of lines. After that we put the rest to the - last line to make ellipzation to happen */ - if (i < lines - 1) - { - if (i < max_lines - 1) - g_string_append_c(wrapped_text, '\n'); - else - g_string_append_c(wrapped_text, ' '); - } - - g_free(line_data); - } - - /* Now update the label to use wrapped text. Use builtin - ellipzation as well. */ - gtk_widget_set_size_request(GTK_WIDGET(label), req.width, -1); - gtk_label_set_text(label, wrapped_text->str); - gtk_label_set_ellipsize(label, PANGO_ELLIPSIZE_END); - gtk_label_set_line_wrap(label, FALSE); - - g_string_free(wrapped_text, TRUE); -} diff --git a/hildon-widgets/hildon-banner.h b/hildon-widgets/hildon-banner.h deleted file mode 100644 index fe8c5d2..0000000 --- a/hildon-widgets/hildon-banner.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_BANNER_H__ -#define __HILDON_BANNER_H__ - -#include -#include -#include - -G_BEGIN_DECLS - -#define HILDON_TYPE_BANNER (hildon_banner_get_type()) - -#define HILDON_BANNER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), HILDON_TYPE_BANNER, HildonBanner)) -#define HILDON_IS_BANNER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), HILDON_TYPE_BANNER)) - -typedef struct _HildonBanner HildonBanner; -typedef struct _HildonBannerClass HildonBannerClass; -typedef struct _HildonBannerPrivate HildonBannerPrivate; - -struct _HildonBanner -{ - GtkWindow parent; - HildonBannerPrivate *priv; -}; - -struct _HildonBannerClass -{ - GtkWindowClass parent_class; -}; - -GType hildon_banner_get_type (void) G_GNUC_CONST; - -void hildon_banner_show_information (GtkWidget *widget, - const gchar *icon_name, - const gchar *text); - -void hildon_banner_show_information_with_markup (GtkWidget *widget, - const gchar *icon_name, - const gchar *markup); - -GtkWidget *hildon_banner_show_animation (GtkWidget *widget, - const gchar *animation_name, - const gchar *text); - -GtkWidget *hildon_banner_show_progress (GtkWidget *widget, - GtkProgressBar *bar, - const gchar *text); - -void hildon_banner_set_text (HildonBanner *self, - const gchar *text); - -void hildon_banner_set_markup (HildonBanner *self, - const gchar *markup); - -void hildon_banner_set_fraction (HildonBanner *self, - gdouble fraction); - - - -/* For internal use of hildon libraries only */ -void _hildon_gtk_label_set_text_n_lines(GtkLabel *label, const gchar *text, gint max_lines); - -G_END_DECLS - -#endif /* __HILDON_BANNER_H__ */ diff --git a/hildon-widgets/hildon-calendar-popup.c b/hildon-widgets/hildon-calendar-popup.c deleted file mode 100644 index 3139374..0000000 --- a/hildon-widgets/hildon-calendar-popup.c +++ /dev/null @@ -1,439 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-calendar-popup - * @shortdesc: CalendarPopup allows choosing a date from a popup calendar. - * @longdesc: The Calendar popup is a dialog that contains a GtkCalendar - * widget. The pop-up is cancelled by pressing the ESC key. - * - * - * @seealso: #HildonDateEditor, #HildonTimeEditor - * - * HildonCalendarPopup is a dialog which contains a GtkCalendar. It - * also contains arrow buttons for changing the month/year. If an - * entered date is invalid, an information message will be shown. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#define _(String) dgettext(PACKAGE, String) - -#define HILDON_CALENDAR_POPUP_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE\ - ((obj), HILDON_TYPE_CALENDAR_POPUP, HildonCalendarPopupPrivate)); - -static GtkDialog *parent_class; - -typedef struct _HildonCalendarPopupPrivate HildonCalendarPopupPrivate; - -static void init_dmy(guint year, guint month, guint day, guint * d, - guint * m, guint * y); - -static void -hildon_calendar_popup_class_init(HildonCalendarPopupClass * cal_class); - -static void hildon_calendar_popup_init(HildonCalendarPopup * cal); - -static void hildon_calendar_selected_date(GtkWidget * self, gpointer cal_popup); - -static gboolean hildon_key_pressed(GtkWidget * widget, GdkEventKey * event, - gpointer cal_popup); - -static void hildon_calendar_popup_set_property(GObject * object, guint property_id, - const GValue * value, GParamSpec * pspec); -static void hildon_calendar_popup_get_property(GObject * object, guint property_id, - GValue * value, GParamSpec * pspec); - -enum { - PROP_0, - PROP_DAY, - PROP_MONTH, - PROP_YEAR, - PROP_MIN_YEAR, - PROP_MAX_YEAR -}; - -struct _HildonCalendarPopupPrivate { - GtkWidget *cal; -}; - -GType hildon_calendar_popup_get_type(void) -{ - static GType popup_type = 0; - - if (!popup_type) { - static const GTypeInfo popup_info = { - sizeof(HildonCalendarPopupClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_calendar_popup_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonCalendarPopup), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_calendar_popup_init, - }; - popup_type = g_type_register_static(GTK_TYPE_DIALOG, - "HildonCalendarPopup", - &popup_info, 0); - } - - return popup_type; -} - -/** - * hildon_calendar_popup_new: - * @parent: parent window for dialog - * @year: initial year - * @month: initial month - * @day: initial day - * - * This function returns a new HildonCalendarPopup. The initially - * selected date is specified by the parameters (year, month, day). - * If the specified date is invalid, the current date is used. - * - * Returns: new @HildonCalendarPopup widget - */ -GtkWidget *hildon_calendar_popup_new(GtkWindow * parent, guint year, - guint month, guint day) -{ - HildonCalendarPopup *cal = NULL; - - /* Create new HildonCalendarPopup */ - cal = HILDON_CALENDAR_POPUP(g_object_new(HILDON_TYPE_CALENDAR_POPUP, - "year", year, "month", month, "day", day, - NULL)); - - if (parent) { - gtk_window_set_transient_for(GTK_WINDOW(cal), parent); - } - - return GTK_WIDGET(cal); -} - -/** - * hildon_calendar_popup_set_date: - * @cal: the @HildonCalendarPopup widget - * @year: year - * @month: month - * @day: day - * - * activates a new date on the calendar popup. - **/ -void -hildon_calendar_popup_set_date(HildonCalendarPopup * cal, - guint year, guint month, guint day) -{ - guint dtmp, mtmp, ytmp = 0; - HildonCalendarPopupPrivate *priv; - - g_return_if_fail(HILDON_IS_CALENDAR_POPUP(cal)); - - priv = HILDON_CALENDAR_POPUP_GET_PRIVATE(cal); - - /* Choose current date if the date is invalid: - */ - init_dmy(year, month, day, &dtmp, &mtmp, &ytmp); - - /* Remove all visual markers */ - gtk_calendar_clear_marks(GTK_CALENDAR(priv->cal)); - - /* Set a new date */ - gtk_calendar_select_month(GTK_CALENDAR(priv->cal), mtmp - 1, ytmp); - gtk_calendar_select_day(GTK_CALENDAR(priv->cal), dtmp); -} - -/** - * hildon_calendar_popup_get_date: - * @cal: the @HildonCalendarPopup widget - * @year: year - * @month: month - * @day: day - * - * Gets the currently selected year, month, and day. - */ -void -hildon_calendar_popup_get_date(HildonCalendarPopup * cal, - guint * year, guint * month, guint * day) -{ - HildonCalendarPopupPrivate *priv; - - g_return_if_fail(HILDON_IS_CALENDAR_POPUP(cal)); - - priv = HILDON_CALENDAR_POPUP_GET_PRIVATE(cal); - gtk_calendar_get_date(GTK_CALENDAR(priv->cal), year, month, day); - *month = *month + 1; - - if (!g_date_valid_dmy(*day, *month, *year)) { - *day = g_date_get_days_in_month(*month, *year); - } -} - -static void -hildon_calendar_popup_class_init(HildonCalendarPopupClass * cal_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS(cal_class); - parent_class = g_type_class_peek_parent(cal_class); - - object_class->set_property = hildon_calendar_popup_set_property; - object_class->get_property = hildon_calendar_popup_get_property; - - g_type_class_add_private(cal_class, - sizeof(HildonCalendarPopupPrivate)); - - /* Install new properties for the GObject_class */ - g_object_class_install_property(object_class, PROP_MIN_YEAR, - g_param_spec_uint("min-year", - "Minimum valid year", - "Minimum valid year", - 1, 2100, - 1970, - G_PARAM_WRITABLE)); - - g_object_class_install_property(object_class, PROP_MAX_YEAR, - g_param_spec_uint("max-year", - "Maximum valid year", - "Maximum valid year", - 1, 2100, - 2037, - G_PARAM_WRITABLE)); - - g_object_class_install_property(object_class, PROP_DAY, - g_param_spec_int ("day", - "Day", - "currently selected day", - G_MININT, - G_MAXINT, - 0, - G_PARAM_READWRITE)); - - g_object_class_install_property(object_class, PROP_MONTH, - g_param_spec_int ("month", - "Month", - "currently selected month", - G_MININT, - G_MAXINT, - 0, - G_PARAM_READWRITE)); - - g_object_class_install_property(object_class, PROP_YEAR, - g_param_spec_int ("year", - "Year", - "the currently selected year", - G_MININT, - G_MAXINT, - 0, - G_PARAM_READWRITE)); - -} - -static void hildon_calendar_popup_init(HildonCalendarPopup * cal) -{ - HildonCalendarPopupPrivate *priv; - static int set_domain = 1; - - priv = HILDON_CALENDAR_POPUP_GET_PRIVATE(cal); - - /* set the domain directory for different language */ - if (set_domain) { - (void) bindtextdomain(PACKAGE, LOCALEDIR); - set_domain = 0; - } - - priv->cal = gtk_calendar_new(); - - /* dialog options and packing */ - gtk_calendar_set_display_options(GTK_CALENDAR(priv->cal), - GTK_CALENDAR_SHOW_HEADING | - GTK_CALENDAR_SHOW_DAY_NAMES | - GTK_CALENDAR_SHOW_WEEK_NUMBERS); - - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(cal)->vbox), priv->cal, - TRUE, TRUE, 0); - gtk_dialog_set_has_separator(GTK_DIALOG(cal), FALSE); - gtk_dialog_add_button(GTK_DIALOG(cal), _("ecdg_bd_calendar_popout_done"), - GTK_RESPONSE_OK); - gtk_widget_show(priv->cal); - - /* Connect signals */ - g_signal_connect(G_OBJECT(priv->cal), "key-press-event", - G_CALLBACK(hildon_key_pressed), cal); - - g_signal_connect(G_OBJECT(priv->cal), "selected_date", - G_CALLBACK(hildon_calendar_selected_date), cal); - - /* set decorations, needs realizing first*/ - gtk_widget_realize(GTK_WIDGET(cal)); - gdk_window_set_decorations(GTK_WIDGET(cal)->window, GDK_DECOR_BORDER); - -} - - -/* - * Signal handler for key-press-event. Closes the dialog for some - * special keys. - */ -static gboolean -hildon_key_pressed(GtkWidget * widget, GdkEventKey * event, gpointer cal_popup) -{ - g_assert(HILDON_IS_CALENDAR_POPUP(cal_popup)); - - /* Handle Return key press as OK response */ - if (event->keyval == GDK_Return) - { - gtk_dialog_response(GTK_DIALOG(cal_popup), GTK_RESPONSE_OK); - return TRUE; - } - - /* Handle Esc key press as CANCEL response */ - if ((event->keyval == GDK_Escape)) - { - gtk_dialog_response(GTK_DIALOG(cal_popup), GTK_RESPONSE_CANCEL); - return TRUE; - } - - return FALSE; -} - - -/* - * Validates the given date or initializes it with the current date - */ -static void -init_dmy(guint year, guint month, guint day, guint *d, guint *m, guint *y) -{ - GDate date; - - /* Initialize the date with a valid selected date */ - if (g_date_valid_dmy(day, month, year)) { - *d = day; - *m = month; - *y = year; - } else { - - /* If selected date is invalid initialize the date with current date */ - g_date_clear(&date, 1); - g_date_set_time(&date, time(NULL)); - - *d = g_date_get_day(&date); - *m = g_date_get_month(&date); - *y = g_date_get_year(&date); - } -} - -/* - * Exits the dialog when "selected_date" signal is emmited. The - * "selected_date" signal is a Hildon addition to GtkCalendar and is - * emitted on button-release. - */ -static void -hildon_calendar_selected_date(GtkWidget * self, gpointer cal_popup) -{ - g_assert(GTK_IS_WIDGET (self)); - g_assert(HILDON_IS_CALENDAR_POPUP (cal_popup)); - - gtk_dialog_response(GTK_DIALOG(cal_popup), GTK_RESPONSE_OK); -} - - -static void hildon_calendar_popup_set_property(GObject * object, guint property_id, - const GValue * value, GParamSpec * pspec) -{ - HildonCalendarPopup *popup = HILDON_CALENDAR_POPUP (object); - HildonCalendarPopupPrivate *priv = - HILDON_CALENDAR_POPUP_GET_PRIVATE(HILDON_CALENDAR_POPUP (object)); - - switch (property_id) { - case PROP_DAY: - { - guint year, month, day = 0; - hildon_calendar_popup_get_date(popup, &year, &month, &day); - - /*Verifies that the date is valid: */ - hildon_calendar_popup_set_date(popup, year, month, g_value_get_int(value)); - break; - } - case PROP_MONTH: - { - guint year, month, day = 0; - hildon_calendar_popup_get_date(popup, &year, &month, &day); - - /*Verifies that the date is valid: */ - hildon_calendar_popup_set_date(popup, year, g_value_get_int(value), day); - break; - } - case PROP_YEAR: - { - guint year, month, day = 0; - hildon_calendar_popup_get_date(popup, &year, &month, &day); - - /*Verifies that the date is valid: */ - hildon_calendar_popup_set_date(popup, g_value_get_int(value), month, day); - break; - } - case PROP_MIN_YEAR: - g_object_set_property(G_OBJECT(priv->cal), "min-year", value); - break; - case PROP_MAX_YEAR: - g_object_set_property(G_OBJECT(priv->cal), "max-year", value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; - } -} - -static void hildon_calendar_popup_get_property(GObject * object, guint property_id, - GValue * value, GParamSpec * pspec) -{ - HildonCalendarPopupPrivate *priv = - HILDON_CALENDAR_POPUP_GET_PRIVATE(HILDON_CALENDAR_POPUP (object)); - - switch (property_id) { - case PROP_DAY: - g_object_get_property(G_OBJECT(priv->cal), pspec->name, value); - break; - case PROP_MONTH: - g_object_get_property(G_OBJECT(priv->cal), pspec->name, value); - break; - case PROP_YEAR: - g_object_get_property(G_OBJECT(priv->cal), pspec->name, value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; - } -} diff --git a/hildon-widgets/hildon-calendar-popup.h b/hildon-widgets/hildon-calendar-popup.h deleted file mode 100644 index e2e1d15..0000000 --- a/hildon-widgets/hildon-calendar-popup.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_CALENDAR_POPUP_H__ -#define __HILDON_CALENDAR_POPUP_H__ - -#include - -G_BEGIN_DECLS -/** - * HILDON_TYPE_CALENDAR_POPUP: - * - * Macro for getting type of calendar popup. - * Since: 0.12.10 - */ -#define HILDON_TYPE_CALENDAR_POPUP ( hildon_calendar_popup_get_type() ) - -/** - * HILDON_CALENDAR_POPUP_TYPE: - * - * Deprecated: use #HILDON_TYPE_CALENDAR_POPUP instead - */ -#define HILDON_CALENDAR_POPUP_TYPE HILDON_TYPE_CALENDAR_POPUP - -#define HILDON_CALENDAR_POPUP(obj) (GTK_CHECK_CAST (obj,\ - HILDON_TYPE_CALENDAR_POPUP, HildonCalendarPopup)) -#define HILDON_CALENDAR_POPUP_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass),\ - HILDON_TYPE_CALENDAR_POPUP, HildonCalendarPopupClass)) -#define HILDON_IS_CALENDAR_POPUP(obj) (GTK_CHECK_TYPE (obj,\ - HILDON_TYPE_CALENDAR_POPUP)) -#define HILDON_IS_CALENDAR_POPUP_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_CALENDAR_POPUP)) - -/** - * HildonCalendarPopup: - * - * Internal struct for calendar popup. - */ -typedef struct _HildonCalendarPopup HildonCalendarPopup; -typedef struct _HildonCalendarPopupClass HildonCalendarPopupClass; - -/* Note: CalendarPopup is no longer derived from GtkWindow - but from GtkDialog */ - -struct _HildonCalendarPopup { - GtkDialog par; -}; - -struct _HildonCalendarPopupClass { - GtkDialogClass parent_class; -}; - -GType hildon_calendar_popup_get_type(void) G_GNUC_CONST; - -GtkWidget *hildon_calendar_popup_new(GtkWindow * parent, guint year, - guint month, guint day); - -void hildon_calendar_popup_set_date(HildonCalendarPopup * cal, - guint year, guint month, guint day); - -void hildon_calendar_popup_get_date(HildonCalendarPopup * cal, - guint * year, guint * month, - guint * day); - -G_END_DECLS -#endif /* __HILDON_CALENDAR_POPUP_H__ */ diff --git a/hildon-widgets/hildon-caption.c b/hildon-widgets/hildon-caption.c deleted file mode 100644 index 5accf57..0000000 --- a/hildon-widgets/hildon-caption.c +++ /dev/null @@ -1,1254 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-caption - * @short_description: A single-child container widget that precedes the - * contained widget with a field label and an optional icon - * - * #HildonCaption is a single-child container widget that precedes the - * contained widget with a field label and an optional icon. It allows - * grouping of several controls together. When a captioned widget has focus, - * both widget and caption label are displayed with active focus. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "hildon-caption.h" -#include "hildon-defines.h" - -#ifdef HAVE_CONFIG_H -#include -#endif -#include -#define _(String) dgettext(PACKAGE, String) - -#define HILDON_CAPTION_SPACING 6 - -#define HILDON_CAPTION_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_CAPTION, HildonCaptionPrivate)); - -/*our parent class*/ -static GtkEventBox *parent_class = NULL; - -typedef struct _HildonCaptionPrivate HildonCaptionPrivate; - -enum -{ - PROP_NONE, - PROP_LABEL, - PROP_ICON, - PROP_STATUS, - PROP_SEPARATOR, - PROP_SIZE_GROUP, - PROP_ICON_POSITION, -}; - -enum -{ - CHILD_PROP_NONE, - CHILD_PROP_EXPAND -}; - -static void hildon_caption_class_init ( HildonCaptionClass *caption_class ); -static void hildon_caption_init ( HildonCaption *caption ); -static void hildon_caption_size_request ( GtkWidget *widget, GtkRequisition *requisition ); -static void hildon_caption_size_allocate( GtkWidget *widget, GtkAllocation *allocation ); - -static void hildon_caption_forall( GtkContainer *container, - gboolean include_internals, - GtkCallback callback, gpointer data ); -static void hildon_caption_hierarchy_changed( GtkWidget *widget, - GtkWidget *previous_toplevel); -static void hildon_caption_set_focus( GtkWindow *window, GtkWidget *widget, - GtkWidget *caption ); -static void hildon_caption_activate( GtkWidget *widget ); - -static void hildon_caption_set_property( GObject *object, guint param_id, - const GValue *value, GParamSpec *pspec ); -static void hildon_caption_get_property( GObject *object, guint param_id, - GValue *value, GParamSpec *pspec ); -static gboolean hildon_caption_expose( GtkWidget *widget, - GdkEventExpose *event ); -static void hildon_caption_destroy( GtkObject *self ); -static gboolean hildon_caption_button_press( GtkWidget *widget, GdkEventButton *event ); - -static void -hildon_caption_set_label_text( HildonCaptionPrivate *priv ); - -static void hildon_caption_set_child_property (GtkContainer *container, - GtkWidget *child, - guint property_id, - const GValue *value, - GParamSpec *pspec); -static void hildon_caption_get_child_property (GtkContainer *container, - GtkWidget *child, - guint property_id, - GValue *value, - GParamSpec *pspec); - -struct _HildonCaptionPrivate -{ - GtkWidget *caption_area; - GtkWidget *label; - GtkWidget *icon; - GtkWidget *icon_align; /* Arbitrary icon widgets do not support alignment */ - GtkSizeGroup *group; - gchar *text; - gchar *separator; - guint is_focused : 1; - guint expand : 1; - HildonCaptionStatus status; - HildonCaptionIconPosition icon_position; -}; - -/* Register optional/mandatory type enumeration */ -/* FIXME: mandatory icon was removed. The mandatory/optional logic - remains, it should most probably be removed as well. This imply APi - change, especially hildon_caption_new() */ -GType -hildon_caption_status_get_type (void) -{ - static GType etype = 0; - if (etype == 0) { - static const GEnumValue values[] = { - { HILDON_CAPTION_OPTIONAL, "HILDON_CAPTION_OPTIONAL", "optional" }, - { HILDON_CAPTION_MANDATORY, "HILDON_CAPTION_MANDATORY", "mandatory" }, - { 0, NULL, NULL } - }; - etype = g_enum_register_static ("HildonCaptionStatus", values); - } - return etype; -} - -GType -hildon_caption_icon_position_get_type (void) -{ - static GType etype = 0; - if (etype == 0) { - static const GEnumValue values[] = { - { HILDON_CAPTION_POSITION_LEFT, "HILDON_CAPTION_POSITION_LEFT", "left" }, - { HILDON_CAPTION_POSITION_RIGHT, "HILDON_CAPTION_POSITION_RIGHT", "right" }, - { 0, NULL, NULL } - }; - etype = g_enum_register_static ("HildonCaptionIconPosition", values); - } - return etype; -} - -/** - * hildon_caption_get_type: - * - * Initialises, and returns the type of a hildon caption. - * - * @Returns: GType of #HildonCaption - */ -GType hildon_caption_get_type (void) -{ - static GType caption_type = 0; - - if (!caption_type) - { - static const GTypeInfo caption_info = { - sizeof(HildonCaptionClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_caption_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonCaption), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_caption_init, - }; - caption_type = g_type_register_static( GTK_TYPE_EVENT_BOX, - "HildonCaption", &caption_info, 0 ); - } - return caption_type; -} - -/* - * Initialises the caption class. - */ -static void hildon_caption_class_init( HildonCaptionClass *caption_class ) -{ - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(caption_class); - GObjectClass *gobject_class = G_OBJECT_CLASS(caption_class); - GtkContainerClass *container_class = GTK_CONTAINER_CLASS(caption_class); - - parent_class = g_type_class_peek_parent( caption_class ); - - g_type_class_add_private( caption_class, sizeof(HildonCaptionPrivate) ); - - /* Override virtual functions */ - gobject_class->get_property = hildon_caption_get_property; - gobject_class->set_property = hildon_caption_set_property; - - caption_class->activate = hildon_caption_activate; - - GTK_OBJECT_CLASS(caption_class)->destroy = hildon_caption_destroy; - - container_class->forall = hildon_caption_forall; - container_class->set_child_property = hildon_caption_set_child_property; - container_class->get_child_property = hildon_caption_get_child_property; - - widget_class->expose_event = hildon_caption_expose; - widget_class->hierarchy_changed = hildon_caption_hierarchy_changed; - widget_class->size_request = hildon_caption_size_request; - widget_class->size_allocate = hildon_caption_size_allocate; - widget_class->button_press_event = hildon_caption_button_press; - - /* Create new signals and properties */ - widget_class->activate_signal = g_signal_new( "activate", - G_OBJECT_CLASS_TYPE( - gobject_class), - G_SIGNAL_RUN_FIRST | - G_SIGNAL_ACTION, - G_STRUCT_OFFSET( HildonCaptionClass, - activate), NULL, NULL, - gtk_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - /** - * HildonCaption:label: - * - * Caption label. - */ - g_object_class_install_property( gobject_class, PROP_LABEL, - g_param_spec_string("label", - "Current label", "Caption label", - NULL, G_PARAM_READABLE | G_PARAM_WRITABLE) ); - - /** - * HildonCaption:icon: - * - * The icon shown on the caption area. - */ - g_object_class_install_property( gobject_class, PROP_ICON, - g_param_spec_object("icon", - "Current icon", - "The icon shown on the caption area", - GTK_TYPE_WIDGET, G_PARAM_READABLE | - G_PARAM_WRITABLE) ); - /** - * HildonCaption:status: - * - * Mandatory or optional status. - */ - g_object_class_install_property( gobject_class, PROP_STATUS, - g_param_spec_enum("status", - "Current status", - "Mandatory or optional status", - HILDON_TYPE_CAPTION_STATUS, - HILDON_CAPTION_OPTIONAL, - G_PARAM_READABLE | G_PARAM_WRITABLE) ); - /** - * HildonCaption:icon-position: - * - * If the icon is positioned on the left or right side. - * - * Since: 0.14.5 - */ - g_object_class_install_property( gobject_class, PROP_ICON_POSITION, - g_param_spec_enum("icon-position", - "Icon position", - "If the icon is on the left or right side", - HILDON_TYPE_CAPTION_ICON_POSITION, - HILDON_CAPTION_POSITION_RIGHT, - G_PARAM_READABLE | G_PARAM_WRITABLE) ); - - /** - * HildonCaption:size_group: - * - * Current size group the caption is in. - */ - g_object_class_install_property( gobject_class, PROP_SIZE_GROUP, - g_param_spec_object("size_group", - "Current size group", - "Current size group the caption is in", - GTK_TYPE_SIZE_GROUP, G_PARAM_READABLE | - G_PARAM_WRITABLE) ); - - /** - * HildonCaption:separator: - * - * The current separator. - */ - g_object_class_install_property( gobject_class, PROP_SEPARATOR, - g_param_spec_string("separator", - "Current separator", "Current separator", - _("ecdg_ti_caption_separator"), - G_PARAM_READABLE | G_PARAM_WRITABLE) ); - - /* Create child properties. These are related to - child <-> parent relationship, not to either of objects itself */ - gtk_container_class_install_child_property (container_class, - CHILD_PROP_EXPAND, - g_param_spec_boolean ("expand", - "Same as GtkBox expand.", - "Same as GtkBox expand. Wheter the child should be expanded or not.", - FALSE, - G_PARAM_READWRITE)); -} - -/* Destroy can be called multiple times, remember to set pointers to NULL */ -static void hildon_caption_destroy( GtkObject *self ) -{ - HildonCaptionPrivate *priv = HILDON_CAPTION_GET_PRIVATE(self); - - /* Free our internal child */ - if( priv->caption_area ) - { - gtk_widget_unparent( priv->caption_area ); - priv->caption_area = NULL; - } - - /* Free user provided strings */ - if( priv->text ) - { - g_free( priv->text ); - priv->text = NULL; - } - if( priv->separator ) - { - g_free( priv->separator ); - priv->separator = NULL; - } - - /* Parent classes destroy takes care of user packed contents */ - if( GTK_OBJECT_CLASS(parent_class)->destroy ) - GTK_OBJECT_CLASS(parent_class)->destroy( self ); -} - -/* Parent, eventbox will run allocate also for the child which may be - * owning a window too. This window is then moved and resized - * and we do not want to do that (it causes flickering). - */ -static gboolean hildon_caption_expose( GtkWidget *widget, - GdkEventExpose *event ) -{ - HildonCaptionPrivate *priv = NULL; - GtkRequisition req; - GtkAllocation alloc; - gfloat align; - - g_assert( HILDON_IS_CAPTION(widget) ); - priv = HILDON_CAPTION_GET_PRIVATE(widget); - - if( !GTK_WIDGET_DRAWABLE(widget) ) - return FALSE; - - GTK_WIDGET_CLASS(parent_class)->expose_event( widget, event ); - - /* If our child control is focused, we draw nice looking focus - graphics for the caption */ - if ( priv->is_focused && priv->text ) - { - /* Determine focus box dimensions */ - gtk_widget_get_child_requisition( priv->caption_area, &req ); - align = hildon_caption_get_label_alignment(HILDON_CAPTION(widget)); - - alloc.width = priv->caption_area->allocation.width + HILDON_CAPTION_SPACING; - alloc.height = MIN (req.height + (2 * widget->style->ythickness), priv->caption_area->allocation.height); - - alloc.x = priv->caption_area->allocation.x - HILDON_CAPTION_SPACING; /* - left margin */ - alloc.y = priv->caption_area->allocation.y + - MAX(((priv->caption_area->allocation.height - alloc.height) * align), 0); - - /* Paint the focus box */ - gtk_paint_box( widget->style, widget->window, GTK_STATE_ACTIVE, - GTK_SHADOW_OUT, NULL, widget, "selection", - alloc.x, alloc.y, alloc.width, alloc.height ); - - /* Paint caption contents on top of the focus box */ - GTK_WIDGET_GET_CLASS(priv->caption_area)->expose_event( - priv->caption_area, event); - } - - return FALSE; -} - -static void hildon_caption_set_property( GObject *object, guint param_id, - const GValue *value, - GParamSpec *pspec ) -{ - HildonCaptionPrivate *priv = HILDON_CAPTION_GET_PRIVATE(object); - - switch( param_id ) - { - case PROP_ICON_POSITION: - - hildon_caption_set_icon_position (HILDON_CAPTION (object), - g_value_get_enum (value)); - - break; - - case PROP_LABEL: - /* Free old label string */ - if( priv->text ) - { - g_free( priv->text ); - priv->text = NULL; - } - - /* Update label */ - priv->text = g_value_dup_string(value); - hildon_caption_set_label_text( priv ); - break; - - case PROP_ICON: - /* Remove old icon */ - if( priv->icon ) - gtk_container_remove( GTK_CONTAINER(priv->icon_align), priv->icon ); - - /* Pack and display new icon */ - priv->icon = g_value_get_object( value ); - if( priv->icon ) - { - gtk_container_add(GTK_CONTAINER(priv->icon_align), priv->icon); - gtk_widget_show_all( priv->caption_area ); - } - break; - - case PROP_STATUS: - priv->status = g_value_get_enum( value ); - break; - - case PROP_SIZE_GROUP: - /* Detach from previous size group */ - if( priv->group ) - gtk_size_group_remove_widget( priv->group, priv->caption_area ); - - priv->group = g_value_get_object( value ); - - /* Attach to new size group */ - if( priv->group ) - gtk_size_group_add_widget( priv->group, priv->caption_area ); - gtk_widget_queue_draw( GTK_WIDGET(object) ); - break; - - case PROP_SEPARATOR: - - /* Free old separator */ - if( priv->separator ) - { - g_free( priv->separator ); - priv->separator = NULL; - } - - priv->separator = g_value_dup_string(value); - hildon_caption_set_label_text( priv ); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); - break; - } -} - -static void hildon_caption_get_property( GObject *object, guint param_id, - GValue *value, GParamSpec *pspec ) -{ - HildonCaptionPrivate *priv = HILDON_CAPTION_GET_PRIVATE(object); - - switch (param_id) - { - case PROP_LABEL: - g_value_set_string( value, priv->text ); - break; - case PROP_ICON: - g_value_set_object( value, priv->icon ); - break; - case PROP_STATUS: - g_value_set_enum( value, priv->status ); - break; - case PROP_ICON_POSITION: - g_value_set_enum( value, priv->icon_position); - break; - case PROP_SIZE_GROUP: - g_value_set_object( value, priv->group ); - break; - case PROP_SEPARATOR: - g_value_set_string( value, priv->separator ); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); - break; - } -} - -static void hildon_caption_set_child_property( GtkContainer *container, - GtkWidget *child, - guint property_id, - const GValue *value, - GParamSpec *pspec ) -{ - switch (property_id) - { - case CHILD_PROP_EXPAND: - hildon_caption_set_child_expand( HILDON_CAPTION(container), - g_value_get_boolean(value) ); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(container, property_id, pspec); - break; - } -} - -static void hildon_caption_get_child_property( GtkContainer *container, - GtkWidget *child, - guint property_id, - GValue *value, - GParamSpec *pspec ) -{ - switch (property_id) - { - case CHILD_PROP_EXPAND: - g_value_set_boolean( value, hildon_caption_get_child_expand( - HILDON_CAPTION(container)) ); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(container, property_id, pspec); - break; - } -} - -/* We want to activate out child control on button press */ -static gboolean hildon_caption_button_press( GtkWidget *widget, - GdkEventButton *event ) -{ - HildonCaptionPrivate *priv = HILDON_CAPTION_GET_PRIVATE(widget); - GtkWidget *child = GTK_BIN(widget)->child; - - /* nothing to do */ - if (priv->is_focused == TRUE) - return; - - /* If child can take focus, we simply grab focus to it */ - if ((GTK_WIDGET_CAN_FOCUS(child) || GTK_IS_CONTAINER(child)) && - GTK_WIDGET_IS_SENSITIVE(child)) - { - /* Only if container can be focusable we must set is_focused to TRUE */ - if (GTK_IS_CONTAINER(child)) - { - if (gtk_widget_child_focus (child, - GTK_DIR_TAB_FORWARD)) - priv->is_focused = TRUE; - } - else - { - priv->is_focused = TRUE; - gtk_widget_grab_focus (GTK_BIN (widget)->child); - } - } - - return FALSE; -} - -static void hildon_caption_init( HildonCaption *caption ) -{ - HildonCaptionPrivate *priv = NULL; - - /* Initialize startup state */ - priv = HILDON_CAPTION_GET_PRIVATE(caption); - priv->status = HILDON_CAPTION_OPTIONAL; - priv->icon = NULL; - priv->group = NULL; - priv->is_focused = FALSE; - priv->text = NULL; - - priv->separator = g_strdup(_("ecdg_ti_caption_separator")); - - gtk_widget_push_composite_child(); - - /* Create caption text */ - priv->caption_area = gtk_hbox_new( FALSE, HILDON_CAPTION_SPACING ); - priv->label = gtk_label_new( NULL ); - priv->icon_align = gtk_alignment_new(0.5f, 0.5f, 0.0f, 0.0f); - priv->icon_position = HILDON_CAPTION_POSITION_RIGHT; - - /* We want to receive button presses for child widget activation */ - gtk_event_box_set_above_child( GTK_EVENT_BOX(caption), FALSE ); - gtk_widget_add_events( GTK_WIDGET(caption), GDK_BUTTON_PRESS_MASK ); - - /* Pack text label caption layout */ - gtk_box_pack_end( GTK_BOX(priv->caption_area), priv->icon_align, FALSE, FALSE, 0); - gtk_box_pack_end( GTK_BOX(priv->caption_area), priv->label, FALSE, FALSE, 0 ); - gtk_widget_set_parent( priv->caption_area, GTK_WIDGET(caption) ); - - - gtk_widget_pop_composite_child(); - - hildon_caption_set_child_expand( caption, TRUE ); - - gtk_widget_show_all( priv->caption_area ); -} - -static void hildon_caption_set_focus( GtkWindow *window, GtkWidget *widget, - GtkWidget *caption ) -{ - HildonCaptionPrivate *priv = HILDON_CAPTION_GET_PRIVATE(caption); - - /* check if ancestor gone */ - if (!widget) - { - return; - } - - /* Try to find caption among the ancestors of widget */ - if (gtk_widget_is_ancestor(widget, caption)) - { - priv->is_focused = TRUE; - gtk_widget_queue_draw( caption ); - return; - } - - if( priv->is_focused == TRUE ) - { - /* Caption wasn't found, so cannot focus */ - priv->is_focused = FALSE; - gtk_widget_queue_draw( caption ); - } -} - -/* We need to connect/disconnect signal handlers to toplevel window - in which we reside. Ww want to update connected signals if our - parent changes */ -static void hildon_caption_hierarchy_changed( GtkWidget *widget, - GtkWidget *previous_toplevel) -{ - GtkWidget *current_ancestor; - HildonCaptionPrivate *priv; - - priv = HILDON_CAPTION_GET_PRIVATE(widget); - - if( GTK_WIDGET_CLASS(parent_class)->hierarchy_changed ) - GTK_WIDGET_CLASS(parent_class)->hierarchy_changed( widget, - previous_toplevel ); - - /* If we already were inside a window, remove old handler */ - if (previous_toplevel) { - /* This is a compilation workaround for gcc > 3.3 since glib is buggy */ - /* see http://bugzilla.gnome.org/show_bug.cgi?id=310175 */ -#ifdef __GNUC__ - __extension__ -#endif - g_signal_handlers_disconnect_by_func - (previous_toplevel, (gpointer) hildon_caption_set_focus, widget); - } - current_ancestor = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW); - - /* Install new handler for focus movement */ - if (current_ancestor) - g_signal_connect( current_ancestor, "set-focus", - G_CALLBACK(hildon_caption_set_focus), widget ); -} - -static void hildon_caption_size_request( GtkWidget *widget, - GtkRequisition *requisition ) -{ - GtkRequisition req; - HildonCaptionPrivate *priv = NULL; - g_return_if_fail( HILDON_IS_CAPTION(widget) ); - priv = HILDON_CAPTION_GET_PRIVATE(widget); - - /* Use the same size requisition for the main box of the caption */ - gtk_widget_size_request( priv->caption_area, &req ); - - if( GTK_WIDGET_CLASS(parent_class)->size_request ) - GTK_WIDGET_CLASS(parent_class)->size_request( widget, requisition ); - - requisition->width += req.width + HILDON_CAPTION_SPACING * 3; - - if( (req.height + (2 * widget->style->ythickness)) > requisition->height ) - requisition->height = req.height + (2 * widget->style->ythickness); -} - -/* We use HILDON_CAPTION_SPACING to make it look a bit nicer */ -static void hildon_caption_size_allocate( GtkWidget *widget, - GtkAllocation *allocation ) -{ - GtkAllocation allocA; - GtkAllocation allocB; - GtkRequisition req; - GtkWidget *child = NULL; - HildonCaptionPrivate *priv = NULL; - - g_assert( HILDON_IS_CAPTION(widget) ); - priv = HILDON_CAPTION_GET_PRIVATE(widget); - - /* Position the caption to its allocated location */ - if( GTK_WIDGET_REALIZED(widget) ) - gdk_window_move_resize (widget->window, - allocation->x + GTK_CONTAINER (widget)->border_width, - allocation->y + GTK_CONTAINER (widget)->border_width, - MAX (allocation->width - GTK_CONTAINER (widget)->border_width * 2, 0), - MAX (allocation->height - GTK_CONTAINER (widget)->border_width * 2, 0)); - - child = GTK_BIN(widget)->child; - - widget->allocation = *allocation; - gtk_widget_get_child_requisition( priv->caption_area, &req ); - - allocA.height = allocB.height = allocation->height; - allocA.width = allocB.width = allocation->width; - allocA.x = allocB.x = allocB.y = allocA.y = 0; - - /* Center the captioned widget */ - if( allocA.width > req.width + HILDON_CAPTION_SPACING ) - { - allocA.x += req.width + HILDON_CAPTION_SPACING * 2; - allocB.width = req.width; - } - - /* Leave at least the space of the HILDON_CAPTION_SPACING in the left */ - allocB.x = HILDON_CAPTION_SPACING; - - /* Leave room for the other drawable parts of the caption control */ - allocA.width -= req.width + HILDON_CAPTION_SPACING * 2; - - /* Give the child at least its minimum requisition, unless it is expandable */ - if( !priv->expand && child && GTK_WIDGET_VISIBLE(child) ) - { - GtkRequisition child_req; - gtk_widget_get_child_requisition( child, &child_req ); - allocA.width = MIN( allocA.width, child_req.width ); - allocA.height = MIN( allocA.height, child_req.height ); - } - - /* Ensure there are no negative dimensions */ - if( allocA.width < 0 ) - { - allocB.width = req.width + allocA.width; - allocA.width = 0; - allocB.width = MAX (allocB.width, 0); - } - - allocA.height = MAX (allocA.height, 0); - allocB.height = MAX (allocB.height, 0); - - if (child && GTK_WIDGET_VISIBLE(child) ) - gtk_widget_size_allocate( child, &allocA ); - - gtk_widget_size_allocate( priv->caption_area, &allocB ); -} - -static void hildon_caption_forall( GtkContainer *container, - gboolean include_internals, - GtkCallback callback, gpointer data ) -{ - HildonCaptionPrivate *priv = NULL; - - g_assert( HILDON_IS_CAPTION(container) ); - g_assert( callback != NULL ); - - priv = HILDON_CAPTION_GET_PRIVATE(container); - - /* Execute callback for the child widgets */ - if( GTK_CONTAINER_CLASS(parent_class)->forall ) - GTK_CONTAINER_CLASS(parent_class)->forall( container, include_internals, - callback, data ); - - if( include_internals ) - /* Execute callback for the parent box as well */ - (*callback)( priv->caption_area, data ); -} - - -/** - * hildon_caption_set_sizegroup: - * @caption : a #HildonCaption - * @new_group : a #GtkSizeGroup - * - * Sets a #GtkSizeGroup of a given captioned control. - * - * Deprecated: use g_object_set, property :size-group - */ -void hildon_caption_set_sizegroup( const HildonCaption *self, - GtkSizeGroup *group ) -{ - g_object_set( G_OBJECT(self), "size_group", group, NULL ); -} - -/** - * hildon_caption_get_sizegroup: - * @caption : a #HildonCaption - * - * Query given captioned control for the #GtkSizeGroup assigned to it. - * - * @Returns : a #GtkSizeGroup - * - * Deprecated: Use g_object_get, property :size-group - */ -GtkSizeGroup *hildon_caption_get_sizegroup( const HildonCaption *self ) -{ - HildonCaptionPrivate *priv; - g_return_val_if_fail( HILDON_IS_CAPTION (self), NULL ); - priv = HILDON_CAPTION_GET_PRIVATE(self); - return priv->group; -} - -/** - * hildon_caption_new: - * @group : a #GtkSizeGroup for controlling the size of related captions, - * Can be NULL - * @value : the caption text to accompany the text entry. The widget makes - * a copy of this text. - * @control : the control that is to be captioned - * @icon : an icon to accompany the label - can be NULL in which case no - * icon is displayed - * @flag : indicates whether this captioned control is mandatory or - * optional - * - * Creates a new instance of hildon_caption widget, with a specific - * control and image. - * Note: Clicking on a focused caption will trigger the activate signal. - * The default behaviour for the caption's activate signal is to call - * gtk_widget_activate on it's control. - * - * @Returns : a #GtkWidget pointer of Caption - */ -GtkWidget *hildon_caption_new( GtkSizeGroup *group, const gchar *value, - GtkWidget *child, GtkWidget *icon, - HildonCaptionStatus flag) -{ - GtkWidget *widget; - g_return_val_if_fail( GTK_IS_WIDGET(child), NULL ); - - widget = g_object_new( HILDON_TYPE_CAPTION, "label", value, - "child" /* From GtkContainer */, child, "size_group", group, "icon", icon, "status", flag, - NULL ); - - return widget; -} - -/** - * hildon_caption_is_mandatory: - * @caption : a #HildonCaption - * - * Query #HildonCaption whether this captioned control is a mandatory one. - * - * @Returns : is this captioned control a mandatory one? - */ - -gboolean hildon_caption_is_mandatory( const HildonCaption *caption ) -{ - HildonCaptionPrivate *priv; - g_return_val_if_fail( HILDON_IS_CAPTION(caption), FALSE ); - priv = HILDON_CAPTION_GET_PRIVATE(caption); - - return priv->status == HILDON_CAPTION_MANDATORY; -} - -/** - * hildon_caption_set_icon_position: - * @caption : a #HildonCaption - * @pos : one of the values from #HildonCaptionIconPosition - * - * Sets #HildonCaption icon position. - * - * Since: 0.14.5 - */ - -void hildon_caption_set_icon_position( HildonCaption *caption, - HildonCaptionIconPosition pos ) -{ - g_return_if_fail (HILDON_IS_CAPTION (caption)); - HildonCaptionPrivate *priv = HILDON_CAPTION_GET_PRIVATE(caption); - - g_return_if_fail (priv->caption_area != NULL); - int order = (pos == HILDON_CAPTION_POSITION_LEFT) ? -1 : 0; - gtk_box_reorder_child (GTK_BOX (priv->caption_area), priv->icon_align, order); - - priv->icon_position = pos; -} - -/** - * hildon_caption_get_icon_position: - * @caption : a #HildonCaption - * - * Gets #HildonCaption icon position. - * - * @Returns : one of the values from #HildonCaptionIconPosition. - * - * Since: 0.14.5 - */ - -HildonCaptionIconPosition hildon_caption_get_icon_position( const HildonCaption *caption ) -{ - g_return_if_fail (HILDON_IS_CAPTION (caption)); - HildonCaptionPrivate *priv = HILDON_CAPTION_GET_PRIVATE(caption); - - return priv->icon_position; -} - -/** - * hildon_caption_set_status: - * @caption : a #HildonCaption - * @flag : one of the values from #HildonCaptionStatus - * - * Sets #HildonCaption status. - */ - -void hildon_caption_set_status( HildonCaption *caption, - HildonCaptionStatus flag ) -{ - g_return_if_fail( HILDON_IS_CAPTION(caption) ); - - g_object_set( G_OBJECT(caption), "status", flag, NULL ); -} - -/** - * hildon_caption_get_status: - * @caption : a #HildonCaption - * - * Gets #HildonCaption status. - * - * @Returns : one of the values from #HildonCaptionStatus - */ - -HildonCaptionStatus hildon_caption_get_status( const HildonCaption *caption ) -{ - HildonCaptionPrivate *priv; - g_return_val_if_fail( HILDON_IS_CAPTION(caption), HILDON_CAPTION_OPTIONAL ); - priv = HILDON_CAPTION_GET_PRIVATE(caption); - - return priv->status; -} - -/** - * hildon_caption_set_icon_image: - * @caption : a #HildonCaption - * @icon : the #GtkImage to use as the icon. - * calls gtk_widget_show on the icon if !GTK_WIDGET_VISIBLE(icon) - * - * Sets the icon to be used by this hildon_caption widget. - */ - -void hildon_caption_set_icon_image( HildonCaption *caption, GtkWidget *icon ) -{ - g_return_if_fail( HILDON_IS_CAPTION(caption) ); - - g_object_set( G_OBJECT(caption), "icon", icon, NULL ); -} - -/** - * hildon_caption_get_icon_image: - * @caption : a #HildonCaption - * - * Gets icon of #HildonCaption - * - * @Returns : the #GtkImage that is being used as the icon by the - * hildon_caption, or NULL if no icon is in use - */ - -GtkWidget *hildon_caption_get_icon_image( const HildonCaption *caption ) -{ - HildonCaptionPrivate *priv; - g_return_val_if_fail( HILDON_IS_CAPTION(caption), NULL ); - priv = HILDON_CAPTION_GET_PRIVATE(caption); - - return priv->icon; -} - -/** - * hildon_caption_set_label: - * @caption : a #HildonCaption - * @label : the text to use - * - * Sets the label text that appears before the control. - * Separator character is added to the end of the label string. By default - * the separator is ":". - */ - -void hildon_caption_set_label( HildonCaption *caption, const gchar *label ) -{ - g_return_if_fail( HILDON_IS_CAPTION(caption) ); - - g_object_set( G_OBJECT(caption), "label", label, NULL ); -} - -/** - * hildon_caption_get_label: - * @caption : a #HildonCaption - * - * Gets label of #HildonCaption - * - * @Returns : the text currently being used as the label of the caption - * control. The string is owned by the label and the caller should never - * free or modify this value. - */ - -gchar *hildon_caption_get_label( const HildonCaption *caption ) -{ - HildonCaptionPrivate *priv; - g_return_val_if_fail(HILDON_IS_CAPTION(caption), ""); - priv = HILDON_CAPTION_GET_PRIVATE(caption); - - return (gchar*)gtk_label_get_text(GTK_LABEL(GTK_LABEL(priv->label))); -} - -/** - * hildon_caption_set_separator: - * @caption : a #HildonCaption - * @separator : the separator to use - * - * Sets the separator character that appears after the label. - * The default seaparator character is ":" - * separately. - */ - -void hildon_caption_set_separator( HildonCaption *caption, - const gchar *separator ) -{ - g_return_if_fail( HILDON_IS_CAPTION(caption) ); - - g_object_set( G_OBJECT(caption), "separator", separator, NULL ); -} - -/** - * hildon_caption_get_separator: - * @caption : a #HildonCaption - * - * Gets separator string of #HildonCaption - * - * @Returns : the text currently being used as the separator of the caption - * control. The string is owned by the caption control and the caller should - * never free or modify this value. - */ - -gchar *hildon_caption_get_separator( const HildonCaption *caption ) -{ - HildonCaptionPrivate *priv; - g_return_val_if_fail(HILDON_IS_CAPTION(caption), ""); - priv = HILDON_CAPTION_GET_PRIVATE(caption); - - return priv->separator; -} - - -/** - * hildon_caption_get_control: - * @caption : a #HildonCaption - * - * Gets caption's control. - * - * @Returns : a #GtkWidget - * - * Deprecated: use gtk_bin_get_child instead - */ -GtkWidget *hildon_caption_get_control( const HildonCaption *caption ) -{ - g_return_val_if_fail( HILDON_IS_CAPTION(caption), NULL ); - return GTK_BIN(caption)->child; -} - -/*activates the child control - *We have this signal so that if needed an application can - *know when we've been activated (useful for captions with - *multiple children - */ -/* FIXME: There never are multiple children. Possibly activate - signal could be removed entirely? (does anyone use it?) */ -static void hildon_caption_activate( GtkWidget *widget ) -{ - HildonCaptionPrivate *priv; - GtkWidget *child = GTK_BIN(widget)->child; - priv = HILDON_CAPTION_GET_PRIVATE(widget); - - gtk_widget_grab_focus( child ); -} - -/** - * hildon_caption_set_child_expand: - * @caption : a #HildonCaption - * @expand : gboolean to determine is the child expandable - * - * Sets child expandability. - */ -void hildon_caption_set_child_expand( HildonCaption *caption, gboolean expand ) -{ - HildonCaptionPrivate *priv = NULL; - GtkWidget *child = NULL; - g_return_if_fail( HILDON_IS_CAPTION(caption) ); - - priv = HILDON_CAPTION_GET_PRIVATE(caption); - - /* Did the setting really change? */ - if( priv->expand == expand ) - return; - - priv->expand = expand; - child = GTK_BIN(caption)->child; - - /* We do not have a child, nothing to do */ - if( !GTK_IS_WIDGET(child) ) - return; - - if( GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (caption) ) - gtk_widget_queue_resize( child ); - - gtk_widget_child_notify( child, "expand" ); -} - -/** - * hildon_caption_get_child_expand: - * @caption : a #HildonCaption - * - * Gets childs expandability. - * - * @Returns : wheter the child is expandable or not. - */ -gboolean hildon_caption_get_child_expand( const HildonCaption *caption ) -{ - HildonCaptionPrivate *priv = NULL; - g_return_val_if_fail( HILDON_IS_CAPTION(caption), FALSE ); - priv = HILDON_CAPTION_GET_PRIVATE(caption); - return priv->expand; -} - -/** - * hildon_caption_set_control: - * @caption : a #HildonCaption - * @control : the control to use. Control should not be NULL. - * - * Sets the control of the caption. - * The old control will be destroyed, unless the caller has added a - * reference to it. - * Function unparents the old control (if there is one) and adds the new - * control. - * - * Deprecated: use gtk_container_add - */ -void hildon_caption_set_control( HildonCaption *caption, GtkWidget *control ) -{ - GtkWidget *child = NULL; - g_return_if_fail( HILDON_IS_CAPTION(caption) ); - child = GTK_BIN(caption)->child; - - if( child ) - gtk_container_remove( GTK_CONTAINER(caption), child ); - - if( control ) - { - gtk_container_add( GTK_CONTAINER(caption), control ); - child = control; - } - else - child = NULL; -} - -static void -hildon_caption_set_label_text( HildonCaptionPrivate *priv ) -{ - gchar *tmp = NULL; - g_assert ( priv != NULL ); - - if ( priv->text ) - { - if( priv->separator ) - { - /* Don't duplicate the separator, if the string already contains one */ - if (g_str_has_suffix(priv->text, priv->separator)) - { - gtk_label_set_text( GTK_LABEL( priv->label ), priv->text ); - } - else - { - /* Append separator and set text */ - tmp = g_strconcat( priv->text, priv->separator, NULL ); - gtk_label_set_text( GTK_LABEL( priv->label ), tmp ); - g_free( tmp ); - } - } - else - { - gtk_label_set_text( GTK_LABEL( priv->label ), priv->text ); - } - } - else - { - /* Clear the label */ - gtk_label_set_text( GTK_LABEL( priv->label ), "" ); - } - -} - -/** - * hildon_caption_set_label_alignment: - * @caption: a #HildonCaption widget - * @alignment: new vertical alignment - * - * Sets the vertical alignment to be used for the - * text part of the caption. Applications need to - * align the child control themselves. - * - * Since: 0.12.0 - */ -void hildon_caption_set_label_alignment(HildonCaption *caption, - gfloat alignment) -{ - HildonCaptionPrivate *priv; - - g_return_if_fail(HILDON_IS_CAPTION(caption)); - - priv = HILDON_CAPTION_GET_PRIVATE(caption); - g_object_set(priv->label, "yalign", alignment, NULL); - g_object_set(priv->icon_align, "yalign", alignment, NULL); - -} - -/** - * hildon_caption_get_label_alignment: - * @caption: a #HildonCaption widget - * - * Gets current vertical alignment for the text part. - * - * Returns: vertical alignment - * - * Since: 0.12.0 - */ -gfloat hildon_caption_get_label_alignment(HildonCaption *caption) -{ - HildonCaptionPrivate *priv; - gfloat result; - - g_return_val_if_fail( HILDON_IS_CAPTION(caption), 0); - priv = HILDON_CAPTION_GET_PRIVATE(caption); - g_object_get(priv->label, "yalign", &result, NULL); - - return result; -} diff --git a/hildon-widgets/hildon-caption.h b/hildon-widgets/hildon-caption.h deleted file mode 100644 index 49d4244..0000000 --- a/hildon-widgets/hildon-caption.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_CAPTION_H__ -#define __HILDON_CAPTION_H__ - -#include -#include -#include -#include - -G_BEGIN_DECLS - - -#define HILDON_TYPE_CAPTION ( hildon_caption_get_type() ) -#define HILDON_CAPTION(obj) \ - (GTK_CHECK_CAST (obj, HILDON_TYPE_CAPTION, HildonCaption)) -#define HILDON_CAPTION_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass),\ - HILDON_TYPE_CAPTION, HildonCaptionClass)) -#define HILDON_IS_CAPTION(obj) (GTK_CHECK_TYPE (obj, HILDON_TYPE_CAPTION)) -#define HILDON_IS_CAPTION_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_CAPTION)) - - -/** - * HildonCaptionStatus: - * @HILDON_CAPTION_OPTIONAL: Optional. - * @HILDON_CAPTION_MANDATORY: Mandatory. - * - * Keys to set the #HildonCaption to be optional or mandatory. - */ -typedef enum /*< skip >*/ -{ - HILDON_CAPTION_OPTIONAL = 0, - HILDON_CAPTION_MANDATORY -} HildonCaptionStatus; - -/** - * HildonCaptionIconPosition: - * @HILDON_CAPTION_POSITION_LEFT: Show the icon on the left side. - * @HILDON_CAPTION_POSITION_RIGHT: Show the icon on the right side. - * - * Keys to set the icon placement in #HildonCaption. - * - * Since: 0.14.5 - */ -typedef enum /*< skip >*/ -{ - HILDON_CAPTION_POSITION_LEFT = 0, - HILDON_CAPTION_POSITION_RIGHT -} HildonCaptionIconPosition; - -#define HILDON_TYPE_CAPTION_STATUS (hildon_caption_status_get_type ()) - -#define HILDON_TYPE_CAPTION_ICON_POSITION (hildon_caption_icon_position_get_type ()) - -GType hildon_caption_status_get_type (void) G_GNUC_CONST; - -GType hildon_caption_icon_position_get_type (void) G_GNUC_CONST; - -/** - * HildonCaption: - * - * Contains only private data. - */ -typedef struct _HildonCaption HildonCaption; -typedef struct _HildonCaptionClass HildonCaptionClass; - - -struct _HildonCaption -{ - GtkEventBox event_box; -}; - - -struct _HildonCaptionClass -{ - GtkEventBoxClass parent_class; - void (*activate) (HildonCaption *widget); -}; - - -GType hildon_caption_get_type (void) G_GNUC_CONST; - -GtkWidget *hildon_caption_new( GtkSizeGroup *group, const gchar *value, - GtkWidget *control, GtkWidget *icon, - HildonCaptionStatus flag ); -#ifndef HILDON_DISABLE_DEPRECATED -GtkSizeGroup *hildon_caption_get_sizegroup( const HildonCaption *caption ); - -void hildon_caption_set_sizegroup( const HildonCaption *caption, - GtkSizeGroup *new_group ); -#endif - -gboolean hildon_caption_is_mandatory( const HildonCaption *caption ); - -void hildon_caption_set_status( HildonCaption *caption, - HildonCaptionStatus flag ); - -HildonCaptionStatus hildon_caption_get_status( const HildonCaption *caption ); - -void hildon_caption_set_icon_position( HildonCaption *caption, - HildonCaptionIconPosition pos ); - -HildonCaptionIconPosition hildon_caption_get_icon_position( const HildonCaption *caption ); - -void hildon_caption_set_icon_image( HildonCaption *caption, GtkWidget *icon ); - -GtkWidget *hildon_caption_get_icon_image(const HildonCaption *caption); - -void hildon_caption_set_label( HildonCaption *caption, const gchar *label ); - -gchar *hildon_caption_get_label( const HildonCaption *caption ); - -void hildon_caption_set_separator( HildonCaption *caption, - const gchar *separator ); - -gchar *hildon_caption_get_separator( const HildonCaption *caption ); - -void hildon_caption_set_label_alignment(HildonCaption *caption, - gfloat alignment); -gfloat hildon_caption_get_label_alignment(HildonCaption *caption); - -#ifndef HILDON_DISABLE_DEPRECATED -GtkWidget *hildon_caption_get_control( const HildonCaption *caption ); - -void hildon_caption_set_control( HildonCaption *caption, GtkWidget *control ); -#endif - -void hildon_caption_set_child_expand( HildonCaption *caption, gboolean expand ); -gboolean hildon_caption_get_child_expand( const HildonCaption *caption ); - -G_END_DECLS -#endif /* __HILDON_CAPTION_H__ */ diff --git a/hildon-widgets/hildon-code-dialog.c b/hildon-widgets/hildon-code-dialog.c deleted file mode 100644 index 9a53ff1..0000000 --- a/hildon-widgets/hildon-code-dialog.c +++ /dev/null @@ -1,480 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - - -#include "hildon-code-dialog.h" -#include "hildon-defines.h" -#include "hildon-banner.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#define HEIGHT (38-HILDON_MARGIN_DEFAULT) -#define WIDTH (60-HILDON_MARGIN_DEFAULT) -#define BACKSPACE_ICON "qgn_calculator_backspace" - -#define _(String) dgettext(PACKAGE, String) -#define c_(String) dgettext("hildon-common-strings", String) -#define DEVICELOCK_OK _("secu_enter_lock_code_dialog_ok") -#define DEVICELOCK_CANCEL _("secu_enter_lock_code_dialog_cancel") -#define DEVICELOCK_TITLE _("secu_application_title") -#define DEVICELOCK_MAX_CHAR_REACHED c_("ckdg_ib_maximum_characters_reached") - - - -#define MAX_PINCODE_LEN (10) - - - -static void hildon_code_dialog_class_init (HildonCodeDialogClass *cd_class); -static void hildon_code_dialog_init (HildonCodeDialog *self); -static void hildon_code_dialog_finalize (GObject *self); -static void hildon_code_dialog_button_clicked (GtkButton *buttonm, - gpointer user_data); -static void hildon_code_dialog_insert_text (GtkEditable *editable, - gchar *new_text, - gint new_text_length, - gint *position, - gpointer user_data); - -static gboolean hildon_code_dialog_key_press_event (GtkWidget *widget, - GdkEventKey *event, - gpointer user_data); - - -GtkDialogClass *parent_class; - -struct _HildonCodeDialogPrivate -{ - GtkWidget *entry; - GtkWidget *buttons[5][3]; - GtkWidget *help_text; -}; - -GType hildon_code_dialog_get_type (void) -{ - static GType type = 0; - - if (!type) - { - static const GTypeInfo info = - { - sizeof(HildonCodeDialogClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_code_dialog_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonCodeDialog), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_code_dialog_init - }; - type = g_type_register_static (GTK_TYPE_DIALOG, - "HildonCodeDialog", &info, 0); - } - return type; -} - -static void hildon_code_dialog_class_init (HildonCodeDialogClass *cd_class) -{ - /* Get convenience variables */ - GObjectClass *object_class = G_OBJECT_CLASS (cd_class); - - parent_class = GTK_DIALOG_CLASS (g_type_class_peek_parent (cd_class)); - - object_class->finalize = hildon_code_dialog_finalize; - -} - -static void hildon_code_dialog_init (HildonCodeDialog *dialog) -{ - HildonCodeDialogPrivate *priv; - gint i, x, y; - GtkWidget *dialog_vbox1 = NULL; - GtkWidget *table = NULL; - GtkWidget *alignment = NULL; - GtkWidget *vbox1 = NULL; - GtkWidget *image1 = NULL; - GtkWidget *dialog_action_area1 = NULL; - GdkGeometry hints; - GtkWidget *okButton; - GtkWidget *cancelButton; - - priv = dialog->priv = (HildonCodeDialogPrivate*) g_malloc0 - (sizeof (HildonCodeDialogPrivate)); - - const gchar* numstrs[10] = { - "0","1","2","3","4","5","6","7","8","9" - }; - - GdkPixbuf* pixbuf = NULL; - GtkIconTheme* icon_theme = NULL; - GtkIconInfo *icon_info = NULL; - gint base_size=0; - - /* Set default title */ - gtk_window_set_title (GTK_WINDOW (dialog), DEVICELOCK_TITLE); - - gtk_window_set_type_hint(GTK_WINDOW (dialog), GDK_WINDOW_TYPE_HINT_DIALOG); - - hints.min_width = -1; - hints.min_height = -1; - hints.max_width = -1; - hints.max_height = -1; - - gtk_window_set_geometry_hints(GTK_WINDOW(dialog), GTK_WIDGET(dialog), - &hints, - GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE); - - table = gtk_table_new (4, 3, FALSE); - gtk_table_set_row_spacings (GTK_TABLE (table), HILDON_MARGIN_DEFAULT ); - gtk_table_set_col_spacings (GTK_TABLE (table), HILDON_MARGIN_DEFAULT ); - - dialog_vbox1 = GTK_DIALOG (dialog)->vbox; - vbox1 = gtk_vbox_new (FALSE, 0); - gtk_box_set_spacing (GTK_BOX(vbox1),HILDON_MARGIN_DOUBLE); - - priv->help_text= gtk_label_new (""); - alignment=gtk_alignment_new(0.5,0,1,1); - gtk_container_add(GTK_CONTAINER(alignment),priv->help_text); - - priv->entry = gtk_entry_new (); - - GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(priv->entry),GTK_CAN_FOCUS); - gtk_entry_set_invisible_char (GTK_ENTRY(priv->entry), g_utf8_get_char ("*")); - gtk_entry_set_alignment (GTK_ENTRY(priv->entry),1.0); - - gtk_editable_set_editable (GTK_EDITABLE(priv->entry),FALSE); - gtk_entry_set_visibility (GTK_ENTRY(priv->entry), FALSE); - - gtk_box_pack_start (GTK_BOX (vbox1),alignment,TRUE,FALSE,0); - gtk_box_pack_start (GTK_BOX (vbox1),priv->entry,TRUE,FALSE,0); - gtk_box_pack_start (GTK_BOX (vbox1),table,FALSE,TRUE,0); - - gtk_box_pack_start (GTK_BOX (dialog_vbox1), vbox1,FALSE,TRUE,0); - - - for(i=1;i<=3;i++) { - priv->buttons[0][i-1] = gtk_button_new_with_mnemonic(numstrs[i]); - gtk_widget_set_size_request(priv->buttons[0][i-1],WIDTH,HEIGHT); - gtk_table_attach_defaults(GTK_TABLE(table), priv->buttons[0][i-1], - i-1,i,0,1); - } - - for(i=4;i<=6;i++) { - priv->buttons[1][i-4] = gtk_button_new_with_mnemonic (numstrs[i]); - gtk_widget_set_size_request(priv->buttons[1][i-4],WIDTH,HEIGHT); - gtk_table_attach_defaults(GTK_TABLE(table),priv->buttons[1][i-4], - i-4,i-3,1,2); - } - - for(i=7;i<=9;i++) { - priv->buttons[2][i-7] = gtk_button_new_with_mnemonic (numstrs[i]); - gtk_widget_set_size_request(priv->buttons[2][i-7], WIDTH,HEIGHT); - gtk_table_attach_defaults(GTK_TABLE(table), priv->buttons[2][i-7], - i-7,i-6,2,3); - } - - priv->buttons[3][0] = priv->buttons[3][1] = - gtk_button_new_with_mnemonic (numstrs[0]); - gtk_widget_set_size_request (priv->buttons[3][0], WIDTH,HEIGHT); - gtk_table_attach (GTK_TABLE(table), priv->buttons[3][0], - 0,2,3,4, (GtkAttachOptions) (GTK_FILL), - (GtkAttachOptions) (0), 0, 0); - - priv->buttons[3][2] = gtk_button_new (); - gtk_widget_set_size_request(priv->buttons[3][2], WIDTH,HEIGHT); - gtk_table_attach_defaults(GTK_TABLE(table), priv->buttons[3][2], - 2,3,3,4); - - icon_theme = gtk_icon_theme_get_default (); - - icon_info = gtk_icon_theme_lookup_icon(icon_theme, BACKSPACE_ICON, 1, - GTK_ICON_LOOKUP_NO_SVG); - base_size = gtk_icon_info_get_base_size(icon_info); - gtk_icon_info_free(icon_info); - icon_info = NULL; - pixbuf = gtk_icon_theme_load_icon (icon_theme, - BACKSPACE_ICON, base_size, - GTK_ICON_LOOKUP_NO_SVG, - NULL); - image1 = gtk_image_new_from_pixbuf (pixbuf); - g_object_unref (G_OBJECT(pixbuf)); - gtk_container_add (GTK_CONTAINER (priv->buttons[3][2]), image1); - dialog_action_area1 = GTK_DIALOG (dialog)->action_area; - gtk_button_box_set_layout (GTK_BUTTON_BOX(dialog_action_area1), - GTK_BUTTONBOX_END); - - okButton = gtk_dialog_add_button (GTK_DIALOG(dialog),DEVICELOCK_OK, - GTK_RESPONSE_OK); - cancelButton = - gtk_dialog_add_button (GTK_DIALOG(dialog),DEVICELOCK_CANCEL, - GTK_RESPONSE_CANCEL); - - gtk_widget_set_sensitive (okButton, FALSE); - - priv->buttons[4][0] = priv->buttons[4][1] = okButton; - priv->buttons[4][2] = cancelButton; - - /* - Connect signals. - */ - g_signal_connect (G_OBJECT(priv->entry), "insert_text", - G_CALLBACK (hildon_code_dialog_insert_text), dialog); - - gtk_entry_set_max_length(GTK_ENTRY(priv->entry),MAX_PINCODE_LEN); - - for (x=0; x<3; x++) - { - for (y=0; y<3 ;y++) - { - g_signal_connect (G_OBJECT (priv->buttons[x][y]), "clicked", - G_CALLBACK (hildon_code_dialog_button_clicked), dialog); - g_signal_connect (G_OBJECT (priv->buttons[x][y]), "key-press-event", - G_CALLBACK (hildon_code_dialog_key_press_event), dialog); - } - } - - g_signal_connect (G_OBJECT (priv->buttons[3][0]), "clicked", - G_CALLBACK (hildon_code_dialog_button_clicked), dialog); - g_signal_connect (G_OBJECT (priv->buttons[3][0]), "key-press-event", - G_CALLBACK (hildon_code_dialog_key_press_event), dialog); - - g_signal_connect (G_OBJECT (priv->buttons[3][2]), "clicked", - G_CALLBACK (hildon_code_dialog_button_clicked), dialog); - g_signal_connect (G_OBJECT (priv->buttons[3][2]), "key-press-event", - G_CALLBACK (hildon_code_dialog_key_press_event), dialog); - - g_signal_connect (G_OBJECT (okButton), "key-press-event", - G_CALLBACK(hildon_code_dialog_key_press_event), dialog); - - g_signal_connect (G_OBJECT (cancelButton), "key-press-event", - G_CALLBACK (hildon_code_dialog_key_press_event), dialog); - -} - -static void hildon_code_dialog_finalize (GObject *self) -{ - HildonCodeDialog *dialog = HILDON_CODE_DIALOG (self); - - fprintf( stderr, "called destroy\n" ); - - g_free (dialog->priv); - - G_OBJECT_CLASS (parent_class)->finalize (self); -} - -/* Signal handlers */ -void hildon_code_dialog_button_clicked (GtkButton *button, gpointer user_data) -{ - HildonCodeDialog *dialog = HILDON_CODE_DIALOG (user_data); - HildonCodeDialogPrivate *priv = dialog->priv; - const char *number = gtk_button_get_label (button); - - if (number && *number ) - { - gtk_entry_append_text (GTK_ENTRY (priv->entry), number); - } - else - { - /* Backspace */ - gchar *text = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->entry))); - gchar *pos; - - pos = text; - - while (*pos != '\0') - { - pos ++; - } - - pos = g_utf8_find_prev_char (text, pos); - - if (pos) - { - *pos=0; - } - - gtk_entry_set_text (GTK_ENTRY (priv->entry), text); - - if (*text == 0) - { - gtk_widget_set_sensitive (priv->buttons[4][0], FALSE); - } - - g_free (text); - } - -} - -static void hildon_code_dialog_insert_text (GtkEditable *editable, - gchar *new_text, - gint new_text_length, - gint *position, - gpointer user_data) -{ - HildonCodeDialog *dialog = HILDON_CODE_DIALOG (user_data); - HildonCodeDialogPrivate *priv = dialog->priv; - gchar * text = g_strdup(gtk_entry_get_text (GTK_ENTRY (priv->entry))); - glong length = g_utf8_strlen (text, -1); - g_free (text); - - if (length == MAX_PINCODE_LEN) - { - hildon_banner_show_information (dialog, - NULL, - DEVICELOCK_MAX_CHAR_REACHED); - } - - else if (!length) - { - /* make the Ok button sensitive */ - gtk_widget_set_sensitive(priv->buttons[4][0], TRUE); - } -} - -static gboolean hildon_code_dialog_key_press_event (GtkWidget *widget, - GdkEventKey *event, - gpointer user_data) -{ - HildonCodeDialog *dialog = HILDON_CODE_DIALOG (user_data); - HildonCodeDialogPrivate *priv = dialog->priv; - GtkWidget *new_widget = widget; - gint x, y; - - for (x = 0; x < 5; x++) - { - for (y = 0; y < 3; y++) - { - if (priv->buttons[x][y] == widget) - goto found; - } - } - return FALSE; - -found: - - while (new_widget == widget) - { - switch (event->keyval) - { - case GDK_Up: - x = (x+4)%5; - break; - - case GDK_Down: - x = (x+1)%5; - break; - - case GDK_Left: - y = (y+2)%3; - break; - - case GDK_Right: - y = (y+1)%3; - break; - - default: - return FALSE; - } - - new_widget = priv->buttons[x][y]; - } - - gtk_widget_grab_focus (new_widget); - - return TRUE; -} - -/* Public methods */ - -/** - * hildon_code_dialog_new: - * - * Use this function to create a new HildonCodeDialog. - * - * Return value: A @HildonCodeDialog. - **/ -GtkWidget *hildon_code_dialog_new() -{ - HildonCodeDialog *dialog = g_object_new (HILDON_TYPE_CODE_DIALOG, NULL); - - return GTK_WIDGET (dialog); -} - -/** - * hildon_code_dialog_get_code: - * @dialog: The #HildonCodeDialog from which to get the entered code - * - * Use this function to access the code entered by the user. - * - * Return value: The entered code. - **/ -const gchar *hildon_code_dialog_get_code (HildonCodeDialog *dialog) -{ - g_return_val_if_fail (HILDON_IS_CODE_DIALOG (dialog), NULL); - return gtk_entry_get_text (GTK_ENTRY (dialog->priv->entry)); -} - -/** - * hildon_code_dialog_clear_clode: - * @dialog: The #HildonCodeDialog whose entry should be cleared: - * - * Use this function to clear the user entered code. - **/ -void hildon_code_dialog_clear_code (HildonCodeDialog *dialog) -{ - g_return_if_fail (HILDON_IS_CODE_DIALOG (dialog)); - gtk_entry_set_text (GTK_ENTRY (dialog->priv->entry), ""); - gtk_widget_set_sensitive (dialog->priv->buttons[4][0], FALSE); -} - -/** - * hildon_code_dialog_set_help_text: - * @dialog: The #HildonCodeDialog whose entry should be cleared: - * @text: The text to use in the help label. - * - * Use this function to set the text that will be displayd in the - * help label - **/ -void hildon_code_dialog_set_help_text (HildonCodeDialog *dialog, - const gchar *text) -{ - g_return_if_fail (HILDON_IS_CODE_DIALOG (dialog)); - gtk_label_set_text (GTK_LABEL (dialog->priv->help_text), text); -} diff --git a/hildon-widgets/hildon-code-dialog.h b/hildon-widgets/hildon-code-dialog.h deleted file mode 100644 index 8ecc5dd..0000000 --- a/hildon-widgets/hildon-code-dialog.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_CODE_DIALOG_H__ -#define __HILDON_CODE_DIALOG_H__ - -#include - -G_BEGIN_DECLS - - -#define HILDON_TYPE_CODE_DIALOG ( hildon_code_dialog_get_type() ) -#define HILDON_CODE_DIALOG(obj) \ - (GTK_CHECK_CAST (obj, HILDON_TYPE_CODE_DIALOG, HildonCodeDialog)) -#define HILDON_CODE_DIALOG_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass),\ - HILDON_TYPE_CODE_DIALOG, HildonCodeDialogClass)) -#define HILDON_IS_CODE_DIALOG(obj) (GTK_CHECK_TYPE (obj, HILDON_TYPE_CODE_DIALOG)) -#define HILDON_IS_CODE_DIALOG_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_CODE_DIALOG)) - - -typedef struct _HildonCodeDialogPrivate HildonCodeDialogPrivate; -typedef struct _HildonCodeDialog HildonCodeDialog; -typedef struct _HildonCodeDialogClass HildonCodeDialogClass; - - -struct _HildonCodeDialog -{ - GtkDialog parent; - - HildonCodeDialogPrivate *priv; -}; - -struct _HildonCodeDialogClass -{ - GtkDialogClass parent_class; -}; - - -GType hildon_code_dialog_get_type (void); -GtkWidget *hildon_code_dialog_new(void); -const gchar *hildon_code_dialog_get_code (HildonCodeDialog *dialog); -void hildon_code_dialog_clear_code (HildonCodeDialog *dialog); -void hildon_code_dialog_set_help_text (HildonCodeDialog *dialog, - const gchar *text); - - -G_END_DECLS -#endif /* __HILDON_CODE_DIALOG_H__ */ diff --git a/hildon-widgets/hildon-color-button.c b/hildon-widgets/hildon-color-button.c deleted file mode 100644 index 430bc94..0000000 --- a/hildon-widgets/hildon-color-button.c +++ /dev/null @@ -1,491 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-color-button - * @short_description: A widget to open HildonColorChooserDialog - * @see_also: #HildonColorChooserDialog, #HildonColorPopup - * - * HildonColorButton is a widget to open a HildonColorChooserDialog. - * The selected color is shown in the button. - * The selected color is a property of the button. - * The property name is "color" and its type is GtkColor. - */ -#include - -#include -#include -#include -#include -#include -#include - -#include "hildon-color-button.h" -#include "hildon-color-chooser-dialog.h" - -#define HILDON_COLOR_BUTTON_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE\ - ((obj), HILDON_TYPE_COLOR_BUTTON, HildonColorButtonPrivate)) - -#define COLOR_FILLED_HEIGHT 22 -#define COLOR_FILLED_WIDTH 22 - -#define COLOR_BUTTON_WIDTH 52 -#define COLOR_BUTTON_HEIGHT 48 - -/* the outer border color */ -#define OUTER_BORDER_RED 0 -#define OUTER_BORDER_BLUE 0 -#define OUTER_BORDER_GREEN 0 -#define OUTER_BORDER_THICKNESS 1 - -/* the inner border color */ -#define INNER_BORDER_RED 65535 -#define INNER_BORDER_BLUE 65535 -#define INNER_BORDER_GREEN 65535 -#define INNER_BORDER_THICKNESS 2 - -struct _HildonColorButtonPrivate -{ - GtkWidget *dialog; - - GdkColor color; - GdkGC *gc; -}; - -enum -{ - PROP_NONE, - PROP_COLOR -}; - -static void -hildon_color_button_class_init(HildonColorButtonClass *klass); -static void -hildon_color_button_init(HildonColorButton *color_button); - -static void -hildon_color_button_finalize(GObject *object); -static void -hildon_color_button_set_property(GObject *object, guint param_id, - const GValue *value, GParamSpec *pspec); -static void -hildon_color_button_get_property(GObject *object, guint param_id, - GValue *value, GParamSpec *pspec); -static void -hildon_color_button_realize(GtkWidget *widget); -static void -hildon_color_button_unrealize(GtkWidget *widget); -static void -hildon_color_button_clicked(GtkButton *button); -static gboolean -hildon_color_button_key_pressed(GtkWidget * button, - GdkEventKey * event, - gpointer data); -static gint -hildon_color_field_expose_event(GtkWidget *widget, GdkEventExpose *event, - HildonColorButton *cb); - -static gboolean -hildon_color_button_mnemonic_activate( GtkWidget *widget, - gboolean group_cycling ); - -static void -draw_grid (GdkDrawable *drawable, GdkGC *gc, - int x, int y, - gint w, gint h); - -static gpointer parent_class = NULL; - -GType -hildon_color_button_get_type(void) -{ - static GType color_button_type = 0; - - if (!color_button_type) - { - static const GTypeInfo color_button_info = - { - sizeof (HildonColorButtonClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_color_button_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (HildonColorButton), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_color_button_init, - }; - - color_button_type = - g_type_register_static (GTK_TYPE_BUTTON, "HildonColorButton", - &color_button_info, 0); - } - - return color_button_type; -} - -static void -hildon_color_button_class_init(HildonColorButtonClass *klass) -{ - GObjectClass *gobject_class; - GtkButtonClass *button_class; - GtkWidgetClass *widget_class; - - gobject_class = G_OBJECT_CLASS (klass); - button_class = GTK_BUTTON_CLASS (klass); - widget_class = GTK_WIDGET_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); - - gobject_class->get_property = hildon_color_button_get_property; - gobject_class->set_property = hildon_color_button_set_property; - gobject_class->finalize = hildon_color_button_finalize; - widget_class->realize = hildon_color_button_realize; - widget_class->unrealize = hildon_color_button_unrealize; - button_class->clicked = hildon_color_button_clicked; - widget_class->mnemonic_activate = hildon_color_button_mnemonic_activate; - - /** - * HildonColorButton:color: - * - * The selected color. - */ - g_object_class_install_property (gobject_class, PROP_COLOR, - g_param_spec_boxed ("color", - "Current Color", - "The selected color", - GDK_TYPE_COLOR, - G_PARAM_READWRITE)); - - g_type_class_add_private (gobject_class, sizeof (HildonColorButtonPrivate)); -} - -/* Draw a dotted grid over the specified area to make it look - * insensitive. Actually, we should generate that pixbuf once and - * just render it over later... */ -static void -draw_grid (GdkDrawable *drawable, GdkGC *gc, - int x, int y, - gint w, gint h) -{ - int currentx; - int currenty; - for (currenty = y; currenty <= h; currenty++) - for (currentx = ((currenty % 2 == 0) ? x : x + 1); currentx <= w; currentx += 2) - gdk_draw_point (drawable, gc, currentx, currenty); -} - -/* Handle exposure events for the color picker's drawing area */ -static gint -hildon_color_field_expose_event(GtkWidget *widget, GdkEventExpose *event, - HildonColorButton *cb) -{ - GdkColor outer_border, inner_border; - - /* Create the outer border color */ - outer_border.pixel = 0; - outer_border.red = OUTER_BORDER_RED; - outer_border.blue = OUTER_BORDER_BLUE; - outer_border.green = OUTER_BORDER_GREEN; - - /* Create the inner border color */ - inner_border.pixel = 0; - inner_border.red = INNER_BORDER_RED; - inner_border.blue = INNER_BORDER_BLUE; - inner_border.green = INNER_BORDER_GREEN; - - /* serve the outer border color to the Graphic Context */ - gdk_gc_set_rgb_fg_color(cb->priv->gc, &outer_border); - /* draw the outer border as a filled rectangle */ - gdk_draw_rectangle(widget->window, - (GTK_WIDGET_IS_SENSITIVE (widget)) ? cb->priv->gc : widget->style->bg_gc [GTK_STATE_INSENSITIVE], - TRUE, - 0, - 0, - widget->allocation.width, - widget->allocation.height); - - /* serve the inner border color to the Graphic Context */ - gdk_gc_set_rgb_fg_color(cb->priv->gc, &inner_border); - /* draw the inner border as a filled rectangle */ - gdk_draw_rectangle(widget->window, - cb->priv->gc, - TRUE, - OUTER_BORDER_THICKNESS, - OUTER_BORDER_THICKNESS, - widget->allocation.width - (OUTER_BORDER_THICKNESS * 2), - widget->allocation.height - (OUTER_BORDER_THICKNESS * 2)); - - /* serve the actual color to the Graphic Context */ - gdk_gc_set_rgb_fg_color(cb->priv->gc, &cb->priv->color); - /* draw the actual rectangle */ - gdk_draw_rectangle(widget->window, - cb->priv->gc, - TRUE, - INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS, - INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS, - widget->allocation.width - ((INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS)*2), - widget->allocation.height - ((INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS)*2)); - - if (! GTK_WIDGET_IS_SENSITIVE (widget)) { - draw_grid (GDK_DRAWABLE (widget->window), widget->style->bg_gc [GTK_STATE_INSENSITIVE], - INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS, - INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS, - widget->allocation.width - ((INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS)*2) + 2, - widget->allocation.height - ((INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS)*2) + 2); - } - - return FALSE; -} - -static void -hildon_color_button_init(HildonColorButton *cb) -{ - GtkWidget *align; - GtkWidget *drawing_area; - - cb->priv = HILDON_COLOR_BUTTON_GET_PRIVATE(cb); - - cb->priv->dialog = NULL; - cb->priv->gc = NULL; - - gtk_widget_push_composite_child(); - - /* create widgets and pixbuf */ - align = gtk_alignment_new(0.5, 0.5, 0, 0); /*composite widget*/ - - drawing_area = gtk_drawing_area_new(); /*composite widget*/ - - /* setting minimum sizes */ - gtk_widget_set_size_request(GTK_WIDGET(cb), COLOR_BUTTON_WIDTH, - COLOR_BUTTON_HEIGHT); - gtk_widget_set_size_request(GTK_WIDGET(drawing_area), - COLOR_FILLED_WIDTH, COLOR_FILLED_HEIGHT); - - /* Connect the callback function for exposure event */ - g_signal_connect(drawing_area, "expose-event", - G_CALLBACK(hildon_color_field_expose_event), cb); - - /* Connect to callback function for key press event */ - g_signal_connect(G_OBJECT(cb), "key-press-event", - G_CALLBACK(hildon_color_button_key_pressed), cb); - - /* packing */ - gtk_container_add(GTK_CONTAINER(align), drawing_area); - gtk_container_add(GTK_CONTAINER(cb), align); - - gtk_widget_show_all(align); - - gtk_widget_pop_composite_child(); -} - -/* Free memory used by HildonColorButton */ -static void -hildon_color_button_finalize(GObject *object) -{ - HildonColorButton *cb = HILDON_COLOR_BUTTON(object); - - if (cb->priv->dialog) - { - gtk_widget_destroy(cb->priv->dialog); - cb->priv->dialog = NULL; - } - - if( G_OBJECT_CLASS(parent_class)->finalize ) - G_OBJECT_CLASS(parent_class)->finalize(object); -} - -static void -hildon_color_button_realize(GtkWidget *widget) -{ - HildonColorButton *cb = HILDON_COLOR_BUTTON(widget); - - GTK_WIDGET_CLASS(parent_class)->realize(widget); - - cb->priv->gc = gdk_gc_new(widget->window); -} - -static void -hildon_color_button_unrealize(GtkWidget *widget) -{ - HildonColorButton *cb = HILDON_COLOR_BUTTON(widget); - - g_object_unref(cb->priv->gc); - cb->priv->gc = NULL; - - GTK_WIDGET_CLASS(parent_class)->unrealize(widget); -} - -/* Make the widget sensitive with the keyboard event */ -static gboolean -hildon_color_button_mnemonic_activate( GtkWidget *widget, - gboolean group_cycling ) -{ - gtk_widget_grab_focus( widget ); - return TRUE; -} - -/* Popup a color selector dialog on button click */ -static void -hildon_color_button_clicked(GtkButton *button) -{ - HildonColorButton *cb = HILDON_COLOR_BUTTON(button); - HildonColorChooserDialog *cs_dialog = HILDON_COLOR_CHOOSER_DIALOG(cb->priv->dialog); - - /* Popup the color selector dialog */ - if (!cs_dialog) - { - /* The dialog hasn't been created yet, do it. */ - GtkWidget *parent = gtk_widget_get_toplevel(GTK_WIDGET(cb)); - cb->priv->dialog = hildon_color_chooser_dialog_new(GTK_WINDOW(parent)); - cs_dialog = HILDON_COLOR_CHOOSER_DIALOG(cb->priv->dialog); - if (parent) - gtk_window_set_transient_for(GTK_WINDOW(cs_dialog), GTK_WINDOW(parent)); - } - - /* Set the initial color for the color selector dialog */ - hildon_color_chooser_dialog_set_color(cs_dialog, &cb->priv->color); - - /* Update the color for color button if selection was made */ - if (gtk_dialog_run(GTK_DIALOG(cs_dialog)) == GTK_RESPONSE_OK) - { - hildon_color_chooser_dialog_get_color(cs_dialog, &cb->priv->color); - hildon_color_button_set_color( HILDON_COLOR_BUTTON( button ), - &(cb->priv->color) ); - } - - gtk_widget_hide(GTK_WIDGET(cs_dialog)); -} - -/* Popup a color selector dialog on hardkey Select press */ -static gboolean -hildon_color_button_key_pressed(GtkWidget * button, - GdkEventKey * event, - gpointer data) -{ - g_return_val_if_fail (HILDON_IS_COLOR_BUTTON(button), FALSE); - - if (event->keyval == HILDON_HARDKEY_SELECT) - { - hildon_color_button_clicked(GTK_BUTTON(button)); - return TRUE; - } - - return FALSE; -} - -/* Set_property function for HildonColorButtonClass initialization */ -static void -hildon_color_button_set_property(GObject *object, guint param_id, - const GValue *value, GParamSpec *pspec) -{ - HildonColorButton *cb = HILDON_COLOR_BUTTON(object); - - switch (param_id) - { - case PROP_COLOR: - cb->priv->color = *(GdkColor*)g_value_get_boxed(value); - gtk_widget_queue_draw(GTK_WIDGET(cb)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); - break; - } -} - -/* Get_property function for HildonColorButtonClass initialization */ -static void -hildon_color_button_get_property(GObject *object, guint param_id, - GValue *value, GParamSpec *pspec) -{ - HildonColorButton *cb = HILDON_COLOR_BUTTON(object); - - switch (param_id) - { - case PROP_COLOR: - g_value_set_boxed(value, &cb->priv->color); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); - break; - } -} - -/** - * hildon_color_button_new: - * - * Creates a new color button. This returns a widget in the form of a - * small button containing a swatch representing the selected color. - * When the button is clicked, a color-selection dialog will open, - * allowing the user to select a color. The swatch will be updated to - * reflect the new color when the user finishes. - * - * Returns: a new color button - */ -GtkWidget * -hildon_color_button_new(void) -{ - return g_object_new( HILDON_TYPE_COLOR_BUTTON, NULL ); -} - -/** - * hildon_color_button_new_with_color: - * @color: a #GdkColor for the initial color - * - * Creates a new color button with @color as the initial color. - * - * Returns: a new color button - */ -GtkWidget * -hildon_color_button_new_with_color(const GdkColor *color) -{ - return g_object_new( HILDON_TYPE_COLOR_BUTTON, "color", color, NULL ); -} - -/** - * hildon_color_button_set_color: - * @button: a #HildonColorButton - * @color: a color to be set - * - * Sets the color selected by the button. - */ -void -hildon_color_button_set_color( HildonColorButton *button, GdkColor *color ) -{ - g_object_set( G_OBJECT(button), "color", color, NULL ); -} - -/** - * hildon_color_button_get_color: - * @button: a #HildonColorButton - * - * Returns: the color selected by the button - */ -GdkColor * -hildon_color_button_get_color( HildonColorButton *button ) -{ - GdkColor *color = NULL; - g_object_get( G_OBJECT(button), "color", &color, NULL ); - return color; -} diff --git a/hildon-widgets/hildon-color-button.h b/hildon-widgets/hildon-color-button.h deleted file mode 100644 index 490788a..0000000 --- a/hildon-widgets/hildon-color-button.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_COLOR_BUTTON_H__ -#define __HILDON_COLOR_BUTTON_H__ - -#include - -G_BEGIN_DECLS - -#define HILDON_TYPE_COLOR_BUTTON (hildon_color_button_get_type ()) -#define HILDON_COLOR_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HILDON_TYPE_COLOR_BUTTON, HildonColorButton)) -#define HILDON_COLOR_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_COLOR_BUTTON, HildonColorButtonClass)) -#define HILDON_IS_COLOR_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_COLOR_BUTTON)) -#define HILDON_IS_COLOR_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_COLOR_BUTTON)) -#define HILDON_COLOR_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), HILDON_TYPE_COLOR_BUTTON, HildonColorButtonClass)) - -typedef struct _HildonColorButton HildonColorButton; -typedef struct _HildonColorButtonClass HildonColorButtonClass; -typedef struct _HildonColorButtonPrivate HildonColorButtonPrivate; - -struct _HildonColorButton -{ - GtkButton button; - HildonColorButtonPrivate *priv; -}; - -struct _HildonColorButtonClass -{ - GtkButtonClass parent_class; - - /* Padding for future expansion */ - void (*_gtk_reserved1) (void); - void (*_gtk_reserved2) (void); - void (*_gtk_reserved3) (void); - void (*_gtk_reserved4) (void); -}; - - -GType -hildon_color_button_get_type( void ) G_GNUC_CONST; - -GtkWidget * -hildon_color_button_new( void ); - -GtkWidget * -hildon_color_button_new_with_color( const GdkColor *color ); - -GdkColor * -hildon_color_button_get_color( HildonColorButton *button ); - -void -hildon_color_button_set_color( HildonColorButton *button, GdkColor *color ); - -G_END_DECLS - -#endif /* __HILDON_COLOR_BUTTON_H__ */ - - - - diff --git a/hildon-widgets/hildon-color-chooser-button.c b/hildon-widgets/hildon-color-chooser-button.c deleted file mode 100644 index ec5ca29..0000000 --- a/hildon-widgets/hildon-color-chooser-button.c +++ /dev/null @@ -1,409 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Author: Kuisma Salonen - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - - -#include - - -#include "hildon-color-chooser-button.h" - -#include "hildon-color-chooser-dialog.h" - - -enum { - COLOR_CHANGED, - LAST_SIGNAL -}; - - -static guint color_chooser_button_signals[LAST_SIGNAL] = { 0 }; - - -static GtkButtonClass *parent_klass = NULL; - - -static void hildon_color_chooser_button_init(HildonColorChooserButton *object); -static void hildon_color_chooser_button_class_init(HildonColorChooserButtonClass *klass); - - -static void hildon_color_chooser_button_size_request(GtkWidget *widget, GtkRequisition *req); -static void hildon_color_chooser_button_size_allocate(GtkWidget *widget, GtkAllocation *alloc); - -static void hildon_color_chooser_button_realize(GtkWidget *widget); -static void hildon_color_chooser_button_unrealize(GtkWidget *widget); - -static void hildon_color_chooser_button_style_set(GtkWidget *widget, GtkStyle *previous_style); - -static void hildon_color_chooser_button_show(GtkWidget *widget); -static void hildon_color_chooser_button_show_all(GtkWidget *widget); - -static void hildon_color_chooser_button_virtual_set_color(HildonColorChooserButton *button, GdkColor *color); -static void hildon_color_chooser_button_virtual_color_changed(HildonColorChooserButton *button, GdkColor *color); - -static void hildon_color_chooser_button_clicked(GtkButton *button); - - -static gboolean hildon_color_chooser_button_area_expose(GtkWidget *widget, GdkEventExpose *event, gpointer data); - - -static void hildon_color_chooser_button_helper_get_style_info(HildonColorChooserButton *button); - - -GtkType hildon_color_chooser_button_get_type () -{ - static GtkType button_type = 0; - - if (!button_type) - { - static const GtkTypeInfo button_info = - { - "HildonColorChooserButton", - sizeof (HildonColorChooserButton), - sizeof (HildonColorChooserButtonClass), - (GtkClassInitFunc) hildon_color_chooser_button_class_init, - (GtkObjectInitFunc) hildon_color_chooser_button_init, - /* reserved_1 */ NULL, - /* reserved_1 */ NULL, - (GtkClassInitFunc) NULL - }; - - button_type = gtk_type_unique (GTK_TYPE_BUTTON, &button_info); - } - - return button_type; -} - - - /* initializer functions */ -static void hildon_color_chooser_button_init(HildonColorChooserButton *object) -{ - object->color.red = 0x0000; - object->color.green = 0x0000; - object->color.blue = 0x0000; - object->color.pixel = 0x00000000; - - - object->area = gtk_drawing_area_new(); - - gtk_container_add(GTK_CONTAINER(object), object->area); - - - g_signal_connect(G_OBJECT(object->area), "expose-event", - G_CALLBACK(hildon_color_chooser_button_area_expose), object); -} - -static void hildon_color_chooser_button_class_init(HildonColorChooserButtonClass *klass) -{ - GtkWidgetClass *widget_klass = GTK_WIDGET_CLASS(klass); - GtkButtonClass *button_klass = GTK_BUTTON_CLASS(klass); - GtkObjectClass *object_klass = GTK_OBJECT_CLASS(klass); - - - parent_klass = g_type_class_peek_parent(klass); - - - klass->set_color = hildon_color_chooser_button_virtual_set_color; - klass->color_changed = hildon_color_chooser_button_virtual_color_changed; - - - button_klass->clicked = hildon_color_chooser_button_clicked; - - - widget_klass->size_request = hildon_color_chooser_button_size_request; - widget_klass->size_allocate = hildon_color_chooser_button_size_allocate; - - widget_klass->realize = hildon_color_chooser_button_realize; - widget_klass->unrealize = hildon_color_chooser_button_unrealize; - - widget_klass->style_set = hildon_color_chooser_button_style_set; - - widget_klass->show = hildon_color_chooser_button_show; - widget_klass->show_all = hildon_color_chooser_button_show_all; - - - gtk_widget_class_install_style_property(widget_klass, - g_param_spec_boxed("outer_border", - "Outer border", - "Size of the outer border", - GTK_TYPE_BORDER, - G_PARAM_READABLE)); - gtk_widget_class_install_style_property(widget_klass, - g_param_spec_boxed("inner_border", - "Inner border", - "Size of the inner border", - GTK_TYPE_BORDER, - G_PARAM_READABLE)); - gtk_widget_class_install_style_property(widget_klass, - g_param_spec_boxed("minimum_size", - "minimum_size", - "Minimum size of the color area", - GTK_TYPE_BORDER, - G_PARAM_READABLE)); - - - color_chooser_button_signals[COLOR_CHANGED] = g_signal_new("color-changed", G_OBJECT_CLASS_TYPE (object_klass), - G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (HildonColorChooserButtonClass, color_changed), - NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, GDK_TYPE_COLOR); -} - - - /* virtual widget functions */ -static void hildon_color_chooser_button_size_request(GtkWidget *widget, GtkRequisition *req) -{ - HildonColorChooserButton *button = HILDON_COLOR_CHOOSER_BUTTON(widget); - - - req->width = button->style_info.outer.left + button->style_info.min.left + button->style_info.outer.right; - req->height = button->style_info.outer.top + button->style_info.min.right + button->style_info.outer.bottom; -} - -static void hildon_color_chooser_button_size_allocate(GtkWidget *widget, GtkAllocation *alloc) -{ - HildonColorChooserButton *button = HILDON_COLOR_CHOOSER_BUTTON(widget); - GtkAllocation child_alloc; - GdkRectangle clip_rect; - - - GTK_WIDGET_CLASS(parent_klass)->size_allocate(widget, alloc); - child_alloc = *alloc; - - - child_alloc.x += button->style_info.outer.left; - child_alloc.y += button->style_info.outer.top; - - child_alloc.width -= (button->style_info.outer.left + button->style_info.outer.right); - child_alloc.height -= (button->style_info.outer.top + button->style_info.outer.bottom); - - - gtk_widget_size_allocate(button->area, &child_alloc); - - - if(GTK_WIDGET_REALIZED(widget)) { - clip_rect.x = button->style_info.inner.left; - clip_rect.y = button->style_info.inner.top; - clip_rect.width = button->area->allocation.width - button->style_info.inner.left - button->style_info.inner.right; - clip_rect.height = button->area->allocation.height - button->style_info.inner.top - button->style_info.inner.bottom; - - gdk_gc_set_clip_rectangle(button->color_gc, &clip_rect); - } -} - - -static void hildon_color_chooser_button_realize(GtkWidget *widget) -{ - HildonColorChooserButton *button = HILDON_COLOR_CHOOSER_BUTTON(widget); - GdkRectangle clip_rect; - - - GTK_WIDGET_CLASS(parent_klass)->realize(widget); - - - button->color_gc = gdk_gc_new(widget->window); - gdk_gc_set_rgb_fg_color(button->color_gc, &button->color); - - - clip_rect.x = button->style_info.inner.left; - clip_rect.y = button->style_info.inner.top; - clip_rect.width = button->area->allocation.width - button->style_info.inner.left - button->style_info.inner.right; - clip_rect.height = button->area->allocation.height - button->style_info.inner.top - button->style_info.inner.bottom; - - gdk_gc_set_clip_rectangle(button->color_gc, &clip_rect); -} - -static void hildon_color_chooser_button_unrealize(GtkWidget *widget) -{ - HildonColorChooserButton *button = HILDON_COLOR_CHOOSER_BUTTON(widget); - - - g_object_unref(button->color_gc); - button->color_gc = NULL; - - - GTK_WIDGET_CLASS(parent_klass)->unrealize(widget); -} - - -static void hildon_color_chooser_button_style_set(GtkWidget *widget, GtkStyle *previous_style) -{ - HildonColorChooserButton *button = HILDON_COLOR_CHOOSER_BUTTON(widget); - GdkRectangle clip_rect; - - - hildon_color_chooser_button_helper_get_style_info(button); - - - if(GTK_WIDGET_REALIZED(widget)) { - clip_rect.x = button->style_info.inner.left; - clip_rect.y = button->style_info.inner.top; - clip_rect.width = button->area->allocation.width - button->style_info.inner.left - button->style_info.inner.right; - clip_rect.height = button->area->allocation.height - button->style_info.inner.top - button->style_info.inner.bottom; - - gdk_gc_set_clip_rectangle(button->color_gc, &clip_rect); - } -} - - -static void hildon_color_chooser_button_show(GtkWidget *widget) -{ - HildonColorChooserButton *button = HILDON_COLOR_CHOOSER_BUTTON(widget); - - - gtk_widget_show(button->area); - - GTK_WIDGET_CLASS(parent_klass)->show(widget); -} - -static void hildon_color_chooser_button_show_all(GtkWidget *widget) -{ - hildon_color_chooser_button_show(widget); -} - - -static void hildon_color_chooser_button_virtual_set_color(HildonColorChooserButton *button, GdkColor *color) -{ - button->color = *color; - - if(GTK_WIDGET_REALIZED(button)) { - gdk_gc_set_rgb_fg_color(button->color_gc, &button->color); - - gtk_widget_queue_draw(button->area); - } - - - g_signal_emit(button, color_chooser_button_signals[COLOR_CHANGED], 0, &button->color); -} - -static void hildon_color_chooser_button_virtual_color_changed(HildonColorChooserButton *button, GdkColor *color) -{ -} - - -static void hildon_color_chooser_button_clicked(GtkButton *button) -{ - HildonColorChooserButton *color_button = HILDON_COLOR_CHOOSER_BUTTON(button); - GtkWidget *dialog; - GdkColor color; - gint result = 0; - - - dialog = hildon_color_chooser_dialog_new(); - gtk_widget_realize(dialog); - hildon_color_chooser_dialog_set_color(HILDON_COLOR_CHOOSER_DIALOG(dialog), &color_button->color); - gtk_widget_show(dialog); - - - result = gtk_dialog_run(GTK_DIALOG(dialog)); - - - if(result == GTK_RESPONSE_OK) { - hildon_color_chooser_dialog_get_color(HILDON_COLOR_CHOOSER_DIALOG(dialog), &color); - hildon_color_chooser_button_virtual_set_color(color_button, &color); - } - - -/*g_object_unref(G_OBJECT(dialog));*/ - gtk_widget_destroy(dialog); -} - - - /* signal handlers */ -static gboolean hildon_color_chooser_button_area_expose(GtkWidget *widget, GdkEventExpose *event, gpointer data) -{ - HildonColorChooserButton *button = HILDON_COLOR_CHOOSER_BUTTON(data); - GtkWidget *button_widget = GTK_WIDGET(data); - - - if(button->style_info.inner.left > 0 || button->style_info.inner.right > 0 || - button->style_info.inner.top > 0 || button->style_info.inner.bottom > 0) { - gtk_paint_box(gtk_widget_get_style(button_widget), widget->window, GTK_WIDGET_STATE(button_widget), GTK_SHADOW_NONE, - &event->area, button_widget, "color-button", 0, 0, widget->allocation.width, widget->allocation.height); - } - - - gdk_draw_rectangle(widget->window, button->color_gc, TRUE, event->area.x, event->area.y, event->area.width, event->area.height); - - - return FALSE; -} - - - /* additional use-only-here functions */ -static void hildon_color_chooser_button_helper_get_style_info(HildonColorChooserButton *button) -{ - GtkBorder *in, *out, *min; - - gtk_widget_style_get(GTK_WIDGET(button), "inner_border", &in, - "outer_border", &out, - "minimum_size", &min, NULL); - - - if(in) { - button->style_info.inner = *in; - g_free(in); - } else { - button->style_info.inner.left = 0; - button->style_info.inner.right = 0; - button->style_info.inner.top = 0; - button->style_info.inner.bottom = 0; - } - - if(out) { - button->style_info.outer = *out; - g_free(out); - } else { - button->style_info.outer.left = 4; - button->style_info.outer.right = 4; - button->style_info.outer.top = 4; - button->style_info.outer.bottom = 4; - } - - if(min) { - button->style_info.min = *min; - g_free(min); - } else { - button->style_info.min.left = 8; - button->style_info.min.right = 8; - button->style_info.min.top = 0; - button->style_info.min.bottom = 0; - } -} - - - /* public API */ -GtkWidget *hildon_color_chooser_button_new() -{ - return gtk_type_new(HILDON_TYPE_COLOR_CHOOSER_BUTTON); -} - - -void hildon_color_chooser_button_set_color(HildonColorChooserButton *button, GdkColor *color) -{ - HILDON_COLOR_CHOOSER_BUTTON_CLASS(G_OBJECT_GET_CLASS(button))->set_color(button, color); -} - -void hildon_color_chooser_button_get_color(HildonColorChooserButton *button, GdkColor *color) -{ - *color = button->color; -} diff --git a/hildon-widgets/hildon-color-chooser-button.h b/hildon-widgets/hildon-color-chooser-button.h deleted file mode 100644 index 9dcb446..0000000 --- a/hildon-widgets/hildon-color-chooser-button.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Author: Kuisma Salonen - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - - -#ifndef __HILDON_COLOR_CHOOSER_BUTTON_H__ -#define __HILDON_COLOR_CHOOSER_BUTTON_H__ - - -#include - -#include - - -#define HILDON_TYPE_COLOR_CHOOSER_BUTTON (hildon_color_chooser_button_get_type()) - -#define HILDON_COLOR_CHOOSER_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HILDON_TYPE_COLOR_CHOOSER_BUTTON, HildonColorChooserButton)) -#define HILDON_COLOR_CHOOSER_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), HILDON_TYPE_COLOR_CHOOSER_BUTTON, HildonColorChooserButtonClass)) -#define HILDON_IS_COLOR_CHOOSER_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_COLOR_CHOOSER_BUTTON)) - - -typedef struct HildonColorChooserButton_ HildonColorChooserButton; -typedef struct HildonColorChooserButtonClass_ HildonColorChooserButtonClass; - - -struct HildonColorChooserButton_ -{ - GtkButton parent; - - GdkColor color; - - GtkWidget *area; - - GdkGC *color_gc; - - - struct { - GtkBorder outer; - GtkBorder inner; - GtkBorder min; - } style_info; -}; - -struct HildonColorChooserButtonClass_ -{ - GtkButtonClass parent; - - void (*color_changed) (HildonColorChooserButton *button, GdkColor *color); - - void (*set_color) (HildonColorChooserButton *, GdkColor *); -}; - - -GtkType hildon_color_chooser_button_get_type(); -GtkWidget *hildon_color_chooser_button_new(); - -void hildon_color_chooser_button_set_color(HildonColorChooserButton *button, GdkColor *color); -void hildon_color_chooser_button_get_color(HildonColorChooserButton *button, GdkColor *color); - - -#endif /* __HILDON_COLOR_CHOOSER_BUTTON_H__ */ diff --git a/hildon-widgets/hildon-color-chooser-dialog.c b/hildon-widgets/hildon-color-chooser-dialog.c deleted file mode 100644 index bb367a4..0000000 --- a/hildon-widgets/hildon-color-chooser-dialog.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Author: Kuisma Salonen - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - - -/** - * SECTION:hildon-color-chooser-dialog - * @short_description: A dialog to choose a color. - * @see_also: #HildonColorButton, #HildonColorChooser - * - * HildonColorChooserDialog is a widget widget to choose a color. - */ -#include - - -#include "hildon-color-chooser-dialog.h" - -#include "hildon-plugin-widget.h" - - -enum { - COLOR_CHANGED, - LAST_SIGNAL -}; - - -static HildonPluginWidgetInfo *global_plugin = NULL; - - -static guint color_chooser_dialog_signals[LAST_SIGNAL] = { 0 }; - - -static void hildon_color_chooser_dialog_init(HildonColorChooserDialog *object); -static void hildon_color_chooser_dialog_class_init(HildonColorChooserDialogClass *klass); - - -GtkType hildon_color_chooser_dialog_get_type () -{ - static GtkType chooser_type = 0; - - if (!chooser_type) - { - static const GtkTypeInfo chooser_info = - { - "HildonColorChooserDialog", - sizeof (HildonColorChooserDialog), - sizeof (HildonColorChooserDialogClass), - (GtkClassInitFunc) hildon_color_chooser_dialog_class_init, - (GtkObjectInitFunc) hildon_color_chooser_dialog_init, - /* reserved_1 */ NULL, - /* reserved_1 */ NULL, - (GtkClassInitFunc) NULL - }; - - chooser_type = gtk_type_unique (GTK_TYPE_DIALOG, &chooser_info); - } - - return chooser_type; -} - - -static void hildon_color_chooser_dialog_init(HildonColorChooserDialog *object) -{ - int i; - - - object->color.red = 0x0000; - object->color.green = 0x0000; - object->color.blue = 0x0000; - object->color.pixel = 0x00000000; - - - for(i = 0; i < 32; i++) { - object->reserved[i] = 0; - } -} - -static void hildon_color_chooser_dialog_class_init(HildonColorChooserDialogClass *klass) -{ - GtkObjectClass *object_klass = GTK_OBJECT_CLASS(klass); - int i; - - - for(i = 0; i < 32; i++) { - klass->reserved[i] = 0; - } - - klass->set_color = 0; - - - color_chooser_dialog_signals[COLOR_CHANGED] = g_signal_new("color-changed", G_OBJECT_CLASS_TYPE (object_klass), - G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (HildonColorChooserDialogClass, color_changed), - NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, GDK_TYPE_COLOR); -} - -/** - * hildon_color_chooser_dialog_new: - * - * Creates a new color chooser dialog. The dialog is created through - * HildonPluginWidget API and is loaded from plugin. The initially selected - * color can be anything, so it's recommended to call - * hildon_color_chooser_dialog_set_color () after creating the widget. - * - * Returns: a new color chooser dialog - */ -GtkWidget *hildon_color_chooser_dialog_new() -{ - if(!global_plugin) { - global_plugin = hildon_plugin_info_initialize(HILDON_TYPE_COLOR_CHOOSER_DIALOG, NULL); - g_return_val_if_fail (global_plugin != NULL, NULL); - } - - return hildon_plugin_info_construct_widget(global_plugin); -} - -/** - * hildon_color_chooser_dialog_set_color: - * @chooser: a #HildonColorChooserDialog - * @color: a color to be set - * - * Sets the color selected in the dialog. - */ -void hildon_color_chooser_dialog_set_color(HildonColorChooserDialog *chooser, GdkColor *color) -{ - HildonColorChooserDialogClass *klass = HILDON_COLOR_CHOOSER_DIALOG_CLASS(G_OBJECT_GET_CLASS(chooser)); - - - chooser->color = *color; - - if(klass->set_color) { - klass->set_color(chooser, color); - } -} - -/** - * hildon_color_chooser_dialog_get_color: - * @chooser: a #HildonColorChooserDialog - * @color: a pointer to #GdkColor to be filled by the function - * - * Gets the color selected in the dialog. - */ -void hildon_color_chooser_dialog_get_color(HildonColorChooserDialog *chooser, GdkColor *color) -{ - *color = chooser->color; -} - - -void hildon_color_chooser_dialog_emit_color_changed(HildonColorChooserDialog *chooser) -{ - g_signal_emit(chooser, color_chooser_dialog_signals[COLOR_CHANGED], 0, &chooser->color); -} diff --git a/hildon-widgets/hildon-color-chooser-dialog.h b/hildon-widgets/hildon-color-chooser-dialog.h deleted file mode 100644 index e03492a..0000000 --- a/hildon-widgets/hildon-color-chooser-dialog.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Author: Kuisma Salonen - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - - -#ifndef __HILDON_COLOR_CHOOSER_DIALOG_H__ -#define __HILDON_COLOR_CHOOSER_DIALOG_H__ - - -#include - -#include - - -#define HILDON_TYPE_COLOR_CHOOSER_DIALOG (hildon_color_chooser_dialog_get_type()) - -#define HILDON_COLOR_CHOOSER_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HILDON_TYPE_COLOR_CHOOSER_DIALOG, HildonColorChooserDialog)) -#define HILDON_COLOR_CHOOSER_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), HILDON_TYPE_COLOR_CHOOSER_DIALOG, HildonColorChooserDialogClass)) -#define HILDON_IS_COLOR_CHOOSER_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_COLOR_CHOOSER_DIALOG)) - - -typedef struct HildonColorChooserDialog_ HildonColorChooserDialog; -typedef struct HildonColorChooserDialogClass_ HildonColorChooserDialogClass; - - -struct HildonColorChooserDialog_ { - GtkDialog parent; - - GdkColor color; - - guint32 reserved[32]; -}; - -struct HildonColorChooserDialogClass_ { - GtkDialogClass parent_class; - - gboolean (*color_changed) (HildonColorChooserDialog *chooser, GdkColor *color); - - void (*set_color) (HildonColorChooserDialog *, GdkColor *); - - void (*reserved[32]) (void *); -}; - - -GtkType hildon_color_chooser_dialog_get_type(); - -GtkWidget *hildon_color_chooser_dialog_new(); - -void hildon_color_chooser_dialog_set_color(HildonColorChooserDialog *chooser, GdkColor *color); -void hildon_color_chooser_dialog_get_color(HildonColorChooserDialog *chooser, GdkColor *color); - -void hildon_color_chooser_dialog_emit_color_changed(HildonColorChooserDialog *chooser); - - -#endif /* __HILDON_COLOR_CHOOSER_DIALOG_H__ */ diff --git a/hildon-widgets/hildon-color-chooser.c b/hildon-widgets/hildon-color-chooser.c deleted file mode 100644 index f781eee..0000000 --- a/hildon-widgets/hildon-color-chooser.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Author: Kuisma Salonen - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - - -/** - * SECTION:hildon-color-chooser - * @short_description: A widget to choose a color. - * @see_also: #HildonColorChooserDialog, #HildonColorButton - * - * HildonColorChooser is a widget to choose a color. - */ -#include - - -#include "hildon-color-chooser.h" - -#include "hildon-plugin-widget.h" - - -enum { - COLOR_CHANGED, - LAST_SIGNAL -}; - - -static HildonPluginWidgetInfo *global_plugin = NULL; - - -static guint color_chooser_signals[LAST_SIGNAL] = { 0 }; - - -static void hildon_color_chooser_init(HildonColorChooser *sel); -static void hildon_color_chooser_class_init(HildonColorChooserClass *klass); - - -GtkType hildon_color_chooser_get_type () -{ - static GtkType chooser_type = 0; - - if (!chooser_type) - { - static const GtkTypeInfo chooser_info = - { - "HildonColorChooser", - sizeof (HildonColorChooser), - sizeof (HildonColorChooserClass), - (GtkClassInitFunc) hildon_color_chooser_class_init, - (GtkObjectInitFunc) hildon_color_chooser_init, - /* reserved_1 */ NULL, - /* reserved_1 */ NULL, - (GtkClassInitFunc) NULL - }; - - chooser_type = gtk_type_unique (GTK_TYPE_WIDGET, &chooser_info); - } - - return chooser_type; -} - - -static void hildon_color_chooser_init(HildonColorChooser *sel) -{ - sel->color.red = 0x0000; - sel->color.green = 0x0000; - sel->color.blue = 0x0000; - sel->color.pixel = 0x00000000; -} - -static void hildon_color_chooser_class_init(HildonColorChooserClass *klass) -{ - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); - GtkObjectClass *object_class = GTK_OBJECT_CLASS(klass); - - klass->set_color = NULL; - - - gtk_widget_class_install_style_property(widget_class, - g_param_spec_boxed("outer_border", - "Outer border", - "Size of outer border", - GTK_TYPE_BORDER, - G_PARAM_READABLE)); - - color_chooser_signals[COLOR_CHANGED] = g_signal_new("color-changed", G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (HildonColorChooserClass, color_changed), - NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, GDK_TYPE_COLOR); -} - -/** - * hildon_color_chooser_new: - * - * Creates a new color chooser widget. The dialog is created through - * HildonPluginWidget API and is loaded from plugin. The initially selected - * color can be anything, so it's recommended to call - * hildon_color_chooser_dialog_set_color () after creating the widget. - * - * Returns: a new color chooser widget - */ -GtkWidget *hildon_color_chooser_new() -{ - if(!global_plugin) { - global_plugin = hildon_plugin_info_initialize(HILDON_TYPE_COLOR_CHOOSER, NULL); - } - - - return hildon_plugin_info_construct_widget(global_plugin); -} - -/** - * hildon_color_chooser_set_color: - * @chooser: a #HildonColorChooser - * @color: a color to be set - * - * Sets the color selected in the widget. - */ -void hildon_color_chooser_set_color(HildonColorChooser *chooser, GdkColor *color) -{ - HildonColorChooserClass *klass = HILDON_COLOR_CHOOSER_CLASS(G_OBJECT_GET_CLASS(chooser)); - - - chooser->color = *color; - - if(klass->set_color) { - klass->set_color(chooser, color); - } -} - -/** - * hildon_color_chooser_get_color: - * @chooser: a #HildonColorChooser - * @color: a pointer to #GdkColor to be filled by the function - * - * Gets the color selected in the widget. - */ -void hildon_color_chooser_get_color(HildonColorChooser *chooser, GdkColor *color) -{ - *color = chooser->color; -} - - -void hildon_color_chooser_emit_color_changed(HildonColorChooser *chooser) -{ - g_signal_emit(chooser, color_chooser_signals[COLOR_CHANGED], 0, &chooser->color); -} diff --git a/hildon-widgets/hildon-color-chooser.h b/hildon-widgets/hildon-color-chooser.h deleted file mode 100644 index 0135085..0000000 --- a/hildon-widgets/hildon-color-chooser.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Author: Kuisma Salonen - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - - -#ifndef __HILDON_COLOR_CHOOSER_H__ -#define __HILDON_COLOR_CHOOSER_H__ - - -#include - -#include - - -#define HILDON_TYPE_COLOR_CHOOSER (hildon_color_chooser_get_type()) - -#define HILDON_COLOR_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HILDON_TYPE_COLOR_CHOOSER, HildonColorChooser)) -#define HILDON_COLOR_CHOOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), HILDON_TYPE_COLOR_CHOOSER, HildonColorChooserClass)) -#define HILDON_IS_COLOR_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_COLOR_CHOOSER)) - - -typedef struct HildonColorChooser_ HildonColorChooser; -typedef struct HildonColorChooserClass_ HildonColorChooserClass; - - -struct HildonColorChooser_ -{ - GtkWidget parent; - - GdkColor color; -}; - -struct HildonColorChooserClass_ -{ - GtkWidgetClass parent; - - void (*color_changed) (HildonColorChooser *selection, GdkColor *color); - - void (*set_color) (HildonColorChooser *, GdkColor *); -}; - - -GtkType hildon_color_chooser_get_type(void); -GtkWidget *hildon_color_chooser_new(void); - -void hildon_color_chooser_set_color(HildonColorChooser *chooser, GdkColor *color); -void hildon_color_chooser_get_color(HildonColorChooser *chooser, GdkColor *color); - -void hildon_color_chooser_emit_color_changed(HildonColorChooser *chooser); - - -#endif /* __HILDON_COLOR_CHOOSER_H__ */ diff --git a/hildon-widgets/hildon-color-popup.c b/hildon-widgets/hildon-color-popup.c deleted file mode 100644 index 1279490..0000000 --- a/hildon-widgets/hildon-color-popup.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-color-popup - * @short_description: A popup dialog for editing a color and showing the - * edited result - * @see_also: #HildonColorButton, #HildonColorSelector - * - * #HildonColorPopup is only used inside #HildonColorButton. It is a - * popup dialog for editing a color. The color can be changed using - * three control bars that are used to adjust the red, green and blue - * color channels. The display is updated in real time when the bars are - * moved. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include "hildon-color-selector.h" -#include "hildon-color-popup.h" -#include "hildon-controlbar.h" - -#include -#define _(String) dgettext(PACKAGE, String) - -/* Pixel sizes */ -#define HILDON_COLOR_PALETTE_SIZE 120 -#define HILDON_COLOR_CONTROLBAR_MAX 31 -#define HILDON_COLOR_CONTROLBAR_MIN 0 -#define HILDON_COLOR_LABELS_LEFT_PAD 35 -#define HILDON_COLOR_PALETTE_POS_PAD 45 -#define HILDON_COLOR_BAR_WIDTH 449 -#define HILDON_COLOR_COL_SPACING 18 - -/* - * Private function prototype definitions - */ - -static gboolean -hildon_popup_palette_expose (GtkWidget * widget, - GdkEventExpose * event, - gpointer data); -/** - * hildon_color_popup_new: - * @parent: the parent window of the dialog - * @initial_color: a #GdkColor with the initial values to be used - * @popup_data: a #HildonColorPopup - * - * This function creates a new popup dialog with three controlbars - * (red, green, blue) and a drawing area with the current color. - * - * Used as normal GtkDialog (run with gtk_dialog_run() and read - * stardard responses (GTK_RESPONSE_OK, GTK_RESPONSE_CANCEL). - * - * Returns: the newly created popup dialog - */ - -GtkWidget * -hildon_color_popup_new(GtkWindow *parent, const GdkColor *initial_color, - HildonColorPopup *popup_data) -{ - GtkWidget *popup; - GtkTable *layout; - GtkWidget *area; - GtkWidget *l_red, *l_green, *l_blue; - - /* Create control bars for HildonColorPopup */ - popup_data->ctrlbar_red = hildon_controlbar_new (); - popup_data->ctrlbar_green = hildon_controlbar_new (); - popup_data->ctrlbar_blue = hildon_controlbar_new (); - area = gtk_drawing_area_new(); - layout = GTK_TABLE(gtk_table_new(12, 2, FALSE)); - - /* Set widgets' size */ - gtk_widget_set_size_request (area, - HILDON_COLOR_PALETTE_SIZE, - HILDON_COLOR_PALETTE_SIZE); - gtk_widget_set_size_request(popup_data->ctrlbar_red, - HILDON_COLOR_BAR_WIDTH, -1); - gtk_widget_set_size_request(popup_data->ctrlbar_green, - HILDON_COLOR_BAR_WIDTH, -1); - gtk_widget_set_size_request(popup_data->ctrlbar_blue, - HILDON_COLOR_BAR_WIDTH, -1); - - /* Create labels for three kinds of color */ - l_red = gtk_label_new(_("ecdg_fi_5bit_colour_selector_red")); - l_green = gtk_label_new(_("ecdg_fi_5bit_colour_selector_green")); - l_blue = gtk_label_new(_("ecdg_fi_5bit_colour_selector_blue")); - - /* Position the labels to start about the same label as the controlbars */ - gtk_misc_set_alignment(GTK_MISC(l_red), 0.08f, 0.5f); - gtk_misc_set_alignment(GTK_MISC(l_green), 0.08f, 0.5f); - gtk_misc_set_alignment(GTK_MISC(l_blue), 0.08f, 0.5f); - - /* Add labels and control bars to the layout table */ - gtk_table_set_col_spacing(layout, 0, HILDON_COLOR_COL_SPACING); - gtk_table_attach_defaults(layout, l_red, 0, 1, 0, 2); - gtk_table_attach_defaults(layout, popup_data->ctrlbar_red, 0, 1, 2, 4); - gtk_table_attach_defaults(layout, l_green, 0, 1, 4, 6); - gtk_table_attach_defaults(layout, popup_data->ctrlbar_green, 0, 1, 6, 8); - gtk_table_attach_defaults(layout, l_blue, 0, 1, 8, 10); - gtk_table_attach_defaults(layout, popup_data->ctrlbar_blue, 0, 1, 10, 12); - gtk_table_attach(layout, area, 1, 2, 3, 11, GTK_SHRINK, GTK_SHRINK, 0, 0); - - /* Give the maximum and minimum limits for each control bar */ - hildon_controlbar_set_range (HILDON_CONTROLBAR(popup_data->ctrlbar_red), - HILDON_COLOR_CONTROLBAR_MIN, - HILDON_COLOR_CONTROLBAR_MAX); - hildon_controlbar_set_range (HILDON_CONTROLBAR(popup_data->ctrlbar_green), - HILDON_COLOR_CONTROLBAR_MIN, - HILDON_COLOR_CONTROLBAR_MAX); - hildon_controlbar_set_range (HILDON_CONTROLBAR(popup_data->ctrlbar_blue), - HILDON_COLOR_CONTROLBAR_MIN, - HILDON_COLOR_CONTROLBAR_MAX); - - /* Give the initial values for each control bar */ - hildon_controlbar_set_value (HILDON_CONTROLBAR(popup_data->ctrlbar_red), - (initial_color->red >> 11)&0x1F); - hildon_controlbar_set_value (HILDON_CONTROLBAR(popup_data->ctrlbar_green), - (initial_color->green >> 11)&0x1F); - hildon_controlbar_set_value (HILDON_CONTROLBAR(popup_data->ctrlbar_blue), - (initial_color->blue >> 11)&0x1F); - - /* Register controlbar callbacks */ - g_signal_connect_swapped(popup_data->ctrlbar_red, "value-changed", - G_CALLBACK(gtk_widget_queue_draw), area); - g_signal_connect_swapped(popup_data->ctrlbar_green, "value-changed", - G_CALLBACK(gtk_widget_queue_draw), area); - g_signal_connect_swapped(popup_data->ctrlbar_blue, "value-changed", - G_CALLBACK(gtk_widget_queue_draw), area); - - /* Attach expose_event callback function to drawing area */ - g_signal_connect (area, "expose_event", - G_CALLBACK(hildon_popup_palette_expose), - popup_data); - - /* Create popup dialog */ - popup = gtk_dialog_new_with_buttons (_("ecdg_ti_5bit_colour_selector"), - GTK_WINDOW(parent), - GTK_DIALOG_DESTROY_WITH_PARENT | - GTK_DIALOG_NO_SEPARATOR, - _("ecdg_bd_5bit_colour_selector_ok"), GTK_RESPONSE_OK, - _("ecdg_bd_5bit_colour_selector_cancel"), - GTK_RESPONSE_CANCEL, - NULL); - - /* Select-key shouldn't do anything unless dialog's button is focused */ - gtk_dialog_set_default_response(GTK_DIALOG(popup), GTK_RESPONSE_NONE); - - /* Add layout table to the Vbox of the popup dialog */ - gtk_box_pack_start (GTK_BOX(GTK_DIALOG(popup)->vbox), - GTK_WIDGET(layout), TRUE, TRUE, 0); - - /* Show thw Vbox of the popup dialog */ - gtk_widget_show_all(GTK_DIALOG(popup)->vbox); - - return popup; -} - -/** - * hildon_color_popup_set_color_from_sliders: - * @color: a pointer to #GdkColor to which the new values will be put - * @popup_data: a #HildonColorPopup - * - * Sets the values in the given #GdkColor to the values of the - * controlbars. - */ - -void -hildon_color_popup_set_color_from_sliders(GdkColor *color, - HildonColorPopup *popup_data) -{ - color->pixel = 0; - color->red = hildon_controlbar_get_value ( - HILDON_CONTROLBAR(popup_data->ctrlbar_red)) << 11; - color->green = hildon_controlbar_get_value ( - HILDON_CONTROLBAR(popup_data->ctrlbar_green)) << 11; - color->blue = hildon_controlbar_get_value ( - HILDON_CONTROLBAR(popup_data->ctrlbar_blue)) << 11; -} - -/* expose_event callback function */ -static gboolean -hildon_popup_palette_expose (GtkWidget * widget, - GdkEventExpose *event, gpointer data) -{ - if (GTK_WIDGET_DRAWABLE(widget)) - { - GdkColor color; - GdkGC * gc = gdk_gc_new (widget->window); - - /* Get the current color value */ - hildon_color_popup_set_color_from_sliders(&color, data); - gdk_gc_set_rgb_fg_color(gc, &color); - - /* draw the color area */ - gdk_draw_rectangle( widget->window, gc, TRUE /* filled */, - 1, 1, widget->allocation.width - 2, - widget->allocation.height - 2); - - color.pixel = color.red = color.green = color.blue = 0; - gdk_gc_set_rgb_fg_color(gc, &color); - - /* Draw frames on color box */ - gdk_draw_rectangle( widget->window, gc, FALSE, - 0, 0, widget->allocation.width - 1, - widget->allocation.height - 1); - - /* Free memory used by the graphics contexts */ - g_object_unref(gc); - } - - return TRUE; -} diff --git a/hildon-widgets/hildon-color-popup.h b/hildon-widgets/hildon-color-popup.h deleted file mode 100644 index d4277a2..0000000 --- a/hildon-widgets/hildon-color-popup.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_COLOR_POPUP_H__ -#define __HILDON_COLOR_POPUP_H__ - -#include -#include -#include - -G_BEGIN_DECLS - -typedef struct -{ - GtkWidget *ctrlbar_red; - GtkWidget *ctrlbar_green; - GtkWidget *ctrlbar_blue; - -} HildonColorPopup; - -GtkWidget *hildon_color_popup_new(GtkWindow *parent, - const GdkColor *initial_color, - HildonColorPopup *popupdata); - -void hildon_color_popup_set_color_from_sliders(GdkColor *color, - HildonColorPopup *popupdata); - - -G_END_DECLS - -#endif /* __HILDON_COLOR_POPUP_H__ */ diff --git a/hildon-widgets/hildon-color-selector.c b/hildon-widgets/hildon-color-selector.c deleted file mode 100644 index d155d1d..0000000 --- a/hildon-widgets/hildon-color-selector.c +++ /dev/null @@ -1,845 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-color-selector - * @short_description: A widget for selecting a color - * @see_also: #HildonColorButton, #HildonColorPopup - * - * #HildonColorSelector allows selection of a color from a standard - * 16-color palette or a palette of 8 user-customizable colors. - * The user-customizable colors can be modified through HildonColorPopup. - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include "hildon-color-selector.h" -#include "hildon-color-popup.h" - -#include -#define _(String) dgettext(PACKAGE, String) - -/* Color amounts */ -#define HILDON_BASE_COLOR_NUM 16 -#define HILDON_CUSTOM_COLOR_NUM 8 -#define HILDON_TOTAL_COLOR_NUM (HILDON_BASE_COLOR_NUM + HILDON_CUSTOM_COLOR_NUM) -#define BLACKIND 0 -#define GREYIND 6 -#define WHITEIND 9 - -#define SELECTION_BORDER_COLOR_NAME "ImageBorderColor" -#define FOCUS_BORDER_COLOR "#8080FF" -#define FOCUS_BORDER_WIDTH 2 - -/* Pixel sizes */ -#define HILDON_COLOR_SELECTOR_BOX_W 26 -#define HILDON_COLOR_SELECTOR_BOX_H 26 -#define HILDON_COLOR_SELECTOR_BORDER_WIDTH 1 -#define HILDON_COLOR_SELECTOR_PADDING_WIDTH 1 - -#define HILDON_COLOR_SELECTOR_BOX_FULL_WIDTH \ - ( HILDON_COLOR_SELECTOR_BOX_W \ - + HILDON_COLOR_SELECTOR_BORDER_WIDTH * 2 \ - + HILDON_COLOR_SELECTOR_PADDING_WIDTH * 2 ) - -#define HILDON_COLOR_SELECTOR_BOX_FULL_HEIGHT \ - ( HILDON_COLOR_SELECTOR_BOX_H \ - + HILDON_COLOR_SELECTOR_BORDER_WIDTH * 2 \ - + HILDON_COLOR_SELECTOR_PADDING_WIDTH * 2 ) - -#define HILDON_COLOR_SELECTOR_COLS 8 -#define HILDON_COLOR_SELECTOR_ROWS 3 - -/* gconf definitions */ -#define HILDON_COLOR_GCONF_PATH "/system/osso/af/color_selector" -#define HILDON_COLOR_GCONF_KEYS "/system/osso/af/color_selector/custom_colors" - -/* Pointer parent class */ -static GtkDialogClass *parent_class; - -struct _HildonColorSelectorPriv -{ - GConfClient *client; - GtkWidget *drawing_area; - GtkWidget *modify_button; - gint selected_index; - gint focused_index; - guint notify_id; - /* one extra place for the modified base color */ - GdkColor color[HILDON_TOTAL_COLOR_NUM + 1]; -}; - -enum -{ - PROP_NONE, - PROP_COLOR -}; - -/* - * Private function prototype definitions - */ -static void -hildon_color_selector_class_init (HildonColorSelectorClass * selector_class); - -static void -hildon_color_selector_init (HildonColorSelector * selector); - -static gboolean -hildon_color_selector_expose (GtkWidget * widget, - GdkEventExpose * event, - gpointer data); - -static gboolean key_pressed (GtkWidget * widget, - GdkEventKey * event); - -static gboolean color_pressed (GtkWidget * widget, - GdkEventButton * event, - gpointer user_data); - -static void select_color_index (HildonColorSelector *selector, - gint idx, - gboolean motion); - -static void select_color (HildonColorSelector * selector, - int event_x, - int event_y, - gboolean motion); - -static gboolean color_moved (GtkWidget * widget, - GdkEventMotion * event, - gpointer data); - -static void -modify_button_clicked (GtkWidget * button, - HildonColorSelector * selector); - -static void modify_focused(HildonColorSelector * colselector); - -static void -hildon_color_selector_set_property(GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec); -static void -hildon_color_selector_get_property(GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec); - -GType -hildon_color_selector_get_type(void) -{ - static GType selector_type = 0; - - if (!selector_type) - { - static const GTypeInfo selector_info = - { - sizeof(HildonColorSelectorClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_color_selector_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonColorSelector), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_color_selector_init, - }; - - selector_type = g_type_register_static(GTK_TYPE_DIALOG, - "HildonColorSelector", - &selector_info, 0); - } - return selector_type; -} - -static void -hildon_color_selector_destroy(GtkObject *obj) -{ - HildonColorSelectorPriv *priv = HILDON_COLOR_SELECTOR(obj)->priv; - - if (priv->client) - { - gconf_client_notify_remove(priv->client, priv->notify_id); - g_object_unref(priv->client); - priv->client = NULL; - } - - GTK_OBJECT_CLASS(parent_class)->destroy(obj); -} - -static void -hildon_color_selector_class_init(HildonColorSelectorClass * selector_class) -{ - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(selector_class); - GObjectClass *gobject_class = G_OBJECT_CLASS (selector_class); - - parent_class = g_type_class_peek_parent(selector_class); - - widget_class->key_press_event = key_pressed; - - g_type_class_add_private(selector_class, - sizeof(HildonColorSelectorPriv)); - - GTK_OBJECT_CLASS(selector_class)->destroy = hildon_color_selector_destroy; - - gobject_class->get_property = hildon_color_selector_get_property; - gobject_class->set_property = hildon_color_selector_set_property; - - /** - * HildonColorSelector:color: - * - * The selected color. - */ - g_object_class_install_property (gobject_class, PROP_COLOR, - g_param_spec_boxed ("color", - "Current Color", - "The selected color", - GDK_TYPE_COLOR, - G_PARAM_READWRITE)); -} - - -/** - * hildon_color_selector_new: - * @parent: the parent window. The X window ID of the parent window - * has to be the same as the X window ID of the application - * - * Creates a new #HildonColorSelector dialog with 3x8 layout of - * base colors and 'OK', 'More..' and 'Cancel' buttons. - * - * Returns: new #HildonColorSelector - **/ -GtkWidget *hildon_color_selector_new(GtkWindow * parent) -{ - GtkWidget *dialog = g_object_new(HILDON_TYPE_COLOR_SELECTOR, NULL); - - g_return_val_if_fail(dialog, NULL); - - if (parent) - { - gtk_window_set_transient_for(GTK_WINDOW(dialog), parent); - } - - return dialog; -} - -static void -hildon_color_selector_set_custom_colors( - HildonColorSelector *selector, - GConfValue *value) -{ - GSList *list; - gint i; - - g_assert(HILDON_IS_COLOR_SELECTOR(selector)); - - /* We have to be really careful. At least gconftool's - stress test may generate unexpected value setups */ - if (value == NULL - || value->type != GCONF_VALUE_LIST - || gconf_value_get_list_type(value) != GCONF_VALUE_STRING) - list = NULL; - else - list = gconf_value_get_list(value); - - /* Use list to fill in the selector's color property */ - for ( i = 0; i < HILDON_CUSTOM_COLOR_NUM; ++i) - { - const gchar *color_string = NULL; - - if (list) { - color_string = gconf_value_get_string(list->data); - list = list->next; - } else { - color_string = "#FFFFFF"; - } - -/* g_print("custom_color: %s\n", color_string); */ - - selector->priv->color[i].pixel = 0; - gdk_color_parse (color_string, - &(selector->priv->color[HILDON_BASE_COLOR_NUM+i])); - } -} - -static void -gconf_notify_func(GConfClient *client, - guint cnxn_id, - GConfEntry *entry, - gpointer data) -{ - hildon_color_selector_set_custom_colors(HILDON_COLOR_SELECTOR(data), - gconf_entry_get_value(entry)); - gtk_widget_queue_draw(GTK_WIDGET(data)); -} - -static void -hildon_color_selector_init(HildonColorSelector * selector) -{ - guint i; - GtkWidget *hbox; - GConfValue *value; - - /* 16 standard Windows colors */ - const char base_colours[][HILDON_BASE_COLOR_NUM] = { - "#000000", "#FFFFFF", "#FF0000", "#660000", "#0000FF", "#000066", - "#FF33FF", "#660066", "#33CC33", "#006600", "#FFCC00", "#CC9900", - "#999999", "#666666", "#00CCCC", "#006666" - }; - - selector->priv = - G_TYPE_INSTANCE_GET_PRIVATE(selector, - HILDON_TYPE_COLOR_SELECTOR, - HildonColorSelectorPriv); - - /* ***********test GConf*********** */ - selector->priv->client = gconf_client_get_default (); - gconf_client_set_error_handling (selector->priv->client, - GCONF_CLIENT_HANDLE_UNRETURNED); - - /* Add our directory to the list of directories the GConfClient will - watch. */ - gconf_client_add_dir (selector->priv->client, HILDON_COLOR_GCONF_PATH, - GCONF_CLIENT_PRELOAD_NONE, - NULL); - - /* Use the value directed by GConfValue to set the color */ - value = gconf_client_get(selector->priv->client, - HILDON_COLOR_GCONF_KEYS, NULL); - - hildon_color_selector_set_custom_colors(selector, value); - - if (value) { - gconf_value_free(value); - } - - /* Listen to changes to our key. */ - selector->priv->notify_id = gconf_client_notify_add (selector->priv->client, - HILDON_COLOR_GCONF_KEYS, gconf_notify_func, selector, NULL, NULL); - - /* ************************************ */ - - selector->priv->selected_index = GREYIND; - selector->priv->focused_index = GREYIND; - - /* init base colors for color boxes */ - for (i = 0; i < HILDON_BASE_COLOR_NUM; ++i) - { - selector->priv->color[i].pixel = 0; - gdk_color_parse (base_colours[i], &(selector->priv->color[i])); - } - - gtk_dialog_set_has_separator(GTK_DIALOG(selector), FALSE); - - /* create drawing area */ - hbox = gtk_hbox_new(TRUE, 0); - selector->priv->drawing_area = gtk_drawing_area_new(); - - /* receive focus from dialog buttons */ - GTK_WIDGET_SET_FLAGS (selector->priv->drawing_area, GTK_CAN_FOCUS); - - gtk_widget_add_events (selector->priv->drawing_area, - GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK); - - /* Arrange size of the drawing area. */ - gtk_widget_set_size_request (selector->priv->drawing_area, - (HILDON_COLOR_SELECTOR_COLS * - HILDON_COLOR_SELECTOR_BOX_FULL_WIDTH), - (HILDON_COLOR_SELECTOR_ROWS * - HILDON_COLOR_SELECTOR_BOX_FULL_HEIGHT)); - - gtk_box_pack_start (GTK_BOX(GTK_DIALOG(selector)->vbox), - hbox, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX(hbox), selector->priv->drawing_area, - FALSE, FALSE, 0); - - /* Register callback functions for the drawing area */ - g_signal_connect (selector->priv->drawing_area, "expose_event", - G_CALLBACK(hildon_color_selector_expose), selector); - g_signal_connect (selector->priv->drawing_area, "button_press_event", - G_CALLBACK(color_pressed), selector); - g_signal_connect (selector->priv->drawing_area, "motion-notify-event", - G_CALLBACK(color_moved), selector); - - gtk_dialog_add_button (GTK_DIALOG(selector), - _("ecdg_bd_colour_selector_ok"), GTK_RESPONSE_OK); - - selector->priv->modify_button = - gtk_button_new_with_label(_("ecdg_bd_colour_selector_modify")); - gtk_widget_set_sensitive(selector->priv->modify_button, FALSE); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(selector)->action_area), - selector->priv->modify_button, FALSE, TRUE, 0); - - g_signal_connect(selector->priv->modify_button, "clicked", - G_CALLBACK(modify_button_clicked), selector); - - gtk_dialog_add_button (GTK_DIALOG(selector), - _("ecdg_bd_colour_selector_cancel"), - GTK_RESPONSE_CANCEL); - - gtk_dialog_set_default_response (GTK_DIALOG(selector), GTK_RESPONSE_OK); - - gtk_window_set_title ( GTK_WINDOW(selector), - _("ecdg_ti_colour_selector") ); - gtk_widget_show_all (GTK_DIALOG(selector)->vbox); -} - -static gboolean -hildon_color_selector_expose(GtkWidget * widget, - GdkEventExpose * event, - gpointer data) -{ - HildonColorSelector *selector; - GdkColor color; - GdkGC *gc, *gc_focus; - gint x, y, idx; - - g_return_val_if_fail (GTK_IS_WIDGET(widget), FALSE); - g_return_val_if_fail (event, FALSE); - g_return_val_if_fail (HILDON_IS_COLOR_SELECTOR(data), FALSE); - - if (!GTK_WIDGET_DRAWABLE(widget)) - return FALSE; - - selector = HILDON_COLOR_SELECTOR(data); - gc = gdk_gc_new (widget->window); - - gc_focus = gdk_gc_new(widget->window); - gdk_gc_set_line_attributes(gc_focus, FOCUS_BORDER_WIDTH, - GDK_LINE_SOLID, GDK_CAP_BUTT, - GDK_JOIN_MITER); - - /* draw the color boxes and a focus for one of them */ - for (y = 0, idx = 0; y < HILDON_COLOR_SELECTOR_ROWS; ++y) - { - for (x = 0; x < HILDON_COLOR_SELECTOR_COLS; ++x, ++idx) - { - gint xpos = x * HILDON_COLOR_SELECTOR_BOX_FULL_WIDTH; - gint ypos = y * HILDON_COLOR_SELECTOR_BOX_FULL_HEIGHT; - - /* frames on color box */ - gdk_draw_rectangle(widget->window, widget->style->black_gc, FALSE, - xpos + HILDON_COLOR_SELECTOR_PADDING_WIDTH, - ypos + HILDON_COLOR_SELECTOR_PADDING_WIDTH, - HILDON_COLOR_SELECTOR_BOX_W + - HILDON_COLOR_SELECTOR_PADDING_WIDTH, - HILDON_COLOR_SELECTOR_BOX_H + - HILDON_COLOR_SELECTOR_PADDING_WIDTH); - - /* color box */ - gdk_gc_set_rgb_fg_color(gc, &(selector->priv->color[idx])); - gdk_draw_rectangle(widget->window, gc, - TRUE, /* filled */ - xpos + HILDON_COLOR_SELECTOR_PADDING_WIDTH + - HILDON_COLOR_SELECTOR_BORDER_WIDTH, - ypos + HILDON_COLOR_SELECTOR_PADDING_WIDTH + - HILDON_COLOR_SELECTOR_BORDER_WIDTH, - HILDON_COLOR_SELECTOR_BOX_W, - HILDON_COLOR_SELECTOR_BOX_H); - - /* focus around the selected and focused color box */ - if (idx == selector->priv->selected_index) - { - /* selected color box */ - if (!gtk_style_lookup_logical_color(widget->style, - SELECTION_BORDER_COLOR_NAME, &color)) - { - /* set default color if color looking up fails */ - color.red = color.green = color.blue = 0; - } - - gdk_gc_set_rgb_fg_color(gc_focus, &color); - gdk_draw_rectangle(widget->window, gc_focus, FALSE, - xpos + 1-(FOCUS_BORDER_WIDTH % 2), - ypos + 1-(FOCUS_BORDER_WIDTH % 2), - HILDON_COLOR_SELECTOR_BOX_W + - HILDON_COLOR_SELECTOR_BORDER_WIDTH * 2 + - (FOCUS_BORDER_WIDTH % 2), - HILDON_COLOR_SELECTOR_BOX_H + - HILDON_COLOR_SELECTOR_BORDER_WIDTH * 2 + - (FOCUS_BORDER_WIDTH % 2)); - } - else if (idx == selector->priv->focused_index) - { - /* focused color box. - There's only zero or one so allocate GC in here. */ - gdk_color_parse(FOCUS_BORDER_COLOR, &color); - - gdk_gc_set_rgb_fg_color(gc_focus, &color); - gdk_draw_rectangle(widget->window, gc_focus, FALSE, - xpos + 1-(FOCUS_BORDER_WIDTH % 2), - ypos + 1-(FOCUS_BORDER_WIDTH % 2), - HILDON_COLOR_SELECTOR_BOX_W + - HILDON_COLOR_SELECTOR_BORDER_WIDTH * 2 + - (FOCUS_BORDER_WIDTH % 2), - HILDON_COLOR_SELECTOR_BOX_H + - HILDON_COLOR_SELECTOR_BORDER_WIDTH * 2 + - (FOCUS_BORDER_WIDTH % 2)); - } - } - } - - g_object_unref(gc); - g_object_unref(gc_focus); - return TRUE; -} - -/** - * hildon_color_selector_get_color: - * @selector: a #HildonColorSelector - * - * Returns: the currently selected #GdkColor. The returned pointer must - * not be freed. - */ -G_CONST_RETURN GdkColor *hildon_color_selector_get_color(HildonColorSelector * selector) -{ - g_return_val_if_fail(HILDON_IS_COLOR_SELECTOR(selector), NULL); - return &(selector->priv->color[selector->priv->selected_index]); -} - -/** - * hildon_color_selector_set_color: - * @selector: #HildonColorSelector - * @color: #Gdkcolor to set - * - * Selects the color specified. Does nothing if the color does not - * exist among the standard colors. - */ -void hildon_color_selector_set_color(HildonColorSelector * selector, - GdkColor * color) -{ - gint i; - - g_return_if_fail(HILDON_IS_COLOR_SELECTOR(selector)); - g_return_if_fail(color); - - /* Select the specified color */ - for (i = 0; - i < (HILDON_BASE_COLOR_NUM + HILDON_CUSTOM_COLOR_NUM); - ++i) - { - if (selector->priv->color[i].red == color->red && - selector->priv->color[i].green == color->green && - selector->priv->color[i].blue == color->blue) - { - selector->priv->selected_index = i; - selector->priv->focused_index = i; - - /* The modify button is active if the color index is bigger than - * the number of base colours. - */ - gtk_widget_set_sensitive(selector->priv->modify_button, - selector->priv->focused_index >= HILDON_BASE_COLOR_NUM); - gtk_widget_queue_draw(selector->priv->drawing_area); - break; - } - } - - /* Notify the color selector that the color has changed */ - g_object_notify (G_OBJECT (selector), "color"); -} - -static gboolean -color_pressed(GtkWidget * widget, GdkEventButton * event, - gpointer user_data) -{ - select_color(HILDON_COLOR_SELECTOR(user_data), event->x, event->y, FALSE); - return TRUE; -} - -/* Handle key press of right, left, up, down and return */ -static gboolean key_pressed(GtkWidget * widget, - GdkEventKey * event) -{ - HildonColorSelector *selector; - gint index; - - g_assert(widget); - - selector = HILDON_COLOR_SELECTOR(widget); - index = selector->priv->focused_index; - - /* if dialog buttons has the focus */ - if (GTK_WIDGET_HAS_FOCUS(selector->priv->drawing_area) == FALSE) - return GTK_WIDGET_CLASS(parent_class)->key_press_event(widget, event); - - /* Since wrapping is not allowed, - * move only if the next index is a valid one. - */ - switch (event->keyval) { - case GDK_KP_Right: - case GDK_Right: - if (index == (HILDON_BASE_COLOR_NUM + HILDON_CUSTOM_COLOR_NUM - 1) - || index == (HILDON_CUSTOM_COLOR_NUM - 1) - || index == (2*HILDON_CUSTOM_COLOR_NUM - 1)) - { - return TRUE; - } - index++; - break; - case GDK_KP_Left: - case GDK_Left: - if (index == 0 - || index == (HILDON_CUSTOM_COLOR_NUM) - || index == (2*HILDON_CUSTOM_COLOR_NUM)) - { - return TRUE; - } - index--; - break; - case GDK_KP_Up: - case GDK_Up: - if (index > (HILDON_COLOR_SELECTOR_COLS - 1)) - { - index -= HILDON_COLOR_SELECTOR_COLS; - } - else - { - return GTK_WIDGET_CLASS(parent_class)->key_press_event(widget, event); - } - break; - case GDK_KP_Down: - case GDK_Down: - if (index < (HILDON_COLOR_SELECTOR_COLS + HILDON_CUSTOM_COLOR_NUM)) - { - index += HILDON_COLOR_SELECTOR_COLS; - } - else - { - return GTK_WIDGET_CLASS(parent_class)->key_press_event(widget, event); - } - break; - case GDK_KP_Enter: - case GDK_Return: - if (index < HILDON_BASE_COLOR_NUM) - select_color_index(selector, selector->priv->focused_index, FALSE); - else - modify_focused(selector); - default: - return GTK_WIDGET_CLASS(parent_class)->key_press_event(widget, event); - } - - if (index < (HILDON_BASE_COLOR_NUM + HILDON_CUSTOM_COLOR_NUM)) - { - selector->priv->focused_index = index; - } - else - { - selector->priv->focused_index = - HILDON_BASE_COLOR_NUM + HILDON_CUSTOM_COLOR_NUM - 1; - } - /* The modify button is active if the color index is bigger than - * the number of base colours. - */ - gtk_widget_set_sensitive(selector->priv->modify_button, - selector->priv->focused_index >= HILDON_BASE_COLOR_NUM); - - gtk_widget_queue_draw(selector->priv->drawing_area); - - return TRUE; -} - -static void -select_color_index(HildonColorSelector * selector, gint idx, gboolean motion) -{ - /* If a custom colour is selected, open a popup to modify the colour */ - if (!motion && - selector->priv->focused_index >= HILDON_BASE_COLOR_NUM && - selector->priv->focused_index == idx) - modify_focused(selector); - - selector->priv->focused_index = selector->priv->selected_index = idx; - gtk_widget_set_sensitive(selector->priv->modify_button, - selector->priv->focused_index >= HILDON_BASE_COLOR_NUM); - - gtk_widget_queue_draw(selector->priv->drawing_area); -} - -static void -select_color(HildonColorSelector * selector, gint event_x, gint event_y, - gboolean motion) -{ - gint x, y; - - g_assert(HILDON_IS_COLOR_SELECTOR(selector)); - - /* Get the selection coordinates */ - x = event_x / HILDON_COLOR_SELECTOR_BOX_FULL_WIDTH; - y = event_y / HILDON_COLOR_SELECTOR_BOX_FULL_HEIGHT; - - /* Get the row and column numbers for the selected color */ - if (x > (HILDON_COLOR_SELECTOR_COLS + HILDON_CUSTOM_COLOR_NUM - 1)) - { - x = HILDON_COLOR_SELECTOR_COLS + HILDON_CUSTOM_COLOR_NUM - 1; - } - else if (x < 0) - { - x = 0; - } - if (y > (HILDON_COLOR_SELECTOR_ROWS - 1)) - { - y = HILDON_COLOR_SELECTOR_ROWS - 1; - } - else if (y < 0) - { - y = 0; - } - - select_color_index(selector, (x + y * HILDON_COLOR_SELECTOR_COLS), motion); -} - -static gboolean -color_moved(GtkWidget * widget, GdkEventMotion * event, gpointer data) -{ - if ( event->state & - (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK) ) - { - select_color(HILDON_COLOR_SELECTOR(data), event->x, event->y, TRUE); - return TRUE; - } - return FALSE; -} - -static void -modify_button_clicked(GtkWidget * button, HildonColorSelector * selector) -{ - modify_focused (selector); -} - -static void -modify_focused(HildonColorSelector * colselector) -{ - HildonColorPopup popupdata; - GtkWidget *popup; - - /* Create a HildonColorPopup dialog */ - popup = hildon_color_popup_new(GTK_WINDOW(colselector), - hildon_color_selector_get_color(colselector), &popupdata); - - if ( gtk_dialog_run(GTK_DIALOG(popup) ) == GTK_RESPONSE_OK) - { - GdkColor *color; - - /* We cannot modify a base color */ - if (colselector->priv->focused_index < HILDON_BASE_COLOR_NUM) - { - colselector->priv->color[HILDON_TOTAL_COLOR_NUM] = - colselector->priv->color[colselector->priv->focused_index]; - colselector->priv->focused_index = HILDON_TOTAL_COLOR_NUM; - } - - /* Update the focused color with the color selected in color popup */ - color = &(colselector->priv->color[colselector->priv->focused_index]); - hildon_color_popup_set_color_from_sliders(color, &popupdata); - - /* If we modified a base color we just accept the dialog */ - if( colselector->priv->focused_index >= HILDON_TOTAL_COLOR_NUM) - { - gtk_dialog_response(GTK_DIALOG(colselector), GTK_RESPONSE_OK); - } - else /* If we mofied custom colors we have to save to gconf */ - { - GConfValue *value; - GSList * list; - gint i; - - value = gconf_value_new(GCONF_VALUE_LIST); - gconf_value_set_list_type(value, GCONF_VALUE_STRING); - list = NULL; - - for ( i = HILDON_BASE_COLOR_NUM; i < HILDON_TOTAL_COLOR_NUM; i++) - { - GConfValue *item; - char buffer[32]; - - g_snprintf(buffer, sizeof(buffer), "#%.2X%.2X%.2X", - (colselector->priv->color[i].red>>8)&0xFF, - (colselector->priv->color[i].green>>8)&0xFF, - (colselector->priv->color[i].blue>>8)&0xFF ); - - item = gconf_value_new(GCONF_VALUE_STRING); - gconf_value_set_string(item, buffer); - list = g_slist_append (list, item); - } - - gconf_value_set_list_nocopy(value, list); - - /* gconf client handles the possible error */ - gconf_client_set(colselector->priv->client, - HILDON_COLOR_GCONF_KEYS, value, NULL); - - gconf_value_free(value); - } - } - - gtk_widget_destroy (popup); - gtk_window_present (GTK_WINDOW(colselector)); -} - -static void -hildon_color_selector_set_property(GObject *object, guint param_id, - const GValue *value, GParamSpec *pspec) -{ - HildonColorSelector *selector = HILDON_COLOR_SELECTOR(object); - - switch (param_id) - { - case PROP_COLOR: - hildon_color_selector_set_color(selector, (GdkColor*)g_value_get_boxed(value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); - break; - } -} - -static void -hildon_color_selector_get_property(GObject *object, guint param_id, - GValue *value, GParamSpec *pspec) -{ - HildonColorSelector *selector = HILDON_COLOR_SELECTOR(object); - - switch (param_id) - { - case PROP_COLOR: - g_value_set_boxed(value, (gconstpointer)hildon_color_selector_get_color(selector)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); - break; - } -} - diff --git a/hildon-widgets/hildon-color-selector.h b/hildon-widgets/hildon-color-selector.h deleted file mode 100644 index 1312c89..0000000 --- a/hildon-widgets/hildon-color-selector.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_COLOR_SELECTOR_H__ -#define __HILDON_COLOR_SELECTOR_H__ - -#include -#include -#include - -G_BEGIN_DECLS -#define HILDON_TYPE_COLOR_SELECTOR \ - ( hildon_color_selector_get_type() ) -#define HILDON_COLOR_SELECTOR(obj) \ - (GTK_CHECK_CAST (obj, HILDON_TYPE_COLOR_SELECTOR, HildonColorSelector)) -#define HILDON_COLOR_SELECTOR_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), HILDON_TYPE_COLOR_SELECTOR,\ - HildonColorSelectorClass)) -#define HILDON_IS_COLOR_SELECTOR(obj) \ - (GTK_CHECK_TYPE (obj, HILDON_TYPE_COLOR_SELECTOR)) -#define HILDON_IS_COLOR_SELECTOR_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), HILDON_COLOR_SELECTOR_CLASS)) - GType hildon_color_selector_get_type(void); - -typedef struct _HildonColorSelector HildonColorSelector; -typedef struct _HildonColorSelectorClass HildonColorSelectorClass; - -/** - * HildonColorSelectorPriv: - * - * Internal struct for color selector. - */ -typedef struct _HildonColorSelectorPriv HildonColorSelectorPriv; - -struct _HildonColorSelector { - GtkDialog parent; - HildonColorSelectorPriv *priv; -}; - -struct _HildonColorSelectorClass { - GtkDialogClass parent_class; -}; - -GType hildon_color_selector_get_type(void) G_GNUC_CONST; -GtkWidget *hildon_color_selector_new(GtkWindow * parent); -G_CONST_RETURN GdkColor *hildon_color_selector_get_color(HildonColorSelector * selector); -void hildon_color_selector_set_color(HildonColorSelector * selector, - GdkColor * color); - -G_END_DECLS -#endif /* __HILDON_COLOR_SELECTOR_H__ */ diff --git a/hildon-widgets/hildon-composite-widget.c b/hildon-widgets/hildon-composite-widget.c deleted file mode 100644 index ab90aaf..0000000 --- a/hildon-widgets/hildon-composite-widget.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include "hildon-composite-widget.h" -#include "hildon-date-editor.h" -#include "hildon-time-editor.h" - -/* This function is a private function of hildon-libs. It hadles focus - * changing for composite hildon widgets: HildonDateEditor, - * HildonNumberEditor, HildonTimeEditor, HildonWeekdayPicker. - * Its purpose is to focus the first widget (from left) inside the container - * regardless of where the focus is coming from. - */ -gboolean -hildon_composite_widget_focus (GtkWidget *widget, GtkDirectionType direction) -{ - GtkWidget *toplevel = NULL; - GtkWidget *focus_widget = NULL; - - /* Get the topmost parent widget */ - toplevel = gtk_widget_get_toplevel (widget); - if (!GTK_IS_WINDOW(toplevel)) - return GTK_WIDGET_CLASS (g_type_class_peek_parent ( - GTK_WIDGET_GET_CLASS (widget)))->focus (widget, direction); - /* Get focus widget in the topmost parent widget */ - focus_widget = GTK_WINDOW (toplevel)->focus_widget; - - if (!GTK_IS_WIDGET (focus_widget)) - return TRUE; - - if (!gtk_widget_is_ancestor (focus_widget, widget)) - { - gtk_widget_grab_focus (widget); - } - else - { - /* Containers grab_focus grabs the focus to the correct widget */ - switch (direction) { - case GTK_DIR_UP: - case GTK_DIR_DOWN: - if (HILDON_IS_DATE_EDITOR(widget) || HILDON_IS_TIME_EDITOR(widget)) - return FALSE; - else - return GTK_WIDGET_CLASS (g_type_class_peek_parent - (GTK_WIDGET_GET_CLASS(widget)))->focus (widget, direction); - break; - - default: - return GTK_WIDGET_CLASS (g_type_class_peek_parent - (GTK_WIDGET_GET_CLASS(widget)))->focus (widget, direction); - break; - } - } - - return TRUE; -} diff --git a/hildon-widgets/hildon-composite-widget.h b/hildon-widgets/hildon-composite-widget.h deleted file mode 100644 index 7a0993a..0000000 --- a/hildon-widgets/hildon-composite-widget.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/* - * @file - * - * Hildon composite widget includes all features which were not fitting into - * the any current class. A new, separate widget was not created because of the - * amount of current features is low. Need for this kind of class was not known - * when the building of the class hierarchy began. When a new feature is added, - * need for a new class should be re-considered. To make this decision one - * should really consider all the common features which are needed in the - * hildon composite widgets. Class position (for hildon-composite-widget) - * in the class hierarchy is between GtkContainer and any composite widget. - * - */ - -#ifndef __HILDON_COMPOSITE_WIDGET__ -#define __HILDON_COMPOSITE_WIDGET__ - - -G_BEGIN_DECLS - - -gboolean -hildon_composite_widget_focus( GtkWidget *widget, GtkDirectionType direction ); - - -G_END_DECLS - - -#endif /*__HILDON_COMPOSITE_WIDGET__*/ diff --git a/hildon-widgets/hildon-controlbar.c b/hildon-widgets/hildon-controlbar.c deleted file mode 100644 index 87e750d..0000000 --- a/hildon-widgets/hildon-controlbar.c +++ /dev/null @@ -1,799 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-controlbar - * @short_description: A widget that allows increasing or decreasing - * a value within a pre-defined range - * - * #HildonControlbar is a horizontally positioned range widget that is - * visually divided into blocks and supports setting a minimum and - * maximum value for the range. - */ - - -#include -#include -#include -#include -#include "hildon-controlbar.h" - -#include -#define _(string) dgettext(PACKAGE, string) - -#define HILDON_CONTROLBAR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ - HILDON_TYPE_CONTROLBAR, HildonControlbarPrivate)); - -#define DEFAULT_WIDTH 234 -#define DEFAULT_HEIGHT 30 -#define DEFAULT_BORDER_WIDTH 2 - -#define HILDON_CONTROLBAR_STEP_INCREMENT 1 -#define HILDON_CONTROLBAR_PAGE_INCREMENT 1 -#define HILDON_CONTROLBAR_PAGE_SIZE 0 -#define HILDON_CONTROLBAR_UPPER_VALUE 10 -#define HILDON_CONTROLBAR_LOWER_VALUE 0.0 -#define HILDON_CONTROLBAR_INITIAL_VALUE 0 - -static GtkScaleClass *parent_class; - -typedef struct _HildonControlbarPrivate HildonControlbarPrivate; - -enum -{ - PROP_MIN = 1, - PROP_MAX, - PROP_VALUE -}; - -enum -{ - END_REACHED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -static void -hildon_controlbar_class_init(HildonControlbarClass * controlbar_class); -static void hildon_controlbar_init(HildonControlbar * controlbar); -static GObject * -hildon_controlbar_constructor(GType type, guint n_construct_properties, - GObjectConstructParam *construct_properties); - -static gint hildon_controlbar_button_press_event(GtkWidget * widget, - GdkEventButton * event); -static gint hildon_controlbar_button_release_event(GtkWidget * widget, - GdkEventButton * event); -static gint -hildon_controlbar_expose_event(GtkWidget * widget, GdkEventExpose * event); -static void -hildon_controlbar_size_request(GtkWidget * self, GtkRequisition * req); -static void -hildon_controlbar_paint(HildonControlbar * self, GdkRectangle * area); -static gboolean -hildon_controlbar_keypress(GtkWidget * widget, GdkEventKey * event); - -static void hildon_controlbar_set_property( GObject *object, guint param_id, - const GValue *value, GParamSpec *pspec ); -static void hildon_controlbar_get_property( GObject *object, guint param_id, - GValue *value, GParamSpec *pspec ); - -static void -hildon_controlbar_value_changed( GtkAdjustment *adj, GtkRange *range ); - -/* - * Purpose of this function is to prevent Up and Down keys from - * changing the widget's value (like Left and Right). Instead they - * are used for changing focus to other widgtes. - */ -static gboolean -hildon_controlbar_change_value( GtkRange *range, GtkScrollType scroll, - gdouble new_value, gpointer data ); - -GType hildon_controlbar_get_type(void) -{ - static GType controlbar_type = 0; - - if (!controlbar_type) { - static const GTypeInfo controlbar_info = { - sizeof(HildonControlbarClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_controlbar_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonControlbar), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_controlbar_init, - }; - controlbar_type = g_type_register_static(GTK_TYPE_SCALE, - "HildonControlbar", - &controlbar_info, 0); - } - return controlbar_type; -} - -struct _HildonControlbarPrivate { - gboolean button_press; - gint old_value; -}; - -static void -hildon_controlbar_class_init(HildonControlbarClass * controlbar_class) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(controlbar_class); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(controlbar_class); - - parent_class = g_type_class_peek_parent(controlbar_class); - - g_type_class_add_private(controlbar_class, - sizeof(HildonControlbarPrivate)); - - gobject_class->get_property = hildon_controlbar_get_property; - gobject_class->set_property = hildon_controlbar_set_property; - widget_class->size_request = hildon_controlbar_size_request; - widget_class->button_press_event = hildon_controlbar_button_press_event; - widget_class->button_release_event = hildon_controlbar_button_release_event; - widget_class->expose_event = hildon_controlbar_expose_event; - widget_class->key_press_event = hildon_controlbar_keypress; - G_OBJECT_CLASS(controlbar_class)->constructor = hildon_controlbar_constructor; - controlbar_class->end_reached = NULL; - - /** - * HildonControlbar:min: - * - * Controlbar minimum value. - */ - g_object_class_install_property( gobject_class, PROP_MIN, - g_param_spec_int("min", - "Minimum value", - "Smallest possible value", - G_MININT, G_MAXINT, - HILDON_CONTROLBAR_LOWER_VALUE, - G_PARAM_READABLE | G_PARAM_WRITABLE) ); - - /** - * HildonControlbar:max: - * - * Controlbar maximum value. - */ - g_object_class_install_property( gobject_class, PROP_MAX, - g_param_spec_int("max", - "Maximum value", - "Greatest possible value", - G_MININT, G_MAXINT, - HILDON_CONTROLBAR_UPPER_VALUE, - G_PARAM_READABLE | G_PARAM_WRITABLE) ); - - /** - * HildonControlbar:value: - * - * Controlbar value. - */ - g_object_class_install_property( gobject_class, PROP_VALUE, - g_param_spec_int("value", - "Current value", - "Current value", - G_MININT, G_MAXINT, - HILDON_CONTROLBAR_INITIAL_VALUE, - G_PARAM_READABLE | G_PARAM_WRITABLE) ); - - - gtk_widget_class_install_style_property(widget_class, - g_param_spec_uint("inner_border_width", - "Inner border width", - "The border spacing between the controlbar border and controlbar blocks.", - 0, G_MAXINT, - DEFAULT_BORDER_WIDTH, - G_PARAM_READABLE)); - - signals[END_REACHED] = - g_signal_new("end-reached", - G_OBJECT_CLASS_TYPE(gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET(HildonControlbarClass, end_reached), - NULL, NULL, - g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, - G_TYPE_BOOLEAN); -} - -static void hildon_controlbar_init(HildonControlbar * controlbar) -{ - GtkRange *range; - HildonControlbarPrivate *priv; - - /* Initialize the private property */ - priv = HILDON_CONTROLBAR_GET_PRIVATE(controlbar); - priv->button_press = FALSE; - priv->old_value = 0; - range = GTK_RANGE(controlbar); - - range->has_stepper_a = TRUE; - range->has_stepper_d = TRUE; - range->round_digits = -1; - - gtk_widget_set_size_request( GTK_WIDGET(controlbar), DEFAULT_WIDTH, - DEFAULT_HEIGHT ); - g_signal_connect( range, "change-value", - G_CALLBACK(hildon_controlbar_change_value), NULL ); -} - -static GObject *hildon_controlbar_constructor(GType type, - guint n_construct_properties, GObjectConstructParam *construct_properties) -{ - GObject *obj; - GtkAdjustment *adj; - - obj = G_OBJECT_CLASS(parent_class)->constructor(type, - n_construct_properties, construct_properties); - - gtk_scale_set_draw_value (GTK_SCALE (obj), FALSE); - - /* Initialize the GtkAdjustment of the controlbar*/ - adj = GTK_RANGE(obj)->adjustment; - adj->step_increment = HILDON_CONTROLBAR_STEP_INCREMENT; - adj->page_increment = HILDON_CONTROLBAR_PAGE_INCREMENT; - adj->page_size = HILDON_CONTROLBAR_PAGE_SIZE; - - g_signal_connect( adj, "value-changed", - G_CALLBACK(hildon_controlbar_value_changed), obj ); - return obj; -} - -static void hildon_controlbar_set_property (GObject *object, guint param_id, - const GValue *value, GParamSpec *pspec) -{ - HildonControlbar *controlbar = HILDON_CONTROLBAR(object); - switch (param_id) - { - case PROP_MIN: - hildon_controlbar_set_min (controlbar, g_value_get_int(value)); - break; - - case PROP_MAX: - hildon_controlbar_set_max (controlbar, g_value_get_int(value)); - break; - - case PROP_VALUE: - hildon_controlbar_set_value (controlbar, g_value_get_int(value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); - break; - } -} - -static void hildon_controlbar_get_property( GObject *object, guint param_id, - GValue *value, GParamSpec *pspec ) -{ - HildonControlbar *controlbar = HILDON_CONTROLBAR(object); - switch (param_id) - { - case PROP_MIN: - g_value_set_int (value, hildon_controlbar_get_min (controlbar)); - break; - - case PROP_MAX: - g_value_set_int (value, hildon_controlbar_get_max (controlbar)); - break; - - case PROP_VALUE: - g_value_set_int (value, hildon_controlbar_get_value (controlbar)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); - break; - } -} - - -static void -hildon_controlbar_value_changed( GtkAdjustment *adj, GtkRange *range ) -{ - HildonControlbarPrivate *priv = HILDON_CONTROLBAR_GET_PRIVATE(range); - - /* Change the controlbar value if the adjusted value is large enough - * otherwise, keep the old value - */ - if( ABS(ceil(adj->value) - priv->old_value) >= 1 ) - { - priv->old_value = ceil(adj->value); - adj->value = priv->old_value; - } - else - g_signal_stop_emission_by_name( adj, "value-changed" ); - gtk_adjustment_set_value( adj, priv->old_value ); -} - -/** - * hildon_controlbar_new: - * - * Creates a new #HildonControlbar widget. - * - * Returns: a #GtkWidget pointer of newly created control bar - * widget - */ -GtkWidget *hildon_controlbar_new(void) -{ - return GTK_WIDGET(g_object_new(HILDON_TYPE_CONTROLBAR, NULL)); -} - -/* This function prevents Up and Down keys from changing the - * widget's value (like Left and Right). - * Instead they are used for changing focus to other widgtes. - */ -static gboolean -hildon_controlbar_keypress(GtkWidget * widget, GdkEventKey * event) -{ - if (event->keyval == GDK_Up || event->keyval == GDK_Down) - return FALSE; - return ((GTK_WIDGET_CLASS(parent_class)->key_press_event) (widget, event)); -} - -static void -hildon_controlbar_size_request(GtkWidget * self, GtkRequisition * req) -{ - if (GTK_WIDGET_CLASS(parent_class)->size_request) - GTK_WIDGET_CLASS(parent_class)->size_request(self, req); - - req->width = DEFAULT_WIDTH; - req->height = DEFAULT_HEIGHT; -} - -/** - * hildon_controlbar_set_value: - * @self: pointer to #HildonControlbar - * @value: value in range of >= 0 && < G_MAX_INT - * - * Change the current value of the control bar to the specified value. - */ -void hildon_controlbar_set_value(HildonControlbar * self, gint value) -{ - GtkAdjustment *adj; - g_return_if_fail (HILDON_IS_CONTROLBAR (self)); - adj = GTK_RANGE(self)->adjustment; - - g_return_if_fail(value >= 0); - - if (value >= adj->upper) - value = adj->upper; - else if (value <= adj->lower) - value = adj->lower; - - adj->value = value; - gtk_adjustment_value_changed(adj); - - g_object_notify (G_OBJECT(self), "value"); -} - -/** - * hildon_controlbar_get_value: - * @self: pointer to #HildonControlbar - * - * Returns: current value as gint - */ -gint hildon_controlbar_get_value(HildonControlbar * self) -{ - GtkAdjustment *adj; - g_return_val_if_fail (HILDON_IS_CONTROLBAR (self), 0); - adj = GTK_RANGE(self)->adjustment; - - return (gint) ceil(adj->value); -} - -/** - * hildon_controlbar_set_max: - * @self: pointer to #HildonControlbar - * @max: maximum value to set. The value needs to be greater than 0. - * - * Set the control bar's maximum to the given value. - * - * If the new maximum is smaller than current value, the value will be - * adjusted so that it equals the new maximum. - */ -void hildon_controlbar_set_max(HildonControlbar * self, gint max) -{ - GtkAdjustment *adj; - g_return_if_fail (HILDON_IS_CONTROLBAR (self)); - adj = GTK_RANGE(self)->adjustment; - - if (max < adj->lower) - max = adj->lower; - - if (adj->value > max) - hildon_controlbar_set_value (self, max); - - adj->upper = max; - gtk_adjustment_changed(adj); - - g_object_notify (G_OBJECT(self), "max"); -} - -/** - * hildon_controlbar_set_min: - * @self: pointer to #HildonControlbar - * @min: minimum value to set. The value needs to be greater than or - * equal to 0. - * - * Set the control bar's minimum to the given value. - * - * If the new minimum is smaller than current value, the value will be - * adjusted so that it equals the new minimum. - */ -void hildon_controlbar_set_min(HildonControlbar * self, gint min) -{ - GtkAdjustment *adj; - g_return_if_fail (HILDON_IS_CONTROLBAR (self)); - adj = GTK_RANGE(self)->adjustment; - - if (min > adj->upper) - min = adj->upper; - - if (adj->value < min) - hildon_controlbar_set_value (self, min); - - adj->lower = min; - gtk_adjustment_changed(adj); - g_object_notify (G_OBJECT(self), "min"); -} - -/** - * hildon_controlbar_set_range: - * @self: pointer to #HildonControlbar - * @max: maximum value to set. The value needs to be greater than 0. - * @min: Minimum value to set. The value needs to be greater than or - * equal to 0. - * - * Set the controlbars range to the given value - * - * If the new maximum is smaller than current value, the value will be - * adjusted so that it equals the new maximum. - * - * If the new minimum is smaller than current value, the value will be - * adjusted so that it equals the new minimum. - */ -void hildon_controlbar_set_range(HildonControlbar * self, gint min, - gint max) -{ - g_return_if_fail (HILDON_IS_CONTROLBAR (self)); - - if (min > max) - min = max; - /* We need to set max first here, because when min is set before - * max is set, it would end up 0, because max can't be bigger than 0. - */ - hildon_controlbar_set_max (self, max); - hildon_controlbar_set_min (self, min); -} - -/** - * hildon_controlbar_get_max: - * @self: a pointer to #HildonControlbar - * - * Returns: maximum value of control bar - */ -gint hildon_controlbar_get_max(HildonControlbar * self) -{ - GtkAdjustment *adj; - g_return_val_if_fail (HILDON_IS_CONTROLBAR (self), 0); - adj = GTK_RANGE(self)->adjustment; - - return (gint) adj->upper; -} - -/** - * hildon_controlbar_get_min: - * @self: a pointer to #HildonControlbar - * - * Returns: minimum value of controlbar - */ -gint hildon_controlbar_get_min(HildonControlbar * self) -{ - GtkAdjustment *adj = GTK_RANGE(self)->adjustment; - return (gint) adj->lower; -} - -/* - * Event handler for button press - * Need to change button1 to button2 before passing this event to - * parent handler. (see specs) - * Also updates button_press variable so that we can draw hilites - * correctly - */ -static gint hildon_controlbar_button_press_event(GtkWidget * widget, - GdkEventButton * event) -{ - HildonControlbar *self; - HildonControlbarPrivate *priv; - gboolean result = FALSE; - - g_return_val_if_fail(widget, FALSE); - g_return_val_if_fail(event, FALSE); - - self = HILDON_CONTROLBAR(widget); - priv = HILDON_CONTROLBAR_GET_PRIVATE(self); - - priv->button_press = TRUE; - event->button = event->button == 1 ? 2 : event->button; - - /* Ugh dirty hack. We manipulate the mouse event location to - compensate for centering the widget in case it is taller than the - default height. */ - if (widget->allocation.height > DEFAULT_HEIGHT) { - gint difference = widget->allocation.height - DEFAULT_HEIGHT; - - if (difference & 1) - difference += 1; - difference = difference / 2; - - event->y -= difference; - } - - - /* call the parent handler */ - if (GTK_WIDGET_CLASS(parent_class)->button_press_event) - result = - GTK_WIDGET_CLASS(parent_class)->button_press_event(widget, event); - - return result; -} - -/* - * Purpose of this function is to prevent Up and Down keys from - * changing the widget's value (like Left and Right). Instead they - * are used for changing focus to other widgtes. - */ -static gboolean -hildon_controlbar_change_value( GtkRange *range, - GtkScrollType scroll, - gdouble new_value, - gpointer data ) -{ - HildonControlbarPrivate *priv; - GtkAdjustment *adj = range->adjustment; - - priv = HILDON_CONTROLBAR_GET_PRIVATE(range); - - /* Emit a signal when upper or lower limit is reached */ - switch (scroll) - { - case GTK_SCROLL_STEP_FORWARD : - case GTK_SCROLL_PAGE_FORWARD : - if( adj->value == priv->old_value ) - if( adj->value == adj->upper ) - g_signal_emit( G_OBJECT(range), signals[END_REACHED], 0, TRUE ); - break; - - case GTK_SCROLL_STEP_BACKWARD : - case GTK_SCROLL_PAGE_BACKWARD : - if( adj->value == priv->old_value ) - if( adj->value == adj->lower ) - g_signal_emit( G_OBJECT(range), signals[END_REACHED], 0, FALSE ); - break; - - default: - break; - } -return FALSE; -} - -/* - * Event handler for button release - * Need to change button1 to button2 before passing this event to - * parent handler. (see specs) - * Also updates button_press variable so that we can draw hilites - * correctly - */ -static gint hildon_controlbar_button_release_event(GtkWidget * widget, - GdkEventButton * event) -{ - HildonControlbar *self; - HildonControlbarPrivate *priv; - gboolean result = FALSE; - - g_return_val_if_fail(widget, FALSE); - g_return_val_if_fail(event, FALSE); - - self = HILDON_CONTROLBAR(widget); - priv = HILDON_CONTROLBAR_GET_PRIVATE(self); - - priv->button_press = FALSE; - event->button = event->button == 1 ? 2 : event->button; - - /* call the parent handler */ - if (GTK_WIDGET_CLASS(parent_class)->button_release_event) - result = - GTK_WIDGET_CLASS(parent_class)->button_release_event(widget, event); - return result; -} - -/* - * Event handler for expose event - */ -static gint hildon_controlbar_expose_event(GtkWidget * widget, - GdkEventExpose * event) -{ - HildonControlbar *self = NULL; - - gboolean result = FALSE; - gint old_height = -1; - gint old_y = -1; - - g_return_val_if_fail(widget, FALSE); - g_return_val_if_fail(event, FALSE); - g_return_val_if_fail(HILDON_IS_CONTROLBAR(widget), FALSE); - - self = HILDON_CONTROLBAR(widget); - - old_height = widget->allocation.height; - old_y = widget->allocation.y; - - if (widget->allocation.height > DEFAULT_HEIGHT) { - int difference = widget->allocation.height - DEFAULT_HEIGHT; - - if (difference & 1) - difference += 1; - difference = difference / 2; - - widget->allocation.y += difference; - widget->allocation.height = DEFAULT_HEIGHT; - } - - /* call the parent handler */ - if (GTK_WIDGET_CLASS(parent_class)->expose_event) - result = GTK_WIDGET_CLASS(parent_class)->expose_event(widget, event); - hildon_controlbar_paint(self, &event->area); - - widget->allocation.height = old_height; - widget->allocation.y = old_y; - - return TRUE; -} - -/* - * Paint method. - * This is where all the work is actually done... - */ -static void hildon_controlbar_paint(HildonControlbar * self, - GdkRectangle * area) -{ - HildonControlbarPrivate *priv; - GtkWidget *widget = GTK_WIDGET(self); - GtkAdjustment *ctrlbar = GTK_RANGE(self)->adjustment; - gint x = widget->allocation.x; - gint y = widget->allocation.y; - gint h = widget->allocation.height; - gint w = widget->allocation.width; - gint max = 0; - gint stepper_size = 0; - gint stepper_spacing = 0; - gint inner_border_width = 0; - gint block_area = 0, block_width = 0, block_x = 0, block_max = 0, block_height,block_y; - /* Number of blocks on the controlbar */ - guint block_count = 0; - /* Number of displayed active blocks */ - guint block_act = 0; - /* Minimum no. of blocks visible */ - guint block_min = 0; - gint separatingpixels = 2; - gint block_remains = 0; - gint i, start_x, end_x, current_width; - GtkStateType state = GTK_STATE_NORMAL; - - g_return_if_fail(area); - - priv = HILDON_CONTROLBAR_GET_PRIVATE(self); - if (GTK_WIDGET_SENSITIVE(self) == FALSE) - state = GTK_STATE_INSENSITIVE; - - gtk_widget_style_get(GTK_WIDGET(self), - "stepper-size", &stepper_size, - "stepper-spacing", &stepper_spacing, - "inner_border_width", &inner_border_width, NULL); - g_object_get(G_OBJECT(self), "minimum_visible_bars", &block_min, NULL); - - block_area = (w - 2 * stepper_size - 2 * stepper_spacing - 2 * inner_border_width); - if (block_area <= 0) - return; - - block_max = ctrlbar->upper - ctrlbar->lower + block_min; - block_act = priv->old_value - GTK_RANGE(self)->adjustment->lower + block_min; - - /* We check border width and maximum value and adjust - * separating pixels for block width here. If the block size would - * become too small, we make the separators smaller. Graceful fallback. - */ - max = ctrlbar->upper; - if( ctrlbar->upper == 0 ) - { - separatingpixels = 3; - } - else if ((block_area - ((max - 1) * 3)) / max >= 4) { - separatingpixels = 3; - } else if ((block_area - ((max - 1) * 2)) / max >= 4) { - separatingpixels = 2; - } else if ((block_area - ((max - 1) * 1)) / max >= 4) { - separatingpixels = 1; - } else - separatingpixels = 0; - - if( block_max == 0 ) - { - /* If block max is 0 then we dim the whole control. */ - state = GTK_STATE_INSENSITIVE; - block_width = block_area; - block_remains = 0; - block_max = 1; - } - else - { - block_width = - (block_area - (separatingpixels * (block_max - 1))) / block_max; - block_remains = - (block_area - (separatingpixels * (block_max - 1))) % block_max; - } - - block_x = x + stepper_size + stepper_spacing + inner_border_width; - block_y = y + inner_border_width; - block_height = h - 2 * inner_border_width; - - block_count = ctrlbar->value - ctrlbar->lower + block_min; - - /* Without this there is vertical block corruption when block_height = - 1. This should work from 0 up to whatever */ - - if (block_height < 2) - block_height = 2; - - /* - * Changed the drawing of the blocks completely, - * because of "do-not-resize-when-changing-max"-specs. - * Now the code calculates from the block_remains when - * it should add one pixel to the block and when not. - */ - - for (i = 1; i <= block_max; i++) { - - /* Here we calculate whether we add one pixel to current_width or - not. */ - start_x = block_width * (i - 1) + ((i - 1) * block_remains) / block_max; - end_x = block_width * i + (i * block_remains) / block_max; - current_width = end_x - start_x; - - gtk_paint_box(widget->style, widget->window, state, - (i <= block_count) ? GTK_SHADOW_IN : GTK_SHADOW_OUT, - NULL, widget, "hildon_block", - block_x, block_y, current_width, - block_height); - - /* We keep the block_x separate because of the - 'separatingpixels' */ - block_x += current_width + separatingpixels; - } - -} diff --git a/hildon-widgets/hildon-controlbar.h b/hildon-widgets/hildon-controlbar.h deleted file mode 100644 index 65c41ee..0000000 --- a/hildon-widgets/hildon-controlbar.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_CONTROLBAR_H__ -#define __HILDON_CONTROLBAR_H__ - -#include - -G_BEGIN_DECLS -#define HILDON_TYPE_CONTROLBAR ( hildon_controlbar_get_type() ) -#define HILDON_CONTROLBAR(obj) (GTK_CHECK_CAST (obj,\ - HILDON_TYPE_CONTROLBAR, HildonControlbar)) -#define HILDON_CONTROLBAR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass),\ - HILDON_TYPE_CONTROLBAR, HildonControlbarClass)) -#define HILDON_IS_CONTROLBAR(obj) \ - (GTK_CHECK_TYPE (obj, HILDON_TYPE_CONTROLBAR)) -#define HILDON_IS_CONTROLBAR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass),\ - HILDON_TYPE_CONTROLBAR)) - -/** - * HildonControlbar: - * - * Contains gboolean variable named 'button_press' whether a button - * has been pressed. - */ -typedef struct _HildonControlbar HildonControlbar; -typedef struct _HildonControlbarClass HildonControlbarClass; - -struct _HildonControlbar { - GtkScale scale; -}; - -struct _HildonControlbarClass { - GtkScaleClass parent_class; - void (*end_reached) (HildonControlbar *controlbar, gboolean end); -}; - -GType hildon_controlbar_get_type(void); -GtkWidget *hildon_controlbar_new(void); -void hildon_controlbar_set_value(HildonControlbar * self, gint value); -gint hildon_controlbar_get_value(HildonControlbar * self); -gint hildon_controlbar_get_max(HildonControlbar * self); -gint hildon_controlbar_get_min(HildonControlbar * self); -void hildon_controlbar_set_max(HildonControlbar * self, gint max); -void hildon_controlbar_set_min(HildonControlbar * self, gint min); -void hildon_controlbar_set_range(HildonControlbar * self, gint min, - gint max); - -G_END_DECLS -#endif /* __HILDON_CONTROLBAR_H__ */ diff --git a/hildon-widgets/hildon-date-editor.c b/hildon-widgets/hildon-date-editor.c deleted file mode 100644 index ad9ed62..0000000 --- a/hildon-widgets/hildon-date-editor.c +++ /dev/null @@ -1,1445 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-date-editor - * @short_description: A widget which queries a date from user or opens - * a HildonCalendarPopup - * @see_also: #HildonCalendarPopup, #HildonTimeEditor - * - * HildonDateEditor is a widget with three entry fields (day, month, - * year) and an icon (button): clicking on the icon opens up a - * HildonCalendarPopup. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include "hildon-composite-widget.h" -#include "hildon-marshalers.h" -#include "hildon-libs-enum-types.h" - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#define _(string) dgettext(PACKAGE, string) - -#define ENTRY_BORDERS 11 -#define DATE_EDITOR_HEIGHT 30 - -#define DAY_ENTRY_WIDTH 2 -#define MONTH_ENTRY_WIDTH 2 -#define YEAR_ENTRY_WIDTH 4 - -#define DEFAULT_MIN_YEAR 1970 -#define DEFAULT_MAX_YEAR 2037 - -#define HILDON_DATE_EDITOR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE((obj),\ - HILDON_TYPE_DATE_EDITOR, HildonDateEditorPrivate)); - -static GtkContainerClass *parent_class; - -typedef struct _HildonDateEditorPrivate HildonDateEditorPrivate; - -static void -hildon_date_editor_class_init(HildonDateEditorClass * editor_class); - -static void hildon_date_editor_init(HildonDateEditor * editor); - -static gboolean -hildon_date_editor_icon_press(GtkWidget * widget, - gpointer data); - -static gboolean -hildon_date_editor_released(GtkWidget * widget, - gpointer data); - -static gboolean -hildon_date_editor_keypress(GtkWidget * widget, GdkEventKey * event, - gpointer data); - -static gboolean -hildon_date_editor_keyrelease(GtkWidget * widget, GdkEventKey * event, - gpointer data); -static gboolean -hildon_date_editor_clicked(GtkWidget * widget, gpointer data); -static gint -hildon_date_editor_entry_validate(GtkWidget *widget, gpointer data); - -static void -hildon_date_editor_entry_changed(GtkEditable *widget, gpointer data); - -static gboolean -hildon_date_editor_entry_focus_out(GtkWidget * widget, GdkEventFocus * event, - gpointer data); - -static gboolean hildon_date_editor_date_error(HildonDateEditor *editor, - HildonDateEditorErrorType type); - -static gboolean hildon_date_editor_entry_focusin(GtkWidget * widget, - GdkEventFocus * event, - gpointer data); -static void hildon_date_editor_get_property( GObject *object, guint param_id, - GValue *value, GParamSpec *pspec ); -static void hildon_date_editor_set_property (GObject *object, guint param_id, - const GValue *value, GParamSpec *pspec); -static void -hildon_child_forall(GtkContainer * container, - gboolean include_internals, - GtkCallback callback, gpointer callback_data); - -static void hildon_date_editor_destroy(GtkObject * self); - -static void -hildon_date_editor_size_allocate(GtkWidget * widget, - GtkAllocation * allocation); - -static void -hildon_date_editor_size_request(GtkWidget * widget, - GtkRequisition * requisition); - -static gboolean -_hildon_date_editor_entry_select_all(GtkWidget *widget); - -/* Property indices */ -enum -{ - PROP_DAY = 1, - PROP_MONTH, - PROP_YEAR, - PROP_MIN_YEAR, - PROP_MAX_YEAR -}; - -struct _HildonDateEditorPrivate { - /* Cache of values in the entries, used in setting only parts of the date */ - guint year; /* current year in the entry */ - guint month; /* current month in the entry */ - guint day; /* current day in the entry */ - - gboolean calendar_icon_pressed; - - GtkWidget *frame; /* borders around the date */ - GtkWidget *d_button_image; /* icon */ - GtkWidget *d_box_date; /* hbox for date */ - - GtkWidget *d_entry; /* GtkEntry for day */ - GtkWidget *m_entry; /* GtkEntry for month */ - GtkWidget *y_entry; /* GtkEntry for year */ - - GList *delims; /* List of delimeters between the fields (and possible at the ends) */ - GtkWidget *calendar_icon; - - gboolean skip_validation; /* don't validate date at all */ - - gint min_year; /* minimum year allowed */ - gint max_year; /* maximum year allowed */ -}; - -enum { - DATE_ERROR, - LAST_SIGNAL -}; - -static guint date_editor_signals[LAST_SIGNAL] = { 0 }; - -GType hildon_date_editor_get_type(void) -{ - static GType editor_type = 0; - - if (!editor_type) { - static const GTypeInfo editor_info = { - sizeof(HildonDateEditorClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_date_editor_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonDateEditor), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_date_editor_init, - }; - editor_type = g_type_register_static(GTK_TYPE_CONTAINER, - "HildonDateEditor", - &editor_info, 0); - } - return editor_type; -} - -static void -hildon_date_editor_class_init(HildonDateEditorClass * editor_class) -{ - GtkContainerClass *container_class = GTK_CONTAINER_CLASS(editor_class); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(editor_class); - GObjectClass *gobject_class = G_OBJECT_CLASS (editor_class); - - parent_class = g_type_class_peek_parent(editor_class); - - g_type_class_add_private(editor_class, - sizeof(HildonDateEditorPrivate)); - - gobject_class->set_property = hildon_date_editor_set_property; - gobject_class->get_property = hildon_date_editor_get_property; - widget_class->size_request = hildon_date_editor_size_request; - widget_class->size_allocate = hildon_date_editor_size_allocate; - widget_class->focus = hildon_composite_widget_focus; - - container_class->forall = hildon_child_forall; - GTK_OBJECT_CLASS(editor_class)->destroy = hildon_date_editor_destroy; - - editor_class->date_error = hildon_date_editor_date_error; - - date_editor_signals[DATE_ERROR] = - g_signal_new("date-error", - G_OBJECT_CLASS_TYPE(gobject_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET(HildonDateEditorClass, date_error), - g_signal_accumulator_true_handled, NULL, - _hildon_marshal_BOOLEAN__ENUM, - G_TYPE_BOOLEAN, 1, HILDON_TYPE_DATE_EDITOR_ERROR_TYPE); - - /** - * HildonDateEditor:year: - * - * Current year. - */ - g_object_class_install_property( gobject_class, PROP_YEAR, - g_param_spec_uint("year", - "Current year", - "Current year", - 1, 2100, - 2005, - G_PARAM_READABLE | G_PARAM_WRITABLE) ); - - /** - * HildonDateEditor:month: - * - * Current month. - */ - g_object_class_install_property( gobject_class, PROP_MONTH, - g_param_spec_uint("month", - "Current month", - "Current month", - 1, 12, - 1, - G_PARAM_READABLE | G_PARAM_WRITABLE) ); - - /** - * HildonDateEditor:day: - * - * Current day. - */ - g_object_class_install_property( gobject_class, PROP_DAY, - g_param_spec_uint("day", - "Current day", - "Current day", - 1, 31, - 1, - G_PARAM_READABLE | G_PARAM_WRITABLE) ); - - /** - * HildonDateEditor:min-year: - * - * Minimum valid year. - */ - g_object_class_install_property( gobject_class, PROP_MIN_YEAR, - g_param_spec_uint("min-year", - "Minimum valid year", - "Minimum valid year", - 1, 2100, - DEFAULT_MIN_YEAR, - G_PARAM_READWRITE) ); - - /** - * HildonDateEditor:max-year: - * - * Maximum valid year. - */ - g_object_class_install_property( gobject_class, PROP_MAX_YEAR, - g_param_spec_uint("max-year", - "Maximum valid year", - "Maximum valid year", - 1, 2100, - DEFAULT_MAX_YEAR, - G_PARAM_READWRITE) ); -} - -/* Forces setting of the icon to certain state. Used initially - and from the actual setter function */ -static void -real_set_calendar_icon_state(HildonDateEditorPrivate *priv, - gboolean pressed) -{ - gtk_image_set_from_icon_name(GTK_IMAGE(priv->calendar_icon), - pressed ? "qgn_widg_datedit_pr" : "qgn_widg_datedit", - HILDON_ICON_SIZE_WIDG); - - priv->calendar_icon_pressed = pressed; -} - -/* Sets the icon to given state (normal/pressed). Returns - info if the state actually changed. */ -static gboolean -hildon_date_editor_set_calendar_icon_state(HildonDateEditor *editor, - gboolean pressed) -{ - HildonDateEditorPrivate *priv; - - g_assert(HILDON_IS_DATE_EDITOR(editor)); - - priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); - if (pressed != priv->calendar_icon_pressed) { - real_set_calendar_icon_state(priv, pressed); - return TRUE; - } - - return FALSE; -} - -/* Packing day, month and year entries depend on locale settings - We find out the order and all separators by converting a known - date to default format and inspecting the result string */ -static void apply_locale_field_order(HildonDateEditorPrivate *priv) -{ - GDate locale_test_date; - GtkWidget *delim; - gchar buffer[256]; - gchar *iter, *delim_text; - - g_date_set_dmy(&locale_test_date, 1, 2, 1970); - (void) g_date_strftime(buffer, sizeof(buffer), "%x", &locale_test_date); - iter = buffer; - - while (*iter) - { - gchar *endp; - unsigned long value; - - /* Try to convert the current location into number. */ - value = strtoul(iter, &endp, 10); - - /* If the conversion didn't progress or the detected value was - unknown (we used a fixed date, you remember), we treat - current position as a literal */ - switch (value) - { - case 1: - gtk_box_pack_start(GTK_BOX(priv->d_box_date), - priv->d_entry, FALSE, FALSE, 0); - break; - case 2: - gtk_box_pack_start(GTK_BOX(priv->d_box_date), - priv->m_entry, FALSE, FALSE, 0); - break; - case 70: /* %x format uses only 2 numbers for some locales */ - case 1970: - gtk_box_pack_start(GTK_BOX(priv->d_box_date), - priv->y_entry, FALSE, FALSE, 0); - break; - default: - /* All non-number characters starting from current position - form the delimeter */ - for (endp = iter; *endp; endp++) - if (g_ascii_isdigit(*endp)) - break; - - /* Now endp points one place past the delimeter text */ - delim_text = g_strndup(iter, endp - iter); - delim = gtk_label_new(delim_text); - gtk_box_pack_start(GTK_BOX(priv->d_box_date), - delim, FALSE, FALSE, 0); - priv->delims = g_list_append(priv->delims, delim); - g_free(delim_text); - - break; - }; - - iter = endp; - } -} - -static void hildon_date_editor_init(HildonDateEditor * editor) -{ - HildonDateEditorPrivate *priv; - GDate cur_date; - - priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); - - GTK_WIDGET_SET_FLAGS(GTK_WIDGET(editor), GTK_NO_WINDOW); - - gtk_widget_push_composite_child(); - - /* initialize values */ - g_date_clear(&cur_date, 1); - g_date_set_time(&cur_date, time(NULL)); - - priv->day = g_date_get_day(&cur_date); - priv->month = g_date_get_month(&cur_date); - priv->year = g_date_get_year(&cur_date); - priv->min_year = DEFAULT_MIN_YEAR; - priv->max_year = DEFAULT_MAX_YEAR; - - /* make widgets */ - priv->frame = gtk_frame_new(NULL); - gtk_container_set_border_width(GTK_CONTAINER(priv->frame), 0); - - priv->d_entry = gtk_entry_new(); - priv->m_entry = gtk_entry_new(); - priv->y_entry = gtk_entry_new(); - - g_object_set (G_OBJECT(priv->d_entry), "input-mode", - HILDON_INPUT_MODE_HINT_NUMERIC, NULL); - g_object_set (G_OBJECT(priv->m_entry), "input-mode", - HILDON_INPUT_MODE_HINT_NUMERIC, NULL); - g_object_set (G_OBJECT(priv->y_entry), "input-mode", - HILDON_INPUT_MODE_HINT_NUMERIC, NULL); - - /* set entry look */ - gtk_entry_set_width_chars(GTK_ENTRY(priv->d_entry), DAY_ENTRY_WIDTH); - gtk_entry_set_width_chars(GTK_ENTRY(priv->m_entry), MONTH_ENTRY_WIDTH); - gtk_entry_set_width_chars(GTK_ENTRY(priv->y_entry), YEAR_ENTRY_WIDTH); - - gtk_entry_set_max_length(GTK_ENTRY(priv->d_entry), DAY_ENTRY_WIDTH); - gtk_entry_set_max_length(GTK_ENTRY(priv->m_entry), MONTH_ENTRY_WIDTH); - gtk_entry_set_max_length(GTK_ENTRY(priv->y_entry), YEAR_ENTRY_WIDTH); - - gtk_entry_set_has_frame(GTK_ENTRY(priv->d_entry), FALSE); - gtk_entry_set_has_frame(GTK_ENTRY(priv->m_entry), FALSE); - gtk_entry_set_has_frame(GTK_ENTRY(priv->y_entry), FALSE); - - gtk_widget_set_composite_name(priv->d_entry, "day_entry"); - gtk_widget_set_composite_name(priv->m_entry, "month_entry"); - gtk_widget_set_composite_name(priv->y_entry, "year_entry"); - - priv->d_box_date = gtk_hbox_new(FALSE, 0); - - priv->d_button_image = gtk_button_new(); - priv->calendar_icon = gtk_image_new(); - real_set_calendar_icon_state(priv, FALSE); - GTK_WIDGET_UNSET_FLAGS(priv->d_button_image, GTK_CAN_FOCUS | GTK_CAN_DEFAULT); - - apply_locale_field_order(priv); - - gtk_container_add(GTK_CONTAINER(priv->frame), priv->d_box_date); - gtk_container_add(GTK_CONTAINER(priv->d_button_image), priv->calendar_icon); - gtk_button_set_relief(GTK_BUTTON(priv->d_button_image), GTK_RELIEF_NONE); - gtk_button_set_focus_on_click(GTK_BUTTON(priv->d_button_image), FALSE); - - gtk_widget_set_parent(priv->frame, GTK_WIDGET(editor)); - gtk_widget_set_parent(priv->d_button_image, GTK_WIDGET(editor)); - gtk_widget_show_all(priv->frame); - gtk_widget_show_all(priv->d_button_image); - - /* image button signal connects */ - g_signal_connect(GTK_OBJECT(priv->d_button_image), "pressed", - G_CALLBACK(hildon_date_editor_icon_press), editor); - g_signal_connect(GTK_OBJECT(priv->d_button_image), "released", - G_CALLBACK(hildon_date_editor_released), editor); - g_signal_connect(GTK_OBJECT(priv->d_button_image), "clicked", - G_CALLBACK(hildon_date_editor_clicked), editor); - g_signal_connect(GTK_OBJECT(priv->d_button_image), "key_press_event", - G_CALLBACK(hildon_date_editor_keypress), editor); - - /* entry signal connects */ - g_signal_connect(GTK_OBJECT(priv->d_entry), "focus-in-event", - G_CALLBACK(hildon_date_editor_entry_focusin), editor); - - g_signal_connect(GTK_OBJECT(priv->m_entry), "focus-in-event", - G_CALLBACK(hildon_date_editor_entry_focusin), editor); - - g_signal_connect(GTK_OBJECT(priv->y_entry), "focus-in-event", - G_CALLBACK(hildon_date_editor_entry_focusin), editor); - - g_signal_connect(GTK_OBJECT(priv->d_entry), "focus-out-event", - G_CALLBACK(hildon_date_editor_entry_focus_out), editor); - - g_signal_connect(GTK_OBJECT(priv->m_entry), "focus-out-event", - G_CALLBACK(hildon_date_editor_entry_focus_out), editor); - - g_signal_connect(GTK_OBJECT(priv->y_entry), "focus-out-event", - G_CALLBACK(hildon_date_editor_entry_focus_out), editor); - - g_signal_connect(GTK_OBJECT(priv->d_entry), "key-press-event", - G_CALLBACK(hildon_date_editor_keypress), editor); - - g_signal_connect(GTK_OBJECT(priv->m_entry), "key-press-event", - G_CALLBACK(hildon_date_editor_keypress), editor); - - g_signal_connect(GTK_OBJECT(priv->y_entry), "key-press-event", - G_CALLBACK(hildon_date_editor_keypress), editor); - - g_signal_connect(GTK_OBJECT(priv->d_entry), "key-release-event", - G_CALLBACK(hildon_date_editor_keyrelease), editor); - - g_signal_connect(GTK_OBJECT(priv->m_entry), "key-release-event", - G_CALLBACK(hildon_date_editor_keyrelease), editor); - - g_signal_connect(GTK_OBJECT(priv->y_entry), "key-release-event", - G_CALLBACK(hildon_date_editor_keyrelease), editor); - - hildon_date_editor_set_date(editor, priv->year, priv->month, priv->day); - - g_signal_connect(GTK_OBJECT(priv->d_entry), "changed", - G_CALLBACK(hildon_date_editor_entry_changed), editor); - - g_signal_connect(GTK_OBJECT(priv->m_entry), "changed", - G_CALLBACK(hildon_date_editor_entry_changed), editor); - - g_signal_connect(GTK_OBJECT(priv->y_entry), "changed", - G_CALLBACK(hildon_date_editor_entry_changed), editor); - - gtk_widget_pop_composite_child(); -} - -static void hildon_date_editor_set_property (GObject *object, guint param_id, - const GValue *value, GParamSpec *pspec) -{ - HildonDateEditor *editor = HILDON_DATE_EDITOR(object); - HildonDateEditorPrivate *priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); - gint val; - - switch (param_id) - { - case PROP_YEAR: - hildon_date_editor_set_year (editor, g_value_get_uint(value)); - break; - - case PROP_MONTH: - hildon_date_editor_set_month (editor, g_value_get_uint(value)); - break; - - case PROP_DAY: - hildon_date_editor_set_day (editor, g_value_get_uint(value)); - break; - - case PROP_MIN_YEAR: - val = g_value_get_uint(value); - if (val <= priv->max_year) - { - priv->min_year = val; - /* Clamp current year */ - if (hildon_date_editor_get_year (editor) < priv->min_year) - hildon_date_editor_set_year (editor, priv->min_year); - } - else - g_warning("min-year cannot be greater than max-year"); - break; - - case PROP_MAX_YEAR: - val = g_value_get_uint(value); - if (val >= priv->min_year) - { - priv->max_year = val; - /* Clamp current year */ - if (hildon_date_editor_get_year (editor) > priv->max_year) - hildon_date_editor_set_year (editor, priv->max_year); - } - else - g_warning("max-year cannot be less than min-year"); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); - break; - } -} - -static void hildon_date_editor_get_property( GObject *object, guint param_id, - GValue *value, GParamSpec *pspec ) -{ - HildonDateEditor *editor = HILDON_DATE_EDITOR(object); - HildonDateEditorPrivate *priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); - - switch (param_id) - { - case PROP_YEAR: - g_value_set_uint (value, hildon_date_editor_get_year (editor)); - break; - - case PROP_MONTH: - g_value_set_uint (value, hildon_date_editor_get_month (editor)); - break; - - case PROP_DAY: - g_value_set_uint (value, hildon_date_editor_get_day (editor)); - break; - - case PROP_MIN_YEAR: - g_value_set_uint (value, priv->min_year); - break; - - case PROP_MAX_YEAR: - g_value_set_uint (value, priv->max_year); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); - break; - } -} - -static void hildon_child_forall(GtkContainer * container, - gboolean include_internals, - GtkCallback callback, - gpointer callback_data) -{ - HildonDateEditor *editor; - HildonDateEditorPrivate *priv; - - g_assert(HILDON_IS_DATE_EDITOR(container)); - g_assert(callback); - - editor = HILDON_DATE_EDITOR(container); - priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); - - if (include_internals) { - (*callback) (priv->frame, callback_data); - (*callback) (priv->d_button_image, callback_data); - } -} - -static void hildon_date_editor_destroy(GtkObject * self) -{ - HildonDateEditorPrivate *priv; - - priv = HILDON_DATE_EDITOR_GET_PRIVATE(self); - - if (priv->frame) { - gtk_widget_unparent(priv->frame); - priv->frame = NULL; - } - if (priv->d_button_image) { - gtk_widget_unparent(priv->d_button_image); - priv->d_button_image = NULL; - } - if (priv->delims) { - g_list_free(priv->delims); - priv->delims = NULL; - } - - if (GTK_OBJECT_CLASS(parent_class)->destroy) - GTK_OBJECT_CLASS(parent_class)->destroy(self); -} - -/** - * hildon_date_editor_new: - * - * Creates a new date editor. The current system date - * is shown in the editor. - * - * Returns: pointer to a new @HildonDateEditor widget. - */ -GtkWidget *hildon_date_editor_new(void) -{ - return GTK_WIDGET(g_object_new(HILDON_TYPE_DATE_EDITOR, NULL)); -} - -/** - * hildon_date_editor_set_date: - * @date: the @HildonDateEditor widget - * @year: year - * @month: month - * @day: day - * - * Sets the date shown in the editor. - */ -void hildon_date_editor_set_date(HildonDateEditor * editor, - guint year, guint month, guint day) -{ - HildonDateEditorPrivate *priv; - - g_return_if_fail(HILDON_IS_DATE_EDITOR(editor)); - - /* This function cannot be implemented by calling - component setters, since applying the individual - values one by one can make the date temporarily - invalid (depending on what the previous values were), - which in turn causes that the desired date - is not set (even though it's valid). We must set all the - components at one go and not try to do any validation etc - there in between. */ - - g_return_if_fail(HILDON_IS_DATE_EDITOR(editor)); - priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); - - if (g_date_valid_dmy(day, month, year)) - { - GDate date; - gchar buffer[256]; - - priv->year = year; - priv->month = month; - priv->day = day; - - g_date_set_dmy(&date, day, month, year); - - /* We apply the new values, but do not want automatic focus move - etc to take place */ - g_snprintf(buffer, sizeof(buffer), "%04d", year); - g_signal_handlers_block_by_func(priv->y_entry, - (gpointer) hildon_date_editor_entry_changed, editor); - gtk_entry_set_text(GTK_ENTRY(priv->y_entry), buffer); - g_signal_handlers_unblock_by_func(priv->y_entry, - (gpointer) hildon_date_editor_entry_changed, editor); - - g_date_strftime(buffer, sizeof(buffer), "%m", &date); - g_signal_handlers_block_by_func(priv->m_entry, - (gpointer) hildon_date_editor_entry_changed, editor); - gtk_entry_set_text(GTK_ENTRY(priv->m_entry), buffer); - g_signal_handlers_unblock_by_func(priv->m_entry, - (gpointer) hildon_date_editor_entry_changed, editor); - - g_date_strftime(buffer, sizeof(buffer), "%d", &date); - g_signal_handlers_block_by_func(priv->d_entry, - (gpointer) hildon_date_editor_entry_changed, editor); - gtk_entry_set_text(GTK_ENTRY(priv->d_entry), buffer); - g_signal_handlers_unblock_by_func(priv->d_entry, - (gpointer) hildon_date_editor_entry_changed, editor); - - g_object_notify(G_OBJECT(editor), "year"); - g_object_notify(G_OBJECT(editor), "month"); - g_object_notify(G_OBJECT(editor), "day"); - } -} - -/** - * hildon_date_editor_get_date: - * @date: the @HildonDateEditor widget - * @year: year - * @month: month - * @day: day - * - * Returns: the year, month, and day currently on the - * date editor. - */ -void hildon_date_editor_get_date(HildonDateEditor * date, - guint * year, guint * month, guint * day) -{ - HildonDateEditorPrivate *priv; - - g_return_if_fail(HILDON_IS_DATE_EDITOR(date)); - g_return_if_fail(year); - g_return_if_fail(month); - g_return_if_fail(day); - - priv = HILDON_DATE_EDITOR_GET_PRIVATE(date); - - /* FIXME: The role of priv->{day,month,year} members vs. entry contents - is unclear. They do not neccesarily match and still the texts are - used as return values and members for some internal validation!! - At least a partly reason is to allow empty text to become - 0 return value, while members are restricted to valid ranges?! - However, if we change the current way, we are likely to break - some applications if they rely on some specific way how this - widget currently handles empty values and temporarily invalid values. - - The key issue is this: What should the _get methods return while - user is editing a field and the result is incomplete. The - partial result? The last good result? If we return partial result - we also need a way to inform if the date is not valid. Current - implementation is some kind of hybrid of these two... - - for example: - hildon_date_editor_set_day(editor, hildon_date_editor_get_day(editor)); - - easily fails, since set_day tries to force validity while get_day - doesn't do that. - - Proposal: Always return the same values that are shown in the - fields. We add a separate flag (Or use GDate) to - indicate if the current date is valid. This would allow - setters to make the date invalid as well. - */ - *year = /*priv->year;*/ - (guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->y_entry))); - *month = /*priv->month;*/ - (guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->m_entry))); - *day = /*priv->day;*/ - (guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->d_entry))); -} - -/* icon button press event */ -static gboolean hildon_date_editor_icon_press(GtkWidget * widget, - gpointer data) -{ - g_assert(GTK_IS_WIDGET(widget)); - g_assert(HILDON_IS_DATE_EDITOR(data)); - - hildon_date_editor_set_calendar_icon_state(HILDON_DATE_EDITOR(data), TRUE); - - return FALSE; -} - -static gboolean hildon_date_editor_entry_focusin(GtkWidget * widget, - GdkEventFocus * event, - gpointer data) -{ - g_idle_add((GSourceFunc) - _hildon_date_editor_entry_select_all, GTK_ENTRY(widget)); - - return FALSE; -} - - -static void popup_calendar_dialog(HildonDateEditor *ed) -{ - guint y = 0, m = 0, d = 0; - GtkWidget *popup; - GtkWidget *parent; - guint result; - GValue val = {0, }; - - hildon_date_editor_get_date(ed, &y, &m, &d); - - parent = gtk_widget_get_ancestor(GTK_WIDGET(ed), GTK_TYPE_WINDOW); - popup = hildon_calendar_popup_new(GTK_WINDOW(parent), y, m, d); - - g_value_init(&val, G_TYPE_INT); - /* Set max/min year in calendar popup to date editor values */ - g_object_get_property(G_OBJECT(ed), "min-year", &val); - g_object_set_property(G_OBJECT(popup), "min-year", &val); - g_object_get_property(G_OBJECT(ed), "max-year", &val); - g_object_set_property(G_OBJECT(popup), "max-year", &val); - - /* Pop up calendar */ - result = gtk_dialog_run(GTK_DIALOG(popup)); - switch (result) { - case GTK_RESPONSE_OK: - case GTK_RESPONSE_ACCEPT: - hildon_calendar_popup_get_date(HILDON_CALENDAR_POPUP(popup), &y, - &m, &d); - hildon_date_editor_set_date(ed, y, m, d); - } - - gtk_widget_destroy(popup); -} - -/* button released */ -static gboolean hildon_date_editor_released(GtkWidget * widget, - gpointer data) -{ - HildonDateEditor *ed; - - g_assert(GTK_IS_WIDGET(widget)); - g_assert(HILDON_IS_DATE_EDITOR(data)); - - ed = HILDON_DATE_EDITOR(data); - - /* restores the icon state. The clicked cycle raises the dialog */ - hildon_date_editor_set_calendar_icon_state(ed, FALSE); - - return FALSE; -} - -/* button released */ -static gboolean hildon_date_editor_clicked(GtkWidget * widget, - gpointer data) -{ - HildonDateEditor *ed; - - g_assert(GTK_IS_WIDGET(widget)); - g_assert(HILDON_IS_DATE_EDITOR(data)); - - ed = HILDON_DATE_EDITOR(data); - - /* restores the non-clicked button state and raises the dialog */ - hildon_date_editor_set_calendar_icon_state(ed, FALSE); - popup_calendar_dialog(ed); - - return FALSE; -} - -/* This is called whenever some editor filed loses the focus and - when the all of the fields are filled. - Earlier this was called whenever an entry changed */ -/* FIXME: Validation on focus_out is broken by concept */ -static gint -hildon_date_editor_entry_validate(GtkWidget *widget, gpointer data) -{ - HildonDateEditor *ed; - HildonDateEditorPrivate *priv; - gint d, m, y, max_days; - gboolean r; /* temp return values for signals */ - const gchar *text; - gint error_code = NO_ERROR; - - g_assert(HILDON_IS_DATE_EDITOR(data)); - g_assert(GTK_IS_ENTRY(widget)); - - ed = HILDON_DATE_EDITOR(data); - priv = HILDON_DATE_EDITOR_GET_PRIVATE(ed); - - if (priv->skip_validation) - return error_code; - - /*check if the calling entry is empty*/ - text = gtk_entry_get_text(GTK_ENTRY(widget)); - if(text == NULL || text[0] == 0) - { - if (widget == priv->d_entry) - g_signal_emit(ed, date_editor_signals[DATE_ERROR], 0, EMPTY_DAY, &r); - else if(widget == priv->m_entry) - g_signal_emit(ed, date_editor_signals[DATE_ERROR], 0, EMPTY_MONTH, &r); - else - g_signal_emit(ed, date_editor_signals[DATE_ERROR], 0, EMPTY_YEAR, &r); - - /* restore empty entry to safe value */ - hildon_date_editor_set_date (ed, priv->year, priv->month, priv->day); - return error_code; - } - - /* Ok, we now check validity. Some fields can be empty */ - text = gtk_entry_get_text(GTK_ENTRY(priv->d_entry)); - if (text == NULL || text[0] == 0) return error_code; - d = atoi(text); - text = gtk_entry_get_text(GTK_ENTRY(priv->m_entry)); - if (text == NULL || text[0] == 0) return error_code; - m = atoi(text); - text = gtk_entry_get_text(GTK_ENTRY(priv->y_entry)); - if (text == NULL || text[0] == 0) return error_code; - y = atoi(text); - - /* Did it actually change? */ - if (d != priv->day || m != priv->month || y != priv->year) - { - /* We could/should use hildon_date_editor_set_year and such functions - * to set the date, instead of use gtk_entry_set_text, and then change - * the priv member but hildon_date_editor_set_year and such functions - * check if the date is valid, we do want to do date validation check - * here according to spec */ - - /* Validate month */ - if(widget == priv->m_entry) { - if(m < 1) { - error_code = MIN_MONTH; - m = 1; - } - else if (m > 12) { - error_code = MAX_MONTH; - m = 12; - } - } - - /* Validate year */ - if(widget == priv->y_entry) { - if (y < priv->min_year) { - error_code = MIN_YEAR; - y = priv->min_year; - } - else if (y > priv->max_year) { - error_code = MAX_YEAR; - y = priv->max_year; - } - } - - /* Validate day. We have to do this in every case, since - changing month or year can make the day number to be invalid */ - max_days = g_date_get_days_in_month(m,y); - if(d < 1) { - error_code = MIN_DAY; - d = 1; - } - else if (d > max_days) { - if (d > 31) { - error_code = MAX_DAY; - d = max_days; - } - else { /* the date does not exist (is invalid) */ - error_code = INVALID_DATE; - /* check what was changed and restore previous value */ - if ( widget == priv->y_entry ) - y = priv->year; - else if ( widget == priv->m_entry ) - m = priv->month; - else - d = priv->day; - } - } - - if (error_code != NO_ERROR) - { - g_signal_emit(ed, date_editor_signals[DATE_ERROR], 0, error_code, &r); - - g_idle_add ((GSourceFunc) - _hildon_date_editor_entry_select_all, - widget); - } - } - - /* Fix and reformat the date after error signal is processed. - reformatting can be needed even in a such case that numerical - values of the date components are the same as earlier. */ - hildon_date_editor_set_date(ed, y, m, d); - return error_code; -} - -/* When entry becomes full, we move the focus to the next field. - If we are on the last field, the whole contents are validated. */ -static void -hildon_date_editor_entry_changed(GtkEditable *ed, gpointer data) -{ - GtkEntry *entry; - gint error_code; - HildonDateEditorPrivate *priv; - - g_assert(GTK_IS_ENTRY(ed)); - g_assert(HILDON_IS_DATE_EDITOR(data)); - - entry = GTK_ENTRY(ed); - - /* If day entry is full, move to next entry or validate */ - if (g_utf8_strlen(gtk_entry_get_text(entry), -1) == gtk_entry_get_max_length(entry)) - { - error_code = hildon_date_editor_entry_validate(GTK_WIDGET(entry), data); - if (error_code == NO_ERROR) - { - priv = HILDON_DATE_EDITOR_GET_PRIVATE(HILDON_DATE_EDITOR(data)); - priv->skip_validation = TRUE; - gtk_widget_child_focus(GTK_WIDGET(data), GTK_DIR_RIGHT); - } - } -} - -static gboolean hildon_date_editor_keyrelease(GtkWidget * widget, - GdkEventKey * event, - gpointer data) -{ - HildonDateEditor *ed; - HildonDateEditorPrivate *priv; - - g_return_val_if_fail(data, FALSE); - g_return_val_if_fail(widget, FALSE); - - ed = HILDON_DATE_EDITOR(data); - priv = HILDON_DATE_EDITOR_GET_PRIVATE(ed); - - if (event->keyval == GDK_KP_Enter || event->keyval == GDK_Return || - event->keyval == GDK_ISO_Enter) { - if (hildon_date_editor_set_calendar_icon_state(ed, FALSE)) - { - popup_calendar_dialog(ed); - return TRUE; - } - } else if (event->keyval == GDK_Escape) - priv->skip_validation = FALSE; - - return FALSE; -} - -/* keyboard handling */ -static gboolean hildon_date_editor_keypress(GtkWidget * widget, - GdkEventKey * event, - gpointer data) -{ - HildonDateEditor *ed; - HildonDateEditorPrivate *priv; - gint pos; - gboolean r; - - g_assert(HILDON_IS_DATE_EDITOR(data)); - g_assert(GTK_IS_ENTRY(widget)); - - ed = HILDON_DATE_EDITOR(data); - priv = HILDON_DATE_EDITOR_GET_PRIVATE(ed); - pos = gtk_editable_get_position(GTK_EDITABLE(widget)); - - /* Show error message in case the key pressed is not allowed - (only digits and control characters are allowed )*/ - if (!g_unichar_isdigit(event->keyval) && !(event->keyval & 0xF000)) { - g_signal_emit(ed, date_editor_signals[DATE_ERROR], 0, INVALID_CHAR, &r); - return TRUE; - } - - switch (event->keyval) { - case GDK_Left: - if (pos == 0) { - (void) gtk_widget_child_focus(GTK_WIDGET(data), GTK_DIR_LEFT); - return TRUE; - } - break; - case GDK_Right: - if (pos >= g_utf8_strlen(gtk_entry_get_text(GTK_ENTRY(widget)), -1)) { - (void) gtk_widget_child_focus(GTK_WIDGET(data), GTK_DIR_RIGHT); - return TRUE; - } - break; - case GDK_Return: - case GDK_ISO_Enter: - /* Ignore return value, since we want to handle event at all times. - otherwise vkb would popup when the keyrepeat starts. */ - (void) hildon_date_editor_set_calendar_icon_state(ed, TRUE); - return TRUE; - - case GDK_Escape: - priv->skip_validation = TRUE; - break; - default: - break; - } - - return FALSE; -} - -static gboolean hildon_date_editor_entry_focus_out(GtkWidget * widget, - GdkEventFocus * event, - gpointer data) -{ - HildonDateEditor *ed; - HildonDateEditorPrivate *priv; - - g_assert(HILDON_IS_DATE_EDITOR(data)); - - ed = HILDON_DATE_EDITOR(data); - priv = HILDON_DATE_EDITOR_GET_PRIVATE(ed); - - hildon_date_editor_entry_validate(widget, data); - priv->skip_validation = FALSE; - - return FALSE; -} - -static gboolean -hildon_date_editor_date_error(HildonDateEditor *editor, - HildonDateEditorErrorType type) -{ - HildonDateEditorPrivate *priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); - - switch(type) - { - case MAX_DAY: - gtk_infoprintf(NULL, _("ckct_ib_maximum_value"), 31); - break; - case MAX_MONTH: - gtk_infoprintf(NULL, _("ckct_ib_maximum_value"), 12); - break; - case MAX_YEAR: - gtk_infoprintf(NULL, _("ckct_ib_maximum_value"), priv->max_year); - break; - case MIN_DAY: - case MIN_MONTH: - gtk_infoprintf(NULL, _("ckct_ib_minimum_value"), 1); - break; - case MIN_YEAR: - gtk_infoprintf(NULL, _("ckct_ib_minimum_value"), priv->min_year); - break; - case EMPTY_DAY: - gtk_infoprintf(NULL, _("ckct_ib_set_a_value_within_range"), 1, 31); - break; - case EMPTY_MONTH: - gtk_infoprintf(NULL, _("ckct_ib_set_a_value_within_range"), 1, 12); - break; - case EMPTY_YEAR: - gtk_infoprintf(NULL, _("ckct_ib_set_a_value_within_range"), - priv->min_year, priv->max_year); - break; - case INVALID_CHAR: - gtk_infoprint(NULL, _("ckct_ib_illegal_character")); - break; - case INVALID_DATE: - gtk_infoprint(NULL, _("ckct_ib_date_does_not_exist")); - break; - default: - /*default error message ?*/ - break; - } - return TRUE; -} - -static void hildon_date_editor_size_request(GtkWidget * widget, - GtkRequisition * requisition) -{ - HildonDateEditor *ed; - HildonDateEditorPrivate *priv; - GtkRequisition f_req, img_req; - - g_assert(GTK_IS_WIDGET(widget)); - g_assert(requisition != NULL); - - ed = HILDON_DATE_EDITOR(widget); - priv = HILDON_DATE_EDITOR_GET_PRIVATE(ed); - - /* Our own children affect our size */ - gtk_widget_size_request(priv->frame, &f_req); - gtk_widget_size_request(priv->d_button_image, &img_req); - - /* calculate our size */ - requisition->width = f_req.width + img_req.width + HILDON_MARGIN_DEFAULT; - - /* FIXME: Fixed size is bad! We should use the maximum of our children, but - doing so would break current pixel specifications, since - the text entry by itself is already 30px tall + then frame takes - something */ - requisition->height = DATE_EDITOR_HEIGHT; -} - -static void hildon_date_editor_size_allocate(GtkWidget * widget, - GtkAllocation * allocation) -{ - HildonDateEditor *ed; - HildonDateEditorPrivate *priv; - GtkAllocation f_alloc, img_alloc; - GtkRequisition req; - GtkRequisition max_req; - GList *iter; - - g_assert(GTK_IS_WIDGET(widget)); - g_assert(allocation != NULL); - - ed = HILDON_DATE_EDITOR(widget); - priv = HILDON_DATE_EDITOR_GET_PRIVATE(ed); - - widget->allocation = *allocation; - - gtk_widget_get_child_requisition(widget, &max_req); - - /* Center vertically */ - f_alloc.y = img_alloc.y = allocation->y + - MAX(allocation->height - max_req.height, 0) / 2; - - /* Center horizontally */ - f_alloc.x = img_alloc.x = allocation->x + - MAX(allocation->width - max_req.width, 0) / 2; - - /* allocate frame */ - if (GTK_WIDGET_VISIBLE(priv->frame)) { - gtk_widget_get_child_requisition(priv->frame, &req); - - f_alloc.width = req.width; - f_alloc.height = max_req.height; - gtk_widget_size_allocate(priv->frame, &f_alloc); - } - - /* allocate icon */ - if (GTK_WIDGET_VISIBLE(priv->d_button_image)) { - gtk_widget_get_child_requisition(priv->d_button_image, - &req); - - img_alloc.x += f_alloc.width + HILDON_MARGIN_DEFAULT; - img_alloc.width = req.width; - img_alloc.height = max_req.height; - gtk_widget_size_allocate(priv->d_button_image, &img_alloc); - } - - /* FIXME: We really should not alloc delimeters by hand (since they - are not our own children, but we need to force to appear - higher. This ugly hack is needed to compensate the forced - height in size_request. */ - for (iter = priv->delims; iter; iter = iter->next) - { - GtkWidget *delim; - GtkAllocation alloc; - - delim = GTK_WIDGET(iter->data); - alloc = delim->allocation; - alloc.height = max_req.height; - alloc.y = priv->d_entry->allocation.y - 2; - - gtk_widget_size_allocate(delim, &alloc); - } -} - -/** - * hildon_date_editor_set_year: - * @editor: the @HildonDateEditor widget - * @year: year - * - * Sets the year shown in the editor. - * - * Returns: TRUE if the year is valid - */ -gboolean hildon_date_editor_set_year(HildonDateEditor *editor, guint year) -{ - HildonDateEditorPrivate *priv; - g_return_val_if_fail( HILDON_IS_DATE_EDITOR(editor), FALSE ); - priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); - - if (g_date_valid_dmy(priv->day, priv->month, year)) - { - gchar buffer[256]; - priv->year = year; - - g_snprintf(buffer, sizeof(buffer), "%04d", year); - - /* We apply the new day, but do not want automatic focus move - etc to take place */ - g_signal_handlers_block_by_func(priv->y_entry, - (gpointer) hildon_date_editor_entry_changed, editor); - gtk_entry_set_text(GTK_ENTRY(priv->y_entry), buffer); - g_signal_handlers_unblock_by_func(priv->y_entry, - (gpointer) hildon_date_editor_entry_changed, editor); - - g_object_notify(G_OBJECT(editor), "year"); - return TRUE; - } - - return FALSE; -} - -/** - * hildon_date_editor_set_month: - * @editor: the @HildonDateEditor widget - * @month: month - * - * Sets the month shown in the editor. - * - * Returns: TRUE if the month is valid - */ -gboolean hildon_date_editor_set_month(HildonDateEditor *editor, guint month) -{ - HildonDateEditorPrivate *priv; - g_return_val_if_fail( HILDON_IS_DATE_EDITOR(editor), FALSE ); - priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); - - if (g_date_valid_dmy(priv->day, month, priv->year)) - { - GDate date; - gchar buffer[256]; - - priv->month = month; - g_date_set_dmy(&date, priv->day, month, priv->year); - g_date_strftime(buffer, sizeof(buffer), "%m", &date); - - /* We apply the new day, but do not want automatic focus move - etc to take place */ - g_signal_handlers_block_by_func(priv->m_entry, - (gpointer) hildon_date_editor_entry_changed, editor); - gtk_entry_set_text(GTK_ENTRY(priv->m_entry), buffer); - g_signal_handlers_unblock_by_func(priv->m_entry, - (gpointer) hildon_date_editor_entry_changed, editor); - - g_object_notify(G_OBJECT(editor), "month"); - return TRUE; - } - return FALSE; -} - -/** - * hildon_date_editor_set_day: - * @editor: the @HildonDateEditor widget - * @day: day - * - * Sets the day shown in the editor. - * - * Returns: TRUE if the day is valid - */ -gboolean hildon_date_editor_set_day(HildonDateEditor *editor, guint day) -{ - HildonDateEditorPrivate *priv; - - g_return_val_if_fail( HILDON_IS_DATE_EDITOR(editor), FALSE ); - priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); - - if (g_date_valid_dmy(day, priv->month, priv->year)) - { - GDate date; - gchar buffer[256]; - - priv->day = day; - g_date_set_dmy(&date, day, priv->month, priv->year); - g_date_strftime(buffer, sizeof(buffer), "%d", &date); - - /* We apply the new day, but do not want automatic focus move - etc to take place */ - g_signal_handlers_block_by_func(priv->d_entry, - (gpointer) hildon_date_editor_entry_changed, editor); - gtk_entry_set_text(GTK_ENTRY(priv->d_entry), buffer); - g_signal_handlers_unblock_by_func(priv->d_entry, - (gpointer) hildon_date_editor_entry_changed, editor); - - g_object_notify(G_OBJECT(editor), "day"); - return TRUE; - } - return FALSE; -} - -/** - * hildon_date_editor_get_year: - * @editor: the @HildonDateEditor widget - * - * Returns: the current year shown in the editor. - */ -guint hildon_date_editor_get_year(HildonDateEditor *editor) -{ - HildonDateEditorPrivate *priv; - g_return_val_if_fail( HILDON_IS_DATE_EDITOR(editor), 0 ); - priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); - return (guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->y_entry))); -} - -/** - * hildon_date_editor_get_month: - * @editor: the @HildonDateEditor widget - * - * Gets the month shown in the editor. - * - * Returns: the current month shown in the editor. - */ - -guint hildon_date_editor_get_month(HildonDateEditor *editor) -{ - HildonDateEditorPrivate *priv; - g_return_val_if_fail( HILDON_IS_DATE_EDITOR(editor), 0 ); - priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); - return (guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->m_entry))); -} - -/** - * hildon_date_editor_get_day: - * @editor: the @HildonDateEditor widget - * - * Gets the day shown in the editor. - * - * Returns: the current day shown in the editor - */ - -guint hildon_date_editor_get_day(HildonDateEditor *editor) -{ - HildonDateEditorPrivate *priv; - g_return_val_if_fail( HILDON_IS_DATE_EDITOR(editor), 0 ); - priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); - return (guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->d_entry))); -} - -/* Idle callback */ -static gboolean -_hildon_date_editor_entry_select_all (GtkWidget *widget) -{ - GDK_THREADS_ENTER (); - gtk_editable_select_region(GTK_EDITABLE(widget), 0, -1); - GDK_THREADS_LEAVE (); - return FALSE; -} diff --git a/hildon-widgets/hildon-date-editor.h b/hildon-widgets/hildon-date-editor.h deleted file mode 100644 index 368cc33..0000000 --- a/hildon-widgets/hildon-date-editor.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_DATE_EDITOR_H__ -#define __HILDON_DATE_EDITOR_H__ - -#include - -G_BEGIN_DECLS -/** - * HILDON_TYPE_DATE_EDITOR: - * - * Macro for getting type of date editor. - * Since: 0.12.10 - */ -#define HILDON_TYPE_DATE_EDITOR ( hildon_date_editor_get_type() ) - - -/** - * HILDON_DATE_EDITOR_TYPE: - * - * Deprecated: use #HILDON_TYPE_DATE_EDITOR instead - */ -#define HILDON_DATE_EDITOR_TYPE HILDON_TYPE_DATE_EDITOR - -#define HILDON_DATE_EDITOR(obj) (GTK_CHECK_CAST (obj,\ - HILDON_TYPE_DATE_EDITOR, HildonDateEditor)) -#define HILDON_DATE_EDITOR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass),\ - HILDON_TYPE_DATE_EDITOR, HildonDateEditorClass)) -#define HILDON_IS_DATE_EDITOR(obj) (GTK_CHECK_TYPE (obj,\ - HILDON_TYPE_DATE_EDITOR)) -#define HILDON_IS_DATE_EDITOR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass),\ - HILDON_TYPE_DATE_EDITOR)) - -/** - * HildonDateEditor: - * - * Internal struct for date editor. - */ -typedef struct _HildonDateEditor HildonDateEditor; -typedef struct _HildonDateEditorClass HildonDateEditorClass; - -typedef enum -{ - NO_ERROR = -1, - MAX_DAY, - MAX_MONTH, - MAX_YEAR, - MIN_DAY, - MIN_MONTH, - MIN_YEAR, - EMPTY_DAY, - EMPTY_MONTH, - EMPTY_YEAR, - INVALID_DATE, - INVALID_CHAR - -}HildonDateEditorErrorType; - -struct _HildonDateEditor { - GtkContainer par; -}; - -struct _HildonDateEditorClass { - GtkContainerClass parent_class; - - gboolean (*date_error) (HildonDateEditor *editor, - HildonDateEditorErrorType type); -}; - -GType hildon_date_editor_get_type(void) G_GNUC_CONST; - -GtkWidget *hildon_date_editor_new(void); - -void hildon_date_editor_set_date(HildonDateEditor * date, - guint year, guint month, guint day); - -void hildon_date_editor_get_date(HildonDateEditor * date, - guint * year, guint * month, guint * day); - -gboolean hildon_date_editor_set_year(HildonDateEditor *editor, guint year); -gboolean hildon_date_editor_set_month(HildonDateEditor *editor, guint month); -gboolean hildon_date_editor_set_day(HildonDateEditor *editor, guint day); - -guint hildon_date_editor_get_year(HildonDateEditor *editor); -guint hildon_date_editor_get_month(HildonDateEditor *editor); -guint hildon_date_editor_get_day(HildonDateEditor *editor); - -G_END_DECLS -#endif /* __HILDON_DATE_EDITOR_H__ */ diff --git a/hildon-widgets/hildon-defines.c b/hildon-widgets/hildon-defines.c deleted file mode 100644 index 18a239f..0000000 --- a/hildon-widgets/hildon-defines.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-defines - * @short_description: Not a widget, just a helper - * - */ - -#include -#include "hildon-defines.h" - -const HildonIconSizes *hildoniconsizes = NULL; -static HildonIconSizes iis; /* hildon internal icon sizes */ - -/** - * hildon_icon_sizes_init: - * - * Initializes the icon sizes. This is automatically - * called when the icon sizes have not been initialized - * and one is requested. - **/ -void hildon_icon_sizes_init (void) -{ - if (hildoniconsizes != NULL) - return; - - hildoniconsizes = &iis; - - iis.icon_size_list = gtk_icon_size_register ("hildon_icon_size_list", 64, 64); - iis.icon_size_small = gtk_icon_size_register ("*icon_size_small", 26, 26); - iis.icon_size_toolbar = gtk_icon_size_register ("icon_size_toolbar", 26, 26); - iis.icon_size_widg = gtk_icon_size_register ("icon_size_widg", 26, 26); - iis.icon_size_widg_wizard = gtk_icon_size_register ("icon_size_widg_wizard", 50, 50); - iis.icon_size_grid = gtk_icon_size_register ("icon_size_grid", 64, 64); - iis.icon_size_big_note = gtk_icon_size_register ("icon_size_big_note", 50, 50); - iis.icon_size_note = gtk_icon_size_register ("icon_size_note", 26, 26); - iis.icon_size_statusbar = gtk_icon_size_register ("icon_size_statusbar", 40, 40); - iis.icon_size_indi_video_player_pre_roll = gtk_icon_size_register ("icon_size_indi_video_player_pre_roll", 64, 64); - iis.icon_size_indi_key_pad_lock = gtk_icon_size_register ("icon_size_indi_key_pad_lock", 50, 50); - iis.icon_size_indi_copy = gtk_icon_size_register ("icon_size_indi_copy", 64, 64); - iis.icon_size_indi_delete = gtk_icon_size_register ("icon_size_indi_delete", 64, 64); - iis.icon_size_indi_process = gtk_icon_size_register ("icon_size_indi_process", 64, 64); - iis.icon_size_indi_progressball = gtk_icon_size_register ("icon_size_indi_progressball", 64, 64); - iis.icon_size_indi_send = gtk_icon_size_register ("icon_size_indi_send", 64, 64); - iis.icon_size_indi_offmode_charging = gtk_icon_size_register ("icon_size_indi_offmode_charging", 50, 50); - iis.icon_size_indi_tap_and_hold = gtk_icon_size_register ("icon_size_indi_tap_and_hold", 34, 34); - iis.icon_size_indi_send_receive = gtk_icon_size_register ("icon_size_indi_send_receive", 64, 64); - iis.icon_size_indi_wlan_strength = gtk_icon_size_register ("icon_size_indi_wlan_strength", 64, 64); - - iis.image_size_indi_nokia_logo = gtk_icon_size_register ("image_size_indi_nokia_logo", 64, 64); - iis.image_size_indi_startup_failed = gtk_icon_size_register ("image_size_indi_startup_failed", 64, 64); - iis.image_size_indi_startup_nokia_logo = gtk_icon_size_register ("image_size_indi_startup_nokia_logo", 64, 64); - iis.image_size_indi_nokia_hands = gtk_icon_size_register ("image_size_indi_nokia_hands", 64, 64); -} - -typedef struct _HildonLogicalData HildonLogicalData; - -struct _HildonLogicalData -{ - GtkRcFlags rcflags; - GtkStateType state; - gchar *logicalcolorstring; - gchar *logicalfontstring; -}; - - -static void hildon_change_style_recursive_from_ld (GtkWidget *widget, GtkStyle *prev_style, HildonLogicalData *ld) -{ - /* Change the style for child widgets */ - if (GTK_IS_CONTAINER (widget)) { - GSList *iterator = gtk_container_get_children (GTK_CONTAINER (widget)); - for (iterator; iterator; iterator = g_list_next (iterator)) - hildon_change_style_recursive_from_ld (iterator->data, prev_style, ld); - } - - /* gtk_widget_modify_*() emit "style_set" signals, so if we got here from - "style_set" signal, we need to block this function from being called - again or we get into inifinite loop. - - FIXME: Compiling with gcc > 3.3 and -pedantic won't allow - conversion between function and object pointers. GLib API however - requires an object pointer for a function, so we have to work - around this. - See http://bugzilla.gnome.org/show_bug.cgi?id=310175 - */ - G_GNUC_EXTENSION - g_signal_handlers_block_matched (G_OBJECT (widget), G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC, - g_signal_lookup ("style_set", G_TYPE_FROM_INSTANCE (widget)), - 0, NULL, - (gpointer) hildon_change_style_recursive_from_ld, - NULL); - - if (ld->logicalcolorstring != NULL) - { - /* Changing logical color */ - GdkColor color; - gtk_widget_ensure_style (widget); - if (gtk_style_lookup_logical_color (widget->style, ld->logicalcolorstring, &color) == TRUE) - switch (ld->rcflags) - { - case GTK_RC_FG: - gtk_widget_modify_fg (widget, ld->state, &color); - break; - case GTK_RC_BG: - gtk_widget_modify_bg (widget, ld->state, &color); - break; - case GTK_RC_TEXT: - gtk_widget_modify_text (widget, ld->state, &color); - break; - case GTK_RC_BASE: - gtk_widget_modify_base (widget, ld->state, &color); - break; - } else - { - g_warning ("Failed to lookup '%s' color!", ld->logicalcolorstring); - } - } - - if (ld->logicalfontstring != NULL) - { - /* Changing logical font */ - GtkStyle *fontstyle = gtk_rc_get_style_by_paths (gtk_settings_get_default (), ld->logicalfontstring, NULL, G_TYPE_NONE); - if (fontstyle != NULL) - { - PangoFontDescription *fontdesc = fontstyle->font_desc; - - if (fontdesc != NULL) - gtk_widget_modify_font (widget, fontdesc); - } - } - - - /* FIXME: Compilation workaround for gcc > 3.3 + -pedantic again */ - G_GNUC_EXTENSION - g_signal_handlers_unblock_matched (G_OBJECT (widget), G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC, - g_signal_lookup ("style_set", G_TYPE_FROM_INSTANCE (widget)), - 0, NULL, - (gpointer) hildon_change_style_recursive_from_ld, - NULL); -} - -static void hildon_logical_data_free (HildonLogicalData *ld) -{ - g_return_if_fail (ld != NULL); - - if (ld->logicalcolorstring) - g_free(ld->logicalcolorstring); - - if (ld->logicalfontstring) - g_free(ld->logicalfontstring); - - g_free(ld); -} - -/** - * hildon_gtk_widget_set_logical_font: - * @widget : A @GtkWidget to assign this logical font for. - * @logicalfontname : A gchar* with the logical font name to assign to the widget with an "osso-" -prefix. - * - * This function assigns a defined logical font to the @widget and all its child widgets. - * It also connects to the "style_set" signal which will retrieve & assign the new font for the given logical name each time the theme is changed. - * The returned signal id can be used to disconnect the signal. - * The previous signal (obtained by calling this function) is disconnected automatically and should not be used. - * - * Return value : The signal id that is triggered every time theme is changed. 0 if font set failed. - **/ -gulong hildon_gtk_widget_set_logical_font (GtkWidget *widget, const gchar *logicalfontname) -{ - HildonLogicalData *ld; - gulong signum = 0; - - g_return_val_if_fail (GTK_IS_WIDGET (widget), 0); - g_return_val_if_fail (logicalfontname != NULL, 0); - - ld = g_malloc (sizeof (HildonLogicalData)); - - ld->rcflags = 0; - ld->state = 0; - ld->logicalcolorstring = NULL; - ld->logicalfontstring = g_strdup(logicalfontname); - - /* Disconnects the previously connected signals. That calls the closure notify - * and effectively disposes the allocated data (hildon_logical_data_free) */ - g_signal_handlers_disconnect_matched (G_OBJECT (widget), G_SIGNAL_MATCH_FUNC, - 0, NULL, NULL, - G_CALLBACK (hildon_change_style_recursive_from_ld), NULL); - - /* Change the font now */ - hildon_change_style_recursive_from_ld (widget, NULL, ld); - - /* Connect to "style_set" so that the font gets changed whenever theme changes. */ - signum = g_signal_connect_data (G_OBJECT (widget), "style_set", - G_CALLBACK (hildon_change_style_recursive_from_ld), - ld, (GClosureNotify) hildon_logical_data_free, 0); - - return signum; -} - -/** - * hildon_gtk_widget_set_logical_color: - * @widget : A @GtkWidget to assign this logical font for. - * @rcflags : @GtkRcFlags enumeration defining whether to assign to FG, BG, TEXT or BASE style. - * @state : @GtkStateType indicating to which state to assign the logical color - * @logicalcolorname : A gchar* with the logical font name to assign to the widget. - * - * This function assigns a defined logical color to the @widget and all it's child widgets. - * It also connects to the "style_set" signal which will retrieve & assign the new color for the given logical name each time the theme is changed. - * The returned signal id can be used to disconnect the signal. - * The previous signal (obtained by calling this function) is disconnected automatically and should not be used. - * - * Example : If the style you want to modify is bg[NORMAL] then set rcflags to GTK_RC_BG and state to GTK_STATE_NORMAL. - * - * Return value : The signal id that is triggered every time theme is changed. 0 if color set failed. - **/ -gulong hildon_gtk_widget_set_logical_color (GtkWidget *widget, GtkRcFlags rcflags, - GtkStateType state, const gchar *logicalcolorname) -{ - HildonLogicalData *ld; - gulong signum = 0; - - g_return_val_if_fail (GTK_IS_WIDGET (widget), 0); - g_return_val_if_fail (logicalcolorname != NULL, 0); - - ld = g_malloc (sizeof (HildonLogicalData)); - - ld->rcflags = rcflags; - ld->state = state; - ld->logicalcolorstring = g_strdup(logicalcolorname); - ld->logicalfontstring = NULL; - - /* Disconnects the previously connected signals. That calls the closure notify - * and effectively disposes the allocated data (hildon_logical_data_free) */ - g_signal_handlers_disconnect_matched (G_OBJECT (widget), G_SIGNAL_MATCH_FUNC, - 0, NULL, NULL, - G_CALLBACK (hildon_change_style_recursive_from_ld), NULL); - - /* Change the colors now */ - hildon_change_style_recursive_from_ld (widget, NULL, ld); - - /* Connect to "style_set" so that the colors gets changed whenever theme */ - signum = g_signal_connect_data (G_OBJECT (widget), "style_set", - G_CALLBACK (hildon_change_style_recursive_from_ld), - ld, (GClosureNotify) hildon_logical_data_free, 0); - - return signum; -} diff --git a/hildon-widgets/hildon-defines.h b/hildon-widgets/hildon-defines.h deleted file mode 100644 index 963ca8c..0000000 --- a/hildon-widgets/hildon-defines.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_DEFINES_H__ -#define __HILDON_DEFINES_H__ - -#include -#include -#include "hildon-appview.h" - -G_BEGIN_DECLS - -void hildon_icon_sizes_init (void); - -typedef struct _HildonIconSizes HildonIconSizes; - -struct _HildonIconSizes -{ - GtkIconSize icon_size_list; - GtkIconSize icon_size_small; - GtkIconSize icon_size_toolbar; - GtkIconSize icon_size_widg; - GtkIconSize icon_size_widg_wizard; - GtkIconSize icon_size_grid; - GtkIconSize icon_size_big_note; - GtkIconSize icon_size_note; - GtkIconSize icon_size_statusbar; - GtkIconSize icon_size_indi_video_player_pre_roll; - GtkIconSize icon_size_indi_key_pad_lock; - GtkIconSize icon_size_indi_copy; - GtkIconSize icon_size_indi_delete; - GtkIconSize icon_size_indi_process; - GtkIconSize icon_size_indi_progressball; - GtkIconSize icon_size_indi_send; - GtkIconSize icon_size_indi_offmode_charging; - GtkIconSize icon_size_indi_tap_and_hold; - GtkIconSize icon_size_indi_send_receive; - GtkIconSize icon_size_indi_wlan_strength; - GtkIconSize image_size_indi_nokia_logo; - GtkIconSize image_size_indi_startup_failed; - GtkIconSize image_size_indi_startup_nokia_logo; - GtkIconSize image_size_indi_nokia_hands; -}; - -extern const HildonIconSizes *hildoniconsizes; - -#define HILDON_ICON_SIZE_CHECK_AND_GET(iconvar) (!hildoniconsizes ? hildon_icon_sizes_init (), hildoniconsizes->iconvar : hildoniconsizes->iconvar) - -#define HILDON_ICON_SIZE_LIST HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_list) -#define HILDON_ICON_SIZE_SMALL HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_small) -#define HILDON_ICON_SIZE_TOOLBAR HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_toolbar) -#define HILDON_ICON_SIZE_WIDG HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_widg) -#define HILDON_ICON_SIZE_WIDG_WIZARD HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_widg_wizard) -#define HILDON_ICON_SIZE_GRID HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_grid) -#define HILDON_ICON_SIZE_BIG_NOTE HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_big_note) -#define HILDON_ICON_SIZE_NOTE HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_note) -#define HILDON_ICON_SIZE_STATUSBAR HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_statusbar) -#define HILDON_ICON_SIZE_INDI_VIDEO_PLAYER_PRE_ROLL HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_indi_video_player_pre_roll) -#define HILDON_ICON_SIZE_INDI_COPY HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_indi_copy) -#define HILDON_ICON_SIZE_INDI_DELETE HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_indi_delete) -#define HILDON_ICON_SIZE_INDI_PROCESS HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_indi_process) -#define HILDON_ICON_SIZE_INDI_PROGRESSBALL HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_indi_progressball) -#define HILDON_ICON_SIZE_INDI_SEND HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_indi_send) -#define HILDON_ICON_SIZE_INDI_OFFMODE_CHARGING HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_indi_offmode) -#define HILDON_ICON_SIZE_INDI_TAP_AND_HOLD HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_tap_and_hold) -#define HILDON_ICON_SIZE_INDI_SEND_RECEIVE HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_indi_send_receive) -#define HILDON_ICON_SIZE_INDI_WLAN_STRENGTH HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_indi_wlan_strength) - -#define HILDON_IMAGE_SIZE_INDI_NOKIA_LOGO HILDON_ICON_SIZE_CHECK_AND_GET(image_size_indi_nokia_logo) -#define HILDON_IMAGE_SIZE_INDI_STARTUP_FAILED HILDON_ICON_SIZE_CHECK_AND_GET(image_size_indi_startup_nokia_failed) -#define HILDON_IMAGE_SIZE_INDI_STARTUP_NOKIA_LOGO HILDON_ICON_SIZE_CHECK_AND_GET(image_size_indi_startup_nokia_logo) -#define HILDON_IMAGE_SIZE_INDI_NOKIA_HAND HILDON_ICON_SIZE_CHECK_AND_GET(image_size_indi_nokia_hands) - -#define HILDON_ICON_PIXEL_SIZE_LIST 64 -#define HILDON_ICON_PIXEL_SIZE_SMALL 26 -#define HILDON_ICON_PIXEL_SIZE_TOOLBAR 26 -#define HILDON_ICON_PIXEL_SIZE_WIDG 26 -#define HILDON_ICON_PIXEL_SIZE_WIDG_WIZARD 50 -#define HILDON_ICON_PIXEL_SIZE_GRID 64 -#define HILDON_ICON_PIXEL_SIZE_BIG_NOTE 50 -#define HILDON_ICON_PIXEL_SIZE_NOTE 26 -#define HILDON_ICON_PIXEL_SIZE_STATUSBAR 40 -#define HILDON_ICON_PIXEL_SIZE_INDI_VIDEO_PLAYER_PRE_ROLL 64 -#define HILDON_ICON_PIXEL_SIZE_INDI_KEY_PAD_LOCK 50 -#define HILDON_ICON_PIXEL_SIZE_INDI_COPY 64 -#define HILDON_ICON_PIXEL_SIZE_INDI_DELETE 64 -#define HILDON_ICON_PIXEL_SIZE_INDI_PROCESS 64 -#define HILDON_ICON_PIXEL_SIZE_INDI_PROGRESSBALL 64 -#define HILDON_ICON_PIXEL_SIZE_INDI_SEND 64 -#define HILDON_ICON_PIXEL_SIZE_INDI_OFFMODE_CHARGING 50 -#define HILDON_ICON_PIXEL_SIZE_INDI_TAP_AND_HOLD 34 -#define HILDON_ICON_PIXEL_SIZE_INDI_SEND_RECEIVE 64 -#define HILDON_ICON_PIXEL_SIZE_INDI_WLAN_STRENGTH 64 - -#define HILDON_IMAGE_PIXEL_SIZE_INDI_NOKIA_LOGO 64 -#define HILDON_IMAGE_PIXEL_SIZE_INDI_STARTUP_FAILED 64 -#define HILDON_IMAGE_PIXEL_SIZE_INDI_STARTUP_NOKIA_LOGO 64 -#define HILDON_IMAGE_PIXEL_SIZE_INDI_NOKIA_HANDS 64 - -#define HILDON_MARGIN_HALF 3 -#define HILDON_MARGIN_DEFAULT 6 -#define HILDON_MARGIN_DOUBLE 12 -#define HILDON_MARGIN_TRIPLE 18 - -#define HILDON_HARDKEY_UP GDK_Up -#define HILDON_HARDKEY_LEFT GDK_Left -#define HILDON_HARDKEY_RIGHT GDK_Right -#define HILDON_HARDKEY_DOWN GDK_Down -#define HILDON_HARDKEY_SELECT GDK_Return -#define HILDON_HARDKEY_MENU GDK_F4 -#define HILDON_HARDKEY_HOME GDK_F5 -#define HILDON_HARDKEY_ESC GDK_Escape -#define HILDON_HARDKEY_FULLSCREEN GDK_F6 -#define HILDON_HARDKEY_INCREASE GDK_F7 -#define HILDON_HARDKEY_DECREASE GDK_F8 - -gulong hildon_gtk_widget_set_logical_font (GtkWidget *widget, const gchar *logicalfontname); -gulong hildon_gtk_widget_set_logical_color (GtkWidget *widget, GtkRcFlags rcflags, - GtkStateType state, const gchar *logicalcolorname); - -G_END_DECLS -#endif /* HILDON_DEFINES_H */ diff --git a/hildon-widgets/hildon-dialoghelp.c b/hildon-widgets/hildon-dialoghelp.c deleted file mode 100644 index 82f828f..0000000 --- a/hildon-widgets/hildon-dialoghelp.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-dialoghelp - * @short_description: A helper which contains a button in a normal dialog to - * open a help if required - * - * #HildonDialoghelp is a helper that provides an API for enabling or - * disabling a help button in the titlebar area of normal dialogs that - * are derived from GtkDialog. - */ - -#include -#include -#include "hildon-dialoghelp.h" - -static guint help_signal = 0; - -static GdkFilterReturn -handle_xevent(GdkXEvent * xevent, GdkEvent * event, gpointer dialog) -{ - XAnyEvent *eventti = xevent; - - if (eventti->type == ClientMessage) { - Atom help_atom, wm_atom; - Display *disp; - XClientMessageEvent *cm; - - disp = GDK_DISPLAY(); - cm = xevent; - - help_atom = XInternAtom(disp, "_NET_WM_CONTEXT_HELP", True); - wm_atom = XInternAtom(disp, "WM_PROTOCOLS", True); - - if (cm->message_type == wm_atom && cm->data.l[0] == help_atom) { - /* XClientMessageEvent *cm = xevent; */ - g_signal_emit(G_OBJECT(dialog), help_signal, 0); - } - - return GDK_FILTER_REMOVE; /* Event handled, don't process - further */ - } - - return GDK_FILTER_CONTINUE; /* Event not handled */ -} - -/** - * gtk_dialog_help_enable: - * @dialog: The dialog for which help is to be enabled. - * - * Enables context help button for a given dialog. The signal "help" can be - * connected to handler by normal GTK methods. Note that this function - * has to be called before the dialog is shown. - * - * The "help" signal itself has no other parameters than the dialog where - * it is connected to, ie.: - * void user_function(GtkDialog *dialog, gpointer user_data); - */ -void gtk_dialog_help_enable(GtkDialog * dialog) -{ - GdkWindow *window; - GdkDisplay *display; - Atom *protocols; - Atom *list; - Atom helpatom; - int amount = 0; - int n = 0; - int i = 0; - int help_enabled = 0; - - /* Create help signal if it didn't exist */ - if (help_signal == 0) { - help_signal = g_signal_new("help", GTK_TYPE_DIALOG, - G_SIGNAL_ACTION, (guint) - 1, NULL, - NULL, g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - } - - g_return_if_fail(GTK_IS_DIALOG(dialog)); - - gtk_widget_realize(GTK_WIDGET(dialog)); - window = GTK_WIDGET(dialog)->window; - display = gdk_drawable_get_display (window); - - /* Create a list of atoms stored in GdkWindow */ - XGetWMProtocols(GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), - &list, &amount); - - protocols = (Atom *) malloc ((amount+1) * sizeof (Atom)); - helpatom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_CONTEXT_HELP"); - - /* Enable the dialoghelp if help_atom is in the atoms' list */ - for (i=0; iwindow; - display = gdk_drawable_get_display (window); - - /* Create a list of atoms stored in GdkWindow */ - XGetWMProtocols(GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), - &list, &amount); - - helpatom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_CONTEXT_HELP"); - protocols = (Atom *) malloc (amount * sizeof (Atom)); - - /* Remove the help_atom if it is in the atoms' list */ - for (i=0; i - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_DIALOG_HELP_H__ -#define __HILDON_DIALOG_HELP_H__ - -#include - -G_BEGIN_DECLS - -void gtk_dialog_help_enable (GtkDialog * dialog); -void gtk_dialog_help_disable (GtkDialog * dialog); - -G_END_DECLS - -#endif /* __HILDON_DIALOG_HELP_H__ */ diff --git a/hildon-widgets/hildon-file-handling-note.c b/hildon-widgets/hildon-file-handling-note.c deleted file mode 100644 index 4b54c01..0000000 --- a/hildon-widgets/hildon-file-handling-note.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-file-handling-note - * @short_description: Displaying the notification when a move - * operation is in progress. - * @see_also: #HildonFileHandlingNote - * - * This is the notification displayed when a move operation is in - * progress. The notification uses a progress bar to indicate the - * progress of the operation. For operation containing multiple items, a - * separe progress bar is shown for each item. The notification has a - * single button, which allows users to stop the move operation. - */ - -#include "hildon-note.h" -#include "hildon-file-handling-note.h" -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_CONFIG_H -#include -#endif - -/* Note types */ -#define MOVING_TYPE 0 -#define DELETING_TYPE 1 -#define OPENING_TYPE 2 -#define SAVING_TYPE 3 - -/*#define _(String) dgettext(PACKAGE, String)*/ -#define _(String) dgettext("hildon-fm", String) /* FIXME: this file should be moved to hildon-fm */ - -#define HILDON_FILE_HANDLING_NOTE_GET_PRIVATE(obj)\ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_FILE_HANDLING_NOTE, HildonFileHandlingNotePrivate)); - -typedef struct _HildonFileHandlingNotePrivate - HildonFileHandlingNotePrivate; - -struct _HildonFileHandlingNotePrivate { - guint note_type; -}; - - -static HildonNote *parent_class; - - -/* standard forbids empty source file, therefore the ifdef must be - placed here. */ - -static void -hildon_file_handling_note_class_init(HildonFileHandlingNoteClass * class); - -static void hildon_file_handling_note_init(HildonFileHandlingNote * - dialog); - -static void hildon_file_handling_note_finalize(GObject * obj_self); - - - - -GType hildon_file_handling_note_get_type() -{ - static GType dialog_type = 0; - - if (!dialog_type) { - static const GTypeInfo dialog_info = { - sizeof(HildonFileHandlingNoteClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_file_handling_note_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonFileHandlingNote), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_file_handling_note_init - }; - - dialog_type = g_type_register_static(HILDON_TYPE_NOTE, - "HildonFileHandlingNote", - &dialog_info, 0); - } - return dialog_type; -} - -static void -hildon_file_handling_note_class_init(HildonFileHandlingNoteClass * class) -{ - GObjectClass *object_class = G_OBJECT_CLASS(class); - - parent_class = g_type_class_peek_parent(class); - g_type_class_add_private(class, sizeof(HildonFileHandlingNotePrivate)); - object_class->finalize = hildon_file_handling_note_finalize; -} - -static void hildon_file_handling_note_init(HildonFileHandlingNote * dialog) -{ - HildonFileHandlingNotePrivate *priv; - - priv = HILDON_FILE_HANDLING_NOTE_GET_PRIVATE(dialog); - priv->note_type = OPENING_TYPE; -} - -static void hildon_file_handling_note_finalize(GObject * obj_self) -{ - if (G_OBJECT_CLASS(parent_class)->finalize) - G_OBJECT_CLASS(parent_class)->finalize(obj_self); -} - -/** - * hildon_file_handling_note_set_counter_and_name: - * @note: the #HildonFileHandlingNote widget - * @current: progress, current item being processed - * @maximum: maximum value for counter (number of items) - * @name: filename - * - * This function sets current counter value, maximum - * counter value and filename for dialog - * - * DEPRECATED: use hildon-note instead of hildon-file-handling-note. - */ -void hildon_file_handling_note_set_counter_and_name(HildonFileHandlingNote - * note, guint current, - guint maximum, - const gchar * name) -{ - gchar str[255]; - HildonNote *p_note = HILDON_NOTE(note); - HildonFileHandlingNotePrivate *priv; - - priv = HILDON_FILE_HANDLING_NOTE_GET_PRIVATE(note); - - if (priv->note_type == MOVING_TYPE) { - if (maximum == 1) - { - g_snprintf(str, 255, _("sfil_nw_moving_file"), name); - hildon_note_set_button_text(p_note, _("sfil_bd_moving_file")); - } else { - g_snprintf(str, 255, _("docm_nw_moving_files"), - current, maximum, name); - hildon_note_set_button_text(p_note, _("docm_bd_moving_files")); - } - } else if (priv->note_type == SAVING_TYPE) { - if (maximum == 1) - { - g_snprintf(str, 255, _("docm_nw_saving_file"), name); - hildon_note_set_button_text(p_note, _("docm_bd_saving_file")); - } else { - g_snprintf(str, 255, _("docm_nw_saving_files"), - current, maximum, name); - hildon_note_set_button_text(p_note, _("docm_bd_saving_files")); - } - } else if (priv->note_type == OPENING_TYPE) { - if (maximum == 1) - { - g_snprintf(str, 255, _("docm_nw_opening_file"), name); - hildon_note_set_button_text(p_note, _("docm_bd_opening_file")); - } else { - g_snprintf(str, 255, _("docm_nw_opening_files"), - current, maximum, name); - hildon_note_set_button_text(p_note, _("docm_bd_opening_files")); - } - } else if (priv->note_type == DELETING_TYPE) { - if (maximum == 1) - { - g_snprintf(str, 255, _("docm_nw_deleting_file"), name); - hildon_note_set_button_text(p_note, _("docm_bd_deleting_file")); - } else { - g_snprintf(str, 255, _("docm_nw_deleting_files"), - current, maximum, name); - hildon_note_set_button_text(p_note, _("docm_bd_deleting_files")); - } - } - - g_object_set(p_note, "description", str, NULL); -} - -/** - * hildon_file_handling_note_set_name: - * @note: the @HildonFileHandlingNote widget - * @name: filename - * - * This function sets the filename for dialog - * DEPRECATED: use hildon-note instead of hildon-file-handling-note. - */ -void hildon_file_handling_note_set_name(HildonFileHandlingNote * note, - const gchar * name) -{ - gchar str[255]; - HildonNote *p_note = HILDON_NOTE(note); - HildonFileHandlingNotePrivate *priv = - HILDON_FILE_HANDLING_NOTE_GET_PRIVATE(note); - - if (priv->note_type == MOVING_TYPE) { - g_snprintf(str, 255, _("sfil_nw_moving_file"), name); - } else if (priv->note_type == SAVING_TYPE) { - g_snprintf(str, 255, _("docm_nw_saving_file"), name); - } else if (priv->note_type == OPENING_TYPE) { - g_snprintf(str, 255, _("docm_nw_opening_file"), name); - } else if (priv->note_type == DELETING_TYPE) { - g_snprintf(str, 255, _("docm_nw_deleting_file"), name); - } - - g_object_set(p_note, "description", str, NULL); -} - -/** - * hildon_file_handling_note_set_fraction: - * @note: the @HildonFileHandlingNote widget - * @frac: value for progress bar - - * This function sets fraction value for - * progress bar. - * DEPRECATED: use hildon-note instead of hildon-file-handling-note. - */ -void hildon_file_handling_note_set_fraction(HildonFileHandlingNote * note, - gfloat frac) -{ - GtkWidget *progbar; - - g_object_get(note, "progressbar", &progbar, NULL); - gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progbar), frac); -} - -/** - * hildon_file_handling_note_new_moving: - * @parent: parent GtkWindow - * - * This function creates new dialog - * which is "moving" type. - * - * Returns: a new #HildonFileHandlingNote - * DEPRECATED: use hildon-note instead of hildon-file-handling-note. - */ -GtkWidget *hildon_file_handling_note_new_moving(GtkWindow * parent) -{ - GtkWidget *progbar; - HildonFileHandlingNote *file_note; - HildonFileHandlingNotePrivate *priv; - - progbar = gtk_progress_bar_new(); - - file_note = g_object_new(HILDON_TYPE_FILE_HANDLING_NOTE, - "note_type", HILDON_NOTE_PROGRESSBAR_TYPE, - "description", _("sfil_nw_moving_file"), - "progressbar", progbar, NULL); - - priv = HILDON_FILE_HANDLING_NOTE_GET_PRIVATE(file_note); - priv->note_type = MOVING_TYPE; - - if (parent != NULL) - gtk_window_set_transient_for(GTK_WINDOW(file_note), parent); - - return GTK_WIDGET(file_note); -} - -/** - * hildon_file_handling_note_new_deleting: - * @parent: parent GtkWindow - * - * This function creates new dialog - * which is "deleting" type. - * - * Returns: a new #HildonFileHandlingNote - * DEPRECATED: use hildon-note instead of hildon-file-handling-note. - */ -GtkWidget *hildon_file_handling_note_new_deleting(GtkWindow * parent) -{ - GtkWidget *progbar; - HildonFileHandlingNote *file_note; - HildonFileHandlingNotePrivate *priv; - - progbar = gtk_progress_bar_new(); - - file_note = g_object_new(HILDON_TYPE_FILE_HANDLING_NOTE, - "note_type", HILDON_NOTE_PROGRESSBAR_TYPE, - "description", _("docm_nw_deleting_file"), - "progressbar", progbar, NULL); - - priv = HILDON_FILE_HANDLING_NOTE_GET_PRIVATE(file_note); - priv->note_type = DELETING_TYPE; - - if (parent != NULL) - gtk_window_set_transient_for(GTK_WINDOW(file_note), parent); - - return GTK_WIDGET(file_note); -} - -/** - * hildon_file_handling_note_new_opening: - * @parent: parent GtkWindow - * - * This function creates new dialog - * which is "opening" type - * - * Returns: a new #HildonFileHandlingNote - * DEPRECATED: use hildon-note instead of hildon-file-handling-note. - */ -GtkWidget *hildon_file_handling_note_new_opening(GtkWindow * parent) -{ - GtkWidget *progbar; - HildonFileHandlingNote *file_note; - HildonFileHandlingNotePrivate *priv; - - progbar = gtk_progress_bar_new(); - - file_note = g_object_new(HILDON_TYPE_FILE_HANDLING_NOTE, - "note_type", HILDON_NOTE_PROGRESSBAR_TYPE, - "description", _("docm_nw_opening_file"), - "progressbar", progbar, NULL); - - priv = HILDON_FILE_HANDLING_NOTE_GET_PRIVATE(file_note); - priv->note_type = OPENING_TYPE; - - if (parent != NULL) - gtk_window_set_transient_for(GTK_WINDOW(file_note), parent); - - return GTK_WIDGET(file_note); -} - -/** - * hildon_file_handling_note_new_saving: - * @parent: parent GtkWindow - * - * This function creates new dialog - * which is "saving" type. - * - * Returns: a new #HildonFileHandlingNote - * DEPRECATED: use hildon-note instead of hildon-file-handling-note. - */ -GtkWidget *hildon_file_handling_note_new_saving(GtkWindow * parent) -{ - GtkWidget *progbar; - HildonFileHandlingNote *file_note; - HildonFileHandlingNotePrivate *priv; - - progbar = gtk_progress_bar_new(); - - file_note = g_object_new(HILDON_TYPE_FILE_HANDLING_NOTE, - "note_type", HILDON_NOTE_PROGRESSBAR_TYPE, - "description", _("docm_nw_saving_file"), - "progressbar", progbar, NULL); - - priv = HILDON_FILE_HANDLING_NOTE_GET_PRIVATE(file_note); - priv->note_type = SAVING_TYPE; - - if (parent != NULL) - gtk_window_set_transient_for(GTK_WINDOW(file_note), parent); - - return GTK_WIDGET(file_note); -} - diff --git a/hildon-widgets/hildon-file-handling-note.h b/hildon-widgets/hildon-file-handling-note.h deleted file mode 100644 index 4da000b..0000000 --- a/hildon-widgets/hildon-file-handling-note.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ -#ifndef __HILDON_FILE_HANDLING_NOTE_H__ -#define __HILDON_FILE_HANDLING_NOTE_H__ - - -#ifndef HILDON_DISABLE_DEPRECATED - -#include "hildon-note.h" - -G_BEGIN_DECLS -#define HILDON_TYPE_FILE_HANDLING_NOTE \ - ( hildon_file_handling_note_get_type() ) -#define HILDON_FILE_HANDLING_NOTE(obj) \ - (GTK_CHECK_CAST (obj, HILDON_TYPE_FILE_HANDLING_NOTE,\ - HildonFileHandlingNote)) -#define HILDON_FILE_HANDLING_NOTE_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), HILDON_TYPE_FILE_HANDLING_NOTE,\ - HildonFileHandlingNoteClass)) -#define HILDON_IS_FILE_HANDLING_NOTE(obj) (GTK_CHECK_TYPE (obj,\ - HILDON_TYPE_FILE_HANDLING_NOTE)) -#define HILDON_IS_FILE_HANDLING_NOTE_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_FILE_HANDLING_NOTE)) -typedef struct _HildonFileHandlingNote HildonFileHandlingNote; -typedef struct _HildonFileHandlingNoteClass HildonFileHandlingNoteClass; - -struct _HildonFileHandlingNote { - HildonNote parent; -}; - -struct _HildonFileHandlingNoteClass { - HildonNoteClass parent_class; -}; - -/* Note creation functions */ -GtkWidget *hildon_file_handling_note_new_moving(GtkWindow * parent); -GtkWidget *hildon_file_handling_note_new_deleting(GtkWindow * parent); -GtkWidget *hildon_file_handling_note_new_opening(GtkWindow * parent); -GtkWidget *hildon_file_handling_note_new_saving(GtkWindow * parent); - -/* Function for progressbar status setting */ -void hildon_file_handling_note_set_fraction(HildonFileHandlingNote * note, - gfloat frac); -void hildon_file_handling_note_set_counter_and_name(HildonFileHandlingNote - * note, guint current, - guint maximum, - const gchar * name); -void hildon_file_handling_note_set_name(HildonFileHandlingNote * note, - const gchar * name); - -GType hildon_file_handling_note_get_type(void); - -G_END_DECLS -#endif /* HILDON_DISABLE_DEPRECATED */ - -#endif /* __HILDON_FILE_HANDLING_NOTE_H__ */ diff --git a/hildon-widgets/hildon-find-toolbar.c b/hildon-widgets/hildon-find-toolbar.c deleted file mode 100644 index 33a9e69..0000000 --- a/hildon-widgets/hildon-find-toolbar.c +++ /dev/null @@ -1,667 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-find-toolbar - * @short_description: A special toolbar to be used with HildonAppView - * @see_also: #HildonAppView - * - * HildonFindToolbar is a predefined toolbar for text searching purpose. - * It contains a GtkListStore which has the text items that the user has - * searched. But once the application is terminated, or HildonFindToolbar - * is trashed. Programmer is responsible for getting the GtkListStore through - * property "list", if he/she wants to use the information in the future. - * And through the same property, programmer is able to set the GtkListStore. - * Note, once the search button is pressed, string in the GtkComboxEntry is - * automatically added to the existing model, unless it is empty. - */ - -#include "hildon-find-toolbar.h" -#include "hildon-defines.h" -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_CONFIG_H -#include -#endif -#include -#define _(String) dgettext(PACKAGE, String) - -/*same define as gtkentry.c as entry will further handle this*/ -#define MAX_SIZE G_MAXUSHORT -#define FIND_LABEL_XPADDING 6 -#define FIND_LABEL_YPADDING 0 - -enum -{ - SEARCH = 0, - CLOSE, - INVALID_INPUT, - HISTORY_APPEND, - - LAST_SIGNAL -}; - -enum -{ - PROP_LABEL = 1, - PROP_PREFIX, - PROP_LIST, - PROP_COLUMN, - PROP_MAX, - PROP_HISTORY_LIMIT -}; - -struct _HildonFindToolbarPrivate -{ - GtkWidget* label; - GtkComboBoxEntry* entry_combo_box; - GtkToolItem* find_button; - GtkToolItem* separator; - GtkToolItem* close_button; - - gint history_limit; -}; -static guint HildonFindToolbar_signal[LAST_SIGNAL] = {0}; - -G_DEFINE_TYPE(HildonFindToolbar, hildon_find_toolbar, GTK_TYPE_TOOLBAR) - -static GtkTreeModel * -hildon_find_toolbar_get_list_model(HildonFindToolbarPrivate *priv) -{ - GtkTreeModel *filter_model = - gtk_combo_box_get_model(GTK_COMBO_BOX(priv->entry_combo_box)); - - return filter_model == NULL ? NULL : - gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(filter_model)); -} - -static GtkEntry * -hildon_find_toolbar_get_entry(HildonFindToolbarPrivate *priv) -{ - return GTK_ENTRY(gtk_bin_get_child(GTK_BIN(priv->entry_combo_box))); -} - -static gboolean -hildon_find_toolbar_filter(GtkTreeModel *model, - GtkTreeIter *iter, - gpointer self) -{ - GtkTreePath *path; - const gint *indices; - gint n; - gint limit; - gint total; - - total = gtk_tree_model_iter_n_children(model, NULL); - g_object_get(self, "history_limit", &limit, NULL); - path = gtk_tree_model_get_path(model, iter); - indices = gtk_tree_path_get_indices (path); - - /* set the row's index, list store has only one level */ - n = indices[0]; - gtk_tree_path_free(path); - - /*if the row is among the latest "history_limit" additions of the - * model, then we show it */ - if( (total - limit <= n) && (n < total) ) - return TRUE; - else - return FALSE; -} - -static void -hildon_find_toolbar_apply_filter(HildonFindToolbar *self, GtkTreeModel *model) -{ - GtkTreeModel *filter; - HildonFindToolbarPrivate *priv = self->priv; - - /* Create a filter for the given model. Its only purpose is to hide - the oldest entries so only "history_limit" entries are visible. */ - filter = gtk_tree_model_filter_new(model, NULL); - - gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(filter), - hildon_find_toolbar_filter, - self, NULL); - gtk_combo_box_set_model(GTK_COMBO_BOX(priv->entry_combo_box), filter); - - /* ComboBox keeps the only needed reference to the filter */ - g_object_unref(filter); -} - -static void -hildon_find_toolbar_get_property(GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - HildonFindToolbarPrivate *priv = HILDON_FIND_TOOLBAR(object)->priv; - const gchar *string; - gint c_n, max_len; - - switch (prop_id) - { - case PROP_LABEL: - string = gtk_label_get_text(GTK_LABEL(priv->label)); - g_value_set_string(value, string); - break; - case PROP_PREFIX: - string = gtk_entry_get_text(hildon_find_toolbar_get_entry(priv)); - g_value_set_string(value, string); - break; - case PROP_LIST: - g_value_set_object(value, hildon_find_toolbar_get_list_model(priv)); - break; - case PROP_COLUMN: - c_n = gtk_combo_box_entry_get_text_column(priv->entry_combo_box); - g_value_set_int(value, c_n); - break; - case PROP_MAX: - max_len = gtk_entry_get_max_length(hildon_find_toolbar_get_entry(priv)); - g_value_set_int(value, max_len); - break; - case PROP_HISTORY_LIMIT: - g_value_set_int(value, priv->history_limit); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -hildon_find_toolbar_set_property(GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - HildonFindToolbar *self = HILDON_FIND_TOOLBAR(object); - HildonFindToolbarPrivate *priv = self->priv; - GtkTreeModel *model; - const gchar *string; - - switch (prop_id) - { - case PROP_LABEL: - string = g_value_get_string(value); - gtk_label_set_text(GTK_LABEL(priv->label), string); - break; - case PROP_PREFIX: - string = g_value_get_string(value); - gtk_entry_set_text(hildon_find_toolbar_get_entry(priv), string); - break; - case PROP_LIST: - model = GTK_TREE_MODEL(g_value_get_object(value)); - hildon_find_toolbar_apply_filter(self, model); - break; - case PROP_COLUMN: - gtk_combo_box_entry_set_text_column(priv->entry_combo_box, - g_value_get_int(value)); - break; - case PROP_MAX: - gtk_entry_set_max_length(hildon_find_toolbar_get_entry(priv), - g_value_get_int(value)); - break; - case PROP_HISTORY_LIMIT: - priv->history_limit = g_value_get_int(value); - - /* Re-apply the history limit to the model. */ - model = hildon_find_toolbar_get_list_model(priv); - if (model != NULL) - { - /* Note that refilter function doesn't update the status of the - combobox popup arrow, so we'll just recreate the filter. */ - hildon_find_toolbar_apply_filter(self, model); - - if (gtk_combo_box_entry_get_text_column(priv->entry_combo_box) == -1) - { - /* FIXME: This is only for backwards compatibility, although - probably nothing actually relies on it. The behavior was only - an accidental side effect of original code */ - gtk_combo_box_entry_set_text_column(priv->entry_combo_box, 0); - } - } - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -hildon_find_toolbar_find_string(HildonFindToolbar *self, - GtkTreeIter *iter, - gint column, - const gchar *string) -{ - GtkTreeModel *model = NULL; - gchar *old_string; - - model = hildon_find_toolbar_get_list_model(self->priv); - - if (gtk_tree_model_get_iter_first(model, iter)) - { - do { - gtk_tree_model_get(model, iter, column, &old_string, -1); - if (old_string != NULL && strcmp(string, old_string) == 0) - { - /* Found it */ - return TRUE; - } - } while (gtk_tree_model_iter_next(model, iter)); - } - - return FALSE; -} - -static gboolean -hildon_find_toolbar_history_append(HildonFindToolbar *self, - gpointer data) -{ - HildonFindToolbarPrivate *priv = HILDON_FIND_TOOLBAR(self)->priv; - gchar *string; - gint column = 0; - GtkTreeModel *model = NULL; - GtkListStore *list = NULL; - GtkTreeIter iter; - gboolean self_create = FALSE; - - g_object_get(self, "prefix", &string, NULL); - - if (*string == '\0') - { - /* empty prefix, ignore */ - g_free(string); - return TRUE; - } - - - /* If list store is set, get it */ - model = hildon_find_toolbar_get_list_model(priv); - if(model != NULL) - { - list = GTK_LIST_STORE(model); - g_object_get(self, "column", &column, NULL); - - if (column < 0) - { - /* Column number is -1 if "column" property hasn't been set but - "list" property is. */ - g_free(string); - return TRUE; - } - - /* Latest string is always the first one in list. If the string - already exists, remove it so there are no duplicates in list. */ - if (hildon_find_toolbar_find_string(self, &iter, column, string)) - gtk_list_store_remove(list, &iter); - } - else - { - /* No list store set. Create our own. */ - list = gtk_list_store_new(1, G_TYPE_STRING); - model = GTK_TREE_MODEL(list); - self_create = TRUE; - } - - /* Add the string to first in list */ - gtk_list_store_append(list, &iter); - gtk_list_store_set(list, &iter, column, string, -1); - - if(self_create) - { - /* Add the created list to ComboBoxEntry */ - hildon_find_toolbar_apply_filter(self, model); - /* ComboBoxEntry keeps the only needed reference to this list */ - g_object_unref(list); - - /* Set the column only after ComboBoxEntry's model is set - in hildon_find_toolbar_apply_filter() */ - g_object_set(self, "column", 0, NULL); - } - else - { - /* Refilter to get the oldest entry hidden from history */ - gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER( - gtk_combo_box_get_model(GTK_COMBO_BOX(priv->entry_combo_box)))); - } - - g_free(string); - - return TRUE; -} - -static void -hildon_find_toolbar_emit_search(GtkButton *button, gpointer self) -{ - gboolean rb; - - /* Clicked search button. Perform search and add search prefix to history */ - g_signal_emit_by_name(self, "search", NULL); - g_signal_emit_by_name(self, "history_append", &rb, NULL); -} - -static void -hildon_find_toolbar_emit_close(GtkButton *button, gpointer self) -{ - HildonFindToolbarPrivate *priv = HILDON_FIND_TOOLBAR(self)->priv; - GtkWidget *entry = gtk_bin_get_child(GTK_BIN(priv->entry_combo_box)); - if (GTK_WIDGET_HAS_FOCUS(entry)) - { - hildon_gtk_im_context_hide(GTK_ENTRY(entry)->im_context); - } - /* Clicked close button */ - g_signal_emit_by_name(self, "close", NULL); -} - -static void -hildon_find_toolbar_emit_invalid_input(GtkEntry *entry, - GtkInvalidInputType type, - gpointer self) -{ - if(type == GTK_INVALID_INPUT_MAX_CHARS_REACHED) - g_signal_emit_by_name(self, "invalid_input", NULL); -} - -static void -hildon_find_toolbar_entry_activate (GtkWidget *widget, - gpointer user_data) -{ - GtkWidget *find_toolbar = GTK_WIDGET(user_data); - gboolean rb; - - /* NB#40936 stop focus from moving to next widget */ - g_signal_stop_emission_by_name (widget, "activate"); - - g_signal_emit_by_name(find_toolbar, "search", NULL); - g_signal_emit_by_name(find_toolbar, "history_append", &rb, NULL); -} - -static void -hildon_find_toolbar_class_init(HildonFindToolbarClass *klass) -{ - GObjectClass *object_class; - - g_type_class_add_private(klass, sizeof(HildonFindToolbarPrivate)); - - object_class = G_OBJECT_CLASS(klass); - - object_class->get_property = hildon_find_toolbar_get_property; - object_class->set_property = hildon_find_toolbar_set_property; - - klass->history_append = hildon_find_toolbar_history_append; - - g_object_class_install_property(object_class, PROP_LABEL, - g_param_spec_string("label", - "Label", "Displayed name for" - " find-toolbar", - _("ecdg_ti_find_toolbar_label"), - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property(object_class, PROP_PREFIX, - g_param_spec_string("prefix", - "Prefix", "Search string", NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property(object_class, PROP_LIST, - g_param_spec_object("list", - "List"," GtkListStore model where " - "history list is kept", - GTK_TYPE_LIST_STORE, - G_PARAM_READWRITE)); - - g_object_class_install_property(object_class, PROP_COLUMN, - g_param_spec_int("column", - "Column", "Column number in GtkListStore " - "where history list strings are kept", - 0, G_MAXINT, - 0, G_PARAM_READWRITE)); - - g_object_class_install_property(object_class, PROP_MAX, - g_param_spec_int("max_characters", - "Maximum number of characters", - "Maximum number of characters " - "in search string", - 0, MAX_SIZE, - 0, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property(object_class, PROP_HISTORY_LIMIT, - g_param_spec_int("history_limit", - "Maximum number of history items", - "Maximum number of history items " - "in search combobox", - 0, G_MAXINT, - 5, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - /** - * HildonFindToolbar::search: - * @toolbar: the toolbar which received the signal - * - * Gets emitted when the find button is pressed. - */ - HildonFindToolbar_signal[SEARCH] = - g_signal_new( - "search", HILDON_TYPE_FIND_TOOLBAR, - G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET - (HildonFindToolbarClass, search), - NULL, NULL, gtk_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - /** - * HildonFindToolbar::close: - * @toolbar: the toolbar which received the signal - * - * Gets emitted when the close button is pressed. - */ - HildonFindToolbar_signal[CLOSE] = - g_signal_new( - "close", HILDON_TYPE_FIND_TOOLBAR, - G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET - (HildonFindToolbarClass, close), - NULL, NULL, gtk_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - /** - * HildonFindToolbar::invalid-input: - * @toolbar: the toolbar which received the signal - * - * Gets emitted when the maximum search prefix length is reached and - * user tries to type more. - */ - HildonFindToolbar_signal[INVALID_INPUT] = - g_signal_new( - "invalid_input", HILDON_TYPE_FIND_TOOLBAR, - G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET - (HildonFindToolbarClass, invalid_input), - NULL, NULL, gtk_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - /** - * HildonFindToolbar::history-append: - * @toolbar: the toolbar which received the signal - * - * Gets emitted when the current search prefix should be added to history. - */ - HildonFindToolbar_signal[HISTORY_APPEND] = - g_signal_new( - "history_append", HILDON_TYPE_FIND_TOOLBAR, - G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET - (HildonFindToolbarClass, history_append), - g_signal_accumulator_true_handled, NULL, - gtk_marshal_BOOLEAN__VOID, - G_TYPE_BOOLEAN, 0); -} - -static void -hildon_find_toolbar_init(HildonFindToolbar *self) -{ - GtkToolItem *label_container; - GtkToolItem *entry_combo_box_container; - - self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self, - HILDON_TYPE_FIND_TOOLBAR, - HildonFindToolbarPrivate); - - /* Create the label */ - self->priv->label = gtk_label_new(_("ecdg_ti_find_toolbar_label")); - - gtk_misc_set_padding (GTK_MISC(self->priv->label), FIND_LABEL_XPADDING, - FIND_LABEL_YPADDING); - - label_container = gtk_tool_item_new(); - gtk_container_add(GTK_CONTAINER(label_container), - self->priv->label); - gtk_widget_show_all(GTK_WIDGET(label_container)); - gtk_toolbar_insert (GTK_TOOLBAR(self), label_container, -1); - - /* ComboBoxEntry for search prefix string / history list */ - self->priv->entry_combo_box = GTK_COMBO_BOX_ENTRY(gtk_combo_box_entry_new()); - g_signal_connect(hildon_find_toolbar_get_entry(self->priv), - "invalid_input", - G_CALLBACK(hildon_find_toolbar_emit_invalid_input), self); - entry_combo_box_container = gtk_tool_item_new(); - gtk_tool_item_set_expand(entry_combo_box_container, TRUE); - gtk_container_add(GTK_CONTAINER(entry_combo_box_container), - GTK_WIDGET(self->priv->entry_combo_box)); - gtk_widget_show_all(GTK_WIDGET(entry_combo_box_container)); - gtk_toolbar_insert (GTK_TOOLBAR(self), entry_combo_box_container, -1); - g_signal_connect(hildon_find_toolbar_get_entry(self->priv), - "activate", - G_CALLBACK(hildon_find_toolbar_entry_activate), self); - - /* Find button */ - self->priv->find_button = gtk_tool_button_new ( - gtk_image_new_from_icon_name ("qgn_toolb_browser_gobutton", - HILDON_ICON_SIZE_TOOLBAR), - "Find"); - g_signal_connect(self->priv->find_button, "clicked", - G_CALLBACK(hildon_find_toolbar_emit_search), self); - gtk_widget_show_all(GTK_WIDGET(self->priv->find_button)); - gtk_toolbar_insert (GTK_TOOLBAR(self), self->priv->find_button, -1); - if ( GTK_WIDGET_CAN_FOCUS( GTK_BIN(self->priv->find_button)->child) ) - GTK_WIDGET_UNSET_FLAGS( - GTK_BIN(self->priv->find_button)->child, GTK_CAN_FOCUS); - - /* Separator */ - self->priv->separator = gtk_separator_tool_item_new(); - gtk_widget_show(GTK_WIDGET(self->priv->separator)); - gtk_toolbar_insert (GTK_TOOLBAR(self), self->priv->separator, -1); - - /* Close button */ - self->priv->close_button = gtk_tool_button_new ( - gtk_image_new_from_icon_name ("qgn_toolb_gene_close", - HILDON_ICON_SIZE_TOOLBAR), - "Close"); - g_signal_connect(self->priv->close_button, "clicked", - G_CALLBACK(hildon_find_toolbar_emit_close), self); - gtk_widget_show_all(GTK_WIDGET(self->priv->close_button)); - gtk_toolbar_insert (GTK_TOOLBAR(self), self->priv->close_button, -1); - if ( GTK_WIDGET_CAN_FOCUS( GTK_BIN(self->priv->close_button)->child) ) - GTK_WIDGET_UNSET_FLAGS( - GTK_BIN(self->priv->close_button)->child, GTK_CAN_FOCUS); -} - -/*Public functions*/ - -/** - * hildon_find_toolbar_new: - * @label: label for the find_toolbar, NULL to set the label to - * default "Find" - * - * Returns a new HildonFindToolbar. - * - * Returns: a new HildonFindToolbar - */ - -GtkWidget * -hildon_find_toolbar_new(const gchar *label) -{ - GtkWidget *findtoolbar; - - findtoolbar = GTK_WIDGET(g_object_new(HILDON_TYPE_FIND_TOOLBAR, NULL)); - if(label != NULL) - g_object_set(findtoolbar, "label", label, NULL); - - return findtoolbar; -} - -/** - * hildon_find_toolbar_new_with_model - * @label: label for the find_toolbar, NULL to set the label to - * default "Find" - * @model: a @GtkListStore - * @column: indicating which column the search histry list will - * retreive string from - * - * Returns a new HildonFindToolbar, with a model. - * - * Returns: a new #HildonFindToolbar - */ -GtkWidget * -hildon_find_toolbar_new_with_model(const gchar *label, - GtkListStore *model, - gint column) -{ - GtkWidget *findtoolbar; - - findtoolbar = hildon_find_toolbar_new(label); - g_object_set(findtoolbar, "list", model, - "column", column, NULL); - - return findtoolbar; -} - -/** - * hildon_find_toolbar_highlight_entry - * @ftb: find Toolbar whose entry is to be highlighted - * @get_focus: if user passes TRUE to this value, then the text in - * the entry will not only get highlighted, but also get focused. - * - */ -void -hildon_find_toolbar_highlight_entry(HildonFindToolbar *ftb, - gboolean get_focus) -{ - GtkEntry *entry = NULL; - - g_return_if_fail(HILDON_IS_FIND_TOOLBAR(ftb)); - - entry = hildon_find_toolbar_get_entry(ftb->priv); - - gtk_editable_select_region(GTK_EDITABLE(entry), 0, -1); - - if(get_focus) - gtk_widget_grab_focus(GTK_WIDGET(entry)); -} diff --git a/hildon-widgets/hildon-find-toolbar.h b/hildon-widgets/hildon-find-toolbar.h deleted file mode 100644 index 2f5919c..0000000 --- a/hildon-widgets/hildon-find-toolbar.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_FIND_TOOLBAR_H__ -#define __HILDON_FIND_TOOLBAR_H__ - -#include -#include - -G_BEGIN_DECLS - -#define HILDON_TYPE_FIND_TOOLBAR (hildon_find_toolbar_get_type()) -#define HILDON_FIND_TOOLBAR(object) \ - (G_TYPE_CHECK_INSTANCE_CAST((object), HILDON_TYPE_FIND_TOOLBAR, \ - HildonFindToolbar)) -#define HILDON_FIND_TOOLBARClass(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), HILDON_TYPE_FIND_TOOLBAR, \ - HildonFindToolbarClass)) -#define HILDON_IS_FIND_TOOLBAR(object) \ - (G_TYPE_CHECK_INSTANCE_TYPE((object), HILDON_TYPE_FIND_TOOLBAR)) -#define HILDON_IS_FIND_TOOLBAR_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), HILDON_TYPE_FIND_TOOLBAR)) -#define HILDON_FIND_TOOLBAR_GET_CLASS(object) \ - (G_TYPE_INSTANCE_GET_CLASS((object), HILDON_TYPE_FIND_TOOLBAR, \ - HildonFindToolbarClass)) - -typedef struct _HildonFindToolbar HildonFindToolbar; -typedef struct _HildonFindToolbarClass HildonFindToolbarClass; -typedef struct _HildonFindToolbarPrivate HildonFindToolbarPrivate; - -struct _HildonFindToolbar -{ - GtkToolbar parent; - - HildonFindToolbarPrivate *priv; -}; - -struct _HildonFindToolbarClass -{ - GtkToolbarClass parent_class; - - void (*search) (HildonFindToolbar *toolbar); - void (*close) (HildonFindToolbar *toolbar); - void (*invalid_input) (HildonFindToolbar *toolbar); - gboolean (*history_append) (HildonFindToolbar *tooblar); -}; - -GType hildon_find_toolbar_get_type (void) G_GNUC_CONST; -GtkWidget* hildon_find_toolbar_new (const gchar *label); -GtkWidget* hildon_find_toolbar_new_with_model (const gchar *label, - GtkListStore* - model, - gint column); -void hildon_find_toolbar_highlight_entry (HildonFindToolbar *ftb, - gboolean get_focus); - -G_END_DECLS - -#endif /* __HILDON_FIND_TOOLBAR_H__ */ diff --git a/hildon-widgets/hildon-font-selection-dialog.c b/hildon-widgets/hildon-font-selection-dialog.c deleted file mode 100644 index 1ffa8c0..0000000 --- a/hildon-widgets/hildon-font-selection-dialog.c +++ /dev/null @@ -1,1998 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-font-selection-dialog - * @short_description: A widget used to allow users to select a font - * with certain properties - * - * Font selection can be made using this widget. Users can select font name, - * size, style, etc. Users can also preview text in the selected font. - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hildon-font-selection-dialog.h" -#include -#include -#include - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#define _(String) dgettext(PACKAGE, String) - -#define SUPERSCRIPT_RISE 3333 -#define SUBSCRIPT_LOW -3333 -#define ON_BIT 0x01 -#define OFF_BIT 0x02 - -/* - * These are what we use as the standard font sizes, for the size list. - */ -static const guint16 font_sizes[] = -{ - 6, 8, 10, 12, 16, 24, 32 -}; - -#define HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(obj) \ -(G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_FONT_SELECTION_DIALOG, \ - HildonFontSelectionDialogPrivate)) - -/*None of designed api function works, so now it all comes down to - *use properties to achieve what we are supposed to achieve*/ -enum -{ - PROP_FAMILY = 1, - PROP_FAMILY_SET, - PROP_SIZE, - PROP_SIZE_SET, - PROP_COLOR, - PROP_COLOR_SET, - PROP_BOLD, - PROP_BOLD_SET, - PROP_ITALIC, - PROP_ITALIC_SET, - PROP_UNDERLINE, - PROP_UNDERLINE_SET, - PROP_STRIKETHROUGH, - PROP_STRIKETHROUGH_SET, - PROP_POSITION, - PROP_POSITION_SET, - PROP_PREVIEW_TEXT, - PROP_FONT_SCALING -}; - -typedef struct -_HildonFontSelectionDialogPrivate HildonFontSelectionDialogPrivate; - -struct _HildonFontSelectionDialogPrivate -{ - GtkNotebook *notebook; - - gchar *preview_text; - - /*Tab one*/ - GtkWidget *cbx_font_type; - GtkWidget *cbx_font_size; - GtkWidget *font_color_button; - - /*Tab two*/ - GtkWidget *chk_bold; - GtkWidget *chk_italic; - GtkWidget *chk_underline; - - /*Tab three*/ - GtkWidget *chk_strikethrough; - GtkWidget *cbx_positioning; - - /*Every family*/ - PangoFontFamily **families; - gint n_families; - - /*color_set is used to show whether the color is inconsistent - * The handler id is used to block the signal emission - * when we change the color setting*/ - - gboolean color_set; - - /* font_scaling is the scaling factor applied to font - * scale in the preview dialog */ - - gdouble font_scaling; - gulong color_modified_signal_handler; -}; - -/*combo box active row indicator -2--inconsistent, -1--undefined - * please make sure that you use settings_init settings_apply - * and settings_destroy, dont even try to touch this structure - * without using the three above interface functions, of course - * if you know what you are doing, do as you please ;-)*/ -typedef struct -{ - HildonFontSelectionDialog - *fsd; /*pointer to our font selection dialog*/ - - gint family; /*combo box indicator*/ - gint size; /*combo box indicator*/ - GdkColor *color; /*free after read the setting*/ - gboolean color_inconsist; - gint weight; /*bit mask*/ - gint style; /*bit mask*/ - gint underline; /*bit mask*/ - gint strikethrough; /*bit mask*/ - gint position; /*combo box indicator*/ - -}HildonFontSelectionDialogSettings; - -static gboolean - hildon_font_selection_dialog_preview_key_press - (GtkWidget * widget, - GdkEventKey * event, - gpointer unused); - -/*Some tools from gtk_font_selection*/ -static int cmp_families (const void *a, const void *b); - -static void hildon_font_selection_dialog_show_preview - (HildonFontSelectionDialog - *fontsel); - -static PangoAttrList* - hildon_font_selection_dialog_create_attrlist - (HildonFontSelectionDialog - *fontsel, guint start_index, - guint len); - -static void hildon_font_selection_dialog_show_available_positionings - (HildonFontSelectionDialogPrivate - *priv); - -static void hildon_font_selection_dialog_show_available_fonts - (HildonFontSelectionDialog - *fontsel); - -static void hildon_font_selection_dialog_show_available_sizes - (HildonFontSelectionDialogPrivate - *priv); - -static void hildon_font_selection_dialog_class_init - (HildonFontSelectionDialogClass - *klass); - -static void hildon_font_selection_dialog_init - (HildonFontSelectionDialog - *fontseldiag); - -static void hildon_font_selection_dialog_finalize - (GObject * object); - -static void hildon_font_selection_dialog_construct_notebook - (HildonFontSelectionDialog - *fontsel); - -static void color_modified_cb (HildonColorButton *button, - GParamSpec *pspec, - gpointer fsd_priv); - -static void check_tags (gpointer data, - gpointer user_data); - -static void settings_init (HildonFontSelectionDialogSettings - *setttings, - HildonFontSelectionDialog - *fsd); - -static void settings_apply (HildonFontSelectionDialogSettings - *setttings); - -static void settings_destroy (HildonFontSelectionDialogSettings - *setttings); - -static void bit_mask_toggle (gint mask, GtkToggleButton* - button, GObject *object, - const gchar *prop, - const gchar *prop_set); - -static void combo_active (gint active, GtkComboBox *box, - GObject *object, - const gchar *prop, - const gchar *prop_set); - -static void add_preview_text_attr (PangoAttrList *list, - PangoAttribute *attr, - guint start, - guint len); - -static void toggle_clicked (GtkButton *button, - gpointer unused); - - - -static GtkDialogClass *font_selection_dialog_parent_class = NULL; - -GType hildon_font_selection_dialog_get_type(void) -{ - static GType font_selection_dialog_type = 0; - - if (!font_selection_dialog_type) { - static const GTypeInfo fontsel_diag_info = { - sizeof(HildonFontSelectionDialogClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_font_selection_dialog_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonFontSelectionDialog), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_font_selection_dialog_init, - }; - - font_selection_dialog_type = - g_type_register_static(GTK_TYPE_DIALOG, - "HildonFontSelectionDialog", - &fontsel_diag_info, 0); - } - - return font_selection_dialog_type; -} - -static void -hildon_font_selection_dialog_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - gint i; - GdkColor *color = NULL; - - HildonFontSelectionDialogPrivate *priv = - HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE( - HILDON_FONT_SELECTION_DIALOG(object)); - - - switch (prop_id) - { - case PROP_FAMILY: - i = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->cbx_font_type)); - if(i >= 0 && i < priv->n_families) - g_value_set_string(value, - pango_font_family_get_name(priv->families[i])); - else - g_value_set_string(value, "Sans"); - break; - - case PROP_FAMILY_SET: - i = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->cbx_font_type)); - if(i >= 0 && i < priv->n_families) - g_value_set_boolean(value, TRUE); - else - g_value_set_boolean(value, FALSE); - break; - - case PROP_SIZE: - i = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->cbx_font_size)); - if(i >= 0 && i < G_N_ELEMENTS(font_sizes)) - g_value_set_int(value, font_sizes[i]); - else - g_value_set_int(value, 16); - break; - - case PROP_SIZE_SET: - i = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->cbx_font_size)); - if(i >= 0 && i < G_N_ELEMENTS(font_sizes)) - g_value_set_boolean(value, TRUE); - else - g_value_set_boolean(value, FALSE); - break; - - case PROP_COLOR: - color = hildon_color_button_get_color - (HILDON_COLOR_BUTTON(priv->font_color_button)); - g_value_set_boxed(value, (gconstpointer) color); - if(color != NULL) - gdk_color_free(color); - break; - - case PROP_COLOR_SET: - g_value_set_boolean(value, priv->color_set); - break; - - case PROP_BOLD: - g_value_set_boolean(value, - gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->chk_bold))); - break; - - case PROP_BOLD_SET: - g_value_set_boolean(value, - !gtk_toggle_button_get_inconsistent - (GTK_TOGGLE_BUTTON(priv->chk_bold))); - break; - - case PROP_ITALIC: - g_value_set_boolean(value, - gtk_toggle_button_get_active - (GTK_TOGGLE_BUTTON(priv->chk_italic))); - break; - - case PROP_ITALIC_SET: - g_value_set_boolean(value, - !gtk_toggle_button_get_inconsistent - (GTK_TOGGLE_BUTTON(priv->chk_italic))); - break; - - case PROP_UNDERLINE: - g_value_set_boolean(value, - gtk_toggle_button_get_active - (GTK_TOGGLE_BUTTON(priv->chk_underline))); - break; - - case PROP_UNDERLINE_SET: - g_value_set_boolean(value, - !gtk_toggle_button_get_inconsistent - (GTK_TOGGLE_BUTTON(priv->chk_underline))); - break; - - case PROP_STRIKETHROUGH: - g_value_set_boolean(value, - gtk_toggle_button_get_active - (GTK_TOGGLE_BUTTON(priv->chk_strikethrough))); - break; - - case PROP_STRIKETHROUGH_SET: - g_value_set_boolean(value, - !gtk_toggle_button_get_inconsistent - (GTK_TOGGLE_BUTTON(priv->chk_strikethrough))); - break; - - case PROP_POSITION: - i = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->cbx_positioning)); - if(i == 1)/*super*/ - g_value_set_int(value, 1); - else if(i == 2)/*sub*/ - g_value_set_int(value, -1); - else - g_value_set_int(value, 0); - break; - - case PROP_FONT_SCALING: - g_value_set_double(value, priv->font_scaling); - break; - - case PROP_POSITION_SET: - i = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->cbx_positioning)); - if(i >= 0 && i < 3) - g_value_set_boolean(value, TRUE); - else - g_value_set_boolean(value, FALSE); - break; - - case PROP_PREVIEW_TEXT: - g_value_set_string(value, - hildon_font_selection_dialog_get_preview_text( - HILDON_FONT_SELECTION_DIALOG(object))); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -hildon_font_selection_dialog_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - gint i, size; - const gchar *str; - gboolean b; - GdkColor *color = NULL; - GdkColor black; - - HildonFontSelectionDialogPrivate *priv = - HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE( - HILDON_FONT_SELECTION_DIALOG(object)); - black.red = black.green = black.blue = 0; - - switch (prop_id) - { - case PROP_FAMILY: - str = g_value_get_string(value); - for(i = 0; i < priv->n_families; i++) - { - if(strcmp(str, pango_font_family_get_name(priv->families[i])) - == 0) - { - gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_font_type), i); - break; - } - } - break; - - case PROP_FAMILY_SET: - b = g_value_get_boolean(value); - if(!b) - gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_font_type), -1); - break; - - case PROP_SIZE: - size = g_value_get_int(value); - for(i = 0; i < G_N_ELEMENTS(font_sizes); i++) - { - if(size == font_sizes[i]) - { - gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_font_size), i); - break; - } - } - break; - - case PROP_SIZE_SET: - b = g_value_get_boolean(value); - if(!b) - gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_font_size), -1); - break; - - case PROP_COLOR: - color = (GdkColor *) g_value_get_boxed(value); - if(color != NULL) - hildon_color_button_set_color(HILDON_COLOR_BUTTON - (priv->font_color_button), - color); - else - hildon_color_button_set_color(HILDON_COLOR_BUTTON - (priv->font_color_button), - &black); - break; - - case PROP_COLOR_SET: - priv->color_set = g_value_get_boolean(value); - if(!priv->color_set) - { - /*set color to black, but block our signal handler*/ - g_signal_handler_block((gpointer) priv->font_color_button, - priv->color_modified_signal_handler); - - hildon_color_button_set_color(HILDON_COLOR_BUTTON - (priv->font_color_button), - &black); - - g_signal_handler_unblock((gpointer) priv->font_color_button, - priv->color_modified_signal_handler); - } - break; - - case PROP_BOLD: - /*this call will make sure that we dont get extra clicked signal*/ - gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(priv->chk_bold), - FALSE); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->chk_bold), - g_value_get_boolean(value)); - break; - - case PROP_BOLD_SET: - gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(priv->chk_bold), - !g_value_get_boolean(value)); - break; - - case PROP_ITALIC: - gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(priv->chk_italic), - FALSE); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->chk_italic), - g_value_get_boolean(value)); - break; - - case PROP_ITALIC_SET: - gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(priv->chk_italic), - !g_value_get_boolean(value)); - break; - - case PROP_UNDERLINE: - gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON - (priv->chk_underline), - FALSE); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->chk_underline), - g_value_get_boolean(value)); - break; - - case PROP_UNDERLINE_SET: - gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(priv->chk_underline), - !g_value_get_boolean(value)); - break; - - case PROP_STRIKETHROUGH: - gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON - (priv->chk_strikethrough), - FALSE); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->chk_strikethrough), - g_value_get_boolean(value)); - break; - - case PROP_STRIKETHROUGH_SET: - gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON - (priv->chk_strikethrough), - !g_value_get_boolean(value)); - break; - - case PROP_POSITION: - i = g_value_get_int(value); - if( i == 1 ) - gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_positioning), 1); - else if(i == -1) - gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_positioning), 2); - else - gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_positioning), 0); - break; - - case PROP_FONT_SCALING: - priv->font_scaling = g_value_get_double(value); - break; - - case PROP_POSITION_SET: - b = g_value_get_boolean(value); - if(!b) - gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_positioning), -1); - break; - - case PROP_PREVIEW_TEXT: - hildon_font_selection_dialog_set_preview_text( - HILDON_FONT_SELECTION_DIALOG(object), - g_value_get_string(value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -hildon_font_selection_dialog_class_init(HildonFontSelectionDialogClass * - klass) -{ - GObjectClass *gobject_class; - - font_selection_dialog_parent_class = g_type_class_peek_parent(klass); - gobject_class = G_OBJECT_CLASS(klass); - gobject_class->finalize = hildon_font_selection_dialog_finalize; - gobject_class->get_property = hildon_font_selection_dialog_get_property; - gobject_class->set_property = hildon_font_selection_dialog_set_property; - - /* Install property to the class */ - g_object_class_install_property(gobject_class, PROP_FAMILY, - g_param_spec_string("family", - "Font family", "String defines" - " the font family", "Sans", - G_PARAM_READWRITE)); - - g_object_class_install_property(gobject_class, PROP_FAMILY_SET, - g_param_spec_boolean ("family-set", - "family inconsistent state", - "Whether the family property" - " is inconsistent", FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - g_object_class_install_property(gobject_class, PROP_SIZE, - g_param_spec_int ("size", - "Font size", - "Font size in Pt", - 6, 32, 16, - G_PARAM_READWRITE)); - - g_object_class_install_property(gobject_class, PROP_SIZE_SET, - g_param_spec_boolean ("size-set", - "size inconsistent state", - "Whether the size property" - " is inconsistent", FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - g_object_class_install_property(gobject_class, PROP_COLOR, - g_param_spec_boxed ("color", - "text color", - "gdk color for the text", - GDK_TYPE_COLOR, - G_PARAM_READWRITE)); - - g_object_class_install_property(gobject_class, PROP_COLOR_SET, - g_param_spec_boolean ("color-set", - "color inconsistent state", - "Whether the color property" - " is inconsistent", FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - g_object_class_install_property(gobject_class, PROP_BOLD, - g_param_spec_boolean ("bold", - "text weight", - "Whether the text is bold", - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property(gobject_class, PROP_BOLD_SET, - g_param_spec_boolean ("bold-set", - "bold inconsistent state", - "Whether the bold" - " is inconsistent", FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - g_object_class_install_property(gobject_class, PROP_ITALIC, - g_param_spec_boolean ("italic", - "text style", - "Whether the text is italic", - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property(gobject_class, PROP_ITALIC_SET, - g_param_spec_boolean ("italic-set", - "italic inconsistent state", - "Whether the italic" - " is inconsistent", FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - g_object_class_install_property(gobject_class, PROP_UNDERLINE, - g_param_spec_boolean ("underline", - "text underline", - "Whether the text is underlined", - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property(gobject_class, PROP_UNDERLINE_SET, - g_param_spec_boolean ("underline-set", - "underline inconsistent state", - "Whether the underline" - " is inconsistent", FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - g_object_class_install_property(gobject_class, PROP_STRIKETHROUGH, - g_param_spec_boolean ("strikethrough", - "strikethroughed text", - "Whether the text is strikethroughed", - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property(gobject_class, PROP_STRIKETHROUGH_SET, - g_param_spec_boolean ("strikethrough-set", - "strikethrough inconsistent state", - "Whether the strikethrough" - " is inconsistent", FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - g_object_class_install_property(gobject_class, PROP_POSITION, - g_param_spec_int ("position", - "Font position", - "Font position super or subscript", - -1, 1, 0, - G_PARAM_READWRITE)); - - /* FIXME This was introduced in 0.14.1. We don't have documentation for - * properties anyways, but once it's there it needs to be marked as - * Since: 0.14.1 */ - g_object_class_install_property(gobject_class, PROP_FONT_SCALING, - g_param_spec_double ("font-scaling", - "Font scaling", - "Font scaling for the preview dialog", - 0, 10, 1, - G_PARAM_READWRITE)); - - g_object_class_install_property(gobject_class, PROP_POSITION_SET, - g_param_spec_boolean ("position-set", - "position inconsistent state", - "Whether the position" - " is inconsistent", FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - g_object_class_install_property(gobject_class, PROP_PREVIEW_TEXT, - g_param_spec_string("preview-text", - "Preview Text", - "the text in preview dialog, which does" - "not include the reference text", - "", - G_PARAM_READWRITE)); - - - g_type_class_add_private(klass, - sizeof(struct _HildonFontSelectionDialogPrivate)); -} - - -static void -hildon_font_selection_dialog_init(HildonFontSelectionDialog *fontseldiag) -{ - HildonFontSelectionDialogPrivate *priv = - HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fontseldiag); - GtkWidget *preview_button; - - priv->notebook = GTK_NOTEBOOK(gtk_notebook_new()); - - hildon_font_selection_dialog_construct_notebook(fontseldiag); - - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fontseldiag)->vbox), - GTK_WIDGET(priv->notebook), TRUE, TRUE, 0); - - /* Add dialog buttons */ - gtk_dialog_add_button(GTK_DIALOG(fontseldiag), - _("ecdg_bd_font_dialog_ok"), - GTK_RESPONSE_OK); - - preview_button = gtk_button_new_with_label(_("ecdg_bd_font_dialog_preview")); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fontseldiag)->action_area), - preview_button, FALSE, TRUE, 0); - g_signal_connect_swapped(preview_button, "clicked", - G_CALLBACK - (hildon_font_selection_dialog_show_preview), - fontseldiag); - gtk_widget_show(preview_button); - - gtk_dialog_add_button(GTK_DIALOG(fontseldiag), - _("ecdg_bd_font_dialog_cancel"), - GTK_RESPONSE_CANCEL); - - /*Set default preview text*/ - priv->preview_text = g_strdup(_("ecdg_fi_preview_font_preview_text")); - - gtk_window_set_title(GTK_WINDOW(fontseldiag), _("ecdg_ti_font")); - /*here is the line to make sure that notebook has the default focus*/ - gtk_container_set_focus_child(GTK_CONTAINER(GTK_DIALOG(fontseldiag)->vbox), - GTK_WIDGET(priv->notebook)); -} - -static void -hildon_font_selection_dialog_construct_notebook (HildonFontSelectionDialog - *fontsel) -{ - gint i; - GtkWidget *vbox_tab[3]; - GtkWidget *font_color_box; - GtkWidget *caption_control; - GtkSizeGroup *group; - - HildonFontSelectionDialogPrivate *priv = - HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fontsel); - - for (i = 0; i < 3; i++) - vbox_tab[i] = gtk_vbox_new(TRUE, 0); - - group = - GTK_SIZE_GROUP(gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL)); - - /* Build the first page of the GtkNotebook: font style */ - priv->cbx_font_type = gtk_combo_box_new_text(); - hildon_font_selection_dialog_show_available_fonts(fontsel); - caption_control = hildon_caption_new(group, - _("ecdg_fi_font_font"), - priv->cbx_font_type, - NULL, - HILDON_CAPTION_OPTIONAL); - gtk_box_pack_start(GTK_BOX(vbox_tab[0]), caption_control, - FALSE, FALSE, 0); - - priv->cbx_font_size = gtk_combo_box_new_text(); - hildon_font_selection_dialog_show_available_sizes(priv); - caption_control = hildon_caption_new(group, - _("ecdg_fi_font_size"), - priv->cbx_font_size, - NULL, - HILDON_CAPTION_OPTIONAL); - gtk_box_pack_start(GTK_BOX(vbox_tab[0]), caption_control, - FALSE, FALSE, 0); - - font_color_box = gtk_hbox_new(FALSE, 0); - priv->font_color_button = hildon_color_button_new(); - priv->color_set = FALSE; - priv->font_scaling = 1.0; - priv->color_modified_signal_handler = - g_signal_connect(G_OBJECT(priv->font_color_button), "notify::color", - G_CALLBACK(color_modified_cb), (gpointer) priv); - gtk_box_pack_start(GTK_BOX(font_color_box), - priv->font_color_button, FALSE, FALSE, 0); - - caption_control = - hildon_caption_new(group, _("ecdg_fi_font_colour_selector"), - font_color_box, - NULL, HILDON_CAPTION_OPTIONAL); - - gtk_box_pack_start(GTK_BOX(vbox_tab[0]), caption_control, - FALSE, FALSE, 0); - - /* Build the second page of the GtkNotebook: font formatting */ - priv->chk_bold = gtk_check_button_new(); - caption_control = hildon_caption_new(group, - _("ecdg_fi_font_bold"), - priv->chk_bold, - NULL, - HILDON_CAPTION_OPTIONAL); - gtk_box_pack_start(GTK_BOX(vbox_tab[1]), caption_control, - FALSE, FALSE, 0); - g_signal_connect(G_OBJECT(priv->chk_bold), "clicked", - G_CALLBACK(toggle_clicked), NULL); - - priv->chk_italic = gtk_check_button_new(); - caption_control = - hildon_caption_new(group, _("ecdg_fi_font_italic"), - priv->chk_italic, - NULL, HILDON_CAPTION_OPTIONAL); - gtk_box_pack_start(GTK_BOX(vbox_tab[1]), caption_control, - FALSE, FALSE, 0); - g_signal_connect(G_OBJECT(priv->chk_italic), "clicked", - G_CALLBACK(toggle_clicked), NULL); - - priv->chk_underline = gtk_check_button_new(); - caption_control = - hildon_caption_new(group, _("ecdg_fi_font_underline"), - priv->chk_underline, NULL, - HILDON_CAPTION_OPTIONAL); - gtk_box_pack_start(GTK_BOX(vbox_tab[1]), caption_control, - FALSE, FALSE, 0); - g_signal_connect(G_OBJECT(priv->chk_underline), "clicked", - G_CALLBACK(toggle_clicked), NULL); - - /* Build the third page of the GtkNotebook: other font properties */ - priv->chk_strikethrough = gtk_check_button_new(); - caption_control = - hildon_caption_new(group, _("ecdg_fi_font_strikethrough"), - priv->chk_strikethrough, NULL, - HILDON_CAPTION_OPTIONAL); - gtk_box_pack_start(GTK_BOX(vbox_tab[2]), caption_control, - FALSE, FALSE, 0); - g_signal_connect(G_OBJECT(priv->chk_strikethrough), "clicked", - G_CALLBACK(toggle_clicked), NULL); - - priv->cbx_positioning = gtk_combo_box_new_text(); - hildon_font_selection_dialog_show_available_positionings(priv); - caption_control = - hildon_caption_new(group, _("ecdg_fi_font_special"), - priv->cbx_positioning, NULL, - HILDON_CAPTION_OPTIONAL); - gtk_box_pack_start(GTK_BOX(vbox_tab[2]), caption_control, - FALSE, FALSE, 0); - - /* Populate notebook */ - gtk_notebook_insert_page(priv->notebook, vbox_tab[0], NULL, 0); - gtk_notebook_insert_page(priv->notebook, vbox_tab[1], NULL, 1); - gtk_notebook_insert_page(priv->notebook, vbox_tab[2], NULL, 2); - gtk_notebook_set_tab_label_text(priv->notebook, vbox_tab[0], - _("ecdg_ti_font_dialog_style")); - gtk_notebook_set_tab_label_text(priv->notebook, vbox_tab[1], - _("ecdg_ti_font_dialog_format")); - gtk_notebook_set_tab_label_text(priv->notebook, vbox_tab[2], - _("ecdg_ti_font_dialog_other")); - - gtk_widget_show_all(GTK_WIDGET(priv->notebook)); -} - -static void -color_modified_cb(HildonColorButton *button, - GParamSpec *pspec, - gpointer fsd_priv) -{ - HildonFontSelectionDialogPrivate *priv = - (HildonFontSelectionDialogPrivate *) fsd_priv; - - priv->color_set = TRUE; -} - -static void -hildon_font_selection_dialog_finalize(GObject * object) -{ - HildonFontSelectionDialogPrivate *priv; - HildonFontSelectionDialog *fontsel; - - g_assert(HILDON_IS_FONT_SELECTION_DIALOG(object)); - fontsel = HILDON_FONT_SELECTION_DIALOG(object); - - priv = HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fontsel); - - g_free(priv->preview_text); - g_free(priv->families); - - if (G_OBJECT_CLASS(font_selection_dialog_parent_class)->finalize) - G_OBJECT_CLASS(font_selection_dialog_parent_class)->finalize(object); -} - -static int -cmp_families(const void *a, const void *b) -{ - const char *a_name = - pango_font_family_get_name(*(PangoFontFamily **) a); - const char *b_name = - pango_font_family_get_name(*(PangoFontFamily **) b); - - return g_utf8_collate(a_name, b_name); -} - -/* Exits the preview dialog with GTK_RESPONSE_CANCEL if Esc key - * was pressed */ -static gboolean -hildon_font_selection_dialog_preview_key_press(GtkWidget * widget, - GdkEventKey * event, - gpointer unused) -{ - g_assert(widget); - g_assert(event); - - if (event->keyval == GDK_Escape) - { - gtk_dialog_response(GTK_DIALOG(widget), GTK_RESPONSE_CANCEL); - return TRUE; - } - - return FALSE; -} - -static void -add_preview_text_attr(PangoAttrList *list, PangoAttribute *attr, - guint start, guint len) -{ - attr->start_index = start; - attr->end_index = start + len; - pango_attr_list_insert(list, attr); -} - -static PangoAttrList* -hildon_font_selection_dialog_create_attrlist(HildonFontSelectionDialog * - fontsel, guint start_index, guint len) -{ - PangoAttrList *list; - PangoAttribute *attr; - gint size, position; - gboolean family_set, size_set, color_set, bold, bold_set, - italic, italic_set, underline, underline_set, - strikethrough, strikethrough_set, position_set; - GdkColor *color = NULL; - gchar *family = NULL; - gdouble font_scaling = 1.0; - - list = pango_attr_list_new(); - - g_object_get(G_OBJECT(fontsel), - "family", &family, "family-set", &family_set, - "size", &size, "size-set", &size_set, - "color", &color, "color-set", &color_set, - "bold", &bold, "bold-set", &bold_set, - "italic", &italic, "italic-set", &italic_set, - "underline", &underline, "underline-set", &underline_set, - "strikethrough", &strikethrough, "strikethrough-set", - &strikethrough_set, "position", &position, - "position-set", &position_set, - "font-scaling", &font_scaling, - NULL); - - /*family*/ - if(family_set) - { - attr = pango_attr_family_new(family); - add_preview_text_attr(list, attr, start_index, len); - } - g_free(family); - - /*size*/ - if(size_set) - { - attr = pango_attr_size_new(size * PANGO_SCALE); - add_preview_text_attr(list, attr, start_index, len); - } - - /*color*/ - if(color_set) - { - attr = pango_attr_foreground_new(color->red, color->green, color->blue); - add_preview_text_attr(list, attr, start_index, len); - } - - if(color != NULL) - gdk_color_free(color); - - /*weight*/ - if(bold_set) - { - if(bold) - attr = pango_attr_weight_new(PANGO_WEIGHT_BOLD); - else - attr = pango_attr_weight_new(PANGO_WEIGHT_NORMAL); - - add_preview_text_attr(list, attr, start_index, len); - } - - /*style*/ - if(italic_set) - { - if(italic) - attr = pango_attr_style_new(PANGO_STYLE_ITALIC); - else - attr = pango_attr_style_new(PANGO_STYLE_NORMAL); - - add_preview_text_attr(list, attr, start_index, len); - } - - /*underline*/ - if(underline_set) - { - if(underline) - attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); - else - attr = pango_attr_underline_new(PANGO_UNDERLINE_NONE); - - add_preview_text_attr(list, attr, start_index, len); - } - - /*strikethrough*/ - if(strikethrough_set) - { - if(strikethrough) - attr = pango_attr_strikethrough_new(TRUE); - else - attr = pango_attr_strikethrough_new(FALSE); - - add_preview_text_attr(list, attr, start_index, len); - } - - /*position*/ - if(position_set) - { - switch(position) - { - case 1: /*super*/ - attr = pango_attr_rise_new(SUPERSCRIPT_RISE); - break; - case -1: /*sub*/ - attr = pango_attr_rise_new(SUBSCRIPT_LOW); - break; - default: /*normal*/ - attr = pango_attr_rise_new(0); - break; - } - - add_preview_text_attr(list, attr, start_index, len); - } - - /*font scaling for preview*/ - if(font_scaling) - { - attr = pango_attr_scale_new(font_scaling); - add_preview_text_attr(list, attr, 0, len + start_index); - } - - return list; -} - -static void -hildon_font_selection_dialog_show_preview(HildonFontSelectionDialog * - fontsel) -{ - HildonFontSelectionDialogPrivate *priv = - HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fontsel); - gint size; - gboolean family_set, size_set; - PangoAttribute *attr; - PangoAttrList *list; - GtkWidget *preview_dialog; - GtkWidget *preview_label; - gchar *str = NULL; - gboolean position_set = FALSE; - gint position = 0; - gboolean show_ref = FALSE; - - g_object_get(G_OBJECT(fontsel), "position-set", &position_set, NULL); - if (position_set) { - g_object_get(G_OBJECT(fontsel), "position", &position, NULL); - if (position == 1 || position == -1) - show_ref = TRUE; - } - - /*Preview dialog init*/ - preview_dialog= - gtk_dialog_new_with_buttons(_("ecdg_ti_preview_font"), NULL, - GTK_DIALOG_MODAL | - GTK_DIALOG_DESTROY_WITH_PARENT | - GTK_DIALOG_NO_SEPARATOR, - _("ecdg_bd_font_dialog_ok"), - GTK_RESPONSE_ACCEPT, - NULL); - - str = (show_ref) ? g_strconcat(_("ecdg_fi_preview_font_preview_reference"), priv->preview_text, 0) : - g_strdup (priv->preview_text); - - preview_label = gtk_label_new(str); - gtk_label_set_line_wrap(GTK_LABEL(preview_label), TRUE); - - g_free(str); - str = NULL; - - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(preview_dialog)->vbox), - preview_label); - - - /* set keypress handler (ESC hardkey) */ - g_signal_connect(G_OBJECT(preview_dialog), "key-press-event", - G_CALLBACK(hildon_font_selection_dialog_preview_key_press), - NULL); - - - /*Set the font*/ - list = (show_ref) ? hildon_font_selection_dialog_create_attrlist(fontsel, - strlen(_("ecdg_fi_preview_font_preview_reference")), - strlen(priv->preview_text)) : - hildon_font_selection_dialog_create_attrlist(fontsel, - 0, - strlen(priv->preview_text)); - - g_object_get(G_OBJECT(fontsel), "family", &str, "family-set", - &family_set, "size", &size, "size-set", &size_set, - NULL); - - /* FIXME: This is a slightly ugly hack to force the width of the window so that - * the whole text fits with various font sizes. It's being done in such a way, - * because of some GtkLabel wrapping issues and other mysterious bugs related to - * truncating ellipsizing. Needs a rethink in future. (MDK) */ - - gint dialog_width = (size_set && size > 24) ? 600 : 500; - gtk_window_set_default_size (GTK_WINDOW(preview_dialog), dialog_width, -1); - - /*make reference text to have the same fontface and size*/ - if(family_set) - { - attr = pango_attr_family_new(str); - add_preview_text_attr(list, attr, 0, strlen(_("ecdg_fi_preview_font_preview_reference"))); - } - g_free(str); - - /*size*/ - if(size_set) - { - attr = pango_attr_size_new(size * PANGO_SCALE); - add_preview_text_attr(list, attr, 0, strlen(_("ecdg_fi_preview_font_preview_reference"))); - } - - gtk_label_set_attributes(GTK_LABEL(preview_label), list); - pango_attr_list_unref(list); - - /*And show the dialog*/ - gtk_window_set_transient_for(GTK_WINDOW(preview_dialog), - GTK_WINDOW(fontsel)); - - gtk_widget_show_all(preview_dialog); - gtk_dialog_run(GTK_DIALOG(preview_dialog)); - gtk_widget_destroy(preview_dialog); -} - - -static gboolean is_internal_font(const gchar * name){ - return strcmp(name, "DeviceSymbols") == 0 - || strcmp(name, "Nokia Smiley" ) == 0 - || strcmp(name, "NewCourier" ) == 0 - || strcmp(name, "NewTimes" ) == 0 - || strcmp(name, "SwissA" ) == 0 - || strcmp(name, "Nokia Sans" ) == 0 - || strcmp(name, "Nokia Sans Cn") == 0; -} - -static void filter_out_internal_fonts(PangoFontFamily **families, int *n_families){ - int i; - int n; /* counts valid fonts */ - const gchar * name = NULL; - - for(i = 0, n = 0; i < *n_families; i++){ - - name = pango_font_family_get_name(families[i]); - - if(!is_internal_font(name)){ - - if(i!=n){ /* there are filtered out families */ - families[n] = families[i]; /* shift the current family */ - } - - n++; /* count one more valid */ - } - }/* foreach font family */ - - *n_families = n; -} - - -static void -hildon_font_selection_dialog_show_available_fonts(HildonFontSelectionDialog - *fontsel) - -{ - gint i; - - HildonFontSelectionDialogPrivate *priv = - HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fontsel); - - pango_context_list_families(gtk_widget_get_pango_context - (GTK_WIDGET(fontsel)), &priv->families, - &priv->n_families); - - filter_out_internal_fonts(priv->families, &priv->n_families); - - qsort(priv->families, priv->n_families, sizeof(PangoFontFamily *), - cmp_families); - - - for (i = 0; i < priv->n_families; i++) - { - const gchar *name = pango_font_family_get_name(priv->families[i]); - - gtk_combo_box_append_text(GTK_COMBO_BOX(priv->cbx_font_type), - name); - } -} - - -static void -hildon_font_selection_dialog_show_available_positionings - (HildonFontSelectionDialogPrivate - *priv) -{ - gtk_combo_box_append_text(GTK_COMBO_BOX(priv->cbx_positioning), - _("ecdg_va_font_printpos_1")); - gtk_combo_box_append_text(GTK_COMBO_BOX(priv->cbx_positioning), - _("ecdg_va_font_printpos_2")); - gtk_combo_box_append_text(GTK_COMBO_BOX(priv->cbx_positioning), - _("ecdg_va_font_printpos_3")); -} - -/*Loads the sizes from a pre-allocated table*/ -static void -hildon_font_selection_dialog_show_available_sizes - (HildonFontSelectionDialogPrivate - *priv) -{ - gchar *size_str; - gint i; - - for (i = 0; i < G_N_ELEMENTS(font_sizes); i++) - { - size_str = g_strdup_printf ("%i%s", - font_sizes[i], - _("ecdg_va_font_size_trailer")); - - gtk_combo_box_append_text(GTK_COMBO_BOX(priv->cbx_font_size), - size_str); - g_free (size_str); - } -} - -/* WARNING: This function is called only from deprecated API */ -static -void check_tags(gpointer data, gpointer user_data) -{ - gchar *font_family; - GdkColor *fore_color = NULL; - gint p_size, p_weight, p_style, p_underline, p_rise; - gboolean b_st, ff_s, size_s, fgc_s, w_s, ss_s, u_s, sth_s, r_s; - - GtkTextTag *tag = (GtkTextTag*) data; - HildonFontSelectionDialogSettings *settings = - (HildonFontSelectionDialogSettings *) user_data; - HildonFontSelectionDialogPrivate *priv = - HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(settings->fsd); - - /*get all the properties*/ - g_object_get(G_OBJECT(tag), - "family", &font_family, "family-set", &ff_s, - "size", &p_size, "size-set", &size_s, - "foreground-gdk", &fore_color, "foreground-set", &fgc_s, - "weight", &p_weight, "weight-set", &w_s, - "style", &p_style, "style-set", &ss_s, - "underline", &p_underline, "underline-set", &u_s, - "strikethrough", &b_st, "strikethrough-set", &sth_s, - "rise", &p_rise, "rise-set", & r_s, - NULL); - - /* Check that the given values are valid. - * If not, set the combobox row indicator to 'inconsistent' */ - if(ff_s) - { - gint new_f = -1; - gint i; - - for(i = 0; i < priv->n_families; i++) - { - if(strcmp(font_family, - pango_font_family_get_name(priv->families[i])) == 0) - { - new_f = i; - break; - } - } - - if(settings->family == -1) - settings->family = new_f; - else if(settings->family != -2 && - settings->family != new_f) - settings->family = -2;/*inconsist*/ - - g_free(font_family); - } - - if(size_s) - { - gint new_size = -1; - gint i; - - for(i = 0; i < G_N_ELEMENTS(font_sizes); i++) - { - if(p_size == font_sizes[i] * PANGO_SCALE) - { - new_size = i; - break; - } - } - - if(settings->size == -1) - settings->size = new_size; - else if(settings->size != -2 && - settings->size != new_size) - settings->size = -2;/*inconsist*/ - } - - if(fgc_s && settings->color == NULL - && !settings->color_inconsist) - settings->color = fore_color; - else if(fore_color != NULL) - { - if(!gdk_color_equal(fore_color, settings->color) - && fgc_s) - settings->color_inconsist = TRUE; - - gdk_color_free(fore_color); - } - - if(w_s) - settings->weight |= p_weight == PANGO_WEIGHT_NORMAL ? OFF_BIT : ON_BIT; - - if(ss_s) - settings->style |= p_style == PANGO_STYLE_NORMAL ? OFF_BIT : ON_BIT; - - if(u_s) - settings->underline |= - p_underline == PANGO_UNDERLINE_NONE ? OFF_BIT : ON_BIT; - - if(sth_s) - settings->strikethrough |= b_st ? ON_BIT : OFF_BIT; - - if(r_s) - { - gint new_rs = -1; - - if(p_rise == 0) - new_rs = 0;/*normal*/ - else if (p_rise > 0) - new_rs = 1;/*super*/ - else - new_rs = 2;/*sub*/ - - if(settings->position == -1) - settings->position = new_rs; - else if(settings->position != -2 && - settings->position != new_rs) - settings->position = -2;/*inconsist*/ - } -} - -/* WARNING: This function is called only from deprecated API */ -static -void check_attrs(gpointer data, gpointer user_data) -{ - PangoAttribute *attr = (PangoAttribute *) data; - HildonFontSelectionDialogSettings *settings = - (HildonFontSelectionDialogSettings *) user_data; - HildonFontSelectionDialogPrivate *priv = - HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(settings->fsd); - - gchar *family; - GdkColor color; - gint i; - gint size, weight, style, underline, strikethrough, rise; - gint new_f = -1, new_size = -1, new_rise = -1; - - /* Check that the given values are valid. - * If not, set the combobox row indicator to 'inconsistent' */ - switch(attr->klass->type) - { - case PANGO_ATTR_FAMILY: - family = ((PangoAttrString *) attr)->value; - - for(i = 0; i < priv->n_families; i++) - { - if(strcmp(family, - pango_font_family_get_name(priv->families[i])) == 0) - { - new_f = i; - break; - } - } - - if(settings->family == -1) - settings->family = new_f; - else if(settings->family != -2 && - settings->family != new_f) - settings->family = -2;/*inconsist*/ - - break; - case PANGO_ATTR_SIZE: - size = ((PangoAttrInt *) attr)->value; - - for(i = 0; i < G_N_ELEMENTS(font_sizes); i++) - { - if(size == font_sizes[i] * PANGO_SCALE) - { - new_size = i; - break; - } - } - - if(settings->size == -1) - settings->size = new_size; - else if(settings->size != -2 && - settings->size != new_size) - settings->size = -2;/*inconsist*/ - - break; - case PANGO_ATTR_FOREGROUND: - color.red = ((PangoAttrColor *) attr)->color.red; - color.green = ((PangoAttrColor *) attr)->color.green; - color.blue = ((PangoAttrColor *) attr)->color.blue; - - if(!settings->color_inconsist && settings->color == NULL) - settings->color = gdk_color_copy(&color); - else if(settings->color != NULL && - !gdk_color_equal(&color, settings->color)) - settings->color_inconsist = TRUE; - - break; - case PANGO_ATTR_WEIGHT: - weight = ((PangoAttrInt *) attr)->value; - - settings->weight |= weight == PANGO_WEIGHT_NORMAL ? OFF_BIT : ON_BIT; - - break; - case PANGO_ATTR_STYLE: - style = ((PangoAttrInt *) attr)->value; - - settings->style |= style == PANGO_STYLE_NORMAL ? OFF_BIT : ON_BIT; - - break; - case PANGO_ATTR_UNDERLINE: - underline = ((PangoAttrInt *) attr)->value; - - settings->underline |= - underline == PANGO_UNDERLINE_NONE ? OFF_BIT : ON_BIT; - - break; - case PANGO_ATTR_STRIKETHROUGH: - strikethrough = ((PangoAttrInt *) attr)->value; - - settings->strikethrough |= strikethrough ? ON_BIT : OFF_BIT; - - break; - case PANGO_ATTR_RISE: - rise = ((PangoAttrInt *) attr)->value; - - if(rise == 0) - new_rise = 0;/*normal*/ - else if (rise > 0) - new_rise = 1;/*super*/ - else - new_rise = 2;/*sub*/ - - if(settings->position == -1) - settings->position = new_rise; - else if(settings->position != -2 && - settings->position != new_rise) - settings->position = -2;/*inconsist*/ - - break; - default: - break; - } - - pango_attribute_destroy(attr); -} - -/* WARNING: This function is called only from deprecated API */ -static void -settings_init(HildonFontSelectionDialogSettings *settings, - HildonFontSelectionDialog *fsd) -{ - settings->fsd = fsd; - settings->family = -1; - settings->size = -1; - settings->color = NULL; - settings->color_inconsist = FALSE; - settings->weight = 0; - settings->style = 0; - settings->underline = 0; - settings->strikethrough = 0; - settings->position = -1; -} - -/* WARNING: This function is called only from deprecated API */ -static void -bit_mask_toggle(gint mask, GtkToggleButton *button, - GObject *object, const gchar *prop, - const gchar *prop_set) -{ - - if(mask == 3) - gtk_toggle_button_set_inconsistent(button, TRUE); - else - { - gtk_toggle_button_set_inconsistent(button, FALSE); - - if(mask == 1) - gtk_toggle_button_set_active(button, TRUE); - else - gtk_toggle_button_set_active(button, FALSE); - - g_object_notify(object, prop); - } - - g_object_notify(object, prop_set); -} - -/* WARNING: This function is called only from deprecated API */ -static void -combo_active(gint active, GtkComboBox *box, - GObject *object, const gchar *prop, const gchar *prop_set) -{ - /*probaly not the best function, but we need all these - * parameters to keep things together*/ - - - if(active >= 0) - { - gtk_combo_box_set_active(box, active); - g_object_notify(object, prop); - } - else - gtk_combo_box_set_active(box, -1); - - g_object_notify(object, prop_set); -} - -/* WARNING: This function is called only from deprecated API */ -static void -settings_apply(HildonFontSelectionDialogSettings *settings) -{ - - HildonFontSelectionDialogPrivate *priv = - HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(settings->fsd); - - /*family*/ - combo_active(settings->family, GTK_COMBO_BOX(priv->cbx_font_type), - G_OBJECT(settings->fsd), "family", "family-set"); - - /*size*/ - combo_active(settings->size, GTK_COMBO_BOX(priv->cbx_font_size), - G_OBJECT(settings->fsd), "size", "size-set"); - - /*block our signal handler indicating color has been changed by - * the user before set the color, and unblock it after setting - * is done*/ - - if(settings->color == NULL || settings->color_inconsist) - { - GdkColor black; - - black.red = black.green = black.blue = 0; - g_signal_handler_block((gpointer) priv->font_color_button, - priv->color_modified_signal_handler); - - g_object_set(G_OBJECT(settings->fsd), "color", &black, "color-set", - FALSE, NULL); - - g_signal_handler_unblock((gpointer) priv->font_color_button, - priv->color_modified_signal_handler); - } - else - g_object_set(G_OBJECT(settings->fsd), "color", settings->color, NULL); - - /*weight*/ - bit_mask_toggle(settings->weight, GTK_TOGGLE_BUTTON(priv->chk_bold), - G_OBJECT(settings->fsd), "bold", "bold-set"); - - /*style*/ - bit_mask_toggle(settings->style, GTK_TOGGLE_BUTTON(priv->chk_italic), - G_OBJECT(settings->fsd), "italic", "italic-set"); - - /*underline*/ - bit_mask_toggle(settings->underline, - GTK_TOGGLE_BUTTON(priv->chk_underline), - G_OBJECT(settings->fsd), "underline", "underline-set"); - - /*strikethrough*/ - bit_mask_toggle(settings->strikethrough, - GTK_TOGGLE_BUTTON(priv->chk_strikethrough), - G_OBJECT(settings->fsd), "strikethrough", - "strikethrough-set"); - - /*position*/ - combo_active(settings->position, GTK_COMBO_BOX(priv->cbx_positioning), - G_OBJECT(settings->fsd), "position", "position-set"); -} - -static void -settings_destroy(HildonFontSelectionDialogSettings *settings) -{ - if(settings->color != NULL) - gdk_color_free(settings->color); -} - -static void -toggle_clicked(GtkButton *button, gpointer unused) -{ - GtkToggleButton *t_b = GTK_TOGGLE_BUTTON(button); - - /*we have to remove the inconsistent state ourselves*/ - if(gtk_toggle_button_get_inconsistent(t_b)) - { - gtk_toggle_button_set_inconsistent(t_b, FALSE); - gtk_toggle_button_set_active(t_b, FALSE); - } -} - -/*******************/ -/*Public functions*/ -/*******************/ - -/** - * hildon_font_selection_dialog_new: - * @parent: the parent window - * @title: the title of font selection dialog - * - * If NULL is passed for title, then default title - * "Font" will be used. - * - * Returns: a new #HildonFontSelectionDialog - */ -GtkWidget * -hildon_font_selection_dialog_new(GtkWindow * parent, - const gchar * title) -{ - HildonFontSelectionDialog *fontseldiag; - - fontseldiag = g_object_new(HILDON_TYPE_FONT_SELECTION_DIALOG, - "has-separator", FALSE, NULL); - - if (title) - gtk_window_set_title(GTK_WINDOW(fontseldiag), title); - - if (parent) - gtk_window_set_transient_for(GTK_WINDOW(fontseldiag), parent); - - return GTK_WIDGET(fontseldiag); -} - -/** - * hildon_font_selection_dialog_get_preview_text: - * @fsd: the font selection dialog - * - * Gets the text in preview dialog, which does not include the - * reference text. The returned string must be freed by the user. - * - * Returns: a string pointer - */ -gchar * -hildon_font_selection_dialog_get_preview_text(HildonFontSelectionDialog * fsd) -{ - HildonFontSelectionDialogPrivate *priv; - - g_return_val_if_fail(HILDON_IS_FONT_SELECTION_DIALOG(fsd), FALSE); - priv = HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fsd); - return g_strdup(priv->preview_text); -} - -/** - * hildon_font_selection_dialog_set_preview_text: - * @fsd: the font selection dialog - * @text: the text to be displayed in the preview dialog - * - * The default preview text is - * "The quick brown fox jumped over the lazy dogs" - */ -void -hildon_font_selection_dialog_set_preview_text(HildonFontSelectionDialog * - fsd, const gchar * text) -{ - HildonFontSelectionDialogPrivate *priv = NULL; - - g_return_if_fail(HILDON_IS_FONT_SELECTION_DIALOG(fsd)); - g_return_if_fail(text); - - priv = HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fsd); - - g_free(priv->preview_text); - priv->preview_text = g_strdup(text); - g_object_notify (G_OBJECT (fsd), "preview-text"); -} - -/** - * hildon_font_selection_dialog_get_text_tag: - * @fsd: the font selection dialog - * - * Get the #GtkTextTag for selections. This function - * is deprecated. The best way to use - * the text tags is to reuse them as much as possible. - * The recommended way is to get the properties of the font - * selection dialog on GTK_RESPONSE_OK, and according to - * these properties use the tags that you have pre-created. - * - * Returns: a #GtkTextTag having corresponding properties - * set - */ -GtkTextTag * -hildon_font_selection_dialog_get_text_tag (HildonFontSelectionDialog *fsd) -{ - GtkTextTag *tag; - gint size, position; - gboolean family_set, size_set, color_set, bold, bold_set, - italic, italic_set, underline, underline_set, - strikethrough, strikethrough_set, position_set; - GdkColor *color = NULL; - gchar *family = NULL; - - tag = gtk_text_tag_new(NULL); - - g_object_get(G_OBJECT(fsd), - "family", &family, "family-set", &family_set, - "size", &size, "size-set", &size_set, - "color", &color, "color-set", &color_set, - "bold", &bold, "bold-set", &bold_set, - "italic", &italic, "italic-set", &italic_set, - "underline", &underline, "underline-set", &underline_set, - "strikethrough", &strikethrough, "strikethrough-set", - &strikethrough_set, "position", &position, - "position-set", &position_set, NULL); - /*family*/ - if(family_set) - g_object_set(G_OBJECT(tag), "family", - family, "family-set", TRUE, NULL); - else - g_object_set(G_OBJECT(tag), "family-set", FALSE, NULL); - - g_free(family); - - /*size*/ - if(size_set) - g_object_set(G_OBJECT(tag), "size", size * PANGO_SCALE, - "size-set", TRUE, NULL); - else - g_object_set(G_OBJECT(tag), "size-set", FALSE, NULL); - - /*color*/ - if(color_set) - g_object_set(G_OBJECT(tag), "foreground-gdk", color, - "foreground-set", TRUE ,NULL); - else - g_object_set(G_OBJECT(tag), "foreground-set", FALSE, NULL); - - if(color != NULL) - gdk_color_free(color); - - /*weight*/ - if(bold_set) - { - if(bold) - g_object_set(G_OBJECT(tag), "weight", PANGO_WEIGHT_BOLD, NULL); - else - g_object_set(G_OBJECT(tag), "weight", PANGO_WEIGHT_NORMAL, NULL); - - g_object_set(G_OBJECT(tag), "weight-set", TRUE, NULL); - } - else - g_object_set(G_OBJECT(tag), "weight-set", FALSE, NULL); - - /*style*/ - if(italic_set) - { - if(italic) - g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_ITALIC, NULL); - else - g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_NORMAL, NULL); - - g_object_set(G_OBJECT(tag), "style-set", TRUE, NULL); - } - else - g_object_set(G_OBJECT(tag), "style-set", FALSE, NULL); - - /*underline*/ - if(underline_set) - { - if(underline) - g_object_set(G_OBJECT(tag), "underline", PANGO_UNDERLINE_SINGLE, NULL); - else - g_object_set(G_OBJECT(tag), "underline", PANGO_UNDERLINE_NONE, NULL); - - g_object_set(G_OBJECT(tag), "underline-set", TRUE, NULL); - } - else - g_object_set(G_OBJECT(tag), "underline-set", FALSE, NULL); - - /*strikethrough*/ - if(strikethrough_set) - { - if(strikethrough) - g_object_set(G_OBJECT(tag), "strikethrough", TRUE, NULL); - else - g_object_set(G_OBJECT(tag), "strikethrough", FALSE, NULL); - - g_object_set(G_OBJECT(tag), "strikethrough-set", TRUE, NULL); - } - else - g_object_set(G_OBJECT(tag), "strikethrough-set", FALSE, NULL); - - /*position*/ - if(position_set) - { - switch(position) - { - case 1: /*super*/ - g_object_set(G_OBJECT(tag), "rise", SUPERSCRIPT_RISE, NULL); - break; - case -1: /*sub*/ - g_object_set(G_OBJECT(tag), "rise", SUBSCRIPT_LOW, NULL); - break; - case 0: /*normal*/ - g_object_set(G_OBJECT(tag), "rise", 0, NULL); - break; - } - g_object_set(G_OBJECT(tag), "rise-set", TRUE, NULL); - } - else - g_object_set(G_OBJECT(tag), "rise-set", FALSE, NULL); - - return tag; -} - -/** - * hildon_font_selection_dialog_set_buffer: - * @fsd: the font selection dialog - * @buffer: a #GtkTextBuffer containing the text to which the selections will - * be applied. Applying is responsibility of application. - * - * This is deprecated. GtkTextBuffer is not enough - * to get the attributes of currently selected text. Please - * inspect the attributes yourself, and set the properties of - * font selection dialog to reflect your inspection. - */ -void -hildon_font_selection_dialog_set_buffer (HildonFontSelectionDialog *fsd, - GtkTextBuffer *buffer) -{ - GtkTextIter begin, end, iter; - HildonFontSelectionDialogSettings settings; - - gtk_text_buffer_get_selection_bounds(buffer, &begin, &end); - - settings_init(&settings, fsd); - - iter = begin; - - /* Keep original settings if the selection includes nothing */ - if(gtk_text_iter_compare(&iter, &end) == 0) - { - GSList *slist; - - slist = gtk_text_iter_get_tags(&iter); - g_slist_foreach(slist, check_tags, (gpointer) &settings); - g_slist_free(slist); - } - - /* Apply the user settings to the selected text */ - while(gtk_text_iter_compare(&iter, &end) < 0) - { - GSList *slist; - - slist = gtk_text_iter_get_tags(&iter); - g_slist_foreach(slist, check_tags, (gpointer) &settings); - g_slist_free(slist); - - if(!gtk_text_iter_forward_cursor_position(&iter)) - break; - } - - settings_apply(&settings); - settings_destroy(&settings); -} - -/** - * hildon_font_selection_dialog_get_font: - * @fsd: the font selection dialog - * - * This is deprecated. @PangoAttrList needs - * starting index, and end index on construction. - * - * Returns: pointer to @PangoAttrList - */ -PangoAttrList -*hildon_font_selection_dialog_get_font(HildonFontSelectionDialog * fsd) -{ - HildonFontSelectionDialogPrivate *priv - = HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fsd); - - g_return_val_if_fail(HILDON_IS_FONT_SELECTION_DIALOG(fsd), FALSE); - /*an approve of none working api, should have ask for start_index, - * and length in bytes of the string, currently using preview_text - * length, KLUDGE!*/ - - return hildon_font_selection_dialog_create_attrlist(fsd, - 0, strlen(priv->preview_text)); -} - -/** - * hildon_font_selection_dialog_set_font: - * @fsd: the font selection dialog - * @list: the pango attribute list - * - * This is a deprecated. - * - * Sets the font to the dialog. - */ -void -hildon_font_selection_dialog_set_font(HildonFontSelectionDialog * fsd, - PangoAttrList * list) -{ - PangoAttrIterator *iter; - HildonFontSelectionDialogSettings settings; - - iter = pango_attr_list_get_iterator(list); - - settings_init(&settings, fsd); - - while(iter != NULL) - { - GSList *slist; - - slist = pango_attr_iterator_get_attrs(iter); - g_slist_foreach(slist, check_attrs, (gpointer) &settings); - g_slist_free(slist); - - if(!pango_attr_iterator_next(iter)) - break; - } - - pango_attr_iterator_destroy(iter); - - settings_apply(&settings); - settings_destroy(&settings); -} diff --git a/hildon-widgets/hildon-font-selection-dialog.h b/hildon-widgets/hildon-font-selection-dialog.h deleted file mode 100644 index da8134b..0000000 --- a/hildon-widgets/hildon-font-selection-dialog.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ -#ifndef __HILDON_FONT_SELECTION_DIALOG_H__ -#define __HILDON_FONT_SELECTION_DIALOG_H__ - -#include -#include - -G_BEGIN_DECLS - -#define HILDON_TYPE_FONT_SELECTION_DIALOG \ - (hildon_font_selection_dialog_get_type ()) -#define HILDON_FONT_SELECTION_DIALOG(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj),\ - HILDON_TYPE_FONT_SELECTION_DIALOG, HildonFontSelectionDialog)) -#define HILDON_FONT_SELECTION_DIALOG_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass),\ - HILDON_TYPE_FONT_SELECTION_DIALOG,\ - HildonFontSelectionDialogClass)) -#define HILDON_IS_FONT_SELECTION_DIALOG(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\ - HILDON_TYPE_FONT_SELECTION_DIALOG)) -#define HILDON_IS_FONT_SELECTION_DIALOG_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass),\ - HILDON_TYPE_FONT_SELECTION_DIALOG)) -#define HILDON_FONT_SELECTION_DIALOG_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj),\ - HILDON_TYPE_FONT_SELECTION_DIALOG,\ - HildonFontSelectionDialogClass)) - -typedef struct _HildonFontSelectionDialog HildonFontSelectionDialog; -typedef struct _HildonFontSelectionDialogClass HildonFontSelectionDialogClass; - -struct _HildonFontSelectionDialog -{ - GtkDialog parent; -}; - -struct _HildonFontSelectionDialogClass -{ - GtkDialogClass parent_class; - - /* Padding for future expansion */ - void (*_gtk_reserved1) (void); - void (*_gtk_reserved2) (void); - void (*_gtk_reserved3) (void); - void (*_gtk_reserved4) (void); -}; - -#ifndef HILDON_DISABLE_DEPRECATED -PangoAttrList* hildon_font_selection_dialog_get_font(HildonFontSelectionDialog *fsd); - -void hildon_font_selection_dialog_set_font(HildonFontSelectionDialog *fsd, - PangoAttrList *list); -#endif - - -GType hildon_font_selection_dialog_get_type (void) G_GNUC_CONST; - -GtkWidget* hildon_font_selection_dialog_new (GtkWindow *parent, - const gchar *title); - - -#ifndef HILDON_DISABLE_DEPRECATED -void hildon_font_selection_dialog_set_buffer (HildonFontSelectionDialog *fsd, - GtkTextBuffer *buffer); - -GtkTextTag* hildon_font_selection_dialog_get_text_tag (HildonFontSelectionDialog *fsd); -#endif - - -gchar* hildon_font_selection_dialog_get_preview_text (HildonFontSelectionDialog *fsd); - -void hildon_font_selection_dialog_set_preview_text (HildonFontSelectionDialog *fsd, - const gchar * text); - -G_END_DECLS - -#endif /* __HILDON_FONT_SELECTION_DIALOG_H__ */ diff --git a/hildon-widgets/hildon-get-password-dialog.c b/hildon-widgets/hildon-get-password-dialog.c deleted file mode 100644 index 45bd412..0000000 --- a/hildon-widgets/hildon-get-password-dialog.c +++ /dev/null @@ -1,569 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-get-password-dialog - * @short_description: A widget used to get a password - * @see_also: #HildonSetPasswordDialog - * - * HildonGetPasswordDialog prompts the user for a password. It allows - * inputting password, with an optional configurable label eg. for - * showing the domain. The maximum length of the password can be set. - */ - -#include - -#include -#include -#include -#include -#include - -#include - -#include "gtk-infoprint.h" -#include "hildon-input-mode-hint.h" - -#include -#include - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#define _(String) dgettext(PACKAGE, String) - -static GtkDialogClass * parent_class; - -typedef struct _HildonGetPasswordDialogPrivate - HildonGetPasswordDialogPrivate; - -struct _HildonGetPasswordDialogPrivate { - GtkButton *okButton; - GtkButton *cancelButton; - - GtkLabel *domainLabel; - HildonCaption *passwordEntry; - gboolean get_old; -}; - - -#define HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_GET_PASSWORD_DIALOG, HildonGetPasswordDialogPrivate)); - -static void -hildon_get_password_dialog_class_init(HildonGetPasswordDialogClass * - class); -static void hildon_get_password_dialog_init(HildonGetPasswordDialog * - widget); -static void hildon_get_password_set_property(GObject * object, - guint prop_id, - const GValue * value, - GParamSpec * pspec); -static void hildon_get_password_get_property(GObject * object, - guint prop_id, GValue * value, - GParamSpec * pspec); -static void create_contents(HildonGetPasswordDialog *dialog); -static void _invalid_input(GtkWidget *widget, GtkInvalidInputType reason, - gpointer unused); - -enum{ - PROP_NONE = 0, - PROP_DOMAIN, - PROP_PASSWORD, - PROP_NUMBERS_ONLY, - PROP_CAPTION_LABEL, - PROP_MAX_CHARS, - PROP_GET_OLD -}; - -/* Private functions */ -static void -hildon_get_password_set_property(GObject * object, - guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - HildonGetPasswordDialog *dialog = HILDON_GET_PASSWORD_DIALOG(object); - HildonGetPasswordDialogPrivate *priv; - - priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE(dialog); - - switch (prop_id) { - case PROP_DOMAIN: - /* Set label text representing password domain */ - gtk_label_set_text(priv->domainLabel, g_value_get_string(value)); - break; - case PROP_PASSWORD: - gtk_entry_set_text(GTK_ENTRY - (hildon_caption_get_control (priv->passwordEntry)), - g_value_get_string(value)); - break; - case PROP_NUMBERS_ONLY: - /* Set input mode for the password entry */ - g_object_set(G_OBJECT(hildon_caption_get_control(priv->passwordEntry)), - "input-mode", - (g_value_get_boolean(value) - ? HILDON_INPUT_MODE_HINT_NUMERIC - : HILDON_INPUT_MODE_HINT_ALPHANUMERICSPECIAL), - NULL); - break; - case PROP_CAPTION_LABEL: - hildon_get_password_dialog_set_caption(dialog, g_value_get_string(value)); - break; - case PROP_MAX_CHARS: - hildon_get_password_dialog_set_max_characters(dialog, - g_value_get_int(value)); - break; - case PROP_GET_OLD: - priv->get_old = g_value_get_boolean(value); - create_contents(dialog); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -hildon_get_password_get_property(GObject * object, - guint prop_id, - GValue * value, GParamSpec * pspec) -{ - HildonGetPasswordDialog *dialog = HILDON_GET_PASSWORD_DIALOG(object); - HildonGetPasswordDialogPrivate *priv; - const gchar *string; - gint max_length; - gint input_mode; - - priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE(dialog); - - switch (prop_id) { - case PROP_DOMAIN: - string = gtk_label_get_text(priv->domainLabel); - g_value_set_string(value, string); - break; - case PROP_PASSWORD: - string = gtk_entry_get_text(GTK_ENTRY (hildon_caption_get_control(priv->passwordEntry))); - g_value_set_string(value, string); - break; - case PROP_NUMBERS_ONLY: - /* This property is set if and only if the input mode - of the password entry has been set to numeric only */ - g_object_get(G_OBJECT(hildon_caption_get_control(priv->passwordEntry)), - "input-mode", &input_mode, NULL); - g_value_set_boolean(value, - (input_mode == HILDON_INPUT_MODE_HINT_NUMERIC)); - break; - case PROP_CAPTION_LABEL: - string = hildon_caption_get_label(priv->passwordEntry); - g_value_set_string(value, string); - break; - case PROP_MAX_CHARS: - max_length = gtk_entry_get_max_length( - GTK_ENTRY (hildon_caption_get_control (priv->passwordEntry))); - g_value_set_int(value, max_length); - break; - case PROP_GET_OLD: - g_value_set_boolean(value, priv->get_old); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -hildon_get_password_dialog_class_init(HildonGetPasswordDialogClass * class) -{ - - GObjectClass *object_class = G_OBJECT_CLASS(class); - - parent_class = g_type_class_peek_parent(class); - - /* Override virtual functions */ - object_class->set_property = hildon_get_password_set_property; - object_class->get_property = hildon_get_password_get_property; - - /* Install new properties */ - g_object_class_install_property - (object_class, - PROP_DOMAIN, - g_param_spec_string ("domain", - "Domain", - "Set domain(content) for optional label.", - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property - (object_class, - PROP_PASSWORD, - g_param_spec_string ("password", - "Password", - "Set content for password entry", - "DEFAULT", - G_PARAM_READWRITE)); - - g_object_class_install_property - (object_class, - PROP_NUMBERS_ONLY, - g_param_spec_boolean ("numbers_only", - "NumbersOnly", - "Set entry to accept only numeric values", - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property - (object_class, - PROP_CAPTION_LABEL, - g_param_spec_string ("caption-label", - "Caption Label", - "The text to be set as the caption label", - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property - (object_class, - PROP_MAX_CHARS, - g_param_spec_int ("max-characters", - "Maximum Characters", - "The maximum number of characters the password" - " dialog accepts", - G_MININT, - G_MAXINT, - 0, - G_PARAM_READWRITE)); - - g_object_class_install_property - (object_class, - PROP_GET_OLD, - g_param_spec_boolean ("get-old", - "Get Old Password", - "TRUE if dialog is a get old password dialog, " - "FALSE if dialog is a get password dialog", - FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - /* Install private structure */ - g_type_class_add_private(class, - sizeof(HildonGetPasswordDialogPrivate)); -} - -static void -hildon_get_password_dialog_init(HildonGetPasswordDialog * dialog) -{ - /* Set initial properties for the dialog; the actual contents are - created once the 'get-old' property is set with g_object_new */ - gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); - gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); - gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); -} - -static void -create_contents(HildonGetPasswordDialog *dialog) -{ - HildonGetPasswordDialogPrivate *priv; - GtkSizeGroup * group; - GtkWidget *control; - - /* Cache private pointer for faster member access */ - priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE(dialog); - - /* Sizegroup for captions */ - group = GTK_SIZE_GROUP(gtk_size_group_new - (GTK_SIZE_GROUP_HORIZONTAL)); - - /* Dialog title */ - gtk_window_set_title(GTK_WINDOW(dialog), - priv->get_old - ? _(HILDON_GET_PASSWORD_DIALOG_TITLE) - : _(HILDON_GET_PASSWORD_VERIFY_DIALOG_TITLE)); - - /* Optional password domain label */ - priv->domainLabel = GTK_LABEL(gtk_label_new(NULL)); - - /* Create buttons */ - priv->okButton = - GTK_BUTTON(gtk_dialog_add_button(GTK_DIALOG(dialog), - (priv->get_old - ? _(HILDON_GET_PASSWORD_DIALOG_OK) - : _(HILDON_GET_PASSWORD_VERIFY_DIALOG_OK)), - - GTK_RESPONSE_OK)); - priv->cancelButton = - GTK_BUTTON(gtk_dialog_add_button(GTK_DIALOG(dialog), - (priv->get_old - ? _(HILDON_GET_PASSWORD_DIALOG_CANCEL) - : _(HILDON_GET_PASSWORD_VERIFY_DIALOG_CANCEL)), - GTK_RESPONSE_CANCEL)); - - /* Create password text entry */ - control = gtk_entry_new(); - gtk_entry_set_width_chars (GTK_ENTRY (control), 20); - - g_object_set (control, "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL); - gtk_entry_set_visibility(GTK_ENTRY(control), FALSE); - priv->passwordEntry = HILDON_CAPTION - (hildon_caption_new(group, - (priv->get_old - ? _(HILDON_GET_PASSWORD_DIALOG_PASSWORD) - : _(HILDON_GET_PASSWORD_VERIFY_DIALOG_PASSWORD)), - control, NULL, - HILDON_CAPTION_OPTIONAL)); - hildon_caption_set_separator(HILDON_CAPTION(priv->passwordEntry), ""); - - /* Do the basic layout */ - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), - GTK_WIDGET(priv->domainLabel), FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), - GTK_WIDGET(priv->passwordEntry), FALSE, FALSE, 0); - gtk_widget_show_all(GTK_DIALOG(dialog)->vbox); - - /* Ensure group is freed when all its contents have been removed */ - g_object_unref(group); -} - - -/* Public functions */ - -/** - * hildon_get_password_dialog_get_type: - * - * Returns GType for HildonGetPasswordDialog as produced by - * g_type_register_static(). - * - * Returns: HildonGetPasswordDialog type - */ -GType hildon_get_password_dialog_get_type(void) -{ - static GType dialog_type = 0; - - if (!dialog_type) { - static const GTypeInfo dialog_info = { - sizeof(HildonGetPasswordDialogClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_get_password_dialog_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonGetPasswordDialog), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_get_password_dialog_init - }; - - dialog_type = g_type_register_static(GTK_TYPE_DIALOG, - "HildonGetPasswordDialog", - &dialog_info, 0); - } - return dialog_type; -} - -/** - * hildon_get_password_dialog_new: - * @parent: parent window; can be NULL - * @get_old: FALSE creates a new get password dialog and - * TRUE creates a new get old password dialog. That is, - * if the password to be obtained is the old password, - * this parameter is specified TRUE. - * - * Construct a new HildonGetPasswordDialog. - * - * Returns: a new #GtkWidget of type HildonGetPasswordDialog - */ -GtkWidget *hildon_get_password_dialog_new(GtkWindow * parent, - gboolean get_old) -{ - HildonGetPasswordDialog *dialog = g_object_new - (HILDON_TYPE_GET_PASSWORD_DIALOG, - "get-old", get_old, NULL); - - if (parent != NULL) { - gtk_window_set_transient_for(GTK_WINDOW(dialog), parent); - } - - return GTK_WIDGET(dialog); -} - -/** - * hildon_get_password_dialog_new_with_default: - * @parent: parent window; can be NULL - * @password: a default password to be shown in password field - * @get_old: FALSE creates a new get password dialog and - * TRUE creates a new get old password dialog.That is, - * if the password to be obtained is the old password, - * this parameter is specified TRUE. - * - * - * Same as #hildon_get_password_dialog_new but with a default password - * in password field. - * - * Returns: a new #GtkWidget of type HildonGetPasswordDialog - */ -GtkWidget *hildon_get_password_dialog_new_with_default (GtkWindow * parent, - const gchar *password, - gboolean get_old) -{ - GtkWidget *dialog; - - dialog = hildon_get_password_dialog_new(parent, get_old); - if(password != NULL) - g_object_set(G_OBJECT(dialog), "password", password, NULL); - - return GTK_WIDGET(dialog); -} - -/** - * hildon_get_password_dialog_get_password: - * @dialog: pointer to HildonSetPasswordDialog - * - * Gets the currently inputted password. - * - * Returns: current password ( if the dialog is successfully - * accepted with 'OK' ) - */ -const gchar - *hildon_get_password_dialog_get_password(HildonGetPasswordDialog * - dialog) -{ - GtkEntry *entry1; - gchar *text1; - - HildonGetPasswordDialogPrivate *priv; - - g_return_val_if_fail (HILDON_IS_GET_PASSWORD_DIALOG(dialog), NULL); - priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE(dialog); - - /* Retrieve the password entry widget */ - entry1 = GTK_ENTRY (hildon_caption_get_control(priv->passwordEntry)); - text1 = GTK_ENTRY(entry1)->text; - - return text1; -} - -/** - * hildon_get_password_dialog_set_domain(GtkWidget *dialog, - * @dialog: the dialog - * @domain: the domain or some other descriptive text to be set - * - * Sets the optional descriptive text. - */ - -void hildon_get_password_dialog_set_domain(HildonGetPasswordDialog *dialog, - const gchar *domain) -{ - HildonGetPasswordDialogPrivate *priv; - - g_return_if_fail (HILDON_IS_GET_PASSWORD_DIALOG(dialog)); - - priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE(dialog); - gtk_label_set_text(priv->domainLabel, domain); - -} - -/** - * hildon_get_password_dialog_set_title: - * @dialog: the dialog - * @new_title: the text to be set as the dialog title - * - * Sets the dialog title. - * - * DEPRECATED! use gtk_window_set_title instead. - */ -void hildon_get_password_dialog_set_title(HildonGetPasswordDialog *dialog, - const gchar *new_title) - -{ - /* FIXME: This method is completely useless, should be deprecated/removed */ - g_return_if_fail (HILDON_IS_GET_PASSWORD_DIALOG(dialog)); - g_return_if_fail (new_title !=NULL); - gtk_window_set_title(GTK_WINDOW(dialog), - new_title); -} - -/** - * hildon_get_password_dialog_set_caption: - * @dialog: the dialog - * @new_caption: the text to be set as the caption label - * - * Sets the password entry field's neigbouring label. - */ - -void hildon_get_password_dialog_set_caption(HildonGetPasswordDialog *dialog, - const gchar *new_caption) -{ - - - HildonGetPasswordDialogPrivate *priv; - - g_return_if_fail (HILDON_IS_GET_PASSWORD_DIALOG(dialog)); - g_return_if_fail (new_caption != NULL); - - priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE(dialog); - hildon_caption_set_label(priv->passwordEntry, new_caption); - -} - -/** - * hildon_get_password_dialog_set_max_characters: - * @dialog: the dialog - * @max_characters: the maximum number of characters the password dialog - * accepts - * @new_caption: the text to be set as the caption label - * - * sets the maximum number of characters allowed as the password - */ - -void hildon_get_password_dialog_set_max_characters (HildonGetPasswordDialog *dialog, gint max_characters ) -{ - HildonGetPasswordDialogPrivate *priv; - - g_return_if_fail (max_characters > 0); - g_return_if_fail (HILDON_IS_GET_PASSWORD_DIALOG(dialog)); - - priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE(dialog); - - /* Apply the given length to password entry */ - gtk_entry_set_max_length(GTK_ENTRY - (hildon_caption_get_control - (priv->passwordEntry)), - max_characters); - - /* Connect callback to show error banner if the limit is exceeded */ - g_signal_connect(GTK_ENTRY - (hildon_caption_get_control - (priv->passwordEntry)), - "invalid_input", - G_CALLBACK(_invalid_input), - NULL - ); -} - -static void _invalid_input(GtkWidget *widget, GtkInvalidInputType reason, - gpointer unused) -{ - if (reason==GTK_INVALID_INPUT_MAX_CHARS_REACHED) { - gtk_infoprint(GTK_WINDOW(widget), _(HILDON_GET_PASSWORD_DIALOG_MAX_CHARS)); - } -} diff --git a/hildon-widgets/hildon-get-password-dialog.h b/hildon-widgets/hildon-get-password-dialog.h deleted file mode 100644 index bca82da..0000000 --- a/hildon-widgets/hildon-get-password-dialog.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_GET_PASSWORD_DIALOG_H__ -#define __HILDON_GET_PASSWORD_DIALOG_H__ - -#include - -G_BEGIN_DECLS - -#define HILDON_TYPE_GET_PASSWORD_DIALOG ( hildon_get_password_dialog_get_type() ) - -#define HILDON_GET_PASSWORD_DIALOG(obj) \ - (GTK_CHECK_CAST (obj, HILDON_TYPE_GET_PASSWORD_DIALOG,\ - HildonGetPasswordDialog)) - -#define HILDON_GET_PASSWORD_DIALOG_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), HILDON_TYPE_GET_PASSWORD_DIALOG, \ - HildonGetPasswordDialogClass)) - -#define HILDON_IS_GET_PASSWORD_DIALOG(obj) \ - (GTK_CHECK_TYPE (obj, HILDON_TYPE_GET_PASSWORD_DIALOG)) - -#define HILDON_IS_GET_PASSWORD_DIALOG_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_GET_PASSWORD_DIALOG)) - - -#define HILDON_GET_PASSWORD_DIALOG_TITLE "ecdg_ti_get_old_password" -#define HILDON_GET_PASSWORD_DIALOG_PASSWORD "ecdg_fi_get_old_pwd_enter_pwd" -#define HILDON_GET_PASSWORD_DIALOG_OK "ecdg_bd_get_old_password_dialog_ok" -#define HILDON_GET_PASSWORD_DIALOG_CANCEL "ecdg_bd_get_old_password_dialog_cancel" - -#define HILDON_GET_PASSWORD_VERIFY_DIALOG_TITLE "ecdg_ti_verify_password" -#define HILDON_GET_PASSWORD_VERIFY_DIALOG_PASSWORD "ecdg_fi_verify_pwd_enter_pwd" -#define HILDON_GET_PASSWORD_VERIFY_DIALOG_OK "ecdg_bd_verify_password_dialog_ok" -#define HILDON_GET_PASSWORD_VERIFY_DIALOG_CANCEL "ecdg_bd_verify_password_dialog_cancel" - -#define HILDON_GET_PASSWORD_DIALOG_MAX_CHARS "ckdg_ib_maximum_characters_reached" - -typedef struct _HildonGetPasswordDialog HildonGetPasswordDialog; -typedef struct _HildonGetPasswordDialogClass HildonGetPasswordDialogClass; - -struct _HildonGetPasswordDialog { - GtkDialog parent; -}; - -struct _HildonGetPasswordDialogClass { - GtkDialogClass parent_class; -}; - -GType hildon_get_password_dialog_get_type(void) G_GNUC_CONST; - -GtkWidget *hildon_get_password_dialog_new (GtkWindow *parent, - gboolean get_old); - -GtkWidget *hildon_get_password_dialog_new_with_default (GtkWindow *parent, - const gchar *password, - gboolean get_old); - -void hildon_get_password_dialog_set_domain (HildonGetPasswordDialog *dialog, - const gchar *domain); - -void hildon_get_password_dialog_set_caption (HildonGetPasswordDialog *dialog, - const gchar *new_caption); - -void hildon_get_password_dialog_set_max_characters(HildonGetPasswordDialog *dialog, - gint max_characters); - -const gchar * hildon_get_password_dialog_get_password(HildonGetPasswordDialog * dialog); - - -#ifndef HILDON_DISABLE_DEPRECATED -void hildon_get_password_dialog_set_title (HildonGetPasswordDialog *dialog, - const gchar *new_title); -#endif /* HILDON_DISABLE_DEPRECATED */ - -G_END_DECLS -#endif /* __HILDON_GET_PASSWORD_DIALOG_H__ */ diff --git a/hildon-widgets/hildon-grid-item-private.h b/hildon-widgets/hildon-grid-item-private.h deleted file mode 100644 index 23ed7db..0000000 --- a/hildon-widgets/hildon-grid-item-private.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/* - * @file hildon-grid-item-private.h - * - * This file is a private header file for he implementation of - * HildonGridItem. HildonGridItem is an item mainly used in HildonGrid. It - * has an icon, emblem and a label. This private header file exists so that - * grid can call semi-public functions of an item. - */ - -#ifndef __HILDON_GRID_ITEM_PRIVATE_H__ -#define __HILDON_GRID_ITEM_PRIVATE_H__ - -#include - -G_BEGIN_DECLS - - -void _hildon_grid_item_set_label(HildonGridItem *item, - const gchar *label); - -void _hildon_grid_item_set_emblem_size(HildonGridItem *item, - const gint emblem_size); -void _hildon_grid_item_set_label_pos(HildonGridItem *item, - HildonGridPositionType label_pos); - -void _hildon_grid_item_set_icon_size(HildonGridItem *item, - HildonGridItemIconSizeType icon_size); - -void _hildon_grid_item_set_focus_margin(HildonGridItem *item, - const gint focus_margin); -void _hildon_grid_item_set_label_height(HildonGridItem *item, - const gint label_height); -void _hildon_grid_item_set_label_icon_margin(HildonGridItem *item, - const gint label_icon_margin); -void _hildon_grid_item_set_icon_width(HildonGridItem *item, - const gint icon_width); -void _hildon_grid_item_set_icon_height(HildonGridItem *item, - const gint icon_height); -void _hildon_grid_item_set_label_height(HildonGridItem *item, - const gint label_height); - -void _hildon_grid_item_done_updating_settings(HildonGridItem *item); - - -G_END_DECLS - -#endif /* __HILDON_GRID_ITEM_PRIVATE_H__ */ diff --git a/hildon-widgets/hildon-grid-item.c b/hildon-widgets/hildon-grid-item.c deleted file mode 100644 index 2edd68c..0000000 --- a/hildon-widgets/hildon-grid-item.c +++ /dev/null @@ -1,1020 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-grid-item - * @short_description: Creating grid items used by #HildonGrid - * @see_also: #HildonGrid - * - * HildonGridItem is used to create grid items used by #HildonGrid. The - * grid item consists of an icon and a label. Based on the displaying - * mode employed by #HildonGrid, the label is justified to the right or - * the bottom. - */ - -/* - * TODO: - * - play with libtool to get _-functions private but accesable from grid - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "hildon-grid-item-private.h" -#include - -#include -#define _(String) dgettext(PACKAGE, String) - -#define HILDON_GRID_ITEM_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_GRID_ITEM, \ - HildonGridItemPrivate)) - -typedef struct _HildonGridItemPrivate HildonGridItemPrivate; - - -/* Default icon. */ -#define DEFAULT_ICON_BASENAME "qgn_list_gene_unknown_file" -#define HILDON_GRID_ICON_SIZE 26 -#define HILDON_GRID_EMBLEM_SIZE 16 - -/* Use some alpha-thing for emblems. */ -#define USE_DIRTY_ALPHA - -struct _HildonGridItemPrivate { - gchar *icon_basename; - gint icon_size; - GtkWidget *icon; - - gchar *emblem_basename; - gint emblem_size; - - GtkWidget *label; /* TODO use pango! */ - HildonGridPositionType label_pos; - - gint focus_margin; - gint label_height; - gint label_icon_margin; - gint column_margin; - gint icon_width; - gint icon_height; - gint row_height; - - gint pending_icon_size; - gint pending_emblem_size; - HildonGridPositionType pending_label_pos; - gint pending_focus_margin; - gint pending_label_height; - gint pending_label_icon_margin; - gint pending_icon_width; - gint pending_icon_height; - - gboolean selected; -}; - -enum{ - PROP_NONE = 0, - PROP_EMBLEM_TYPE, - PROP_ICON_BASENAME -}; - -/* Prototypes. */ -static void hildon_grid_item_class_init(HildonGridItemClass * klass); -static void hildon_grid_item_init(HildonGridItem * item); -static gboolean hildon_grid_item_expose(GtkWidget * widget, - GdkEventExpose * event); -static void hildon_grid_item_size_request(GtkWidget * widget, - GtkRequisition * requisition); -static void hildon_grid_item_size_allocate(GtkWidget * widget, - GtkAllocation * allocation); -static void hildon_grid_item_forall(GtkContainer * container, - gboolean include_int, - GtkCallback callback, - gpointer callback_data); -static void hildon_grid_item_remove(GtkContainer * container, - GtkWidget * child); - -static void hildon_grid_item_finalize(GObject * object); - -static void update_icon(HildonGridItem * item); -static void set_label_justify(HildonGridItem * item); - -static void hildon_grid_item_set_icon_size(HildonGridItem *item, - HildonGridItemIconSizeType icon_size); - -static void hildon_grid_item_set_property(GObject * object, - guint prop_id, - const GValue * value, - GParamSpec * pspec); - -static void hildon_grid_item_get_property(GObject * object, - guint prop_id, GValue * value, - GParamSpec * pspec); - - -static GtkContainerClass *parent_class = NULL; - -/* Private functions */ -static void -hildon_grid_item_set_property(GObject * object, - guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - HildonGridItem *item = HILDON_GRID_ITEM(object); - HildonGridItemPrivate *priv; - - priv = HILDON_GRID_ITEM_GET_PRIVATE(item); - - switch (prop_id) { - case PROP_EMBLEM_TYPE: - hildon_grid_item_set_emblem_type(item, g_value_get_string(value)); - break; - case PROP_ICON_BASENAME: - if(priv->icon_basename) - g_free(priv->icon_basename); - - priv->icon_basename = g_strdup(g_value_get_string(value)); - update_icon(item); - - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -hildon_grid_item_get_property(GObject * object, - guint prop_id, - GValue * value, GParamSpec * pspec) -{ - HildonGridItem *item = HILDON_GRID_ITEM(object); - HildonGridItemPrivate *priv; - const gchar *string; - - priv = HILDON_GRID_ITEM_GET_PRIVATE(item); - - switch (prop_id) { - case PROP_EMBLEM_TYPE: - string = hildon_grid_item_get_emblem_type(item); - g_value_set_string(value, string); - break; - case PROP_ICON_BASENAME: - g_value_set_string(value, priv->icon_basename); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - - -GType -hildon_grid_item_get_type(void) -{ - static GType grid_item_type = 0; - - if (!grid_item_type) { - static const GTypeInfo grid_item_info = { - sizeof(HildonGridItemClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_grid_item_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonGridItem), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_grid_item_init, - }; - grid_item_type = g_type_register_static(GTK_TYPE_CONTAINER, - "HildonGridItem", - &grid_item_info, 0); - } - - return grid_item_type; -} - -static void -hildon_grid_item_class_init(HildonGridItemClass *klass) -{ - GtkWidgetClass *widget_class; - GtkContainerClass *container_class; - GObjectClass *gobject_class; - - widget_class = GTK_WIDGET_CLASS(klass); - gobject_class = G_OBJECT_CLASS(klass); - container_class = GTK_CONTAINER_CLASS(klass); - - parent_class = g_type_class_peek_parent(klass); - - g_type_class_add_private(klass, sizeof(HildonGridItemPrivate)); - - gobject_class->finalize = hildon_grid_item_finalize; - - widget_class->expose_event = hildon_grid_item_expose; - widget_class->size_request = hildon_grid_item_size_request; - widget_class->size_allocate = hildon_grid_item_size_allocate; - - container_class->forall = hildon_grid_item_forall; - container_class->remove = hildon_grid_item_remove; - - gobject_class->set_property = hildon_grid_item_set_property; - gobject_class->get_property = hildon_grid_item_get_property; - - g_object_class_install_property - (gobject_class, - PROP_EMBLEM_TYPE, - g_param_spec_string ("emblem-type", - "Emblem Type", - "The emblem's basename", - NULL, - G_PARAM_WRITABLE)); - - g_object_class_install_property - (gobject_class, - PROP_ICON_BASENAME, - g_param_spec_string ("icon-basename", - "Icon Basename", - "The icon's basename", - NULL, - G_PARAM_WRITABLE)); - -} - -static void -hildon_grid_item_init(HildonGridItem *item) -{ - HildonGridItemPrivate *priv; - - priv = HILDON_GRID_ITEM_GET_PRIVATE(item); - - priv->icon_basename = NULL; - priv->pending_icon_size = priv->icon_size = HILDON_GRID_ICON_SIZE; - priv->icon = NULL; - - priv->emblem_basename = NULL; - priv->pending_emblem_size = priv->emblem_size = HILDON_GRID_EMBLEM_SIZE; - - priv->label = NULL; - priv->pending_label_pos = priv->label_pos = - HILDON_GRID_ITEM_LABEL_POS_BOTTOM; - - priv->selected = FALSE; - - priv->pending_focus_margin = priv->focus_margin = 6; - priv->pending_label_height = priv->label_height = 30; - priv->pending_label_icon_margin = priv->label_icon_margin = 6; - priv->pending_icon_width = priv->icon_width = 64; - priv->pending_icon_height = priv->icon_height = 54; - priv->pending_label_height = priv->label_height = 30; - - - GTK_WIDGET_SET_FLAGS(GTK_WIDGET(item), GTK_CAN_FOCUS); - - priv->label = gtk_label_new(NULL); - gtk_widget_set_name(priv->label, "hildon-grid-item-label"); - gtk_widget_set_parent(priv->label, GTK_WIDGET(item)); - - update_icon(item); - set_label_justify(item); - - gtk_widget_show(priv->label); -} - -/** - * hildon_grid_item_new: - * @icon_basename: icon base name - * - * Creates a new #HildonGridItem. - * - * Returns: a new #HildonGridItem - */ -GtkWidget * -hildon_grid_item_new(const gchar *icon_basename) -{ - HildonGridItem *item; - - item = g_object_new(HILDON_TYPE_GRID_ITEM, "icon-basename", icon_basename, NULL); - - return GTK_WIDGET(item); -} - -/** - * hildon_grid_item_new_with_label: - * @icon_basename: icon base name - * @label: text label for icon - * - * Creates a new #HildonGridItem with a specified label for the icon. - * - * Returns: a new #HildonGridItem - */ -GtkWidget * -hildon_grid_item_new_with_label(const gchar *icon_basename, - const gchar *label) -{ - HildonGridItem *item; - - item = g_object_new(HILDON_TYPE_GRID_ITEM, "icon-basename", icon_basename, NULL); - - hildon_grid_item_set_label(item, label); - - return GTK_WIDGET(item); -} - - -static void -update_icon(HildonGridItem *item) -{ - GtkIconTheme *icon_theme; - GdkPixbuf *icon; - GdkPixbuf *emblem_icon; - HildonGridItemPrivate *priv; - GError *error; - - priv = HILDON_GRID_ITEM_GET_PRIVATE(item); - - if (priv->icon != NULL) { - if (GTK_WIDGET_VISIBLE(priv->icon)) - gtk_widget_hide(priv->icon); - gtk_widget_unparent(priv->icon); - } - - icon_theme = gtk_icon_theme_get_default(); - - /* Load icon. Fall to default if loading fails. */ - icon = NULL; - if (priv->icon_basename) - { - error = NULL; - icon = gtk_icon_theme_load_icon(icon_theme, - priv->icon_basename, - priv->icon_size, 0, &error); - if (icon == NULL) { - g_warning("Couldn't load icon \"%s\": %s", priv->icon_basename, - error->message); - g_error_free(error); - } - } - - if (icon == NULL) { - error = NULL; - icon = gtk_icon_theme_load_icon(icon_theme, - DEFAULT_ICON_BASENAME, - priv->icon_size, 0, &error); - if (icon == NULL) { - g_warning("Couldn't load default icon: %s!\n", error->message); - g_error_free(error); - } - } - priv->icon_width = gdk_pixbuf_get_width(icon); - priv->icon_height = gdk_pixbuf_get_height(icon); - - - /* Load and merge emblem if one is specified. */ - if (priv->emblem_basename != NULL) { - error = NULL; - emblem_icon = gtk_icon_theme_load_icon(icon_theme, - priv->emblem_basename, - priv->emblem_size, - 0, &error); - if (emblem_icon == NULL) { - g_warning("Couldn't load emblem \"%s\": %s", - priv->emblem_basename, error->message); - g_error_free(error); - } else { - gint icon_height; - gint width, height, y; - -#ifdef USE_DIRTY_ALPHA - GdkPixbuf *tmp; -#endif - - icon_height = gdk_pixbuf_get_height(icon); - width = MIN(gdk_pixbuf_get_width(emblem_icon), - gdk_pixbuf_get_width(icon)); - height = MIN(gdk_pixbuf_get_height(emblem_icon), icon_height); - y = icon_height - height; -#ifndef USE_DIRTY_ALPHA - gdk_pixbuf_copy_area(emblem_icon, 0, 0, width, height, - icon, 0, y); -#else - /* - * Using composite to copy emblem to lower left corner creates - * some garbage on top of emblem. This way it can be avoided. - */ - tmp = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, - 8, width, icon_height); - gdk_pixbuf_fill(tmp, 0x00000000); - gdk_pixbuf_copy_area(emblem_icon, 0, 0, width, height, - tmp, 0, y); - gdk_pixbuf_composite(tmp, icon, - 0, 0, width, icon_height, - 0.0, 0.0, 1.0, 1.0, - GDK_INTERP_NEAREST, 255); - g_object_unref(tmp); -#endif /* ifndef else USE_DIRTY_ALPHA */ - g_object_unref(emblem_icon); - } - } - - priv->icon = gtk_image_new_from_pixbuf(icon); - g_object_unref(icon); - - gtk_widget_set_parent(priv->icon, GTK_WIDGET(item)); - gtk_widget_show(priv->icon); - - gtk_widget_queue_draw(priv->icon); -} - -void -hildon_grid_item_set_label(HildonGridItem *item, const gchar *label) -{ - HildonGridItemPrivate *priv; - - g_return_if_fail(HILDON_IS_GRID_ITEM(item)); - - if (label == NULL) - label = ""; - - priv = HILDON_GRID_ITEM_GET_PRIVATE(item); - if (strcmp (gtk_label_get_label (GTK_LABEL (priv->label)), label) == 0) - return; - gtk_label_set_label(GTK_LABEL(priv->label), label); -} - -static void -hildon_grid_item_set_icon_size(HildonGridItem *item, - HildonGridItemIconSizeType icon_size) -{ - HildonGridItemPrivate *priv; - - g_return_if_fail(HILDON_IS_GRID_ITEM(item)); - - priv = HILDON_GRID_ITEM_GET_PRIVATE(item); - if (priv->pending_icon_size == icon_size) { - return; - } - priv->pending_icon_size = icon_size; -} - - -void -_hildon_grid_item_set_label_pos(HildonGridItem *item, - HildonGridPositionType label_pos) -{ - HildonGridItemPrivate *priv; - - g_return_if_fail(HILDON_IS_GRID_ITEM(item)); - - priv = HILDON_GRID_ITEM_GET_PRIVATE(item); - if (priv->pending_label_pos == label_pos) { - return; - } - priv->pending_label_pos = label_pos; -} - - -void -_hildon_grid_item_set_emblem_size(HildonGridItem *item, gint emblem_size) -{ - HildonGridItemPrivate *priv; - - g_return_if_fail(HILDON_IS_GRID_ITEM(item)); - - priv = HILDON_GRID_ITEM_GET_PRIVATE(item); - if (priv->pending_emblem_size == emblem_size) { - return; - } - priv->pending_emblem_size = emblem_size; -} - - -void -_hildon_grid_item_set_focus_margin(HildonGridItem *item, - const gint focus_margin) -{ - HildonGridItemPrivate *priv; - - g_return_if_fail(HILDON_IS_GRID_ITEM(item)); - - priv = HILDON_GRID_ITEM_GET_PRIVATE(item); - if (priv->pending_focus_margin == focus_margin) { - return; - } - priv->pending_focus_margin = focus_margin; -} - - -void -_hildon_grid_item_set_label_height(HildonGridItem *item, - const gint label_height) -{ - HildonGridItemPrivate *priv; - - g_return_if_fail(HILDON_IS_GRID_ITEM(item)); - - priv = HILDON_GRID_ITEM_GET_PRIVATE(item); - if (priv->pending_label_height == label_height) { - return; - } - priv->pending_label_height = label_height; -} - - -void -_hildon_grid_item_set_label_icon_margin(HildonGridItem *item, - const gint label_icon_margin) -{ - HildonGridItemPrivate *priv; - - g_return_if_fail(HILDON_IS_GRID_ITEM(item)); - - priv = HILDON_GRID_ITEM_GET_PRIVATE(item); - if (priv->pending_label_icon_margin == label_icon_margin) { - return; - } - priv->pending_label_icon_margin = label_icon_margin; -} - - -void -_hildon_grid_item_set_icon_height(HildonGridItem *item, - const gint icon_height) -{ - HildonGridItemPrivate *priv; - - g_return_if_fail(HILDON_IS_GRID_ITEM(item)); - - priv = HILDON_GRID_ITEM_GET_PRIVATE(item); - if (priv->pending_icon_height == icon_height) { - return; - } - priv->pending_icon_height = icon_height; -} - - -void -_hildon_grid_item_set_icon_width(HildonGridItem *item, - const gint icon_width) -{ - HildonGridItemPrivate *priv; - - g_return_if_fail(HILDON_IS_GRID_ITEM(item)); - - hildon_grid_item_set_icon_size(item, icon_width); - - priv = HILDON_GRID_ITEM_GET_PRIVATE(item); - if (priv->pending_icon_width == icon_width) { - return; - } - priv->pending_icon_width = icon_width; -} - - -static void -set_label_justify(HildonGridItem *item) -{ - HildonGridItemPrivate *priv; - - priv = HILDON_GRID_ITEM_GET_PRIVATE(item); - - if (priv->label != NULL) { - switch (priv->label_pos) { - case HILDON_GRID_ITEM_LABEL_POS_BOTTOM: - gtk_misc_set_alignment(GTK_MISC(priv->label), 0.5, 0.5); - break; - - case HILDON_GRID_ITEM_LABEL_POS_RIGHT: - gtk_misc_set_alignment(GTK_MISC(priv->label), 0.0, 0.5); - break; - - default: - g_warning("Invalid position!"); - break; - } - } -} - -static void -hildon_grid_item_remove(GtkContainer *container, GtkWidget *child) -{ - HildonGridItem *item; - HildonGridItemPrivate *priv; - - item = HILDON_GRID_ITEM(container); - priv = HILDON_GRID_ITEM_GET_PRIVATE(item); - - g_return_if_fail(GTK_IS_WIDGET(child)); - g_return_if_fail(child == priv->label || child == priv->icon); - - if (child == priv->label) { - gtk_widget_unparent(child); - priv->label = NULL; - } else if (child == priv->icon) { - gtk_widget_unparent(child); - priv->icon = NULL; - } -} - -static gboolean -hildon_grid_item_expose(GtkWidget *widget, GdkEventExpose *event) -{ - HildonGridItem *item; - HildonGridItemPrivate *priv; - - g_return_val_if_fail(widget, FALSE); - g_return_val_if_fail(HILDON_IS_GRID_ITEM(widget), FALSE); - g_return_val_if_fail(event, FALSE); - - item = HILDON_GRID_ITEM(widget); - priv = HILDON_GRID_ITEM_GET_PRIVATE(item); - - if (priv->label == NULL && priv->icon == NULL) { - return FALSE; - } - if (GTK_WIDGET_HAS_FOCUS(GTK_WIDGET(item))) { - GdkRectangle clip; - GtkWidget *focused; - - if (priv->label != NULL) { - focused = priv->label; - } else { - focused = priv->icon; - } - - /* Determine the coordinates and size of clip */ - switch (priv->label_pos) { - case HILDON_GRID_ITEM_LABEL_POS_BOTTOM: - clip.x = focused->allocation.x - priv->focus_margin; - clip.y = focused->allocation.y; - clip.width = focused->allocation.width + priv->focus_margin * 2; - clip.height = focused->allocation.height; - if (clip.x < widget->allocation.x || - clip.width > widget->allocation.width) { - clip.x = widget->allocation.x; - clip.width = widget->allocation.width; - } - if (clip.y + clip.height > - widget->allocation.y + widget->allocation.height) { - clip.height = widget->allocation.y + - widget->allocation.height - clip.y; - } - break; - - case HILDON_GRID_ITEM_LABEL_POS_RIGHT: - clip.x = widget->allocation.x; - clip.y = widget->allocation.y; - clip.width = widget->allocation.width; - clip.height = widget->allocation.height; - break; - } - - /* Build painting box for the exposure event */ - gtk_paint_box(focused->style, - gtk_widget_get_toplevel(focused)->window, - GTK_STATE_SELECTED, - GTK_SHADOW_NONE, - &clip, focused, "selected", - clip.x, clip.y, clip.width, clip.height); - } - - /* - * Items are not exposed unless they are visible. - * -> No need to "optimize" by checking if they need exposing. - */ - gtk_container_propagate_expose(GTK_CONTAINER(widget), - priv->icon, event); - gtk_container_propagate_expose(GTK_CONTAINER(widget), - priv->label, event); - return TRUE; -} - - -static void -hildon_grid_item_size_request(GtkWidget *widget, GtkRequisition *requisition) -{ - HildonGridItem *item; - HildonGridItemPrivate *priv; - GtkRequisition label_req; - gint label_margin; - - item = HILDON_GRID_ITEM(widget); - priv = HILDON_GRID_ITEM_GET_PRIVATE(item); - - label_margin = priv->focus_margin; - - gtk_widget_size_request(priv->icon, requisition); - gtk_widget_size_request(priv->label, &label_req); - - switch (priv->label_pos) { - case HILDON_GRID_ITEM_LABEL_POS_BOTTOM: - requisition->width = MAX(requisition->width, label_req.width); - requisition->height += label_req.height + label_margin; - break; - - case HILDON_GRID_ITEM_LABEL_POS_RIGHT: - requisition->width += label_req.width + label_margin; - requisition->height = MAX(requisition->height, label_req.height); - break; - default: - g_warning("bad position"); - return; - break; - } -} - -static void -hildon_grid_item_size_allocate(GtkWidget *widget, GtkAllocation *allocation) -{ - HildonGridItem *item; - HildonGridItemPrivate *priv; - GtkRequisition l_req; - GtkAllocation i_alloc, l_alloc; - - g_return_if_fail(widget); - g_return_if_fail(allocation); - - item = HILDON_GRID_ITEM(widget); - priv = HILDON_GRID_ITEM_GET_PRIVATE(item); - widget->allocation = *allocation; - - /* If creating label and icon failed, don't show a thing... */ - if (priv->label == NULL && priv->icon == NULL) { - return; - } - if (priv->label != NULL) { - gtk_widget_get_child_requisition(priv->label, &l_req); - } else { - l_req.width = l_req.height = 0; - } - - /* Determine icon and label allocation based on label position */ - switch (priv->label_pos) { - case HILDON_GRID_ITEM_LABEL_POS_BOTTOM: - i_alloc.x = (allocation->width - priv->icon_width) / 2 + - allocation->x; - if (priv->label != NULL) { - i_alloc.y = allocation->y + (allocation->height - - priv->label_height - - priv->label_icon_margin - - priv->icon_height) / 2; - } else { - i_alloc.y = (allocation->height - priv->icon_height) / 2 + - allocation->y; - } - - if (priv->label != NULL) { - l_alloc.x = allocation->x + priv->focus_margin; - l_alloc.y = i_alloc.y + priv->icon_height + - priv->label_icon_margin; - l_alloc.width = allocation->width - priv->focus_margin * 2; - l_alloc.height = priv->label_height; - } - break; - - case HILDON_GRID_ITEM_LABEL_POS_RIGHT: - i_alloc.x = allocation->x + priv->focus_margin; - i_alloc.y = allocation->y + - (priv->label_height - priv->icon_height) / 2; - - if (priv->label != NULL) { - l_alloc.x = allocation->x + priv->focus_margin + - priv->icon_width + priv->label_icon_margin; - l_alloc.y = allocation->y; - l_alloc.width = allocation->width - priv->focus_margin * 2 - - priv->label_icon_margin - priv->icon_width; - l_alloc.height = priv->label_height; - } - break; - default: - g_warning("bad label position"); - return; - break; - } - - if (i_alloc.y < allocation->y) { - i_alloc.height -= i_alloc.height - allocation->height; - i_alloc.y = allocation->y; - } - if (i_alloc.y + i_alloc.height > allocation->y + allocation->height) { - i_alloc.height-= i_alloc.y + i_alloc.height - - allocation->y - allocation->height; - } - - - i_alloc.width = priv->icon_width; - i_alloc.height = priv->icon_height; - - if (priv->label != NULL) { - gtk_widget_size_allocate(priv->label, &l_alloc); - } - if (priv->icon != NULL) { - gtk_widget_size_allocate(priv->icon, &i_alloc); - } -} - -static void -hildon_grid_item_forall(GtkContainer *container, - gboolean include_int, - GtkCallback callback, - gpointer callback_data) -{ - HildonGridItem *item; - HildonGridItemPrivate *priv; - - g_return_if_fail(container); - g_return_if_fail(callback); - - item = HILDON_GRID_ITEM(container); - priv = HILDON_GRID_ITEM_GET_PRIVATE(item); - - /* Connect callback functions to the item */ - if (priv->icon != NULL) { - (*callback) (priv->icon, callback_data); - } - if (priv->label != NULL) { - (*callback) (priv->label, callback_data); - } -} - -static void -hildon_grid_item_finalize(GObject *object) -{ - HildonGridItem *item; - HildonGridItemPrivate *priv; - - item = HILDON_GRID_ITEM(object); - priv = HILDON_GRID_ITEM_GET_PRIVATE(item); - - g_free(priv->icon_basename); - if (priv->emblem_basename != NULL) { - g_free(priv->emblem_basename); - } - - G_OBJECT_CLASS(parent_class)->finalize(object); -} - -#if 0 -static int hildon_time_get_font_width(GtkWidget * widget) -{ - PangoContext *context; - PangoFontMetrics *metrics; - gint digit_width; - - context = gtk_widget_get_pango_context(widget); - metrics = pango_context_get_metrics(context, - widget->style->font_desc, - pango_context_get_language - (context)); - - digit_width = pango_font_metrics_get_approximate_digit_width(metrics); - digit_width = PANGO_PIXELS(digit_width); - - pango_font_metrics_unref(metrics); - - return digit_width; -} -#endif - - -/** - * hildon_grid_item_set_emblem_type: - * @item: #HildonGridItem - * @emblem_basename: emblem's basename - * - * Sets item emblem type. - */ -void -hildon_grid_item_set_emblem_type(HildonGridItem *item, - const gchar *emblem_basename) -{ - HildonGridItemPrivate *priv; - - g_return_if_fail(HILDON_IS_GRID_ITEM(item)); - - priv = HILDON_GRID_ITEM_GET_PRIVATE(item); - - if (priv->emblem_basename != NULL) { - g_free(priv->emblem_basename); - } - - priv->emblem_basename = g_strdup(emblem_basename); - - update_icon(item); - - g_object_notify (G_OBJECT (item), "emblem-type"); -} - -/** - * hildon_grid_item_get_emblem_type: - * @item: #HildonGridItem - * - * Returns: emblem's basename. Must not be changed or freed. - */ -const gchar * -hildon_grid_item_get_emblem_type(HildonGridItem *item) -{ - g_return_val_if_fail(HILDON_IS_GRID_ITEM(item), NULL); - - return HILDON_GRID_ITEM_GET_PRIVATE(item)->emblem_basename; -} - - - -void -_hildon_grid_item_done_updating_settings(HildonGridItem *item) -{ - gboolean need_update_icon; - gboolean need_resize; - - HildonGridItemPrivate *priv; - g_return_if_fail(HILDON_IS_GRID_ITEM(item)); - priv = HILDON_GRID_ITEM_GET_PRIVATE(item); - - need_update_icon = need_resize = FALSE; - - if (priv->pending_icon_size != priv->icon_size) { - if (priv->pending_icon_size > 0) { - priv->icon_size = priv->pending_icon_size; - } else { - priv->icon_size = 1; - } - need_update_icon = TRUE; - } - if (priv->pending_emblem_size != priv->emblem_size) { - priv->emblem_size = priv->pending_emblem_size; - need_update_icon = TRUE; - } - if (priv->pending_label_pos != priv->label_pos) { - priv->label_pos = priv->pending_label_pos; - /* No refresh here, grid will do it. */ - set_label_justify(item); - } - /* - * grid will take care of this - * - if (priv->pending_focus_margin != priv->focus_margin) { - priv->focus_margin = priv->pending_focus_margin; - need_resize = TRUE; - } - if (priv->pending_label_height != priv->label_height) { - priv->label_height = priv->pending_label_height; - need_resize = TRUE; - } - if (priv->pending_label_icon_margin != priv->label_icon_margin) { - priv->label_icon_margin = priv->pending_label_icon_margin; - need_resize = TRUE; - } - if (priv->pending_icon_height != priv->icon_height) { - priv->icon_height = priv->pending_icon_height; - need_resize = TRUE; - } - if (priv->pending_icon_width != priv->icon_width) { - priv->icon_width = priv->pending_icon_width; - need_resize = TRUE; - } - */ - - if (need_update_icon == TRUE) { - update_icon(HILDON_GRID_ITEM(item)); - } - /* - if (need_resize == TRUE) { - gtk_widget_queue_resize(GTK_WIDGET(item)); - } - */ -} diff --git a/hildon-widgets/hildon-grid-item.h b/hildon-widgets/hildon-grid-item.h deleted file mode 100644 index 89a5984..0000000 --- a/hildon-widgets/hildon-grid-item.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/* - * @file hildon-grid-item.h - * - * This file is a header file for he implementation of HildonGridItem. - * HildonGridItem is an item mainly used in HildonGrid. It has an icon, - * emblem and a label. - */ - -#ifndef __HILDON_GRID_ITEM_H__ -#define __HILDON_GRID_ITEM_H__ - -#include -#include - -G_BEGIN_DECLS -#define HILDON_TYPE_GRID_ITEM (hildon_grid_item_get_type ()) -#define HILDON_GRID_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - HILDON_TYPE_GRID_ITEM, \ - HildonGridItem)) -#define HILDON_GRID_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),\ - HILDON_TYPE_GRID_ITEM, \ - HildonGridItemClass)) -#define HILDON_IS_GRID_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ - HILDON_TYPE_GRID_ITEM)) -#define HILDON_IS_GRID_ITEM_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_GRID_ITEM)) -#define HILDON_GRID_ITEM_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - HILDON_TYPE_GRID_ITEM, HildonGridItemClass)) - -typedef enum { - HILDON_GRID_ITEM_LABEL_POS_BOTTOM = 1, - HILDON_GRID_ITEM_LABEL_POS_RIGHT -} HildonGridPositionType; - -typedef enum { - HILDON_GRID_ITEM_ICON_27x27 = 1, - HILDON_GRID_ITEM_ICON_128x128 -} HildonGridItemIconSizeType; - - -typedef struct _HildonGridItem HildonGridItem; -typedef struct _HildonGridItemClass HildonGridItemClass; - - -struct _HildonGridItem { - GtkContainer parent; -}; - -struct _HildonGridItemClass { - GtkContainerClass parent_class; -}; - - - -GType hildon_grid_item_get_type(void); -GtkWidget *hildon_grid_item_new(const gchar * icon_basename); -GtkWidget *hildon_grid_item_new_with_label(const gchar * icon_basename, - const gchar * label); - -void hildon_grid_item_set_emblem_type(HildonGridItem * item, - const gchar * emblem_basename); -const gchar *hildon_grid_item_get_emblem_type(HildonGridItem * item); -void hildon_grid_item_set_label(HildonGridItem *item, const gchar *label); - - -G_END_DECLS -#endif /* __HILDON_GRID_ITEM_H__ */ diff --git a/hildon-widgets/hildon-grid.c b/hildon-widgets/hildon-grid.c deleted file mode 100644 index 286c75e..0000000 --- a/hildon-widgets/hildon-grid.c +++ /dev/null @@ -1,2348 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-grid - * @short_description: Being used where ever a number of single tap - * activatable items need to be presented (e.g. Control Panel applets) - * @see_also: #HildonGridItem - * - * HildonGrid is a set of application-defineable items that are presented in a - * table. There are two modes for the form of the table; large icon mode - * and small icon mode. - * - * In large icon mode, the Grid View items are presented with a large - * icon and a label under it. In small icon mode, the items are - * presented with a small icon and a label on the right side of the - * icon. - * - * The label has a solid background as wide as the maximum text width. - * This allows the text to have focus as well as be legible when - * displayed upon a black or dark background image. Long names are - * truncated with an ellipsis ("...") appended. - */ - -/* - * TODO - * - there must be a predefined place for the "no items" -label... - * - performance :-) - * - dimmed items & scrolling by scrollbar - */ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "hildon-grid-item-private.h" -#include "hildon-marshalers.h" -#include "hildon-app.h" -#include -#include - -#include -#define _(String) dgettext(PACKAGE, String) - -#define HILDON_GRID_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_GRID, \ - HildonGridPrivate)) - - -#define DEFAULT_STYLE "largeicons-home" - -#define DEFAULT_N_COLUMNS 3 -#define GRID_LABEL_POS_PAD 16 - -#define DRAG_SENSITIVITY 6 - - -enum { - ACTIVATE_CHILD, - POPUP_CONTEXT, - LAST_SIGNAL -}; - -enum { - PROP_0, - PROP_EMPTY_LABEL, - PROP_STYLE, - PROP_SCROLLBAR_POS -}; - - -typedef struct _HildonGridChild HildonGridChild; -typedef struct _HildonGridPrivate HildonGridPrivate; - - -struct _HildonGridChild { - GtkWidget *widget; -}; - - -struct _HildonGridPrivate { - GList *children; - GtkWidget *scrollbar; - gint old_sb_pos; - GdkWindow *event_window; - - gchar *style; - gint emblem_size; - GtkWidget *empty_label; - - gint item_width; - gint item_height; - gint h_margin; - gint v_margin; - gint focus_margin; - gint icon_label_margin; - gint icon_width; - gint num_columns; - HildonGridPositionType label_pos; - gint label_height; - - gint focus_index; - guint click_x; - guint click_y; - - /* Handy variables outsize _allocate. */ - gint area_height; - gint area_rows; - gint scrollbar_width; - - gint first_index; - GdkEventType last_button_event; - gint old_item_height; -}; - - - -/* Prototypes. */ -static void hildon_grid_class_init(HildonGridClass * klass); -static void hildon_grid_init(HildonGrid * grid); -static void hildon_grid_realize(GtkWidget * widget); -static void hildon_grid_unrealize(GtkWidget * widget); -static void hildon_grid_map(GtkWidget * widget); -static void hildon_grid_unmap(GtkWidget * widget); -static gboolean hildon_grid_expose(GtkWidget * widget, - GdkEventExpose * event); -static void hildon_grid_size_request(GtkWidget * widget, - GtkRequisition * requisition); -static void hildon_grid_size_allocate(GtkWidget * widget, - GtkAllocation * allocation); -static void hildon_grid_add(GtkContainer * container, GtkWidget * widget); -static void hildon_grid_remove(GtkContainer * container, - GtkWidget * widget); -static void hildon_grid_set_focus_child(GtkContainer * container, - GtkWidget * widget); -static void hildon_grid_forall(GtkContainer * container, - gboolean include_internals, - GtkCallback callback, - gpointer callback_data); -static void hildon_grid_tap_and_hold_setup(GtkWidget * widget, - GtkWidget * menu, - GtkCallback func, - GtkWidgetTapAndHoldFlags flags); - -static GType hildon_grid_child_type(GtkContainer * container); - - -static void hildon_grid_set_property(GObject * object, - guint prop_id, - const GValue * value, - GParamSpec * pspec); -static void hildon_grid_get_property(GObject * object, - guint prop_id, - GValue * value, GParamSpec * pspec); - -static void hildon_grid_set_empty_label(HildonGrid *grid, - const gchar *empty_label); -static const gchar *hildon_grid_get_empty_label(HildonGrid * grid); -static void hildon_grid_set_num_columns(HildonGrid *grid, gint num_cols); -static void hildon_grid_set_label_pos(HildonGrid *grid, - HildonGridPositionType label_pos); -static void hildon_grid_set_focus_margin(HildonGrid *grid, - gint focus_margin); -static void hildon_grid_set_icon_label_margin(HildonGrid *grid, - gint icon_label_margin); -static void hildon_grid_set_icon_width(HildonGrid *grid, gint icon_width); -static void hildon_grid_set_emblem_size(HildonGrid *grid, gint emblem_size); -static void hildon_grid_set_label_height(HildonGrid *grid, - gint label_height); -static void hildon_grid_destroy(GtkObject * self); -static void hildon_grid_finalize(GObject * object); - -/* Signal handlers. */ -static gboolean hildon_grid_button_pressed(GtkWidget * widget, - GdkEventButton * event); -static gboolean hildon_grid_button_released(GtkWidget * widget, - GdkEventButton * event); -static gboolean hildon_grid_key_pressed(GtkWidget * widget, - GdkEventKey * event); -static gboolean hildon_grid_scrollbar_moved(GtkWidget * widget, - gpointer data); -static gboolean hildon_grid_state_changed(GtkWidget * widget, - GtkStateType state, - gpointer data); - -/* Other internal functions. */ -static void get_style_properties(HildonGrid * grid); -static gint get_child_index(HildonGridPrivate * priv, GtkWidget * child); -static gint get_child_index_by_coord(HildonGridPrivate * priv, - gint x, gint y); -static GtkWidget *get_child_by_index(HildonGridPrivate * priv, gint index); - -static gboolean jump_scrollbar_to_focused(HildonGrid * grid); -static gboolean adjust_scrollbar_height(HildonGrid * grid); -static gboolean update_contents(HildonGrid * grid); -static void set_focus(HildonGrid * grid, - GtkWidget * widget, gboolean refresh_view); - -static GtkContainerClass *parent_class = NULL; -static guint grid_signals[LAST_SIGNAL] = { 0 }; - - -GType hildon_grid_get_type(void) -{ - static GType grid_type = 0; - - if (!grid_type) { - static const GTypeInfo grid_info = { - sizeof(HildonGridClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_grid_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonGrid), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_grid_init, - }; - grid_type = g_type_register_static(GTK_TYPE_CONTAINER, - "HildonGrid", &grid_info, 0); - } - - return grid_type; -} - - - -static void hildon_grid_class_init(HildonGridClass * klass) -{ - GObjectClass *gobject_class; - GtkWidgetClass *widget_class; - GtkContainerClass *container_class; - - widget_class = GTK_WIDGET_CLASS(klass); - container_class = GTK_CONTAINER_CLASS(klass); - gobject_class = G_OBJECT_CLASS(klass); - - parent_class = g_type_class_peek_parent(klass); - - g_type_class_add_private(klass, sizeof(HildonGridPrivate)); - - GTK_OBJECT_CLASS(klass)->destroy = hildon_grid_destroy; - gobject_class->finalize = hildon_grid_finalize; - gobject_class->set_property = hildon_grid_set_property; - gobject_class->get_property = hildon_grid_get_property; - - widget_class->realize = hildon_grid_realize; - widget_class->unrealize = hildon_grid_unrealize; - widget_class->map = hildon_grid_map; - widget_class->unmap = hildon_grid_unmap; - widget_class->expose_event = hildon_grid_expose; - widget_class->size_request = hildon_grid_size_request; - widget_class->size_allocate = hildon_grid_size_allocate; - widget_class->tap_and_hold_setup = hildon_grid_tap_and_hold_setup; - widget_class->key_press_event = hildon_grid_key_pressed; - widget_class->button_press_event = hildon_grid_button_pressed; - widget_class->button_release_event = hildon_grid_button_released; - - container_class->add = hildon_grid_add; - container_class->remove = hildon_grid_remove; - container_class->forall = hildon_grid_forall; - container_class->child_type = hildon_grid_child_type; - container_class->set_focus_child = hildon_grid_set_focus_child; - - /* Install properties to the class */ - g_object_class_install_property(gobject_class, PROP_EMPTY_LABEL, - g_param_spec_string("empty_label", - "Empty label", - "Label to show when grid has no items", - _("ckct_wi_grid_no_items"), G_PARAM_READWRITE)); - - g_object_class_install_property(gobject_class, PROP_STYLE, - g_param_spec_string("style", - "Style", - "Widget's Style. Setting style sets widget size, " - "spacing, label position, number of columns, " - "and icon sizeLabel to show when grid has no items", - DEFAULT_STYLE, G_PARAM_READWRITE)); - - g_object_class_install_property(gobject_class, PROP_SCROLLBAR_POS, - g_param_spec_int("scrollbar-position", - "Scrollbar Position", - "View (scrollbar) position.", - G_MININT, G_MAXINT, 0, G_PARAM_READWRITE)); - - gtk_widget_class_install_style_property(widget_class, - g_param_spec_uint("item_width", - "Item width", - "Total width of an item (obsolete)", - 1, G_MAXINT, 212, G_PARAM_READABLE)); - - gtk_widget_class_install_style_property(widget_class, - g_param_spec_uint("item_height", - "Item height", - "Total height of an item", - 1, G_MAXINT, 96, G_PARAM_READABLE)); - - gtk_widget_class_install_style_property(widget_class, - g_param_spec_uint("item_hspacing", - "Item horizontal spacing", - "Margin between two columns and labels", - 0, G_MAXINT, 12, G_PARAM_READABLE)); - - gtk_widget_class_install_style_property(widget_class, - g_param_spec_uint("item_vspacing", - "Item vertical spacing", - "Icon on right: Margin between rows / Icon at bottom: Vertical margin betweeb label and icon", - 0, G_MAXINT, 6, G_PARAM_READABLE)); - - gtk_widget_class_install_style_property(widget_class, - g_param_spec_uint("label_hspacing", - "Focus margin", - "Margin between focus edge and item edge", - 0, G_MAXINT, 6, G_PARAM_READABLE)); - - gtk_widget_class_install_style_property(widget_class, - g_param_spec_uint("label_vspacing", - "Vertical label spacing", - "Vertical margin between item and label", - 0, G_MAXINT, 6, G_PARAM_READABLE)); - - gtk_widget_class_install_style_property(widget_class, - g_param_spec_uint("label_height", - "Label height", - "Height of icon label", - 1, G_MAXINT, 30, G_PARAM_READABLE)); - - gtk_widget_class_install_style_property(widget_class, - g_param_spec_uint("n_columns", - "Columns", - "Number of columns", - 0, G_MAXINT, DEFAULT_N_COLUMNS, G_PARAM_READABLE)); - - gtk_widget_class_install_style_property(widget_class, - g_param_spec_uint("label_pos", - "Label position", - "Position of label related to the icon", - 1, 2, 1, G_PARAM_READABLE)); - - gtk_widget_class_install_style_property(widget_class, - g_param_spec_uint("icon_size", - "Icon size", - "Size of the icon in pixels (width)", - 1, G_MAXINT, 64, G_PARAM_READABLE)); - - gtk_widget_class_install_style_property(widget_class, - g_param_spec_uint("emblem_size", - "Emblem size", - "Size of the emblem in pixels", - 1, G_MAXINT, 25, G_PARAM_READABLE)); - - /** - * HildonGrid::activate-child: - * - * Emitted when a child (@HildonGridItem) is activated either by - * tapping on it or by pressing enter. - */ - grid_signals[ACTIVATE_CHILD] = - g_signal_new("activate-child", - G_OBJECT_CLASS_TYPE(gobject_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET(HildonGridClass, activate_child), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, HILDON_TYPE_GRID_ITEM); - - /** - * HildonGrid::popup-context-menu: - * - * Emitted when popup-menu is supposed to open. Used for tap-and-hold. - */ - grid_signals[POPUP_CONTEXT] = - g_signal_new("popup-context-menu", - G_OBJECT_CLASS_TYPE(gobject_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET(HildonGridClass, popup_context_menu), - NULL, NULL, - _hildon_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, HILDON_TYPE_GRID_ITEM); -} - - - -/* - * hildon_grid_set_empty_label: - * @grid: #HildonGrid - * @empty_label: New label - * - * Sets empty label. - */ -static void -hildon_grid_set_empty_label(HildonGrid * grid, const gchar * empty_label) -{ - /* No need to worry about update -- label receives a signal for it. */ - gtk_label_set_label(GTK_LABEL(HILDON_GRID_GET_PRIVATE - (grid)->empty_label), - empty_label == NULL ? "" : empty_label); -} - -/* - * _hildon_grid_get_empty_label: - * @grid: #HildonGrid - * - * Returns: empty label. Label must not be modified nor freed. - */ -static const gchar * -hildon_grid_get_empty_label(HildonGrid * grid) -{ - return gtk_label_get_label(GTK_LABEL(HILDON_GRID_GET_PRIVATE - (grid)->empty_label)); -} - -/* - * hildon_grid_set_num_columns: - * @grid: #HildonGrid - * @columns: Number of columns - * - * Sets number of columns. - */ -static void -hildon_grid_set_num_columns(HildonGrid * grid, gint columns) -{ - HildonGridPrivate *priv; - - g_return_if_fail(HILDON_IS_GRID(grid)); - priv = HILDON_GRID_GET_PRIVATE(grid); - - if (priv->num_columns == columns) { - return; - } - - if (columns != 0) - priv->num_columns = columns; - else - priv->num_columns = DEFAULT_N_COLUMNS; - - /* Update estimated row-count for jump_scrollbar... */ - priv->area_rows = MAX(priv->area_height / priv->num_columns, 1); - - /* Size could have changed. Scroll view so there's something to show. */ - adjust_scrollbar_height(grid); - jump_scrollbar_to_focused(grid); - gtk_widget_queue_resize(GTK_WIDGET(grid)); -} - -/* - * hildon_grid_set_label_pos: - * @grid: #HildonGrid - * @label_pos: Label position - * - * Sets icon label position. - */ -static void -hildon_grid_set_label_pos(HildonGrid * grid, - HildonGridPositionType label_pos) -{ - HildonGridPrivate *priv; - GList *list; - GtkWidget *child; - - priv = HILDON_GRID_GET_PRIVATE(grid); - - if (label_pos == priv->label_pos) - return; - - /* gtknotebook doesn't check if we use valid values -- why should - we?-) */ - - priv->label_pos = label_pos; - - /* Set label position to each HildonGridItem */ - for (list = priv->children; list != NULL; list = list->next) { - child = ((HildonGridChild *) list->data)->widget; - - _hildon_grid_item_set_label_pos(HILDON_GRID_ITEM(child), - label_pos); - } -} - -/* - * hildon_grid_set_focus_margin: - * @grid: #HildonGrid - * @focus_margin: Focus margin - * - * Sets margin between icon edge and label edge - */ -static void -hildon_grid_set_focus_margin(HildonGrid *grid, gint focus_margin) -{ - HildonGridPrivate *priv; - GList *list; - GtkWidget *child; - - priv = HILDON_GRID_GET_PRIVATE(grid); - if (focus_margin == priv->focus_margin) - return; - - priv->focus_margin = focus_margin; - - /* Update children. */ - for (list = priv->children; list != NULL; list = list->next) { - child = ((HildonGridChild *) list->data)->widget; - - _hildon_grid_item_set_focus_margin(HILDON_GRID_ITEM(child), - priv->focus_margin); - } -} - - -/* - * hildon_grid_set_icon_label_margin: - * @grid: #HildonGrid - * @hspacing: Vertical spacing - * - * Sets vertical spacing for label. - * XXX - */ -static void -hildon_grid_set_icon_label_margin(HildonGrid *grid, gint icon_label_margin) -{ - HildonGridPrivate *priv; - - priv = HILDON_GRID_GET_PRIVATE(grid); - if (icon_label_margin == priv->icon_label_margin) - return; - - priv->icon_label_margin = icon_label_margin; -} - - -/* - * hildon_grid_set_icon_width: - * @grid: #HildonGrid - * @icon_size: Icon size (width) - * - * Sets icon size (in pixels). - */ -static void -hildon_grid_set_icon_width(HildonGrid * grid, gint icon_width) -{ - HildonGridPrivate *priv; - GList *list; - GtkWidget *child; - - priv = HILDON_GRID_GET_PRIVATE(grid); - - if (icon_width == priv->icon_width) - return; - - priv->icon_width = icon_width; - - for (list = priv->children; list != NULL; list = list->next) { - child = ((HildonGridChild *) list->data)->widget; - - _hildon_grid_item_set_icon_width(HILDON_GRID_ITEM(child), - icon_width); - } -} - - -/* - * hildon_grid_set_emblem_size: - * @grid: #HildonGrid - * @emblem_size: Emblem size - * - * Sets emblem size (in pixels). - */ -static void -hildon_grid_set_emblem_size(HildonGrid *grid, gint emblem_size) -{ - HildonGridPrivate *priv; - GList *list; - GtkWidget *child; - - priv = HILDON_GRID_GET_PRIVATE(grid); - - if (emblem_size == priv->emblem_size) - return; - - priv->emblem_size = emblem_size; - - for (list = priv->children; list != NULL; list = list->next) { - child = ((HildonGridChild *) list->data)->widget; - - _hildon_grid_item_set_emblem_size(HILDON_GRID_ITEM(child), - emblem_size); - } -} - - -static void -hildon_grid_set_label_height(HildonGrid *grid, - gint label_height) -{ - HildonGridPrivate *priv; - GList *list; - GtkWidget *child; - - priv = HILDON_GRID_GET_PRIVATE(grid); - - if (label_height == priv->label_height) - return; - - priv->label_height = label_height; - - for (list = priv->children; list != NULL; list = list->next) { - child = ((HildonGridChild *) list->data)->widget; - - _hildon_grid_item_set_label_height(HILDON_GRID_ITEM(child), - label_height); - } -} - - -static GType hildon_grid_child_type(GtkContainer * container) -{ - return GTK_TYPE_WIDGET; -} - -static void hildon_grid_init(HildonGrid * grid) -{ - HildonGridPrivate *priv; - - priv = HILDON_GRID_GET_PRIVATE(grid); - - GTK_CONTAINER(grid)->focus_child = NULL; - priv->focus_index = -1; - - priv->scrollbar = gtk_vscrollbar_new(NULL); - priv->empty_label = gtk_label_new(_("ckct_wi_grid_no_items")); - priv->style = NULL; - - priv->area_height = 1; - priv->area_rows = 1; - priv->children = NULL; - - priv->first_index = 0; - priv->click_x = 0; - priv->click_y = 0; - - priv->item_height = 96; - priv->h_margin = 12; - priv->v_margin = 6; - priv->focus_margin = 6; - priv->icon_label_margin = 6; - priv->icon_width = 64; - priv->label_pos = HILDON_GRID_ITEM_LABEL_POS_BOTTOM; - - priv->old_sb_pos = -1; - priv->old_item_height = -1; - - gtk_widget_set_parent(priv->scrollbar, GTK_WIDGET(grid)); - gtk_widget_set_parent(priv->empty_label, GTK_WIDGET(grid)); - - priv->last_button_event = GDK_NOTHING; - - GTK_WIDGET_SET_FLAGS(grid, GTK_NO_WINDOW); - - /* Signal for scrollbar. */ - g_signal_connect(G_OBJECT(priv->scrollbar), "value-changed", - G_CALLBACK(hildon_grid_scrollbar_moved), grid); - - /* Signal for key press. */ - GTK_WIDGET_SET_FLAGS(GTK_WIDGET(grid), GTK_CAN_FOCUS); - gtk_widget_set_events(GTK_WIDGET(grid), GDK_KEY_PRESS_MASK); - - GTK_WIDGET_UNSET_FLAGS(priv->scrollbar, GTK_CAN_FOCUS); - hildon_grid_set_style(grid, DEFAULT_STYLE); -} - -/** - * hildon_grid_new: - * - * Creates a new #HildonGrid. - * - * Returns: a new #HildonGrid - */ -GtkWidget *hildon_grid_new(void) -{ - - HildonGrid *grid; - - grid = g_object_new(HILDON_TYPE_GRID, NULL); - - return GTK_WIDGET(grid); -} - - -static void hildon_grid_realize(GtkWidget * widget) -{ - HildonGrid *grid; - HildonGridPrivate *priv; - GdkWindowAttr attr; - gint attr_mask; - - - GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED); - - grid = HILDON_GRID(widget); - priv = HILDON_GRID_GET_PRIVATE(grid); - - /* Create GdkWindow for catching events. */ - attr.x = widget->allocation.x; - attr.y = widget->allocation.y; - attr.width = widget->allocation.width - priv->scrollbar_width; - attr.height = widget->allocation.height; - attr.window_type = GDK_WINDOW_CHILD; - attr.event_mask = gtk_widget_get_events(widget) - | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK; - - widget->window = gtk_widget_get_parent_window(widget); - g_object_ref(widget->window); - - attr.wclass = GDK_INPUT_ONLY; - attr_mask = GDK_WA_X | GDK_WA_Y; - - priv->event_window = gdk_window_new(widget->window, &attr, attr_mask); - gdk_window_set_user_data(priv->event_window, widget); - - widget->style = gtk_style_attach(widget->style, widget->window); - - gtk_style_set_background(widget->style, - widget->window, GTK_STATE_NORMAL); -} - - -static void hildon_grid_unrealize(GtkWidget * widget) -{ - HildonGridPrivate *priv; - - priv = HILDON_GRID_GET_PRIVATE(HILDON_GRID(widget)); - - if (priv->event_window != NULL) { - gdk_window_set_user_data(priv->event_window, NULL); - gdk_window_destroy(priv->event_window); - priv->event_window = NULL; - } - - if (GTK_WIDGET_CLASS(parent_class)->unrealize) { - (*GTK_WIDGET_CLASS(parent_class)->unrealize) (widget); - } -} - - - -static void hildon_grid_map(GtkWidget * widget) -{ - HildonGrid *grid; - HildonGridPrivate *priv; - GList *list; - GtkWidget *child; - - g_return_if_fail(HILDON_IS_GRID(widget)); - - if (!GTK_WIDGET_VISIBLE(widget)) - return; - - grid = HILDON_GRID(widget); - priv = HILDON_GRID_GET_PRIVATE(grid); - - (*GTK_WIDGET_CLASS(parent_class)->map) (widget); - - /* We shouldn't really need the following...*/ - if (priv->scrollbar != NULL && GTK_WIDGET_VISIBLE(priv->scrollbar)) { - if (!GTK_WIDGET_MAPPED(priv->scrollbar)) { - gtk_widget_map(priv->scrollbar); - } - } - - if (priv->empty_label != NULL && - GTK_WIDGET_VISIBLE(priv->empty_label)) { - if (!GTK_WIDGET_MAPPED(priv->empty_label)) { - gtk_widget_map(priv->empty_label); - } - } - - for (list = priv->children; list != NULL; list = list->next) { - child = ((HildonGridChild *) list->data)->widget; - - if (GTK_WIDGET_VISIBLE(child)) { - if (!GTK_WIDGET_MAPPED(child)) { - gtk_widget_map(child); - } - } - } - /* END OF don't really need */ - - /* Also make event window visible. */ - gdk_window_show(priv->event_window); -} - - - -static void hildon_grid_unmap(GtkWidget * widget) -{ - HildonGridPrivate *priv; - - priv = HILDON_GRID_GET_PRIVATE(HILDON_GRID(widget)); - - if (priv->event_window != NULL) { - gdk_window_hide(priv->event_window); - } - - (*GTK_WIDGET_CLASS(parent_class)->unmap) (widget); -} - - - -static gboolean -hildon_grid_expose(GtkWidget * widget, GdkEventExpose * event) -{ - HildonGrid *grid; - HildonGridPrivate *priv; - GtkContainer *container; - GList *list; - gint child_no; - - g_return_val_if_fail(widget, FALSE); - g_return_val_if_fail(HILDON_IS_GRID(widget), FALSE); - g_return_val_if_fail(event, FALSE); - - grid = HILDON_GRID(widget); - priv = HILDON_GRID_GET_PRIVATE(grid); - container = GTK_CONTAINER(grid); - - /* If grid has no children, - * propagate the expose event to the label is one exists */ - if (priv->children == NULL || g_list_length(priv->children) == 0) { - if (priv->empty_label != NULL) { - gtk_container_propagate_expose(container, - priv->empty_label, event); - } - return FALSE; - } - - /* Only expose visible children. */ - - /* Jump over invisible. */ - for (list = priv->children, child_no = 0; - list != NULL && child_no < priv->first_index; - list = list->next, child_no++) { - ; /* Nothing here. */ - } - - for (; list != NULL && child_no < priv->first_index + - priv->num_columns * priv->area_rows; list = list->next) { - gtk_container_propagate_expose(container, - ((HildonGridChild *) list->data) - ->widget, event); - } - - /* Keep focused item focused. */ - if (container->focus_child != NULL - && !GTK_WIDGET_HAS_FOCUS(container->focus_child)) { - set_focus(grid, container->focus_child, FALSE); - } - if (priv->scrollbar_width > 0 && priv->scrollbar != NULL) { - gtk_container_propagate_expose(container, priv->scrollbar, event); - } - - return FALSE; -} - - -static void -hildon_grid_size_request(GtkWidget * widget, GtkRequisition * requisition) -{ - HildonGrid *grid; - HildonGridPrivate *priv; - GList *list; - GtkWidget *child; - GtkRequisition req; - - g_return_if_fail(widget); - g_return_if_fail(requisition); - - grid = HILDON_GRID(widget); - priv = HILDON_GRID_GET_PRIVATE(grid); - - /* Want as big as possible. */ - requisition->width = 0x7fff; /* Largest possible gint16 */ - requisition->height = 0x7fff; /* Largest possible gint16 */ - - if (priv->children == NULL) { - if (priv->empty_label != NULL && - GTK_WIDGET_VISIBLE(priv->empty_label)) { - gtk_widget_size_request(priv->empty_label, &req); - } - } - - if (priv->scrollbar != NULL && GTK_WIDGET_VISIBLE(priv->scrollbar)) { - gtk_widget_size_request(priv->scrollbar, &req); - } - - for (list = priv->children; list != NULL; list = list->next) { - child = ((HildonGridChild *) list->data)->widget; - - gtk_widget_size_request(child, &req); - } -} - -/* - * hildon_grid_size_allocate: - * - * Supposingly called when size of grid changes and after view have moved so - * that items need to be relocated. - */ -static void -hildon_grid_size_allocate(GtkWidget * widget, GtkAllocation * allocation) -{ - HildonGrid *grid; - HildonGridPrivate *priv; - GList *list; - GtkWidget *child; - gint child_no; - gint y_offset; - gint row_margin; - - GtkAllocation alloc; - GtkRequisition req; - - g_return_if_fail(widget); - g_return_if_fail(allocation); - - grid = HILDON_GRID(widget); - priv = HILDON_GRID_GET_PRIVATE(grid); - widget->allocation = *allocation; - - get_style_properties(grid); - - /* First of all, make sure GdkWindow is over our widget. */ - if (priv->event_window != NULL) { - gdk_window_move_resize(priv->event_window, - widget->allocation.x, - widget->allocation.y, - widget->allocation.width - - priv->scrollbar_width, - widget->allocation.height); - } - /* Show the label if there are no items. */ - if (priv->children == NULL) { - /* - * We probably don't need this as scrollbar should be hidden when - * removing items, but one can never be too sure... - */ - if (priv->scrollbar != NULL && - GTK_WIDGET_VISIBLE(priv->scrollbar)) { - priv->scrollbar_width = 0; - gtk_widget_hide(priv->scrollbar); - } - - /* Show label if creating one actually worked. */ - if (priv->empty_label != NULL) { - gtk_widget_get_child_requisition(priv->empty_label, &req); - - /* ...for sure we must have a position for the label here... */ - alloc.x = allocation->x + GRID_LABEL_POS_PAD; - alloc.y = allocation->y + GRID_LABEL_POS_PAD; - alloc.width = MIN(req.width, allocation->width - - GRID_LABEL_POS_PAD); - alloc.height = MIN(req.height, allocation->height - - GRID_LABEL_POS_PAD); - - /* Make sure we don't use negative values. */ - if (alloc.width < 0) { - alloc.width = 0; - } - if (alloc.height < 0) { - alloc.height = 0; - } - - gtk_widget_size_allocate(priv->empty_label, &alloc); - - if (!GTK_WIDGET_VISIBLE(priv->empty_label)) { - gtk_widget_show(priv->empty_label); - } - } - - return; - } - - /* As we have some items, hide label if it was visible. */ - if (priv->empty_label != NULL && - GTK_WIDGET_VISIBLE(priv->empty_label)) { - gtk_widget_hide(priv->empty_label); - } - - priv->area_height = allocation->height; - priv->area_rows = allocation->height / priv->item_height; - - /* Adjust/show/hide scrollbar. */ - adjust_scrollbar_height(grid); - if (priv->old_item_height != priv->item_height) { - priv->old_item_height = priv->item_height; - jump_scrollbar_to_focused(grid); - } - - /* Update item width. */ - if (priv->num_columns == 1) { - priv->item_width = allocation->width - priv->scrollbar_width - - priv->h_margin - priv->scrollbar_width; - } else { - priv->item_width = (allocation->width - priv->scrollbar_width) / - priv->num_columns; - } - - priv->first_index = - (int) gtk_range_get_value(GTK_RANGE(priv->scrollbar)) / - priv->item_height * priv->num_columns; - - /* Hide items before visible ones. */ - for (list = priv->children, child_no = 0; - list != NULL && child_no < priv->first_index; - list = list->next, child_no++) { - child = ((HildonGridChild *) list->data)->widget; - - if (GTK_WIDGET_VISIBLE(child)) { - gtk_widget_hide(child); - } - } - - /* Allocate visible items. */ - alloc.width = priv->item_width - priv->h_margin; - switch (priv->label_pos) { - case HILDON_GRID_ITEM_LABEL_POS_BOTTOM: - row_margin = priv->icon_label_margin; - break; - case HILDON_GRID_ITEM_LABEL_POS_RIGHT: - row_margin = priv->v_margin; - break; - default: - row_margin = 0; - break; - } - alloc.height = priv->item_height - row_margin; - - for (y_offset = priv->first_index / priv->num_columns * priv->item_height; - list != NULL && child_no < priv->first_index + - priv->area_rows * priv->num_columns; - list = list->next, child_no++) { - child = ((HildonGridChild *) list->data)->widget; - - if (!GTK_WIDGET_VISIBLE(child)) { - gtk_widget_show(child); - } - - /* Don't update icons which are not visible... */ - alloc.y = (child_no / priv->num_columns) * priv->item_height + - allocation->y - y_offset + row_margin; - alloc.x = (child_no % priv->num_columns) * priv->item_width + - allocation->x; - - _hildon_grid_item_done_updating_settings(HILDON_GRID_ITEM(child)); - gtk_widget_size_allocate(child, &alloc); - } - - /* Hide items after visible items. */ - for (; list != NULL; list = list->next) { - child = ((HildonGridChild *) list->data)->widget; - - if (GTK_WIDGET_VISIBLE(child)) { - gtk_widget_hide(child); - } - } -} - - - -/** - * hildon_grid_add: - * @container: container (#HildonGrid) to add HildonGridItem into - * @widget: #GtkWidget (#HildonGridItem) to add - * - * Adds a new HildonGridItem into HildonGrid. - */ -static void hildon_grid_add(GtkContainer * container, GtkWidget * widget) -{ - HildonGrid *grid; - HildonGridPrivate *priv; - HildonGridChild *child; - - - g_return_if_fail(HILDON_IS_GRID(container)); - g_return_if_fail(HILDON_IS_GRID_ITEM(widget)); - - grid = HILDON_GRID(container); - priv = HILDON_GRID_GET_PRIVATE(HILDON_GRID(grid)); - GTK_WIDGET_SET_FLAGS(widget, GTK_NO_WINDOW); - - child = g_new(HildonGridChild, 1); - if (child == NULL) { - g_critical("no memory for child - not adding"); - return; - } - child->widget = widget; - - _hildon_grid_item_set_label_pos (HILDON_GRID_ITEM(widget), priv->label_pos); - _hildon_grid_item_set_focus_margin(HILDON_GRID_ITEM(widget), priv->focus_margin); - _hildon_grid_item_set_icon_width (HILDON_GRID_ITEM(widget), priv->icon_width); - _hildon_grid_item_set_emblem_size (HILDON_GRID_ITEM(widget), priv->emblem_size); - - /* Add the new item to the grid */ - priv->children = g_list_append(priv->children, child); - gtk_widget_set_parent(widget, GTK_WIDGET(grid)); - - /* Property changes (child's set_sensitive) */ - g_signal_connect_after(G_OBJECT(widget), "state-changed", - G_CALLBACK(hildon_grid_state_changed), grid); - - /* Matches both empty grid and all-dimmed grid. */ - if (GTK_CONTAINER(grid)->focus_child == NULL) - set_focus(grid, widget, TRUE); - - /* - * If item was added in visible area, relocate items. Otherwise update - * scrollbar and see if items need relocating. - */ - if (g_list_length(priv->children) < priv->first_index + - priv->area_rows * priv->num_columns) { - gtk_widget_queue_resize(GTK_WIDGET(grid)); - } else { - gboolean updated; - - updated = adjust_scrollbar_height(grid); - /* Basically this other test is useless -- shouldn't need to jump. - */ - updated |= jump_scrollbar_to_focused(grid); - - if (updated) { - gtk_widget_queue_resize(GTK_WIDGET(grid)); - } - } -} - -/** - * hildon_grid_remove: - * @container: container (#HildonGrid) to remove #HildonGridItem from - * @widget: widget (#HildonGridItem) to be removed - * - * Removes HildonGridItem from HildonGrid. - */ -static void -hildon_grid_remove(GtkContainer * container, GtkWidget * widget) -{ - HildonGrid *grid; - HildonGridPrivate *priv; - HildonGridChild *child; - GtkWidget *child_widget; - GList *list; - gint index, old_index; - gboolean deleted; - gboolean updated; - - g_return_if_fail(HILDON_IS_GRID(container)); - g_return_if_fail(HILDON_IS_GRID_ITEM(widget)); - - grid = HILDON_GRID(container); - priv = HILDON_GRID_GET_PRIVATE(container); - - old_index = priv->focus_index; - updated = GTK_WIDGET_VISIBLE(widget); - - for (list = priv->children, index = 0, deleted = FALSE; - list != NULL; list = list->next, index++) { - child = (HildonGridChild *) list->data; - child_widget = child->widget; - - /* Remove the Item if it is found in the grid */ - if (child_widget == widget) { - gtk_widget_unparent(child_widget); - priv->children = g_list_remove_link(priv->children, list); - g_list_free(list); - g_free(child); - - deleted = TRUE; - - break; - } - } - - /* Emit warning if the item is not found */ - if (!deleted) { - g_warning("tried to remove unexisting item"); - return; - } - - /* Move focus somewhere. */ - if (old_index == index) { - if (old_index == g_list_length(priv->children)) { - if (index == 0) { - set_focus(grid, NULL, TRUE); - } else { - set_focus(grid, - get_child_by_index(priv, old_index - 1), TRUE); - } - } else { - set_focus(grid, get_child_by_index(priv, old_index), TRUE); - } - } else { - set_focus(grid, GTK_CONTAINER(grid)->focus_child, TRUE); - } - - updated |= adjust_scrollbar_height(grid); - updated |= jump_scrollbar_to_focused(grid); - - if (updated) { - gtk_widget_queue_resize(GTK_WIDGET(grid)); - } -} - -/** - * hildon_grid_set_focus_child: - * @container: HildonGrid - * @widget: HildonGridItem - * - * Sets focus. - */ -static void -hildon_grid_set_focus_child(GtkContainer * container, GtkWidget * widget) -{ - HildonGrid *grid; - HildonGridPrivate *priv; - - g_return_if_fail(HILDON_IS_GRID(container)); - g_return_if_fail(HILDON_IS_GRID_ITEM(widget) || widget == NULL); - - grid = HILDON_GRID(container); - priv = HILDON_GRID_GET_PRIVATE(grid); - - if (GTK_CONTAINER(grid)->focus_child == widget || widget == NULL) - return; - - set_focus(grid, widget, TRUE); -} - - - -static void -set_focus(HildonGrid * grid, GtkWidget * widget, gboolean refresh_view) -{ - HildonGridPrivate *priv; - GtkContainer *container; - gboolean view_updated; - - - priv = HILDON_GRID_GET_PRIVATE(grid); - container = GTK_CONTAINER(grid); - - /* If widget is NULL -> unfocus */ - if (widget == NULL && container->focus_child != NULL) - GTK_WIDGET_UNSET_FLAGS(container->focus_child, GTK_HAS_FOCUS); - - GTK_CONTAINER(grid)->focus_child = widget; - if (widget == NULL) { - priv->focus_index = -1; - return; - } - - /* Get the child index which the user wanted to focus */ - priv->focus_index = get_child_index(priv, widget); - - gtk_widget_grab_focus(widget); - - if (refresh_view) { - view_updated = jump_scrollbar_to_focused(grid); - } else { - view_updated = FALSE; - } - - if (view_updated) { - hildon_grid_size_allocate(GTK_WIDGET(grid), - >K_WIDGET(grid)->allocation); - } -} - -static void -hildon_grid_forall(GtkContainer * container, - gboolean include_internals, - GtkCallback callback, gpointer callback_data) -{ - HildonGrid *grid; - HildonGridPrivate *priv; - GList *list; - - g_return_if_fail(container); - g_return_if_fail(callback); - - grid = HILDON_GRID(container); - priv = HILDON_GRID_GET_PRIVATE(grid); - - /* Connect callback functions */ - if (include_internals) { - if (priv->scrollbar != NULL) { - (*callback) (priv->scrollbar, callback_data); - } - if (priv->empty_label != NULL) { - (*callback) (priv->empty_label, callback_data); - } - } - - for (list = priv->children; list != NULL; list = list->next) { - (*callback) (((HildonGridChild *) list->data)->widget, - callback_data); - } -} - -static void hildon_grid_destroy(GtkObject * self) -{ - HildonGridPrivate *priv; - - g_return_if_fail(self != NULL); - g_return_if_fail(HILDON_IS_GRID(self)); - - priv = HILDON_GRID_GET_PRIVATE(self); - - if (GTK_WIDGET(self)->window != NULL) { - g_object_unref(G_OBJECT(GTK_WIDGET(self)->window)); - } - - gtk_container_forall(GTK_CONTAINER(self), - (GtkCallback) gtk_object_ref, NULL); - gtk_container_forall(GTK_CONTAINER(self), - (GtkCallback) gtk_widget_unparent, NULL); - - GTK_OBJECT_CLASS(parent_class)->destroy(self); -} - -static void hildon_grid_finalize(GObject * object) -{ - HildonGrid *grid; - HildonGridPrivate *priv; - - grid = HILDON_GRID(object); - priv = HILDON_GRID_GET_PRIVATE(grid); - - gtk_container_forall(GTK_CONTAINER(object), - (GtkCallback) gtk_object_unref, NULL); - - if (priv->style != NULL) { - g_free(priv->style); - } - if (G_OBJECT_CLASS(parent_class)->finalize) { - G_OBJECT_CLASS(parent_class)->finalize(object); - } -} - -/* - * hildon_grid_key_pressed: - * @widget: Widget where we get the signal from - * @event: EventKey - * @data: #HildonGrid - * - * Handle user key press (keyboard navigation). - * - * And here's how it works if some items are dimmed (moving to right): - * . . . . . . # . . 2 # . . # . . - * . 1 # 2 . 1 # # 1 # # # 1 # # # - * . . . . . 2 . . . . 2 . - * - * '.' = item, - * '#' = dimmed item, - * '1' = starting position, - * '2' = final position - * - * ...although only the first example is implemented right now. - * - * Return value: Signal handled - */ -static gboolean -hildon_grid_key_pressed(GtkWidget * widget, - GdkEventKey * event) -{ - GtkAdjustment *adjustment; - GtkContainer *container; - GtkWidget *new_focus; - HildonGrid *grid; - HildonGridPrivate *priv; - gboolean shift; - gint keyval; - gint x, y; - gint focus_index; - gint child_count, child_rows; - gint t; - gint addition, max_add; - - g_return_val_if_fail(widget, FALSE); - - grid = HILDON_GRID(widget); - priv = HILDON_GRID_GET_PRIVATE(grid); - - /* - * If focus was never lost, we could just see if an item is focused - - * if not, there's nothing else to focus... - */ - - /* No items? */ - if (priv->children == NULL || g_list_length(priv->children) == 0) - return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event); - - /* Focused item is dimmed? */ - /* If we have no focus, allow non-existing focus to move... */ - container = GTK_CONTAINER(grid); - if (container->focus_child != NULL - && !GTK_WIDGET_IS_SENSITIVE(container->focus_child)) { - return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event); - } - /* At the moment we don't want to do anything here if alt or control - or MODX is pressed, so return now. Shift + TAB are accepted (from - hildon-table-grid) And right now modifiers do not make any - difference... */ - - /* Said somewhere that "foo = a == b" is not desirable. */ - if (event->state & GDK_SHIFT_MASK) { - shift = TRUE; - } else { - shift = FALSE; - } - - keyval = event->keyval; - if (gtk_widget_get_default_direction() == GTK_TEXT_DIR_RTL) { - switch (event->keyval) { - case GDK_Left: - keyval = GDK_Right; - break; - case GDK_KP_Left: - keyval = GDK_KP_Right; - break; - case GDK_Right: - keyval = GDK_Left; - break; - case GDK_KP_Right: - keyval = GDK_KP_Left; - break; - } - } - - child_count = g_list_length(priv->children); - child_rows = (child_count - 1) / priv->num_columns + 1; - - if (priv->focus_index != -1) { - x = priv->focus_index % priv->num_columns; - y = priv->focus_index / priv->num_columns; - } else { - x = y = 0; - } - - switch (keyval) { - case GDK_KP_Page_Up: - case GDK_Page_Up: - if (priv->first_index == 0) { - if (priv->focus_index == 0) { - return TRUE; - } - set_focus(grid, get_child_by_index(priv, 0), TRUE); - return TRUE; - } - - t = MAX(priv->first_index / priv->num_columns - priv->area_rows, 0); - adjustment = gtk_range_get_adjustment(GTK_RANGE(priv->scrollbar)); - adjustment->value = (gdouble) (t * priv->item_height); - gtk_range_set_adjustment(GTK_RANGE(priv->scrollbar), adjustment); - gtk_widget_queue_draw(priv->scrollbar); - update_contents(grid); - - /* Want to update now. */ - hildon_grid_size_allocate(GTK_WIDGET(grid), - >K_WIDGET(grid)->allocation); - - return TRUE; - break; - - case GDK_KP_Page_Down: - case GDK_Page_Down: - if (priv->first_index / priv->num_columns == - child_rows - priv->area_rows) { - if (priv->focus_index == child_count - 1) { - return TRUE; - } - set_focus(grid, get_child_by_index(priv, child_count - 1), - TRUE); - return TRUE; - } - - t = MIN(priv->first_index / priv->num_columns + - priv->area_rows, child_rows - priv->area_rows); - adjustment = gtk_range_get_adjustment(GTK_RANGE(priv->scrollbar)); - adjustment->value = (gdouble) (t * priv->item_height); - gtk_range_set_adjustment(GTK_RANGE(priv->scrollbar), adjustment); - gtk_widget_queue_draw(priv->scrollbar); - update_contents(grid); - - /* Want to update now. */ - hildon_grid_size_allocate(GTK_WIDGET(grid), - >K_WIDGET(grid)->allocation); - - return TRUE; - break; - - case GDK_KP_Up: - case GDK_Up: - if (y <= 0) { - return TRUE; - } - addition = -priv->num_columns; - max_add = y; - y--; - break; - - case GDK_KP_Down: - case GDK_Down: - if (y >= (child_count - 1) / priv->num_columns) { - return TRUE; - } - t = child_count % priv->num_columns; - if (t == 0) { - t = priv->num_columns; - } - if (y == (child_count - 1) / priv->num_columns - 1 && x >= t) { - x = t - 1; - } - y++; - addition = priv->num_columns; - max_add = child_rows - y; - break; - - case GDK_KP_Left: - case GDK_Left: - if (x <= 0) { - return TRUE; - } - addition = -1; - max_add = x; - x--; - break; - - case GDK_KP_Right: - case GDK_Right: - if (x >= priv->num_columns - 1) { - return TRUE; - } - if (y == 0 && x >= child_count - 1) { - return TRUE; - } - x++; - addition = 1; - max_add = priv->num_columns - x; - if (y * priv->num_columns + x == child_count) { - y--; - } - break; - case GDK_KP_Enter: - case GDK_Return: - hildon_grid_activate_child(grid, - HILDON_GRID_ITEM - (GTK_CONTAINER(grid)->focus_child)); - return TRUE; - break; - default: - return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event); - break; - } - - focus_index = y * priv->num_columns + x; - new_focus = get_child_by_index(priv, focus_index); - - while (new_focus != NULL && - focus_index < child_count && !GTK_WIDGET_SENSITIVE(new_focus)) { - max_add--; - - if (max_add == 0) { - return TRUE; - } - focus_index += addition; - new_focus = get_child_by_index(priv, focus_index); - } - - if (new_focus != NULL) { - set_focus(grid, new_focus, TRUE); - } - return TRUE; -} - - -/* - * hildon_grid_button_pressed: - * @widget: Widget where signal is coming from - * @event: #EventButton - * @data: #HildonGrid - * - * Handle mouse button press. - * - * Return value: Signal handled - */ -static gboolean -hildon_grid_button_pressed(GtkWidget * widget, - GdkEventButton * event) -{ - HildonGrid *grid; - HildonGridPrivate *priv; - GtkWidget *child; - int child_no; - - grid = HILDON_GRID(widget); - priv = HILDON_GRID_GET_PRIVATE(grid); - -/* Watch out for double/triple click press events */ - - if (event->type == GDK_2BUTTON_PRESS || - event->type == GDK_3BUTTON_PRESS) { - priv->last_button_event = event->type; - return FALSE; - } - - priv->last_button_event = event->type; - - if (event->type != GDK_BUTTON_PRESS) - return FALSE; - - - child_no = get_child_index_by_coord(priv, event->x, event->y); - - if (child_no == -1 || child_no >= g_list_length(priv->children)) - return FALSE; - - child = get_child_by_index(priv, child_no); - if (!GTK_WIDGET_IS_SENSITIVE(child)) - return FALSE; - - priv->click_x = event->x; - priv->click_y = event->y; - - return FALSE; -} - -/* - * hildon_grid_button_released: - * @widget: Widget the signal is coming from - * @event: #EventButton - * @data: #HildonGrid - * - * Handle mouse button release. - * - * Return value: Signal handled - */ -static gboolean -hildon_grid_button_released(GtkWidget * widget, - GdkEventButton * event) -{ - HildonGrid *grid; - HildonGridPrivate *priv; - GtkWidget *child; - int child_no; - gboolean already_selected; - - grid = HILDON_GRID(widget); - priv = HILDON_GRID_GET_PRIVATE(grid); - - /* In case of double/triple click, silently ignore the release event */ - - if (priv->last_button_event == GDK_2BUTTON_PRESS || - priv->last_button_event == GDK_3BUTTON_PRESS) { - priv->last_button_event = event->type; - return FALSE; - } - - child_no = get_child_index_by_coord(priv, event->x, event->y); - - if (child_no == -1 || child_no >= g_list_length(priv->children)) { - return FALSE; - } - child = get_child_by_index(priv, child_no); - if (!GTK_WIDGET_IS_SENSITIVE(child)) { - return FALSE; - } - if (abs(priv->click_x - event->x) >= DRAG_SENSITIVITY - && abs(priv->click_y - event->y) >= DRAG_SENSITIVITY) { - return FALSE; - } - - /* Check if this element was already selected */ - already_selected = (priv->focus_index == child_no); - - set_focus(grid, child, TRUE); - priv->last_button_event = event->type; - - /* If this is not the first click in this element, activate it */ - if (already_selected) - hildon_grid_activate_child(grid, HILDON_GRID_ITEM(child)); - - return FALSE; -} - -/* - * hildon_grid_scrollbar_moved: - * @widget: Widget which sent the signal - * @data: #HildonGrid - * - * Update HildonGrid contents when scrollbar is moved. - * - * Return value: Signal handeld - */ -static gboolean -hildon_grid_scrollbar_moved(GtkWidget * widget, gpointer data) -{ - HildonGrid *grid; - HildonGridPrivate *priv; - gboolean updated = FALSE; - - grid = HILDON_GRID(data); - priv = HILDON_GRID_GET_PRIVATE(grid); - updated = update_contents(grid); - - /* - * If grid changes focus while dragging scrollbar and pointer leaves - * scrollbar, focus is moved to prev_focus... This prevents that. - */ - gtk_window_set_prev_focus_widget(GTK_WINDOW - (gtk_widget_get_toplevel(widget)), - GTK_CONTAINER(grid)->focus_child); - - if (updated) - /* Don't just queue it, let's do it now! */ - hildon_grid_size_allocate(GTK_WIDGET(grid), - >K_WIDGET(grid)->allocation); - - return TRUE; -} - - -/* - * update_contents: - * @grid: #HildonGrid - * - * Update the view if scrollbar has moved so that first visible row - * should've changed. Returns true if location actually changed. - * - * Return value: Content changed - */ -static gboolean update_contents(HildonGrid * grid) -{ - HildonGridPrivate *priv; - gint new_row; - - priv = HILDON_GRID_GET_PRIVATE(grid); - new_row = (int) gtk_range_get_value(GTK_RANGE(priv->scrollbar)) - / priv->item_height; - - if (new_row != priv->old_sb_pos) { - priv->old_sb_pos = new_row; - priv->first_index = new_row * priv->num_columns; - - return TRUE; - } - return FALSE; -} - -/* - * jump_scrollbar_to_focused: - * @grid: #HildonGrid - * - * Moves scrollbar position so that focused item will be shown - * in visible area. - * Returns TRUE if visible position of widgets have changed. - * - * Return value: Content changed - */ -static gboolean jump_scrollbar_to_focused(HildonGrid * grid) -{ - HildonGridPrivate *priv; - GtkAdjustment *adjustment; - gint child_count; - gint empty_grids; - gint new_row; - - priv = HILDON_GRID_GET_PRIVATE(grid); - /* If we don't have scrollbar, let the focus be broken, too. */ - g_return_val_if_fail(priv->scrollbar != NULL, FALSE); - - /* Make sure "first widget" is something sensible. */ - priv->first_index = priv->first_index - - priv->first_index % priv->num_columns; - - child_count = g_list_length(priv->children); - empty_grids = priv->num_columns * priv->area_rows - child_count + - priv->first_index; - - /* Determine the position of the new row */ - if (priv->focus_index < priv->first_index) { - new_row = priv->focus_index / priv->num_columns; - } else if (priv->focus_index >= priv->first_index + - priv->area_rows * priv->num_columns) { - gint last_top_row; - new_row = priv->focus_index / priv->num_columns - - priv->area_rows + 1; - last_top_row = child_count / priv->num_columns - priv->area_rows + 1; - if (child_count % priv->num_columns != 0) { - last_top_row++; - } - if (new_row > last_top_row) { - new_row = last_top_row; - } - } else if (empty_grids >= priv->num_columns) { - new_row = ((child_count - 1) / priv->num_columns + 1) - - priv->area_rows; - if (new_row < 0) { - new_row = 0; - } - } else { - return FALSE; - } - - /* Move scrollbar accordingly. */ - adjustment = gtk_range_get_adjustment(GTK_RANGE(priv->scrollbar)); - adjustment->value = (gdouble) (new_row * priv->item_height); - gtk_range_set_adjustment(GTK_RANGE(priv->scrollbar), adjustment); - priv->first_index = new_row * priv->num_columns; - priv->old_sb_pos = new_row; - - gtk_widget_queue_draw(priv->scrollbar); - - return TRUE; -} - - -/* - * adjust_scrollbar_height: - * @grid: HildonGridPrivate - * - * Return value: View should change - * - * Adjust scrollbar according the #HildonGrid contents. - * Show/hide scrollbar if - * appropriate. Also sets priv->first_index. - */ -static gboolean adjust_scrollbar_height(HildonGrid * grid) -{ - HildonGridPrivate *priv; - GtkRequisition req; - GtkAdjustment *adj; - GtkAllocation alloc; - GtkAllocation *gridalloc; - gint old_upper; - gint need_rows; - gint need_pixels; - gboolean updated; - - priv = HILDON_GRID_GET_PRIVATE(grid); - g_return_val_if_fail(priv->scrollbar != NULL, FALSE); - - updated = FALSE; - gridalloc = >K_WIDGET(grid)->allocation; - - /* See if we need scrollbar at all. */ - if (priv->num_columns == 0) { - priv->num_columns = DEFAULT_N_COLUMNS; - } else { - priv->num_columns = MAX(1, priv->num_columns); - } - - if (g_list_length(priv->children) != 0) { - need_rows = (g_list_length(priv->children) - 1) / - priv->num_columns + 1; - } else { - need_rows = 0; - } - - if (need_rows <= priv->area_rows) { - updated = priv->first_index != 0; - priv->scrollbar_width = 0; - - priv->first_index = 0; - if (GTK_WIDGET_VISIBLE(priv->scrollbar)) { - GtkWidget *parent = gtk_widget_get_toplevel (GTK_WIDGET (grid)); - if (HILDON_IS_APP (parent)) - g_object_set (parent, "scroll-control", FALSE, NULL); - gtk_widget_hide(priv->scrollbar); - updated = TRUE; - } - - return updated; - } - - /* All right then, we need scrollbar. Place scrollbar on the screen. */ - gtk_widget_get_child_requisition(priv->scrollbar, &req); - priv->scrollbar_width = req.width; - - alloc.width = req.width; - alloc.height = gridalloc->height; - alloc.x = gridalloc->width - req.width + gridalloc->x; - alloc.y = gridalloc->y; - gtk_widget_size_allocate(priv->scrollbar, &alloc); - - if (!GTK_WIDGET_VISIBLE(priv->scrollbar)) { - GtkWidget *parent = gtk_widget_get_toplevel (GTK_WIDGET (grid)); - if (HILDON_IS_APP (parent)) - g_object_set (parent, "scroll-control", TRUE, NULL); - gtk_widget_show(priv->scrollbar); - updated = TRUE; - } - - - need_pixels = need_rows * priv->item_height; - - /* Once we know how much space we need, update the scrollbar. */ - adj = gtk_range_get_adjustment(GTK_RANGE(priv->scrollbar)); - old_upper = (int) adj->upper; - adj->lower = 0.0; - adj->upper = (gdouble) need_pixels; - adj->step_increment = (gdouble) priv->item_height; - adj->page_increment = (gdouble) (priv->area_rows * priv->item_height); - adj->page_size = - (gdouble) (priv->area_height - priv->area_height % priv->item_height); - - /* Also update position if needed to show focused item. */ - - gtk_range_set_adjustment(GTK_RANGE(priv->scrollbar), adj); - - /* Then set first_index. */ - priv->first_index = (int) adj->value / priv->item_height * - priv->num_columns; - - /* Finally, ask Gtk to redraw the scrollbar. */ - if (old_upper != (int) adj->upper) { - gtk_widget_queue_draw(priv->scrollbar); - } - return updated; -} - -/* - * get_child_index_by_coord: - * @priv: HildonGridPrivate - * @x: X-coordinate - * @y: Y-coordinate - * - * Returns index of child at given coordinates, -1 if no child. - * - * Return value: Index - */ -static gint -get_child_index_by_coord(HildonGridPrivate * priv, gint x, gint y) -{ - int xgap, ygap; - int t; - - if (priv->item_width==0 || priv->item_height==0) { - return -1; - } - - xgap = x % priv->item_width; - ygap = y % priv->item_height; - - if (xgap > priv->item_width - priv->h_margin) { /*FIXME*/ - return -1; - } - - /* Event may come from outside of the grid. Skipping those events */ - if (x >= priv->item_width * priv->num_columns) - return -1; - - t = y / priv->item_height * priv->num_columns + - x / priv->item_width + priv->first_index; - - if (t >= priv->first_index + priv->area_rows * priv->num_columns || - t >= g_list_length(priv->children) || t < 0) { - return -1; - } - return t; -} - -/* - * get_child_by_index: - * @priv: HildonGridPrivate - * @index: Index of child - * - * Returns child that is #th in HildonGrid or NULL if child was not found - * among the children. - * - * Return value: GtkWidget - */ -static GtkWidget *get_child_by_index(HildonGridPrivate * priv, gint index) -{ - GList *list; - int i = 0; - - if (index >= g_list_length(priv->children) || index < 0) { - return NULL; - } - for (list = priv->children, i = 0; list != NULL; - list = list->next, i++) { - if (index == i) { - return ((HildonGridChild *) list->data)->widget; - } - } - - g_warning("no such child"); - return NULL; -} - -/* - * get_child_index: - * @priv: HildonGridPrivate - * @child: #GtkWidget to look for - * - * Returns index of a child or -1 if child was not found among the - * children. - * - * Return value: Index - */ -static gint get_child_index(HildonGridPrivate * priv, GtkWidget * child) -{ - GList *list; - gint index; - - if (child == NULL) - return -1; - - for (list = priv->children, index = 0; - list != NULL; list = list->next, index++) { - if (((HildonGridChild *) list->data)->widget == child) { - return index; - } - } - - g_warning("no such child"); - return -1; -} - - -/** - * hildon_grid_activate_child: - * @grid: #HildonGrid - * @item: #HildonGridItem - * - * Sends a signal to indicate that this HildonGridItem is activated. - */ -void hildon_grid_activate_child(HildonGrid * grid, HildonGridItem * item) -{ - g_return_if_fail(HILDON_IS_GRID(grid)); - - g_signal_emit(grid, grid_signals[ACTIVATE_CHILD], 0, item); -} - - - -/** - * hildon_grid_set_style: - * @grid: #HildonGrid - * @style_name: style name - * - * Sets style. Setting style sets widget size, spacing, label position, - * number of columns, and icon size. - */ -void hildon_grid_set_style(HildonGrid * grid, const gchar * style_name) -{ - HildonGridPrivate *priv; - - g_return_if_fail(HILDON_IS_GRID(grid)); - - - priv = HILDON_GRID_GET_PRIVATE(grid); - if (priv->style != NULL) { - g_free((gpointer) priv->style); - } - if (style_name != NULL) { - priv->style = g_strdup(style_name); - } else { - priv->style = NULL; - } - - gtk_widget_set_name(GTK_WIDGET(grid), style_name); - get_style_properties(grid); - - gtk_widget_queue_resize(GTK_WIDGET(grid)); -} - -/** - * hildon_grid_get_style: - * @grid: #HildonGrid - * - * Returns the name of style currently used in HildonGrid. - * - * Returns: style name - */ -const gchar *hildon_grid_get_style(HildonGrid * grid) -{ - g_return_val_if_fail(HILDON_IS_GRID(grid), NULL); - - return gtk_widget_get_name(GTK_WIDGET(grid)); -} - -/* - * get_style_properties: - * @grid: #HildonGrid - * - * Gets widget size and other properties from gtkrc. If some properties - * have changed, notify children of this, too. - */ -static void get_style_properties(HildonGrid * grid) -{ - GList *iter; - gint num_columns; - HildonGridPositionType label_pos; - gint emblem_size; - - gint h_margin, v_margin; - gint item_height; - gint icon_width; - gint focus_margin, icon_label_margin; - gint label_height; - - HildonGridPrivate *priv; - g_return_if_fail(HILDON_IS_GRID(grid)); - priv = HILDON_GRID_GET_PRIVATE(grid); - - gtk_widget_style_get(GTK_WIDGET(grid), - "item_hspacing", &h_margin, - "item_vspacing", &v_margin, - "item_height", &item_height, - "icon_size", &icon_width, - "n_columns", &num_columns, - "label_pos", &label_pos, - "label_hspacing", &focus_margin, - "label_vspacing", &icon_label_margin, - "emblem_size", &emblem_size, - "label_height", &label_height, - NULL); - - hildon_grid_set_icon_width(grid, icon_width); - hildon_grid_set_num_columns(grid, num_columns); - hildon_grid_set_label_pos(grid, label_pos); - hildon_grid_set_focus_margin(grid, focus_margin); - hildon_grid_set_icon_label_margin(grid, icon_label_margin); - hildon_grid_set_emblem_size(grid, emblem_size); - hildon_grid_set_label_height(grid, label_height); - - priv->h_margin = h_margin; - priv->v_margin = v_margin; - priv->item_height = item_height; - - iter = NULL; - /* - for (iter = priv->children; iter != NULL; iter = iter->next) { - HildonGridItem *child; - child = HILDON_GRID_ITEM(((HildonGridChild *) iter->data)->widget); - _hildon_grid_item_done_updating_settings(child); - } - */ -} - - - -/** - * hildon_grid_set_scrollbar_pos: - * @grid: #HildonGrid - * @scrollbar_pos: new position (in pixels) - * - * Sets view (scrollbar) to specified position. - */ -void hildon_grid_set_scrollbar_pos(HildonGrid * grid, gint scrollbar_pos) -{ - HildonGridPrivate *priv; - GtkAdjustment *adjustment; - - g_return_if_fail(HILDON_IS_GRID(grid)); - - priv = HILDON_GRID_GET_PRIVATE(grid); - adjustment = gtk_range_get_adjustment(GTK_RANGE(priv->scrollbar)); - adjustment->value = (gdouble) scrollbar_pos; - - gtk_range_set_adjustment(GTK_RANGE(priv->scrollbar), adjustment); - - g_object_notify (G_OBJECT (grid), "scrollbar-position"); - - /* If grid isn't drawable, updating anything could mess up focus. */ - if (!GTK_WIDGET_DRAWABLE(GTK_WIDGET(grid))) - return; - - update_contents(grid); -} - -/** - * hildon_grid_get_scrollbar_pos: - * @grid: #HildonGrid - * - * Returns: position of scrollbar (in pixels). - */ -gint hildon_grid_get_scrollbar_pos(HildonGrid * grid) -{ - GtkAdjustment *adjustment; - - g_return_val_if_fail(HILDON_IS_GRID(grid), -1); - - adjustment = gtk_range_get_adjustment(GTK_RANGE - (HILDON_GRID_GET_PRIVATE - (grid)->scrollbar)); - return (int) adjustment->value; -} - -static void -hildon_grid_set_property(GObject * object, - guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - HildonGrid *grid; - - grid = HILDON_GRID(object); - - switch (prop_id) { - case PROP_EMPTY_LABEL: - hildon_grid_set_empty_label(grid, g_value_get_string(value)); - break; - - case PROP_STYLE: - hildon_grid_set_style(grid, g_value_get_string(value)); - break; - - case PROP_SCROLLBAR_POS: - hildon_grid_set_scrollbar_pos(grid, g_value_get_int(value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -hildon_grid_get_property(GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec) -{ - HildonGrid *grid; - - grid = HILDON_GRID(object); - - switch (prop_id) { - case PROP_EMPTY_LABEL: - g_value_set_string(value, hildon_grid_get_empty_label(grid)); - break; - - case PROP_STYLE: - g_value_set_string(value, hildon_grid_get_style(grid)); - break; - - case PROP_SCROLLBAR_POS: - g_value_set_int(value, hildon_grid_get_scrollbar_pos(grid)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static gboolean -hildon_grid_state_changed(GtkWidget * widget, - GtkStateType state, gpointer data) -{ - HildonGrid *grid; - HildonGridPrivate *priv; - GList *list; - GtkWidget *current; - GtkWidget *prev_focusable, *next_focusable; - gboolean found_old; - - g_return_val_if_fail(HILDON_IS_GRID(data), FALSE); - g_return_val_if_fail(HILDON_IS_GRID_ITEM(widget), FALSE); - - grid = HILDON_GRID(data); - priv = HILDON_GRID_GET_PRIVATE(grid); - - - if (GTK_WIDGET_IS_SENSITIVE(widget)) - return FALSE; - - prev_focusable = next_focusable = NULL; - found_old = FALSE; - - for (list = priv->children; list != NULL; list = list->next) { - current = ((HildonGridChild *) list->data)->widget; - - if (GTK_WIDGET_IS_SENSITIVE(current)) { - if (found_old) { - next_focusable = current; - break; - } else { - prev_focusable = current; - } - } else if (current == widget) { - found_old = TRUE; - } - } - - if (next_focusable == NULL) { - next_focusable = prev_focusable; - } - - gtk_container_set_focus_child(GTK_CONTAINER(grid), next_focusable); - - return FALSE; -} - - - -static void -hildon_grid_tap_and_hold_setup(GtkWidget * widget, - GtkWidget * menu, - GtkCallback func, - GtkWidgetTapAndHoldFlags flags) -{ - g_return_if_fail(HILDON_IS_GRID(widget) && GTK_IS_MENU(menu)); - - parent_class->parent_class.tap_and_hold_setup - (widget, menu, func, flags | GTK_TAP_AND_HOLD_NO_INTERNALS); -} diff --git a/hildon-widgets/hildon-grid.h b/hildon-widgets/hildon-grid.h deleted file mode 100644 index 4863566..0000000 --- a/hildon-widgets/hildon-grid.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/* - * @file hildon-grid.h - * - * This file is a header file for hildon-grid.c, the implementation of - * #HildonGrid. #HildonGrid is used in views like Home and Control Panel - * which have single-tap activated items. - */ - -#ifndef __HILDON_GRID_H__ -#define __HILDON_GRID_H__ - -#include -#include - -G_BEGIN_DECLS -#define HILDON_TYPE_GRID (hildon_grid_get_type ()) -#define HILDON_GRID(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - HILDON_TYPE_GRID, \ - HildonGrid)) -#define HILDON_GRID_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \ - HILDON_TYPE_GRID, \ - HildonGridClass)) -#define HILDON_IS_GRID(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ - HILDON_TYPE_GRID)) -#define HILDON_IS_GRID_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \ - HILDON_TYPE_GRID)) -#define HILDON_GRID_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - HILDON_TYPE_GRID, \ - HildonGridClass)) -typedef struct _HildonGrid HildonGrid; -typedef struct _HildonGridClass HildonGridClass; - - - -struct _HildonGrid { - GtkContainer parent; -}; - -struct _HildonGridClass { - GtkContainerClass parent_class; - - void (*activate_child) (HildonGrid * grid, HildonGridItem * item); - void (*popup_context_menu) (HildonGrid * grid, HildonGridItem * item); -}; - -GType hildon_grid_get_type(void); -GtkWidget *hildon_grid_new(void); - -/* - * Use GtkContainer API: - * - * void gtk_container_set_focus_child (GtkContainer *container, - * GtkWidget *child); - * - * GTK_CONTAINER (grid)->focus_child can be used to get focused child. - */ - -void hildon_grid_set_style(HildonGrid * grid, const gchar * style_name); -const gchar *hildon_grid_get_style(HildonGrid * grid); - -void hildon_grid_set_scrollbar_pos(HildonGrid * grid, gint scrollbar_pos); -gint hildon_grid_get_scrollbar_pos(HildonGrid * grid); - - -/* - * We are going to use gtk_container_add/remove, so these are internal. - * If GridView is not visible, it won't update the view, so it should be - * hidden when doing massive modifications. - * - * - * Use GtkContainer API: - * - * void gtk_container_add (GtkContainer *container, - * GtkWidget *widget); - * - * void gtk_container_remove (GtkContainer *container, - * GtkWidget *widget); - */ - -void hildon_grid_activate_child(HildonGrid * grid, HildonGridItem * item); - -G_END_DECLS -#endif /* __HILDON_GRID_H__ */ diff --git a/hildon-widgets/hildon-hvolumebar.c b/hildon-widgets/hildon-hvolumebar.c deleted file mode 100644 index c3d7a10..0000000 --- a/hildon-widgets/hildon-hvolumebar.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-hvolumebar - * @short_description: A widget that displays a horizontal volume bar - * @see_also: #HildonVVolumebar, #HildonVolumebar - * - * The #HildonHVolumebar widget displays a horizontal volume bar that allows - * increasing or decreasing volume within a pre-defined range, and includes - * a mute icon which users can click to mute the sound. - */ - - -/* Horizontal volumebar subclass */ - -#include -#include "hildon-hvolumebar.h" -#include "hildon-volumebar.h" -#include "hildon-volumebar-range.h" -#include "hildon-volumebar-private.h" - -/* Defines for normal version of HVolumebar */ -/* Toggle button */ -#define DEFAULT_TBUTTON_WIDTH 26 -#define DEFAULT_TBUTTON_HEIGHT 26 -/* Volume bar */ -#define MINIMUM_BAR_WIDTH 147 -#define DEFAULT_BAR_HEIGHT 58 -#define DEFAULT_ENDING_SIZE 20 - -/* Gap to leave for mute button */ -#define VERTICAL_MUTE_GAP 16 -#define HORIZONTAL_MUTE_GAP 6 - -/* Sizes inside a toolbar */ -/* Toggle button */ -#define TOOL_DEFAULT_TBUTTON_WIDTH 26 -#define TOOL_DEFAULT_TBUTTON_HEIGHT 26 -/* Volumebar */ -#define TOOL_MINIMUM_BAR_WIDTH 121 -#define TOOL_DEFAULT_BAR_HEIGHT 40 -#define TOOL_DEFAULT_ENDING_SIZE 0 -#define TOOL_VERTICAL_MUTE_GAP ((TOOL_DEFAULT_BAR_HEIGHT - TOOL_DEFAULT_TBUTTON_HEIGHT) / 2) - -static HildonVolumebarClass *parent_class; -static void hildon_hvolumebar_class_init(HildonHVolumebarClass * klass); -static void hildon_hvolumebar_init(HildonHVolumebar * hvolumebar); - -static gboolean hildon_hvolumebar_expose(GtkWidget * widget, - GdkEventExpose * event); -static void hildon_hvolumebar_size_request(GtkWidget * widget, - GtkRequisition * requisition); -static void hildon_hvolumebar_size_allocate(GtkWidget * widget, - GtkAllocation * allocation); -static void hildon_hvolumebar_map(GtkWidget * widget); - - -GType hildon_hvolumebar_get_type(void) -{ - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof(HildonHVolumebarClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_hvolumebar_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonHVolumebar), - 0, - (GInstanceInitFunc) hildon_hvolumebar_init, - }; - type = g_type_register_static(HILDON_TYPE_VOLUMEBAR, - "HildonHVolumebar", &info, 0); - } - return type; -} - - -static void hildon_hvolumebar_class_init(HildonHVolumebarClass * klass) -{ - GtkWidgetClass *volumebar_class = GTK_WIDGET_CLASS(klass); - - parent_class = g_type_class_peek_parent(klass); - - volumebar_class->size_request = hildon_hvolumebar_size_request; - volumebar_class->size_allocate = hildon_hvolumebar_size_allocate; - volumebar_class->map = hildon_hvolumebar_map; - volumebar_class->expose_event = hildon_hvolumebar_expose; -} - - -static void hildon_hvolumebar_init(HildonHVolumebar * hvolumebar) -{ - HildonVolumebarPrivate *priv; - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(hvolumebar); - - priv->volumebar = - HILDON_VOLUMEBAR_RANGE(hildon_volumebar_range_new - (GTK_ORIENTATION_HORIZONTAL)); - - GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(hvolumebar), GTK_CAN_FOCUS); - - gtk_widget_set_parent(GTK_WIDGET(priv->tbutton), GTK_WIDGET(hvolumebar)); - gtk_widget_set_parent(GTK_WIDGET(priv->volumebar), GTK_WIDGET(hvolumebar)); - - gtk_scale_set_draw_value(GTK_SCALE(priv->volumebar), FALSE); - - /* Signals */ - g_signal_connect_swapped(G_OBJECT(priv->volumebar), "value-changed", - G_CALLBACK(hildon_volumebar_level_change), - hvolumebar); - g_signal_connect_swapped(priv->tbutton, "toggled", - G_CALLBACK(_hildon_volumebar_mute_toggled), hvolumebar); - - gtk_widget_show(GTK_WIDGET(priv->volumebar)); -} - -/** - * hildon_hvolumebar_new: - * - * Creates a new #HildonHVolumebar widget. - * - * Returns: a new #HildonHVolumebar - */ -GtkWidget *hildon_hvolumebar_new(void) -{ - return GTK_WIDGET(g_object_new(HILDON_TYPE_HVOLUMEBAR, NULL)); -} - -static void hildon_hvolumebar_map(GtkWidget * widget) -{ - HildonVolumebarPrivate *priv; - GtkWidget *parent; - - g_assert(HILDON_IS_HVOLUMEBAR(widget)); - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget); - parent = gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_TOOLBAR); - - /* Check if the volumebar is in a toolbar */ - if (parent) - priv->is_toolbar = TRUE; - - GTK_WIDGET_CLASS(parent_class)->map(widget); -} - -static gboolean hildon_hvolumebar_expose(GtkWidget * widget, - GdkEventExpose * event) -{ - HildonVolumebarPrivate *priv; - - g_assert(HILDON_IS_HVOLUMEBAR(widget)); - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(HILDON_VOLUMEBAR(widget)); - - if (GTK_WIDGET_DRAWABLE(widget)) { - /* Paint background */ - gtk_paint_box(widget->style, widget->window, - GTK_WIDGET_STATE(priv->volumebar), GTK_SHADOW_OUT, - NULL, widget, "background", - widget->allocation.x, - widget->allocation.y, - widget->allocation.width, - widget->allocation.height); - - /* The contents of the widget can paint themselves */ - (*GTK_WIDGET_CLASS(parent_class)->expose_event) (widget, event); - } - - return FALSE; -} - -static void -hildon_hvolumebar_size_request(GtkWidget * widget, - GtkRequisition * requisition) -{ - HildonVolumebarPrivate *priv; - - g_assert(HILDON_IS_HVOLUMEBAR(widget)); - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(HILDON_VOLUMEBAR(widget)); - - /* Volumebar has different dimensions in toolbar */ - requisition->width = (priv->is_toolbar - ? TOOL_MINIMUM_BAR_WIDTH - : MINIMUM_BAR_WIDTH); - requisition->height = (priv->is_toolbar - ? TOOL_DEFAULT_BAR_HEIGHT - : DEFAULT_BAR_HEIGHT); -} - -static void -hildon_hvolumebar_size_allocate(GtkWidget * widget, - GtkAllocation * allocation) -{ - HildonVolumebarPrivate *priv; - GtkAllocation button_allocation, range_allocation; - - g_assert(HILDON_IS_HVOLUMEBAR(widget)); - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget); - - button_allocation.x = 0; - button_allocation.width = 0; - - /* Center the widget vertically */ - if (priv->is_toolbar && allocation->height > TOOL_DEFAULT_BAR_HEIGHT) { - allocation->y += (allocation->height - TOOL_DEFAULT_BAR_HEIGHT) / 2; - allocation->height = TOOL_DEFAULT_BAR_HEIGHT; - } - if (!priv->is_toolbar && allocation->height > DEFAULT_BAR_HEIGHT) { - allocation->y += (allocation->height - DEFAULT_BAR_HEIGHT) / 2; - allocation->height = DEFAULT_BAR_HEIGHT; - } - - GTK_WIDGET_CLASS(parent_class)->size_allocate(widget, allocation); - - if (priv->tbutton && GTK_WIDGET_VISIBLE(priv->tbutton)) { - - /* Allocate space for the mute button */ - if (priv->is_toolbar) { - button_allocation.x = allocation->x; - button_allocation.y = allocation->y + TOOL_VERTICAL_MUTE_GAP; - button_allocation.width = TOOL_DEFAULT_TBUTTON_WIDTH; - button_allocation.height = TOOL_DEFAULT_TBUTTON_HEIGHT; - } else { - button_allocation.x = allocation->x + DEFAULT_ENDING_SIZE; - button_allocation.y = allocation->y + VERTICAL_MUTE_GAP; - button_allocation.width = DEFAULT_TBUTTON_WIDTH; - button_allocation.height = DEFAULT_TBUTTON_HEIGHT; - } - gtk_widget_size_allocate(GTK_WIDGET(priv->tbutton), - &button_allocation); - } - if (priv->volumebar && GTK_WIDGET_VISIBLE(priv->volumebar)) { - - /* Allocate space for the slider */ - range_allocation.y = allocation->y; - - if (priv->tbutton && GTK_WIDGET_VISIBLE(priv->tbutton)) - { - /* Leave room for the mute button */ - range_allocation.x = button_allocation.x - + button_allocation.width - + HORIZONTAL_MUTE_GAP; - - if (priv->is_toolbar) - { - /* In toolbar with mute button */ - range_allocation.width = MAX(0, - allocation->width - - 2 * TOOL_DEFAULT_ENDING_SIZE - - TOOL_DEFAULT_TBUTTON_WIDTH - - HORIZONTAL_MUTE_GAP); - - range_allocation.height = TOOL_DEFAULT_BAR_HEIGHT; - - } - - else - { - /* Standalone with mute button */ - range_allocation.width = MAX(0, - allocation->width - - 2 * DEFAULT_ENDING_SIZE - - DEFAULT_TBUTTON_WIDTH - - HORIZONTAL_MUTE_GAP); - - range_allocation.height = DEFAULT_BAR_HEIGHT; - } - - } - - else - { - if (priv->is_toolbar) - { - /* In toolbar without mute button */ - range_allocation.x = allocation->x; - - range_allocation.width = MAX(0, - allocation->width - - 2 * TOOL_DEFAULT_ENDING_SIZE ); - - range_allocation.height = TOOL_DEFAULT_BAR_HEIGHT; - - } - - else - { - /* Standalone without mute button */ - range_allocation.x = allocation->x + DEFAULT_ENDING_SIZE; - - range_allocation.width = MAX(0, - allocation->width - - 2 * DEFAULT_ENDING_SIZE ); - - range_allocation.height = DEFAULT_BAR_HEIGHT; - } - } - - gtk_widget_size_allocate(GTK_WIDGET(priv->volumebar), - &range_allocation); - } -} diff --git a/hildon-widgets/hildon-hvolumebar.h b/hildon-widgets/hildon-hvolumebar.h deleted file mode 100644 index 1b13432..0000000 --- a/hildon-widgets/hildon-hvolumebar.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_HVOLUMEBAR_H__ -#define __HILDON_HVOLUMEBAR_H__ - -#include - -G_BEGIN_DECLS - -#define HILDON_TYPE_HVOLUMEBAR ( hildon_hvolumebar_get_type() ) -#define HILDON_HVOLUMEBAR(obj) (GTK_CHECK_CAST (obj,\ - HILDON_TYPE_HVOLUMEBAR, HildonHVolumebar)) -#define HILDON_HVOLUMEBAR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass),\ - HILDON_TYPE_HVOLUMEBAR, HildonHVolumebarClass)) -#define HILDON_IS_HVOLUMEBAR(obj) (GTK_CHECK_TYPE (obj,\ - HILDON_TYPE_HVOLUMEBAR)) -#define HILDON_IS_HVOLUMEBAR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass),\ - HILDON_TYPE_HVOLUMEBAR)) - -typedef struct _HildonHVolumebar HildonHVolumebar; -typedef struct _HildonHVolumebarClass HildonHVolumebarClass; - -struct _HildonHVolumebar { - /* This is our parent class */ - HildonVolumebar volumebar; -}; - -struct _HildonHVolumebarClass { - HildonVolumebarClass parent_class; -}; - -GType hildon_hvolumebar_get_type(void) G_GNUC_CONST; -GtkWidget *hildon_hvolumebar_new(void); - -G_END_DECLS -#endif /* __HILDON_HVOLUMEBAR_H__ */ diff --git a/hildon-widgets/hildon-input-mode-hint.h b/hildon-widgets/hildon-input-mode-hint.h deleted file mode 100644 index f6833fc..0000000 --- a/hildon-widgets/hildon-input-mode-hint.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_INPUT_MODE_HINT_H__ -#define __HILDON_INPUT_MODE_HINT_H__ - -G_BEGIN_DECLS - -/* Hildon wrapper for setting the input mode in a GtkEntry - * Usage: g_object_set(G_OBJECT(entry), HILDON_INPUT_MODE_HINT, HILDON_INPUT_MODE_HINT_HEXA, NULL); - */ -#define HILDON_INPUT_MODE_HINT "input-mode" - -/* Hildon wrapper for setting the autocapitalization in text widgets. - * Usage: g_object_set(G_OBJECT(entry), HILDON_AUTOCAP, FALSE, NULL); - */ -#define HILDON_AUTOCAP "autocap" - -/** - * HildonInputModeHint: - * @HILDON_INPUT_MODE_HINT_ALPHANUMERICSPECIAL: accept all characters. - * @HILDON_INPUT_MODE_HINT_NUMERIC: accept only NUMERIC characters. - * @HILDON_INPUT_MODE_HINT_ALPHA: accept only ALPHA characters - * @HILDON_INPUT_MODE_HINT_NUMERICSPECIAL: accept only NUMERIC and SPECIAL - * @HILDON_INPUT_MODE_HINT_ALPHASPECIAL: accept only ALPHA and SPECIAL - * @HILDON_INPUT_MODE_HINT_ALPHANUMERIC: accept only ALPHA and NUMERIC - * @HILDON_INPUT_MODE_HINT_HEXA: accept only HEXA - * @HILDON_INPUT_MODE_HINT_HEXASPECIAL: accept only HEXA and SPECIAL - * @HILDON_INPUT_MODE_HINT_TELE: accept only TELEPHONE - * @HILDON_INPUT_MODE_HINT_TELESPECIAL: accept only TELEPHONE and SPECIAL - * - * Keys to set the mode in a GtkEntry widget into ALPHANUMERIC or NUMERIC mode. Note that this is only a hint; it only shows VKB with specified layout. Use it by calling 'g_object_set(G_OBJECT(entry), "input-mode", HILDON_INPUT_MODE_HINT_NUMERIC, NULL);'. - */ -typedef enum { - HILDON_INPUT_MODE_HINT_ALPHANUMERICSPECIAL = 0, - HILDON_INPUT_MODE_HINT_NUMERIC, - HILDON_INPUT_MODE_HINT_ALPHA, - HILDON_INPUT_MODE_HINT_NUMERICSPECIAL, - HILDON_INPUT_MODE_HINT_ALPHASPECIAL, - HILDON_INPUT_MODE_HINT_ALPHANUMERIC, - HILDON_INPUT_MODE_HINT_HEXA, - HILDON_INPUT_MODE_HINT_HEXASPECIAL, - HILDON_INPUT_MODE_HINT_TELE, - HILDON_INPUT_MODE_HINT_TELESPECIAL - -} HildonInputModeHint; - -G_END_DECLS -#endif /* __HILDON_INPUT_MODE_HINT_H__ */ diff --git a/hildon-widgets/hildon-marshalers.c b/hildon-widgets/hildon-marshalers.c deleted file mode 100644 index b5dd899..0000000 --- a/hildon-widgets/hildon-marshalers.c +++ /dev/null @@ -1,134 +0,0 @@ -#include - -#include - - -#ifdef G_ENABLE_DEBUG -#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) -#define g_marshal_value_peek_char(v) g_value_get_char (v) -#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) -#define g_marshal_value_peek_int(v) g_value_get_int (v) -#define g_marshal_value_peek_uint(v) g_value_get_uint (v) -#define g_marshal_value_peek_long(v) g_value_get_long (v) -#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) -#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) -#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) -#define g_marshal_value_peek_enum(v) g_value_get_enum (v) -#define g_marshal_value_peek_flags(v) g_value_get_flags (v) -#define g_marshal_value_peek_float(v) g_value_get_float (v) -#define g_marshal_value_peek_double(v) g_value_get_double (v) -#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) -#define g_marshal_value_peek_param(v) g_value_get_param (v) -#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) -#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) -#define g_marshal_value_peek_object(v) g_value_get_object (v) -#else /* !G_ENABLE_DEBUG */ -/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. - * Do not access GValues directly in your code. Instead, use the - * g_value_get_*() functions - */ -#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int -#define g_marshal_value_peek_char(v) (v)->data[0].v_int -#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint -#define g_marshal_value_peek_int(v) (v)->data[0].v_int -#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint -#define g_marshal_value_peek_long(v) (v)->data[0].v_long -#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong -#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 -#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 -#define g_marshal_value_peek_enum(v) (v)->data[0].v_long -#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong -#define g_marshal_value_peek_float(v) (v)->data[0].v_float -#define g_marshal_value_peek_double(v) (v)->data[0].v_double -#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer -#endif /* !G_ENABLE_DEBUG */ - - -/* BOOLEAN:ENUM (hildon-marshalers.list:26) */ -void -_hildon_marshal_BOOLEAN__ENUM (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data) -{ - typedef gboolean (*GMarshalFunc_BOOLEAN__ENUM) (gpointer data1, - gint arg_1, - gpointer data2); - register GMarshalFunc_BOOLEAN__ENUM callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - gboolean v_return; - - g_return_if_fail (return_value != NULL); - g_return_if_fail (n_param_values == 2); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_BOOLEAN__ENUM) (marshal_data ? marshal_data : cc->callback); - - v_return = callback (data1, - g_marshal_value_peek_enum (param_values + 1), - data2); - - g_value_set_boolean (return_value, v_return); -} - -/* BOOLEAN:INT,INT,INT (hildon-marshalers.list:27) */ -void -_hildon_marshal_BOOLEAN__INT_INT_INT (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data) -{ - typedef gboolean (*GMarshalFunc_BOOLEAN__INT_INT_INT) (gpointer data1, - gint arg_1, - gint arg_2, - gint arg_3, - gpointer data2); - register GMarshalFunc_BOOLEAN__INT_INT_INT callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - gboolean v_return; - - g_return_if_fail (return_value != NULL); - g_return_if_fail (n_param_values == 4); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_BOOLEAN__INT_INT_INT) (marshal_data ? marshal_data : cc->callback); - - v_return = callback (data1, - g_marshal_value_peek_int (param_values + 1), - g_marshal_value_peek_int (param_values + 2), - g_marshal_value_peek_int (param_values + 3), - data2); - - g_value_set_boolean (return_value, v_return); -} - -/* VOID:OBJECT (hildon-marshalers.list:28) */ - diff --git a/hildon-widgets/hildon-marshalers.h b/hildon-widgets/hildon-marshalers.h deleted file mode 100644 index f616e9d..0000000 --- a/hildon-widgets/hildon-marshalers.h +++ /dev/null @@ -1,31 +0,0 @@ - -#ifndef ___HILDON_MARSHALERS_H__ -#define ___HILDON_MARSHALERS_H__ - -#include - -G_BEGIN_DECLS - -/* BOOLEAN:ENUM (hildon-marshalers.list:26) */ -extern void _hildon_marshal_BOOLEAN__ENUM (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -/* BOOLEAN:INT,INT,INT (hildon-marshalers.list:27) */ -extern void _hildon_marshal_BOOLEAN__INT_INT_INT (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); - -/* VOID:OBJECT (hildon-marshalers.list:28) */ -#define _hildon_marshal_VOID__OBJECT g_cclosure_marshal_VOID__OBJECT - -G_END_DECLS - -#endif /* __HILDON_MARSHALERS_H__ */ - diff --git a/hildon-widgets/hildon-marshalers.list b/hildon-widgets/hildon-marshalers.list deleted file mode 100644 index d8596b2..0000000 --- a/hildon-widgets/hildon-marshalers.list +++ /dev/null @@ -1,28 +0,0 @@ -# A copy of gtkmarshalers.list header for convenience -# -# see glib-genmarshal(1) for a detailed description of the file format, -# possible parameter types are: -# VOID indicates no return type, or no extra -# parameters. if VOID is used as the parameter -# list, no additional parameters may be present. -# BOOLEAN for boolean types (gboolean) -# CHAR for signed char types (gchar) -# UCHAR for unsigned char types (guchar) -# INT for signed integer types (gint) -# UINT for unsigned integer types (guint) -# LONG for signed long integer types (glong) -# ULONG for unsigned long integer types (gulong) -# ENUM for enumeration types (gint) -# FLAGS for flag enumeration types (guint) -# FLOAT for single-precision float types (gfloat) -# DOUBLE for double-precision float types (gdouble) -# STRING for string types (gchar*) -# BOXED for boxed (anonymous but reference counted) types (GBoxed*) -# POINTER for anonymous pointer types (gpointer) -# OBJECT for GObject or derived types (GObject*) -# NONE deprecated alias for VOID -# BOOL deprecated alias for BOOLEAN - -BOOLEAN:ENUM -BOOLEAN:INT,INT,INT -VOID:OBJECT diff --git a/hildon-widgets/hildon-name-password-dialog.c b/hildon-widgets/hildon-name-password-dialog.c deleted file mode 100644 index 327e1f0..0000000 --- a/hildon-widgets/hildon-name-password-dialog.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-name-password-dialog - * @short_description: A widget which allows a user to enter an username - * and a password - * @see_also: #HildonGetPasswordDialog, #HildonSetPasswordDialog - * - * #HildonNamePasswordDialog is used to enter a username and password - * when accessing a password protected function. The widget performs no - * input checking and is used only for retrieving a user name and a - * password. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#define _(String) dgettext(PACKAGE, String) - -static GtkDialogClass *parent_class; - -typedef struct _HildonNamePasswordDialogPrivate - HildonNamePasswordDialogPrivate; - -struct _HildonNamePasswordDialogPrivate { - GtkButton *okButton; - GtkButton *closeButton; - - GtkLabel *domainLabel; - GtkEntry *nameEntry; - GtkEntry *passwordEntry; -}; - -/* Macro to access the private data of the object instance */ -#define HILDON_NAME_PASSWORD_DIALOG_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), HILDON_TYPE_NAME_PASSWORD_DIALOG,\ - HildonNamePasswordDialogPrivate)) - -enum{ - PROP_NONE = 0, - PROP_CONTENT, - PROP_USERNAME, - PROP_PASSWORD -}; - -static void -hildon_name_password_dialog_class_init(HildonNamePasswordDialogClass *class); -static void hildon_name_password_dialog_init(HildonNamePasswordDialog *widget); -static void hildon_name_password_dialog_set_property(GObject * object, - guint prop_id, - const GValue * value, - GParamSpec * pspec); -static void hildon_name_password_dialog_get_property(GObject * object, - guint prop_id, - GValue * value, - GParamSpec * pspec); - -static void -hildon_name_password_dialog_set_property(GObject * object, - guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - HildonNamePasswordDialog *dialog = NULL; - HildonNamePasswordDialogPrivate *priv = NULL; - - dialog = HILDON_NAME_PASSWORD_DIALOG(object); - priv = HILDON_NAME_PASSWORD_DIALOG_GET_PRIVATE(dialog); - - switch (prop_id) { - case PROP_CONTENT: - /* Set the password domain text */ - hildon_name_password_dialog_set_domain(dialog, g_value_get_string(value)); - break; - case PROP_USERNAME: - /* Set the current username displayed in the dialog */ - gtk_entry_set_text(priv->nameEntry, g_value_get_string(value)); - break; - case PROP_PASSWORD: - /* Set the currently entered password */ - gtk_entry_set_text(priv->passwordEntry, g_value_get_string(value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -hildon_name_password_dialog_get_property(GObject * object, - guint prop_id, - GValue * value, GParamSpec * pspec) -{ - HildonNamePasswordDialog *dialog = NULL; - HildonNamePasswordDialogPrivate *priv = NULL; - - dialog = HILDON_NAME_PASSWORD_DIALOG(object); - priv = HILDON_NAME_PASSWORD_DIALOG_GET_PRIVATE(dialog); - - switch (prop_id) { - case PROP_CONTENT: - g_value_set_string(value, gtk_label_get_text(priv->domainLabel)); - break; - case PROP_USERNAME: - g_value_set_string(value, hildon_name_password_dialog_get_name(dialog)); - break; - case PROP_PASSWORD: - g_value_set_string(value, hildon_name_password_dialog_get_password(dialog)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -hildon_name_password_dialog_class_init(HildonNamePasswordDialogClass *class) -{ - GObjectClass *object_class = G_OBJECT_CLASS(class); - - parent_class = g_type_class_peek_parent(class); - - /* Override virtual functions */ - object_class->set_property = hildon_name_password_dialog_set_property; - object_class->get_property = hildon_name_password_dialog_get_property; - - /* Install new properties */ - g_object_class_install_property(object_class, - PROP_CONTENT, - g_param_spec_string ("content", - "Content", - "Set content for content label.", - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property(object_class, - PROP_USERNAME, - g_param_spec_string ("username", - "Username", - "Set content for name entry.", - "DEFAULT", - G_PARAM_READWRITE)); - - g_object_class_install_property(object_class, - PROP_PASSWORD, - g_param_spec_string ("password", - "Password", - "Set content for password entry", - "DEFAULT", - G_PARAM_READWRITE)); - - /* Install private data structure */ - g_type_class_add_private(class, - sizeof(HildonNamePasswordDialogPrivate)); -} - -static void -hildon_name_password_dialog_init(HildonNamePasswordDialog * dialog) -{ - /* Access private structure */ - HildonNamePasswordDialogPrivate *priv = - HILDON_NAME_PASSWORD_DIALOG_GET_PRIVATE(dialog); - - /* Size group for captions */ - GtkSizeGroup *group = - GTK_SIZE_GROUP(gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL)); - HildonCaption *caption; - - /* Initialize dialog */ - gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); - gtk_window_set_title(GTK_WINDOW(dialog), _(HILDON_NAME_PASSWORD_DIALOG_TITLE)); - - /* Optional domain name label */ - priv->domainLabel = GTK_LABEL(gtk_label_new(NULL)); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), - GTK_WIDGET(priv->domainLabel), FALSE, FALSE, 0); - - /* Create buttons */ - priv->okButton = - GTK_BUTTON(gtk_dialog_add_button(GTK_DIALOG(dialog), - _(HILDON_NAME_PASSWORD_DIALOG_OK), - GTK_RESPONSE_OK)); - priv->closeButton = - GTK_BUTTON(gtk_dialog_add_button(GTK_DIALOG(dialog), - _(HILDON_NAME_PASSWORD_DIALOG_CANCEL), - GTK_RESPONSE_CANCEL)); - - /* Setup user name entry */ - priv->nameEntry = GTK_ENTRY(gtk_entry_new()); - g_object_set (priv->nameEntry, "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL); - gtk_entry_set_visibility(GTK_ENTRY(priv->nameEntry), FALSE); - caption = HILDON_CAPTION(hildon_caption_new - (group, - _(HILDON_NAME_PASSWORD_DIALOG_NAME ), - GTK_WIDGET(priv->nameEntry), NULL, - HILDON_CAPTION_OPTIONAL)); - hildon_caption_set_separator(caption, ""); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), - GTK_WIDGET(caption), FALSE, FALSE, 0); - - /* Setup password entry */ - priv->passwordEntry = GTK_ENTRY(gtk_entry_new()); - g_object_set (priv->passwordEntry, "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL); - gtk_entry_set_visibility(GTK_ENTRY(priv->passwordEntry), FALSE); - caption = - HILDON_CAPTION(hildon_caption_new(group, - _(HILDON_NAME_PASSWORD_DIALOG_PASSWORD), - GTK_WIDGET(priv->passwordEntry), - NULL, - HILDON_CAPTION_OPTIONAL)); - hildon_caption_set_separator(caption, ""); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), - GTK_WIDGET(caption), FALSE, FALSE, 0); - - gtk_widget_show_all(GTK_DIALOG(dialog)->vbox); - gtk_widget_show_all(GTK_DIALOG(dialog)->action_area); - gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); - - /* Ensure group is freed when all its contents have been removed */ - g_object_unref(group); -} - -GType hildon_name_password_dialog_get_type(void) -{ - static GType dialog_type = 0; - - if (!dialog_type) { - static const GTypeInfo dialog_info = { - sizeof(HildonNamePasswordDialogClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_name_password_dialog_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonNamePasswordDialog), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_name_password_dialog_init - }; - dialog_type = g_type_register_static(GTK_TYPE_DIALOG, - "HildonNamePasswordDialog", - &dialog_info, 0); - } - - return dialog_type; -} - -/** - * hildon_name_password_dialog_new: - * @parent: the parent window of the dialog - * - * Creates a new #HildonNamePasswordDialog widget with Ok and Close - * buttons. - * - * Returns: the newly created #HildonNamePasswordDialog - */ -GtkWidget *hildon_name_password_dialog_new(GtkWindow * parent) -{ - GtkWidget *self = g_object_new(HILDON_TYPE_NAME_PASSWORD_DIALOG,NULL); - - if (parent) - gtk_window_set_transient_for(GTK_WINDOW(self), parent); - - return self; -} - -/** - * hildon_name_password_dialog_new_with_default: - * @parent: the parent window of the dialog - * @name: default username, NULL if unset - * @password: default password, NULL if unset - * - * Same as #hildon_name_password_dialog_new, but with a - * default name and password. - * - * Returns: the newly created #HildonNamePasswordDialog - */ -GtkWidget *hildon_name_password_dialog_new_with_default(GtkWindow *parent, - const gchar *name, - const gchar *password) -{ - GtkWidget *self = hildon_name_password_dialog_new(parent); - - if(name != NULL) - g_object_set(G_OBJECT(self), "username", name, NULL); - if(password != NULL) - g_object_set(G_OBJECT(self), "password", password, NULL); - - return self; -} - -/** - * hildon_name_password_dialog_get_name: - * @dialog: the dialog - * - * Gets the text that's in the name entry. - * - * Returns: a pointer to the name string. - */ -const gchar *hildon_name_password_dialog_get_name(HildonNamePasswordDialog - * dialog) -{ - HildonNamePasswordDialogPrivate *priv; - - g_return_val_if_fail(HILDON_IS_NAME_PASSWORD_DIALOG(dialog), NULL); - - priv = HILDON_NAME_PASSWORD_DIALOG_GET_PRIVATE(dialog); - - return gtk_entry_get_text(priv->nameEntry); -} - -/** - * hildon_name_password_dialog_get_password: - * @dialog: the dialog - * - * Gets the text that's in the password entry. - * - * Returns: a pointer to the password string - */ -const gchar *hildon_name_password_dialog_get_password(HildonNamePasswordDialog - * dialog) -{ - HildonNamePasswordDialogPrivate *priv; - - g_return_val_if_fail(HILDON_IS_NAME_PASSWORD_DIALOG(dialog), NULL); - - priv = HILDON_NAME_PASSWORD_DIALOG_GET_PRIVATE(dialog); - - return gtk_entry_get_text(priv->passwordEntry); -} - -/** - * hildon_name_password_dialog_set_domain(GtkWidget *dialog, - * @dialog: the dialog - * @domain: the domain or some other descriptive text to be set - * - * sets the optional descriptive text - */ - -void hildon_name_password_dialog_set_domain(HildonNamePasswordDialog *dialog, - const gchar *domain) -{ - HildonNamePasswordDialogPrivate *priv; - - g_return_if_fail(HILDON_IS_NAME_PASSWORD_DIALOG(dialog)); - - priv = HILDON_NAME_PASSWORD_DIALOG_GET_PRIVATE(dialog); - gtk_label_set_text(priv->domainLabel, domain); -} diff --git a/hildon-widgets/hildon-name-password-dialog.h b/hildon-widgets/hildon-name-password-dialog.h deleted file mode 100644 index 25783b4..0000000 --- a/hildon-widgets/hildon-name-password-dialog.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_NAME_PASSWORD_DIALOG_H__ -#define __HILDON_NAME_PASSWORD_DIALOG_H__ - -#include - -G_BEGIN_DECLS -#define HILDON_TYPE_NAME_PASSWORD_DIALOG \ - ( hildon_name_password_dialog_get_type() ) -#define HILDON_NAME_PASSWORD_DIALOG(obj) \ - (GTK_CHECK_CAST (obj, HILDON_TYPE_NAME_PASSWORD_DIALOG,\ - HildonNamePasswordDialog)) -#define HILDON_NAME_PASSWORD_DIALOG_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), HILDON_TYPE_NAME_PASSWORD_DIALOG, \ - HildonNamePasswordDialogClass)) -#define HILDON_IS_NAME_PASSWORD_DIALOG(obj) \ - (GTK_CHECK_TYPE (obj, HILDON_TYPE_NAME_PASSWORD_DIALOG)) -#define HILDON_IS_NAME_PASSWORD_DIALOG_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_NAME_PASSWORD_DIALOG)) - -#define HILDON_NAME_PASSWORD_DIALOG_TITLE "frw_ti_get_user_name_and_pwd" -#define HILDON_NAME_PASSWORD_DIALOG_NAME \ - "frw_ti_get_user_name_and_pwd_enter_user_name" -#define HILDON_NAME_PASSWORD_DIALOG_PASSWORD \ - "frw_ti_get_user_name_and_pwd_enter_pwd" -#define HILDON_NAME_PASSWORD_DIALOG_OK "frw_bd_get_user_name_and_pwd_ok" -#define HILDON_NAME_PASSWORD_DIALOG_CANCEL \ - "frw_bd_get_user_name_and_pwd_cancel" - - -typedef struct _HildonNamePasswordDialog HildonNamePasswordDialog; -typedef struct _HildonNamePasswordDialogClass - HildonNamePasswordDialogClass; - -struct _HildonNamePasswordDialog { - GtkDialog parent; -}; - -struct _HildonNamePasswordDialogClass { - GtkDialogClass parent_class; -}; - -GType hildon_name_password_dialog_get_type(void) G_GNUC_CONST; - -GtkWidget *hildon_name_password_dialog_new(GtkWindow * parent); - -GtkWidget *hildon_name_password_dialog_new_with_default(GtkWindow *parent, - const gchar *name, - const gchar *pass); - - -const gchar *hildon_name_password_dialog_get_name(HildonNamePasswordDialog - * dialog); - -const gchar *hildon_name_password_dialog_get_password(HildonNamePasswordDialog - * dialog); - -void hildon_name_password_dialog_set_domain(HildonNamePasswordDialog *dialog, - const gchar *domain); - -G_END_DECLS -#endif /* __HILDON_NAME_PASSWORD_DIALOG_H__ */ diff --git a/hildon-widgets/hildon-note.c b/hildon-widgets/hildon-note.c deleted file mode 100644 index a58ca02..0000000 --- a/hildon-widgets/hildon-note.c +++ /dev/null @@ -1,869 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-note - * @short_description: A widget to ask confirmation from the user - * - * Notes are used to for confirmation (OK/Cancel/etc.) from the user. - * A simple note contains an information text and an OK button to be - * pressed. Additional features such as progress bars or animation can - * also be included. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "hildon-note.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for _hildon_gtk_label_set_text_n_lines */ - -#include -#include - -/* FIXME: Can these be included from somewhere? */ -#define CONFIRMATION_SOUND_PATH "/usr/share/sounds/ui-confirmation_note.wav" -#define INFORMATION_SOUND_PATH "/usr/share/sounds/ui-information_note.wav" -#define HILDON_NOTE_CONFIRMATION_ICON "qgn_note_confirm" -#define HILDON_NOTE_INFORMATION_ICON "qgn_note_info" - -#define _(String) dgettext(PACKAGE, String) - -static GtkDialogClass *parent_class; - -#define HILDON_NOTE_GET_PRIVATE(obj)\ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_NOTE, HildonNotePrivate)); - -typedef struct _HildonNotePrivate HildonNotePrivate; - -static void hildon_note_class_init(HildonNoteClass * class); -static void hildon_note_init(HildonNote * dialog); - -static void hildon_note_rebuild(HildonNote *note); -static void hildon_note_finalize(GObject * obj_self); -static void hildon_note_realize (GtkWidget *widget); - -static void hildon_note_set_property(GObject * object, - guint prop_id, - const GValue * value, - GParamSpec * pspec); -static void hildon_note_get_property(GObject * object, - guint prop_id, - GValue * value, GParamSpec * pspec); - -static gboolean -sound_handling(GtkWidget * widget, GdkEventExpose *event, gpointer data); - -struct _HildonNotePrivate { - GtkWidget *okButton; - GtkWidget *cancelButton; - GtkWidget *label; - GtkWidget *box; - GtkWidget *icon; - - HildonNoteType note_n; - GtkWidget *progressbar; - gulong sound_signal_handler; - - gchar *original_description; -}; - -enum { - PROP_NONE = 0, - PROP_HILDON_NOTE_TYPE, - PROP_HILDON_NOTE_DESCRIPTION, - PROP_HILDON_NOTE_ICON, - PROP_HILDON_NOTE_PROGRESSBAR, - PROP_HILDON_NOTE_STOCK_ICON -}; - -static void -hildon_note_set_property(GObject * object, - guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - HildonNote *note = HILDON_NOTE(object); - HildonNotePrivate *priv; - GtkWidget *widget; - - priv = HILDON_NOTE_GET_PRIVATE(note); - - switch (prop_id) { - case PROP_HILDON_NOTE_TYPE: - priv->note_n = g_value_get_enum(value); - hildon_note_rebuild(note); - break; - case PROP_HILDON_NOTE_DESCRIPTION: - g_free(priv->original_description); - priv->original_description = g_value_dup_string(value); - - _hildon_gtk_label_set_text_n_lines(GTK_LABEL(priv->label), - priv->original_description, - priv->note_n == HILDON_NOTE_PROGRESSBAR_TYPE ? 1 : 5); - - break; - case PROP_HILDON_NOTE_ICON: - gtk_image_set_from_icon_name(GTK_IMAGE(priv->icon), - g_value_get_string(value), HILDON_ICON_SIZE_BIG_NOTE); - break; - case PROP_HILDON_NOTE_STOCK_ICON: - gtk_image_set_from_stock(GTK_IMAGE(priv->icon), - g_value_get_string(value), HILDON_ICON_SIZE_BIG_NOTE); - break; - case PROP_HILDON_NOTE_PROGRESSBAR: - widget = g_value_get_object(value); - if (widget != priv->progressbar) - { - if (priv->progressbar) - g_object_unref(priv->progressbar); - - priv->progressbar = widget; - - if (widget) - { - g_object_ref(widget); - gtk_object_sink(GTK_OBJECT(widget)); - } - - hildon_note_rebuild(note); - } - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -hildon_note_get_property(GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec) -{ - HildonNote *note = HILDON_NOTE(object); - HildonNotePrivate *priv; - - priv = HILDON_NOTE_GET_PRIVATE(note); - - switch (prop_id) { - case PROP_HILDON_NOTE_TYPE: - g_value_set_enum(value, priv->note_n); - break; - case PROP_HILDON_NOTE_DESCRIPTION: - g_value_set_string(value, priv->original_description); - break; - case PROP_HILDON_NOTE_ICON: - g_object_get_property(G_OBJECT(priv->icon), "icon-name", value); - break; - case PROP_HILDON_NOTE_STOCK_ICON: - g_object_get_property(G_OBJECT(priv->icon), "stock", value); - break; - case PROP_HILDON_NOTE_PROGRESSBAR: - g_value_set_object(value, priv->progressbar); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -GType hildon_note_type_get_type (void) -{ - static GType notetype = 0; - if (notetype == 0) { - static const GEnumValue values[] = { - { HILDON_NOTE_CONFIRMATION_TYPE, "HILDON_NOTE_CONFIRMATION_TYPE", "confirmation" }, - { HILDON_NOTE_CONFIRMATION_BUTTON_TYPE, "HILDON_NOTE_CONFIRMATION_BUTTON_TYPE", "confirmation-button" }, - { HILDON_NOTE_INFORMATION_TYPE, "HILDON_NOTE_INFORMATION_TYPE", "note-information" }, - { HILDON_NOTE_INFORMATION_THEME_TYPE, "HILDON_NOTE_INFORMATION_THEME_TYPE", "note-information-theme" }, - { HILDON_NOTE_PROGRESSBAR_TYPE, "HILDON_NOTE_PROGRESSBAR_TYPE", "note-progressbar" }, - { 0, NULL, NULL } - }; - notetype = g_enum_register_static ("HildonNoteType", values); - } - return notetype; -} - - -GType hildon_note_get_type() -{ - static GType dialog_type = 0; - - if (!dialog_type) { - static const GTypeInfo dialog_info = { - sizeof(HildonNoteClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_note_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonNote), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_note_init - }; - dialog_type = g_type_register_static(GTK_TYPE_DIALOG, - "HildonNote", - &dialog_info, 0); - } - return dialog_type; -} - -static void hildon_note_class_init(HildonNoteClass * class) -{ - GObjectClass *object_class = G_OBJECT_CLASS(class); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(class); - - /* set the global parent_class */ - parent_class = g_type_class_peek_parent(class); - - g_type_class_add_private(class, sizeof(HildonNotePrivate)); - - object_class->finalize = hildon_note_finalize; - object_class->set_property = hildon_note_set_property; - object_class->get_property = hildon_note_get_property; - widget_class->realize = hildon_note_realize; - - g_object_class_install_property(object_class, - PROP_HILDON_NOTE_TYPE, - g_param_spec_enum("note_type", - "note type", - "The type of the note dialog", - hildon_note_type_get_type(), - HILDON_NOTE_CONFIRMATION_TYPE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - /** - * HildonNote:description: - * - * Description for note. - */ - g_object_class_install_property(object_class, - PROP_HILDON_NOTE_DESCRIPTION, - g_param_spec_string("description", - "note description", - "The text that appears in the note dialog", - "", - G_PARAM_READWRITE)); - - /** - * HildonNote:icon: - * - * Icon for note. - */ - g_object_class_install_property(object_class, - PROP_HILDON_NOTE_ICON, - g_param_spec_string("icon", - "note icon", - "The name of the icon that appears in the note dialog", - "", - G_PARAM_READWRITE)); - - /** - * HildonNote:stock-icon: - * - * Stock icon for note. - */ - g_object_class_install_property(object_class, - PROP_HILDON_NOTE_STOCK_ICON, - g_param_spec_string("stock-icon", - "Stock note icon", - "The stock name of the icon that appears in the note dialog", - "", - G_PARAM_READWRITE)); - - /** - * HildonNote:progressbar: - * - * Progressbar for note. - */ - g_object_class_install_property(object_class, - PROP_HILDON_NOTE_PROGRESSBAR, - g_param_spec_object("progressbar", - "Progressbar widget", - "The progressbar that appears in the note dialog", - GTK_TYPE_PROGRESS_BAR, - G_PARAM_READWRITE)); -} - -static void hildon_note_init(HildonNote * dialog) -{ - HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE(dialog); - - priv->label = gtk_label_new(NULL); - priv->icon = gtk_image_new(); - - /* Acquire real references to our internal children, since - they are not nessecarily packed into container in each - layout */ - g_object_ref(priv->label); - g_object_ref(priv->icon); - gtk_object_sink(GTK_OBJECT(priv->label)); - gtk_object_sink(GTK_OBJECT(priv->icon)); - - gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); - gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); -} - - -static void hildon_note_finalize(GObject * obj_self) -{ - HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE(obj_self); - - /* Free internal data */ - g_object_unref(priv->label); - g_object_unref(priv->icon); - if (priv->progressbar) - g_object_unref(priv->progressbar); - - g_free(priv->original_description); - - G_OBJECT_CLASS(parent_class)->finalize(obj_self); -} - -static void -hildon_note_realize (GtkWidget *widget) -{ - HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE(widget); - - /* Make widget->window accessible */ - GTK_WIDGET_CLASS (parent_class)->realize (widget); - - /* Border only, no titlebar */ - gdk_window_set_decorations (widget->window, GDK_DECOR_BORDER); - - /* Because ESD is synchronous, we wish to play sound after the - note is already on screen to avoid blocking its appearance */ - if (priv->sound_signal_handler == 0) - priv->sound_signal_handler = g_signal_connect_after(widget, - "expose-event", G_CALLBACK(sound_handling), NULL); -} - -/* Helper function for removing a widget from it's container. - we own a separate reference to each object we try to unpack, - so extra referencing is not needed. */ -static void unpack_widget(GtkWidget *widget) -{ - g_assert(widget == NULL || GTK_IS_WIDGET(widget)); - - if (widget && widget->parent) - gtk_container_remove(GTK_CONTAINER(widget->parent), widget); -} - -static void -hildon_note_rebuild(HildonNote *note) -{ - GtkDialog *dialog; - HildonNotePrivate *priv; - gboolean IsHorizontal = TRUE; - - g_assert(HILDON_IS_NOTE(note)); - - priv = HILDON_NOTE_GET_PRIVATE (note); - dialog = GTK_DIALOG(note); - - /* Reuse exiting content widgets for new layout */ - unpack_widget(priv->label); - unpack_widget(priv->icon); - unpack_widget(priv->progressbar); - - /* Destroy old layout and buttons */ - if (priv->box) { - gtk_widget_destroy(priv->box); - priv->box = NULL; - } - if (priv->okButton) { - gtk_widget_destroy(priv->okButton); - priv->okButton = NULL; - } - if (priv->cancelButton) { - gtk_widget_destroy(priv->cancelButton); - priv->cancelButton = NULL; - } - - /* Add needed buttons and images for each note type */ - switch (priv->note_n) - { - case HILDON_NOTE_CONFIRMATION_TYPE: - priv->okButton = gtk_dialog_add_button(dialog, - _("ecdg_bd_confirmation_note_ok"), GTK_RESPONSE_OK); - priv->cancelButton = gtk_dialog_add_button(dialog, - _("ecdg_bd_confirmation_note_cancel"), GTK_RESPONSE_CANCEL); - - /* Fall through */ - case HILDON_NOTE_CONFIRMATION_BUTTON_TYPE: - gtk_image_set_from_icon_name(GTK_IMAGE(priv->icon), - HILDON_NOTE_CONFIRMATION_ICON, - HILDON_ICON_SIZE_BIG_NOTE); - break; - - case HILDON_NOTE_INFORMATION_THEME_TYPE: - case HILDON_NOTE_INFORMATION_TYPE: - /* Add clickable OK button (cancel really, - but doesn't matter since this is info) */ - priv->cancelButton = gtk_dialog_add_button(dialog, - _("ecdg_bd_information_note_ok"), GTK_RESPONSE_CANCEL); - gtk_image_set_from_icon_name(GTK_IMAGE(priv->icon), - HILDON_NOTE_INFORMATION_ICON, - HILDON_ICON_SIZE_BIG_NOTE); - break; - - case HILDON_NOTE_PROGRESSBAR_TYPE: - priv->cancelButton = gtk_dialog_add_button(dialog, - _("ecdg_bd_cancel_note_cancel"), GTK_RESPONSE_CANCEL); - IsHorizontal = FALSE; - break; - - default: - break; - } - - if (IsHorizontal) { - /* Pack item with label horizontally */ - priv->box = gtk_hbox_new(FALSE, HILDON_MARGIN_DEFAULT); - gtk_container_add(GTK_CONTAINER(dialog->vbox), priv->box); - - if (priv->icon) { - GtkWidget *alignment = gtk_alignment_new(0, 0, 0, 0); - - gtk_box_pack_start(GTK_BOX(priv->box), alignment, FALSE, FALSE, 0); - gtk_container_add(GTK_CONTAINER(alignment), priv->icon); - } - gtk_box_pack_start(GTK_BOX(priv->box), priv->label, TRUE, TRUE, 0); - - } else { - /* Pack item with label vertically */ - priv->box = gtk_vbox_new(FALSE, HILDON_MARGIN_DOUBLE); - gtk_container_add(GTK_CONTAINER(dialog->vbox), priv->box); - gtk_box_pack_start(GTK_BOX(priv->box), priv->label, TRUE, TRUE, 0); - - if (priv->progressbar) - gtk_box_pack_start(GTK_BOX(priv->box), priv->progressbar, FALSE, FALSE, 0); - } - - gtk_widget_show_all(priv->box); -} - -/** - * hildon_note_new_confirmation_add_buttons: - * @parent: the parent window. The X window ID of the parent window - * has to be the same as the X window ID of the application. This is - * important so that the window manager could handle the windows - * correctly. - * In GTK the X window ID can be checked using - * GDK_WINDOW_XID(GTK_WIDGET(parent)->window). - * @description: the message to confirm - * @Varargs: arguments pairs for new buttons(label and return value). - * Terminate the list with %NULL value. - * - * Create a new confirmation note with custom buttons. Confirmation - * note has a text and any number of buttons. It's important to note - * that even though the name of the function might suggest, the - * default ok/cancel buttons are not appended but you have to provide - * all of the buttons. - * - * FIXME: This doc seems to be wrong, the two buttons aren't added so - * it would only contain the "additional" buttons? However, changing - * this would break those applications that rely on current behaviour. - * - * Returns: A #GtkWidget pointer of the note - */ -GtkWidget *hildon_note_new_confirmation_add_buttons(GtkWindow *parent, - const gchar *description, - ...) -{ - va_list args; - char *message; - int value; - - g_return_val_if_fail(parent == NULL || GTK_IS_WINDOW(parent), NULL); - - GtkWidget *conf_note = - g_object_new(HILDON_TYPE_NOTE, - "note_type", HILDON_NOTE_CONFIRMATION_BUTTON_TYPE, - "description", description, - "icon", HILDON_NOTE_CONFIRMATION_ICON, - NULL); - - if (parent != NULL) - gtk_window_set_transient_for(GTK_WINDOW(conf_note), parent); - - /* Add the buttons from varargs */ - va_start(args, description); - - while (TRUE) { - message = va_arg(args, char *); - - if (!message) { - break; - } - value = va_arg(args, int); - - gtk_dialog_add_button(GTK_DIALOG(conf_note), message, value); - } - - va_end(args); - - return conf_note; -} - - -/** - * hildon_note_new_confirmation: - * @parent: the parent window. The X window ID of the parent window - * has to be the same as the X window ID of the application. This is - * important so that the window manager could handle the windows - * correctly. In GTK the X window ID can be checked using - * GDK_WINDOW_XID(GTK_WIDGET(parent)->window). - * @description: the message to confirm - * - * Create a new confirmation note. Confirmation note has text (description) - * that you specify, two buttons and a default confirmation stock icon. - * - * Returns: a #GtkWidget pointer of the note - */ -GtkWidget *hildon_note_new_confirmation(GtkWindow * parent, - const gchar * description) -{ - return hildon_note_new_confirmation_with_icon_name - (parent, description, HILDON_NOTE_CONFIRMATION_ICON); -} - - -/** - * hildon_note_new_confirmation_with_icon_stock: - * @parent: the parent window. The X window ID of the parent window - * has to be the same as the X window ID of the application. This is - * important so that the window manager could handle the windows - * correctly. In GTK the X window ID can be checked using - * GDK_WINDOW_XID(GTK_WIDGET(parent)->window). - * @description: the message to confirm - * @stock_id: icon to be displayed. If NULL, default icon is used. - * - * Create a new confirmation note. Confirmation note has text (description) - * that you specify, two buttons and an icon. - * - * Deprecated: this function is broken, and really should not be used by anyone! - * - * Returns: a #GtkWidget pointer of the note - */ -GtkWidget *hildon_note_new_confirmation_with_icon_stock(GtkWindow * parent, - const gchar * - description, - const gchar * - stock_id) -{ - GtkWidget *dialog = g_object_new(HILDON_TYPE_NOTE, - "note_type", - HILDON_NOTE_CONFIRMATION_TYPE, - "description", description, "stock-icon", - stock_id, NULL); - - if (parent != NULL) - gtk_window_set_transient_for(GTK_WINDOW(dialog), parent); - - return dialog; -} - -/** - * hildon_note_new_confirmation_with_icon_name: - * @parent: the parent window. The X window ID of the parent window - * has to be the same as the X window ID of the application. This is - * important so that the window manager could handle the windows - * correctly. In GTK the X window ID can be checked using - * GDK_WINDOW_XID(GTK_WIDGET(parent)->window). - * @description: the message to confirm - * @icon_name: icon to be displayed. If NULL, default icon is used. - * - * Create a new confirmation note. Confirmation note has text(description) - * that you specify, two buttons and an icon. - * - * Returns: a #GtkWidget pointer of the note - */ -GtkWidget *hildon_note_new_confirmation_with_icon_name(GtkWindow * parent, - const gchar * - description, - const gchar * - icon_name) -{ - GtkWidget *dialog = NULL; - - g_return_val_if_fail(parent == NULL || GTK_IS_WINDOW(parent), NULL); - - dialog = g_object_new(HILDON_TYPE_NOTE, - "note_type", - HILDON_NOTE_CONFIRMATION_TYPE, - "description", description, "icon", - icon_name, NULL); - if (parent != NULL) - gtk_window_set_transient_for(GTK_WINDOW(dialog), parent); - - return dialog; -} - -/** - * hildon_note_new_information: - * @parent: the parent window. The X window ID of the parent window - * has to be the same as the X window ID of the application. This is - * important so that the window manager could handle the windows - * correctly. In GTK the X window ID can be checked using - * GDK_WINDOW_XID(GTK_WIDGET(parent)->window). - * @description: the message to confirm - * - * Create a new information note. Information note has a text(description) - * that you specify, an OK button and an icon. - * - * Returns: a #GtkWidget pointer of the note - */ -GtkWidget *hildon_note_new_information(GtkWindow * parent, - const gchar * description) -{ - return hildon_note_new_information_with_icon_name - (parent, description, HILDON_NOTE_INFORMATION_ICON); -} - -/** - * hildon_note_new_information_with_icon_stock: - * @parent: the parent window. The X window ID of the parent window - * has to be the same as the X window ID of the application. This is - * important so that the window manager could handle the windows - * correctly. In GTK the X window ID can be checked using - * GDK_WINDOW_XID(GTK_WIDGET(parent)->window). - * @description: the message to confirm - * @stock_id: icon to be displayed. If NULL, default icon is used. - * - * Create a new information note. Information note has text(description) - * that you specify, an OK button and a default stock note icon. - * - * Note! This function is broken and deprecated and should not be - * used by anybody. Since the platform doesn't use stock icons, - * use #hildon_note_new_information_with_icon_name instead. - * - * Returns: a #GtkWidget pointer of the note - */ -GtkWidget *hildon_note_new_information_with_icon_stock(GtkWindow * parent, - const gchar * - description, - const gchar * - stock_id) -{ - GtkWidget *dialog = NULL; - - g_return_val_if_fail(parent == NULL || GTK_IS_WINDOW(parent), NULL); - - dialog = g_object_new(HILDON_TYPE_NOTE, - "note_type", - HILDON_NOTE_INFORMATION_TYPE, - "description", description, - "icon", stock_id, NULL); - if (parent != NULL) - gtk_window_set_transient_for(GTK_WINDOW(dialog), parent); - - return dialog; -} - -/** - * hildon_note_new_information_with_icon_name: - * @parent: the parent window. The X window ID of the parent window - * has to be the same as the X window ID of the application. This is - * important so that the window manager could handle the windows - * correctly. In GTK the X window ID can be checked using - * GDK_WINDOW_XID(GTK_WIDGET(parent)->window). - * @description: the message to confirm - * @icon_name: icon to be displayed. If NULL, default icon is used. - * - * Create a new information note. Information note has text(description) - * that you specify, an OK button and an icon. - * - * Returns: a #GtkWidget pointer of the note - */ -GtkWidget *hildon_note_new_information_with_icon_name(GtkWindow * parent, - const gchar * - description, - const gchar * - icon_name) -{ - GtkWidget *dialog = NULL; - - g_return_val_if_fail(parent == NULL || GTK_IS_WINDOW(parent), NULL); - - dialog = g_object_new(HILDON_TYPE_NOTE, - "note_type", - HILDON_NOTE_INFORMATION_THEME_TYPE, - "description", description, - "icon", icon_name, NULL); - if (parent != NULL) - gtk_window_set_transient_for(GTK_WINDOW(dialog), parent); - - return dialog; -} - -/** - * hildon_note_new_information_with_icon_theme: - * @parent: the parent window. The X window ID of the parent window - * has to be the same as the X window ID of the application. This is - * important so that the window manager could handle the windows - * correctly. In GTK the X window ID can be checked using - * GDK_WINDOW_XID(GTK_WIDGET(parent)->window). - * @description: the message to confirm - * @icon: #GtkIconTheme icon to be displayed - * - * This function is deprecated. Use - * #hildon_note_new_information_with_icon_name instead. - * - * Create a new information note. Information note has text(description) - * that you specify, an OK button and an icon. - * - * Returns: a #GtkWidget pointer of the note. - */ -GtkWidget *hildon_note_new_information_with_icon_theme(GtkWindow *parent, - const gchar *description, - const gchar *icon) -{ - return hildon_note_new_information_with_icon_name(parent, description, icon); -} - -/** - * hildon_note_new_cancel_with_progress_bar: - * @parent: the parent window. The X window ID of the parent window - * has to be the same as the X window ID of the application. This is - * important so that the window manager could handle the windows - * correctly. In GTK the X window ID can be checked using - * GDK_WINDOW_XID(GTK_WIDGET(parent)->window). - * @description: the action to cancel - * @progressbar: a pointer to #GtkProgressBar to be filled with the - * progressbar assigned to this note. Use this to set the fraction of - * progressbar done. This parameter can be %NULL as well, in which - * case plain text cancel note appears. - * - * Create a new cancel note with a progress bar. Cancel note has - * text(description) that you specify, a Cancel button and a progress bar. - * - * Returns: a #GtkDialog. Use this to get rid of this note when you - * no longer need it. - */ -GtkWidget *hildon_note_new_cancel_with_progress_bar(GtkWindow * parent, - const gchar * - description, - GtkProgressBar * - progressbar) -{ - GtkWidget *dialog = NULL; - - g_return_val_if_fail(parent == NULL || GTK_IS_WINDOW(parent), NULL); - - dialog = g_object_new(HILDON_TYPE_NOTE, - "note_type", - HILDON_NOTE_PROGRESSBAR_TYPE, - "description", description, - "progressbar", - progressbar, NULL); - if (parent != NULL) - gtk_window_set_transient_for(GTK_WINDOW(dialog), parent); - - return dialog; -} - - -/** - * hildon_note_set_button_text: - * @note: a #HildonNote - * @text: sets the button text and if there is two buttons in dialog, - * the button texts will be <text>, "Cancel". - * - * Sets the button text to be used by the hildon_note widget. - */ -void hildon_note_set_button_text(HildonNote * note, const gchar * text) -{ - HildonNotePrivate *priv; - - g_return_if_fail(HILDON_IS_NOTE(note)); - - priv = HILDON_NOTE_GET_PRIVATE(HILDON_NOTE(note)); - if (priv->okButton) { - gtk_button_set_label(GTK_BUTTON(priv->okButton), text); - gtk_button_set_label(GTK_BUTTON(priv->cancelButton), - _("ecdg_bd_confirmation_note_cancel")); - } else { - gtk_button_set_label(GTK_BUTTON(priv->cancelButton), text); - } -} - -/** - * hildon_note_set_button_texts: - * @note: a #HildonNote - * @textOk: the new text of the default OK button - * @textCancel: the new text of the default cancel button - * - * Sets the button texts to be used by this hildon_note widget. - */ -void hildon_note_set_button_texts(HildonNote * note, - const gchar * textOk, - const gchar * textCancel) -{ - HildonNotePrivate *priv; - - g_return_if_fail(HILDON_IS_NOTE(note)); - - priv = HILDON_NOTE_GET_PRIVATE(HILDON_NOTE(note)); - if (priv->okButton) { - gtk_button_set_label(GTK_BUTTON(priv->okButton), textOk); - gtk_button_set_label(GTK_BUTTON(priv->cancelButton), - textCancel); - } else { - gtk_button_set_label(GTK_BUTTON(priv->cancelButton), textCancel); - } -} - -/* We play a system sound when the note comes visible */ -static gboolean -sound_handling(GtkWidget * widget, GdkEventExpose *event, gpointer data) -{ - HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE(widget); - g_signal_handler_disconnect(widget, priv->sound_signal_handler); - priv->sound_signal_handler = 0; - - switch (priv->note_n) - { - case HILDON_NOTE_INFORMATION_TYPE: - case HILDON_NOTE_INFORMATION_THEME_TYPE: - hildon_play_system_sound(INFORMATION_SOUND_PATH); - break; - case HILDON_NOTE_CONFIRMATION_TYPE: - case HILDON_NOTE_CONFIRMATION_BUTTON_TYPE: - hildon_play_system_sound(CONFIRMATION_SOUND_PATH); - break; - default: - break; - }; - - return FALSE; -} diff --git a/hildon-widgets/hildon-note.h b/hildon-widgets/hildon-note.h deleted file mode 100644 index 359eb23..0000000 --- a/hildon-widgets/hildon-note.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ -#ifndef __HILDON_NOTE_H__ -#define __HILDON_NOTE_H__ - -#include -#include - -G_BEGIN_DECLS -#define HILDON_TYPE_NOTE ( hildon_note_get_type() ) -#define HILDON_NOTE(obj) \ - (GTK_CHECK_CAST (obj, HILDON_TYPE_NOTE, HildonNote)) -#define HILDON_NOTE_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), HILDON_TYPE_NOTE, HildonNoteClass)) -#define HILDON_IS_NOTE(obj) (GTK_CHECK_TYPE (obj, HILDON_TYPE_NOTE)) -#define HILDON_IS_NOTE_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_NOTE)) - -typedef struct _HildonNote HildonNote; -typedef struct _HildonNoteClass HildonNoteClass; - -typedef enum /*< skip >*/ -{ - HILDON_NOTE_CONFIRMATION_TYPE = 0, - HILDON_NOTE_CONFIRMATION_BUTTON_TYPE, - HILDON_NOTE_INFORMATION_TYPE, - HILDON_NOTE_INFORMATION_THEME_TYPE, - HILDON_NOTE_PROGRESSBAR_TYPE -} HildonNoteType; - -struct _HildonNote { - GtkDialog parent; -}; - -struct _HildonNoteClass { - GtkDialogClass parent_class; -}; - -GtkWidget *hildon_note_new_confirmation(GtkWindow * parent, - const gchar * description); - -GtkWidget *hildon_note_new_confirmation_add_buttons(GtkWindow * parent, - const gchar * - description, ...); -#ifndef HILDON_DISABLE_DEPRECATED -GtkWidget *hildon_note_new_confirmation_with_icon_stock(GtkWindow * parent, - const gchar * - description, - const gchar * - stock_id); -#endif /* HILDON_DISABLE_DEPRECATED */ - -GtkWidget *hildon_note_new_confirmation_with_icon_name(GtkWindow * parent, - const gchar * - description, - const gchar * - icon_name); - - -GtkWidget *hildon_note_new_cancel_with_progress_bar(GtkWindow * parent, - const gchar * - description, - GtkProgressBar * - progressbar); - -GtkWidget *hildon_note_new_information(GtkWindow * parent, - const gchar * description); - -GtkWidget *hildon_note_new_information_with_icon_name(GtkWindow * parent, - const gchar * - description, - const gchar * - icon_name); -#ifndef HILDON_DISABLE_DEPRECATED -GtkWidget *hildon_note_new_information_with_icon_stock(GtkWindow * parent, - const gchar * - description, - const gchar * - stock_id); - -GtkWidget *hildon_note_new_information_with_icon_theme(GtkWindow * parent, - const gchar * - description, - const gchar * - icon); -#endif /* HILDON_DISABLE_DEPRECATED */ - -void hildon_note_set_button_text(HildonNote * note, const gchar * text); - -void hildon_note_set_button_texts(HildonNote * note, const gchar * textOk, - const gchar * textCancel); - -GType hildon_note_get_type(void) G_GNUC_CONST; -GType hildon_note_type_get_type(void) G_GNUC_CONST; - -G_END_DECLS -#endif /* __HILDON_NOTE_H__ */ diff --git a/hildon-widgets/hildon-number-editor.c b/hildon-widgets/hildon-number-editor.c deleted file mode 100644 index bdca6db..0000000 --- a/hildon-widgets/hildon-number-editor.c +++ /dev/null @@ -1,964 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-number-editor - * @short_description: A widget used to enter a number within a pre-defined range - * - * HildonNumberEditor is used to enter a number from a specific range. - * There are two buttons to scroll the value in number field. - * Manual input is also possible. - */ - -#include -#include - -#include -#include -#include - -#include "hildon-number-editor.h" -#include "hildon-marshalers.h" -#include -#include "hildon-composite-widget.h" -#include -#include -#include "hildon-libs-enum-types.h" - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#define _(String) dgettext(PACKAGE, String) - -/*Pixel spec defines*/ -#define NUMBER_EDITOR_HEIGHT 30 - -/* Size of plus and minus buttons */ -#define BUTTON_HEIGHT 30 -#define BUTTON_WIDTH 30 - -#define HILDON_NUMBER_EDITOR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_NUMBER_EDITOR, \ - HildonNumberEditorPrivate)); - -typedef struct _HildonNumberEditorPrivate HildonNumberEditorPrivate; - -static void -hildon_number_editor_class_init (HildonNumberEditorClass *editor_class); - -static void -hildon_number_editor_init (HildonNumberEditor *editor); - -static gboolean -hildon_number_editor_entry_focusout (GtkWidget *widget, GdkEventFocus *event, - gpointer data); - -static void -hildon_number_editor_entry_changed (GtkWidget *widget, gpointer data); - -static void -hildon_number_editor_size_request (GtkWidget *widget, - GtkRequisition *requisition); - -static void -set_widget_allocation (GtkWidget *widget, GtkAllocation *alloc, - const GtkAllocation *allocation); - -static void -hildon_number_editor_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); - -static gboolean -hildon_number_editor_entry_keypress (GtkWidget *widget, GdkEventKey *event, - gpointer data); - -static gboolean -hildon_number_editor_button_pressed (GtkWidget *widget, GdkEventButton *event, - gpointer data); - -static gboolean -hildon_number_editor_entry_button_released (GtkWidget *widget, - GdkEventButton *event, - gpointer data); -static gboolean -hildon_number_editor_button_released (GtkWidget *widget, - GdkEvent *event, - HildonNumberEditor *editor); -static gboolean -do_mouse_timeout (HildonNumberEditor *editor); - -static void -change_numbers (HildonNumberEditor *editor, gint update); - -static void -hildon_number_editor_forall (GtkContainer *container, gboolean include_internals, - GtkCallback callback, gpointer callback_data); - -static void -hildon_number_editor_destroy (GtkObject *self); - -static gboolean -hildon_number_editor_start_timer (HildonNumberEditor *editor); - -static void -hildon_number_editor_finalize (GObject *self); - -static gboolean -hildon_number_editor_range_error(HildonNumberEditor *editor, - HildonNumberEditorErrorType type); - -static gboolean -hildon_number_editor_select_all (HildonNumberEditorPrivate *priv); - -static void -hildon_number_editor_validate_value(HildonNumberEditor *editor, gboolean allow_intermediate); - -static void hildon_number_editor_set_property(GObject * object, - guint prop_id, - const GValue * value, - GParamSpec * pspec); - -static void hildon_number_editor_get_property(GObject * object, - guint prop_id, - GValue * value, GParamSpec * pspec); - -/* Signal indices */ -enum -{ - RANGE_ERROR, - LAST_SIGNAL -}; - -/* Property indices */ -enum { - PROP_0, - PROP_VALUE -}; - -static GtkContainerClass *parent_class; - -static guint HildonNumberEditor_signal[LAST_SIGNAL] = {0}; - -struct _HildonNumberEditorPrivate -{ - /* Child widgets */ - GtkWidget *num_entry; - GtkWidget *plus; - GtkWidget *minus; - - gint start; /* Minimum */ - gint end; /* Maximum */ - gint default_val; - gint button_type; /* Type of button pressed: 1 = plus, -1 = minus */ - - /* Timer IDs */ - guint button_event_id; /* Repeat change when button is held */ - guint select_all_idle_id; /* Selection repaint hack - see hildon_number_editor_select_all */ -}; - - -GType hildon_number_editor_get_type(void) -{ - static GType editor_type = 0; - - if (!editor_type) - { - static const GTypeInfo editor_info = - { - sizeof(HildonNumberEditorClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_number_editor_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonNumberEditor), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_number_editor_init, - }; - editor_type = g_type_register_static(GTK_TYPE_CONTAINER, - "HildonNumberEditor", - &editor_info, 0); - } - return editor_type; -} - -static void -hildon_number_editor_class_init(HildonNumberEditorClass * editor_class) -{ - GtkContainerClass *container_class = GTK_CONTAINER_CLASS(editor_class); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(editor_class); - GObjectClass *gobject_class = G_OBJECT_CLASS(editor_class); - - g_type_class_add_private(editor_class, - sizeof(HildonNumberEditorPrivate)); - - parent_class = g_type_class_peek_parent(editor_class); - - widget_class->size_request = hildon_number_editor_size_request; - widget_class->size_allocate = hildon_number_editor_size_allocate; - widget_class->focus = hildon_composite_widget_focus; - - editor_class->range_error = hildon_number_editor_range_error; - - /* Because we derived our widget from GtkContainer, we should override - forall method */ - container_class->forall = hildon_number_editor_forall; - GTK_OBJECT_CLASS(editor_class)->destroy = hildon_number_editor_destroy; - gobject_class->finalize = hildon_number_editor_finalize; - gobject_class->set_property = hildon_number_editor_set_property; - gobject_class->get_property = hildon_number_editor_get_property; - - g_object_class_install_property(gobject_class, PROP_VALUE, - g_param_spec_int("value", - "Value", - "The current value of number editor", - G_MININT, - G_MAXINT, - 0, G_PARAM_READWRITE)); - - HildonNumberEditor_signal[RANGE_ERROR] = - g_signal_new("range_error", HILDON_TYPE_NUMBER_EDITOR, - G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET - (HildonNumberEditorClass, range_error), - g_signal_accumulator_true_handled, NULL, - _hildon_marshal_BOOLEAN__ENUM, - G_TYPE_BOOLEAN, 1, HILDON_TYPE_NUMBER_EDITOR_ERROR_TYPE); -} - -static void -hildon_number_editor_forall(GtkContainer *container, gboolean include_internals, - GtkCallback callback, gpointer callback_data) -{ - HildonNumberEditorPrivate *priv = - HILDON_NUMBER_EDITOR_GET_PRIVATE(container); - - g_assert(callback != NULL); - - if (!include_internals) - return; - - /* Enumerate child widgets */ - (*callback) (priv->minus, callback_data); - (*callback) (priv->num_entry, callback_data); - (*callback) (priv->plus, callback_data); -} - -static void -hildon_number_editor_destroy(GtkObject *self) -{ - HildonNumberEditorPrivate *priv; - - priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(self); - - /* Free child widgets */ - if (priv->minus) - { - gtk_widget_unparent(priv->minus); - priv->minus = NULL; - } - if (priv->num_entry) - { - gtk_widget_unparent(priv->num_entry); - priv->num_entry = NULL; - } - if (priv->plus) - { - gtk_widget_unparent(priv->plus); - priv->plus = NULL; - } - - if (GTK_OBJECT_CLASS(parent_class)->destroy) - GTK_OBJECT_CLASS(parent_class)->destroy(self); -} - -static void -hildon_number_editor_stop_repeat_timer(HildonNumberEditorPrivate *priv) -{ - if (priv->button_event_id) - { - g_source_remove(priv->button_event_id); - priv->button_event_id = 0; - } -} - -static void -hildon_number_editor_finalize (GObject *self) -{ - HildonNumberEditorPrivate *priv; - - priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(self); - - /* Free timers */ - hildon_number_editor_stop_repeat_timer(priv); - - if (priv->select_all_idle_id) - g_source_remove (priv->select_all_idle_id); - - /* Call parent class finalize, if have one */ - if (G_OBJECT_CLASS (parent_class)->finalize) - G_OBJECT_CLASS (parent_class)->finalize(self); -} - -static void -hildon_number_editor_init (HildonNumberEditor *editor) -{ - HildonNumberEditorPrivate *priv; - - priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); - GTK_WIDGET_SET_FLAGS(GTK_WIDGET(editor), GTK_NO_WINDOW); - - /* Create child widgets */ - priv->num_entry = gtk_entry_new(); - priv->minus = gtk_button_new(); - priv->plus = gtk_button_new(); - - gtk_widget_set_name( priv->minus, "ne-minus-button" ); - gtk_widget_set_name( priv->plus, "ne-plus-button" ); - gtk_widget_set_size_request( priv->minus, BUTTON_WIDTH, BUTTON_HEIGHT ); - gtk_widget_set_size_request( priv->plus, BUTTON_WIDTH, BUTTON_HEIGHT ); - gtk_entry_set_alignment (GTK_ENTRY(priv->num_entry), 1); - - GTK_WIDGET_UNSET_FLAGS( priv->minus, GTK_CAN_FOCUS ); - GTK_WIDGET_UNSET_FLAGS( priv->plus, GTK_CAN_FOCUS ); - - priv->button_event_id = 0; - priv->select_all_idle_id = 0; - - gtk_widget_set_parent(priv->minus, GTK_WIDGET(editor)); - gtk_widget_set_parent(priv->num_entry, GTK_WIDGET(editor)); - gtk_widget_set_parent(priv->plus, GTK_WIDGET(editor)); - - /* Connect child widget signals */ - g_signal_connect(GTK_OBJECT(priv->num_entry), "changed", - G_CALLBACK(hildon_number_editor_entry_changed), - editor); - - g_signal_connect(GTK_OBJECT(priv->num_entry), "focus-out-event", - G_CALLBACK(hildon_number_editor_entry_focusout), - editor); - - g_signal_connect(GTK_OBJECT(priv->num_entry), "key-press-event", - G_CALLBACK(hildon_number_editor_entry_keypress), - editor); - - g_signal_connect(GTK_OBJECT(priv->num_entry), "button-release-event", - G_CALLBACK(hildon_number_editor_entry_button_released), - NULL); - - g_signal_connect(GTK_OBJECT(priv->minus), "button-press-event", - G_CALLBACK(hildon_number_editor_button_pressed), - editor); - - g_signal_connect(GTK_OBJECT(priv->plus), "button-press-event", - G_CALLBACK(hildon_number_editor_button_pressed), - editor); - - g_signal_connect(GTK_OBJECT(priv->minus), "button-release-event", - G_CALLBACK(hildon_number_editor_button_released), - editor); - - g_signal_connect(GTK_OBJECT(priv->plus), "button-release-event", - G_CALLBACK(hildon_number_editor_button_released), - editor); - - g_signal_connect(GTK_OBJECT(priv->minus), "leave-notify-event", - G_CALLBACK(hildon_number_editor_button_released), - editor); - - g_signal_connect(GTK_OBJECT(priv->plus), "leave-notify-event", - G_CALLBACK(hildon_number_editor_button_released), - editor); - - g_object_set( G_OBJECT(priv->num_entry), - "input-mode", HILDON_INPUT_MODE_HINT_NUMERIC, NULL ); - - gtk_widget_show(priv->num_entry); - gtk_widget_show(priv->minus); - gtk_widget_show(priv->plus); - - hildon_number_editor_set_range(editor, G_MININT, G_MAXINT); -} - -static gboolean -hildon_number_editor_entry_button_released (GtkWidget *widget, - GdkEventButton *event, - gpointer data) -{ - gtk_editable_select_region(GTK_EDITABLE(widget), 0, -1); - return FALSE; -} - -static gboolean -hildon_number_editor_button_released (GtkWidget *widget, GdkEvent *event, - HildonNumberEditor *editor) -{ - HildonNumberEditorPrivate *priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); - hildon_number_editor_stop_repeat_timer(priv); - return FALSE; -} - -/* Format given number to editor field, no checks performed, all signals - are sent normally. */ -static void -hildon_number_editor_real_set_value (HildonNumberEditorPrivate *priv, gint value) -{ - gchar buffer[32]; - - /* Update text in entry to new value */ - g_snprintf(buffer, sizeof(buffer), "%d", value); - gtk_entry_set_text(GTK_ENTRY(priv->num_entry), buffer); -} - -static gboolean -hildon_number_editor_button_pressed (GtkWidget *widget, GdkEventButton *event, - gpointer data) -{ - /* FIXME: XXX Why aren't we using hildon_number_editor_start_timer here? XXX */ - /* Need to fetch current value from entry and increment or decrement - it */ - HildonNumberEditor *editor; - HildonNumberEditorPrivate *priv; - GtkSettings *settings; - guint timeout; - - g_assert(HILDON_IS_NUMBER_EDITOR(data)); - - editor = HILDON_NUMBER_EDITOR(data); - priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); - settings = gtk_settings_get_default(); - g_object_get(settings, "gtk-initial-timeout", &timeout, NULL); - - /* Save type of button pressed */ - if (GTK_BUTTON(widget) == GTK_BUTTON(priv->plus)) - priv->button_type = 1; - else - priv->button_type = -1; - - /* Start repetition timer */ - if (!priv->button_event_id) - { - do_mouse_timeout(editor); - priv->button_event_id = g_timeout_add (timeout, - (GSourceFunc) hildon_number_editor_start_timer, - editor); - } - - return FALSE; -} - -static gboolean -hildon_number_editor_start_timer (HildonNumberEditor *editor) -{ - HildonNumberEditorPrivate *priv; - GtkSettings *settings; - guint timeout; - - priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); - settings = gtk_settings_get_default(); - g_object_get(settings, "gtk-update-timeout", &timeout, NULL); - - priv->button_event_id = g_timeout_add(timeout, - (GSourceFunc) do_mouse_timeout, - editor); - return FALSE; -} - -static gboolean -do_mouse_timeout (HildonNumberEditor *editor) -{ - HildonNumberEditorPrivate *priv; - - GDK_THREADS_ENTER (); - - g_assert(HILDON_IS_NUMBER_EDITOR(editor)); - - /* Update value based on button held */ - priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); - change_numbers(editor, priv->button_type); - - GDK_THREADS_LEAVE (); - - return TRUE; -} - -/* Changes the current number value by the amount of update - and verifies the result. */ -static void -change_numbers (HildonNumberEditor *editor, gint update) -{ - HildonNumberEditorPrivate *priv; - gint current_value; - - g_assert(HILDON_IS_NUMBER_EDITOR(editor)); - - priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); - current_value = hildon_number_editor_get_value(editor); - - /* We need to rerun validation by hand, since validation - done in "changed" callback allows intermediate values */ - hildon_number_editor_real_set_value(priv, current_value + update); - hildon_number_editor_validate_value(editor, FALSE); - g_object_notify (G_OBJECT(editor), "value"); -} - -static void -add_select_all_idle (HildonNumberEditorPrivate *priv) -{ - if (!priv->select_all_idle_id) - { - priv->select_all_idle_id = - g_idle_add((GSourceFunc) hildon_number_editor_select_all, priv); - } -} - -static void -hildon_number_editor_validate_value(HildonNumberEditor *editor, gboolean allow_intermediate) -{ - HildonNumberEditorPrivate *priv; - gint error_code, fixup_value; - const gchar *text; - long value; - gchar *tail; - gboolean r; - - g_assert(HILDON_IS_NUMBER_EDITOR(editor)); - - priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); - text = gtk_entry_get_text(GTK_ENTRY(priv->num_entry)); - error_code = -1; - fixup_value = priv->default_val; - - if (text && text[0]) - { - /* Try to convert entry text to number */ - value = strtol(text, &tail, 10); - - /* Check if conversion succeeded */ - if (tail[0] == 0) - { - /* Check if value is in allowed range. This is tricky in those - cases when user is editing a value. - For example: Range = [100, 500] and user have just inputted "4". - This should not lead into error message. Otherwise value is - resetted back to "100" and next "4" press will reset it back - and so on. */ - if (allow_intermediate) - { - /* We now have the following error cases: - * If inputted value as above maximum and - maximum is either positive or then maximum - negative and value is positive. - * If inputted value is below minimum and minimum - is negative or minumum positive and value - negative or zero. - In all other cases situation can be fixed just by - adding new numbers to the string. - */ - if (value > priv->end && (priv->end >= 0 || (priv->end < 0 && value >= 0))) - { - error_code = MAXIMUM_VALUE_EXCEED; - fixup_value = priv->end; - } - else if (value < priv->start && (priv->start < 0 || (priv->start >= 0 && value <= 0))) - { - error_code = MINIMUM_VALUE_EXCEED; - fixup_value = priv->start; - } - } - else - { - if (value > priv->end) { - error_code = MAXIMUM_VALUE_EXCEED; - fixup_value = priv->end; - } - else if (value < priv->start) { - error_code = MINIMUM_VALUE_EXCEED; - fixup_value = priv->start; - } - } - } - /* The only valid case when conversion can fail is when we - have plain '-', intermediate forms are allowed AND - minimum bound is negative */ - else if (!allow_intermediate || strcmp(text, "-") != 0 || priv->start >= 0) - error_code = ERRONEOUS_VALUE; - } - else if (!allow_intermediate) - error_code = ERRONEOUS_VALUE; - - if (error_code != -1) - { - /* If entry is empty and intermediate forms are nor allowed, - emit error signal */ - /* Change to default value */ - hildon_number_editor_set_value(editor, fixup_value); - g_signal_emit(editor, HildonNumberEditor_signal[RANGE_ERROR], - 0, error_code, &r); - add_select_all_idle(priv); - } -} - -static void -hildon_number_editor_entry_changed(GtkWidget *widget, gpointer data) -{ - g_assert(HILDON_IS_NUMBER_EDITOR(data)); - hildon_number_editor_validate_value(HILDON_NUMBER_EDITOR(data), TRUE); - g_object_notify (G_OBJECT(data), "value"); -} - -static void -hildon_number_editor_size_request (GtkWidget *widget, - GtkRequisition *requisition) -{ - HildonNumberEditor *editor; - HildonNumberEditorPrivate *priv; - GtkRequisition req; - - editor = HILDON_NUMBER_EDITOR(widget); - priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); - - /* Requested size is size of all child widgets plus border space */ - gtk_widget_size_request(priv->minus, &req); - requisition->width = req.width; - - gtk_widget_size_request(priv->num_entry, &req); - requisition->width += req.width; - - gtk_widget_size_request(priv->plus, &req); - requisition->width += req.width; - - requisition->width += HILDON_MARGIN_DEFAULT * 2; - - /* FIXME: XXX Height is fixed */ - requisition->height = NUMBER_EDITOR_HEIGHT; -} - -/* Update @alloc->width so widget fits, update @alloc->x to point to free space */ -static void -set_widget_allocation (GtkWidget *widget, GtkAllocation *alloc, - const GtkAllocation *allocation) -{ - GtkRequisition child_requisition; - - gtk_widget_get_child_requisition(widget, &child_requisition); - - /* Fit to widget width */ - if (allocation->width + allocation->x > - alloc->x + child_requisition.width) - alloc->width = child_requisition.width; - else - { - alloc->width = allocation->width - (alloc->x - allocation->x); - if (alloc->width < 0) - alloc->width = 0; - } - - gtk_widget_size_allocate(widget, alloc); - /* Update x position */ - alloc->x += alloc->width; -} - -static void -hildon_number_editor_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - HildonNumberEditor *editor; - HildonNumberEditorPrivate *priv; - GtkAllocation alloc; - - editor = HILDON_NUMBER_EDITOR(widget); - priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); - - widget->allocation = *allocation; - - /* Add upper border */ - alloc.y = widget->allocation.y + widget->style->ythickness; - - /* Fix height */ - if (widget->allocation.height > NUMBER_EDITOR_HEIGHT) - { - alloc.height = NUMBER_EDITOR_HEIGHT - widget->style->ythickness * 2; - alloc.y += (widget->allocation.height - NUMBER_EDITOR_HEIGHT) / 2; - } - else - alloc.height = widget->allocation.height - widget->style->ythickness * 2; - - if (alloc.height < 0) - alloc.height = 0; - - /* Add left border */ - alloc.x = allocation->x + widget->style->xthickness; - - /* Allocate positions for widgets (left-to-right) */ - set_widget_allocation(priv->minus, &alloc, &widget->allocation); - alloc.x += HILDON_MARGIN_DEFAULT; - - set_widget_allocation(priv->num_entry, &alloc, &widget->allocation); - alloc.x += HILDON_MARGIN_DEFAULT; - - set_widget_allocation(priv->plus, &alloc, &widget->allocation); -} - -static gboolean -hildon_number_editor_entry_focusout (GtkWidget *widget, GdkEventFocus *event, - gpointer data) -{ - g_assert(HILDON_IS_NUMBER_EDITOR(data)); - hildon_number_editor_validate_value(HILDON_NUMBER_EDITOR(data), FALSE); - return FALSE; -} - -static gboolean -hildon_number_editor_entry_keypress (GtkWidget *widget, GdkEventKey *event, - gpointer data) -{ - GtkEditable *editable; - gint cursor_pos; - - g_assert(HILDON_IS_NUMBER_EDITOR(data)); - - editable = GTK_EDITABLE(widget); - cursor_pos = gtk_editable_get_position(editable); - - switch (event->keyval) - { - case GDK_Left: - /* If the cursor is on the left, try to decrement */ - if (cursor_pos == 0) { - change_numbers(HILDON_NUMBER_EDITOR(data), -1); - return TRUE; - } - break; - - case GDK_Right: - /* If the cursor is on the right, try to increment */ - if (cursor_pos >= g_utf8_strlen(gtk_entry_get_text(GTK_ENTRY(widget)), -1)) - { - change_numbers(HILDON_NUMBER_EDITOR(data), 1); - gtk_editable_set_position(editable, cursor_pos); - return TRUE; - } - break; - - default: - break; - }; - - return FALSE; -} - -static gboolean -hildon_number_editor_range_error(HildonNumberEditor *editor, - HildonNumberEditorErrorType type) -{ - - gint min, max; - gchar *err_msg = NULL; - HildonNumberEditorPrivate *priv; - - priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); - min = priv->start; - max = priv->end; - - /* Construct error message */ - switch (type) - { - case MAXIMUM_VALUE_EXCEED: - err_msg = g_strdup_printf(_("ckct_ib_maximum_value"), max, max); - break; - case MINIMUM_VALUE_EXCEED: - err_msg = g_strdup_printf(_("ckct_ib_minimum_value"), min, min); - break; - case ERRONEOUS_VALUE: - err_msg = - g_strdup_printf(_("ckct_ib_set_a_value_within_range"), min, max); - break; - } - - /* Infoprint error */ - if (err_msg) - { - gtk_infoprint(GTK_WINDOW(gtk_widget_get_ancestor(GTK_WIDGET(editor), - GTK_TYPE_WINDOW)), err_msg); - g_free(err_msg); - } - - return TRUE; -} - - -/** - * hildon_number_editor_new: - * @min: minimum accepted value - * @max: maximum accepted value - * - * Creates new number editor - * - * Returns: a new #HildonNumberEditor widget - */ -GtkWidget * -hildon_number_editor_new (gint min, gint max) -{ - HildonNumberEditor *editor = - g_object_new(HILDON_TYPE_NUMBER_EDITOR, NULL); - - /* Set user inputted range to editor */ - hildon_number_editor_set_range(editor, min, max); - - return GTK_WIDGET(editor); -} - -/** - * hildon_number_editor_set_range: - * @editor: a #HildonNumberEditor widget - * @min: minimum accepted value - * @max: maximum accepted value - * - * Sets accepted number range for editor - */ -void -hildon_number_editor_set_range (HildonNumberEditor *editor, gint min, gint max) -{ - HildonNumberEditorPrivate *priv; - gchar buffer_min[32], buffer_max[32]; - gint a, b; - - g_return_if_fail(HILDON_IS_NUMBER_EDITOR(editor)); - - priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); - - /* Set preferences */ - priv->start = MIN(min, max); - priv->end = MAX(min, max); - - /* Find maximum allowed length of value */ - g_snprintf(buffer_min, sizeof(buffer_min), "%d", min); - g_snprintf(buffer_max, sizeof(buffer_max), "%d", max); - a = strlen(buffer_min); - b = strlen(buffer_max); - - /* Set maximum size of entry */ - gtk_entry_set_width_chars(GTK_ENTRY(priv->num_entry), MAX(a, b)); - hildon_number_editor_set_value(editor, priv->start); -} - -/** - * hildon_number_editor_get_value: - * @editor: pointer to #HildonNumberEditor - * - * Returns: current NumberEditor value - */ -gint -hildon_number_editor_get_value (HildonNumberEditor *editor) -{ - HildonNumberEditorPrivate *priv; - - g_return_val_if_fail(HILDON_IS_NUMBER_EDITOR(editor), 0); - - priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); - return atoi(gtk_entry_get_text(GTK_ENTRY(priv->num_entry))); -} - -/** - * hildon_number_editor_set_value: - * @editor: pointer to #HildonNumberEditor - * @value: numeric value for number editor - * - * Sets numeric value for number editor - */ -void -hildon_number_editor_set_value (HildonNumberEditor *editor, gint value) -{ - HildonNumberEditorPrivate *priv; - - g_return_if_fail(HILDON_IS_NUMBER_EDITOR(editor)); - - priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); - - g_return_if_fail(value <= priv->end); - g_return_if_fail(value >= priv->start); - - priv->default_val = value; - hildon_number_editor_real_set_value(priv, value); - g_object_notify (G_OBJECT(editor), "value"); -} - -/* When calling gtk_entry_set_text, the entry widget does things that can - * cause the whole widget to redraw. This redrawing is delayed and if any - * selections are made right after calling the gtk_entry_set_text the - * setting of the selection might seem to have no effect. - * - * If the selection is delayed with a lower priority than the redrawing, - * the selection should stick. Calling this function with g_idle_add should - * do it. - */ -static gboolean -hildon_number_editor_select_all (HildonNumberEditorPrivate *priv) -{ - GDK_THREADS_ENTER (); - gtk_editable_select_region(GTK_EDITABLE(priv->num_entry), 0, -1); - priv->select_all_idle_id = 0; - GDK_THREADS_LEAVE (); - return FALSE; -} - -static void -hildon_number_editor_set_property(GObject * object, - guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - HildonNumberEditor *editor; - - editor = HILDON_NUMBER_EDITOR(object); - - switch (prop_id) { - case PROP_VALUE: - hildon_number_editor_set_value(editor, g_value_get_int(value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -hildon_number_editor_get_property(GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec) -{ - HildonNumberEditor *editor; - - editor = HILDON_NUMBER_EDITOR(object); - - switch (prop_id) { - case PROP_VALUE: - g_value_set_int(value, hildon_number_editor_get_value(editor)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} diff --git a/hildon-widgets/hildon-number-editor.h b/hildon-widgets/hildon-number-editor.h deleted file mode 100644 index bb1d999..0000000 --- a/hildon-widgets/hildon-number-editor.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_NUMBER_EDITOR_H__ -#define __HILDON_NUMBER_EDITOR_H__ - -#include - -G_BEGIN_DECLS - - - -#define HILDON_TYPE_NUMBER_EDITOR ( hildon_number_editor_get_type() ) - -#define HILDON_NUMBER_EDITOR(obj) (GTK_CHECK_CAST (obj, HILDON_TYPE_NUMBER_EDITOR, HildonNumberEditor)) -#define HILDON_NUMBER_EDITOR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), HILDON_TYPE_NUMBER_EDITOR, HildonNumberEditorClass)) -#define HILDON_IS_NUMBER_EDITOR(obj) (GTK_CHECK_TYPE (obj, HILDON_TYPE_NUMBER_EDITOR)) -#define HILDON_IS_NUMBER_EDITOR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_NUMBER_EDITOR)) - -typedef struct _HildonNumberEditor HildonNumberEditor; -typedef struct _HildonNumberEditorClass HildonNumberEditorClass; - - -struct _HildonNumberEditor -{ - GtkContainer parent; -}; - - -typedef enum -{ - MAXIMUM_VALUE_EXCEED, - MINIMUM_VALUE_EXCEED, - ERRONEOUS_VALUE - -} HildonNumberEditorErrorType; - - -struct _HildonNumberEditorClass -{ - GtkContainerClass parent_class; - - gboolean (*range_error) (HildonNumberEditor *editor, HildonNumberEditorErrorType type); -}; - - -GType hildon_number_editor_get_type (void) G_GNUC_CONST; - -GtkWidget* hildon_number_editor_new (gint min, gint max); - -void hildon_number_editor_set_range (HildonNumberEditor *editor, - gint min, - gint max); - -gint hildon_number_editor_get_value (HildonNumberEditor *editor); -void hildon_number_editor_set_value (HildonNumberEditor *editor, gint value); - - -G_END_DECLS -#endif /* __HILDON_NUMBER_EDITOR_H__ */ diff --git a/hildon-widgets/hildon-plugin-widget.c b/hildon-widgets/hildon-plugin-widget.c deleted file mode 100644 index de061b1..0000000 --- a/hildon-widgets/hildon-plugin-widget.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Author: Kuisma Salonen - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-plugin-widget - * @short_description: A simple interface to load plugin based widgets. Not - * compatible with GObject. - * - * #HildonPluginWidgetInfo is a struct containing information about loaded - * module which contains code for a widget. - */ - - -#include -#include -#include - -#include - - -#include "hildon-plugin-widget.h" - - -#ifndef PLUGIN_DIR -#define PLUGIN_DIR "/usr/lib/hildon-widgets" -#endif - - -struct HildonPluginWidgetInfo_ { - GType base_type; - - gchar *filename; - - GModule *module; - int refcount; - - GType (*get_type) (); -}; - - -static gchar *hildon_plugin_filename(GType base_type, const gchar *name); - - /* WARNING: works properly only with ASCII */ -static gchar *ascii_decapitalize_without_dashes(gchar *source); - -static gchar *hildon_plugin_default_name(gchar *typename); - -/** - * hildon_plugin_info_initialize: - * @base_type: a #GType representing parent type of object that will be - * loaded. - * @name: Name of child. To load default (or #GtkSettings defined), NULL - * should be passed as name. To load specific child type, decapitalized name - * should be passed here. - * - * Creates a new #HildonPluginWidgetInfo structure and opens a module. - * - * The naming of child widgets (or objects) doesn't matter, but for plugins - * the file names should be type - * -.so where the - * decapitalized type name would be for example for #GtkWidget gtk-widget. - * - * The name comes from name argument or from #GtkSettings where the variable - * storing it is with name -plugin, for #GtkWidget this would - * be "GtkWidget-plugin". If nothing is defined in #GtkSettings, name - * "default" is assumed. For this case there should be symlink to some child - * type plugin named -default.so - * - * Returns: a #HildonPluginWidgetInfo struct pointer upon success, NULL if - * failed. - */ -HildonPluginWidgetInfo *hildon_plugin_info_initialize(GType base_type, const gchar *name) -{ - HildonPluginWidgetInfo *ret; - GModule *module; - gchar *filename; - - - if(!base_type) { - return NULL; - } - - - filename = hildon_plugin_filename(base_type, name); - g_return_val_if_fail (filename != NULL, NULL); - - - module = g_module_open(filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); - if(!module) { - g_warning ("Failed to load plugin for '%s' (filename: '%s')", name, filename); - g_free(filename); - return NULL; - } - - - ret = (HildonPluginWidgetInfo *)g_malloc0(sizeof(HildonPluginWidgetInfo) + strlen(filename) + 1); - ret->filename = (gchar *)ret + sizeof(HildonPluginWidgetInfo); - - ret->base_type = base_type; - - ret->module = module; - - g_module_symbol(module, "export_type", (void **)&ret->get_type); - - memcpy(ret->filename, filename, strlen(filename)); - - - g_free(filename); - - - return ret; -} - -/** - * hildon_plugin_info_construct_widget: - * @info: pointer to a #HildonPluginWidgetInfo struct. - * - * Creates instance of loaded type from module stored in - * #HildonPluginWidgetInfo struct. Designed for loading types inherited from - * GtkWidget, but could be basically any GTK+ type. - * - * Returns: a GtkWidget pointer to instance of loaded type. - */ -GtkWidget *hildon_plugin_info_construct_widget(HildonPluginWidgetInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); - info->refcount++; - - - return GTK_WIDGET(g_type_create_instance(info->get_type())); -} - -/** - * hildon_plugin_info_kill: - * @info: a pointer to a #HildonPluginWidgetInfo struct that should be - * destroyed. - * - * Frees the plugin information structure and unloads the module. - */ -void hildon_plugin_info_kill(HildonPluginWidgetInfo *info) -{ - if(!info) { - return; - } - - - g_module_close(info->module); - - - g_free(info); -} - - -static gchar *hildon_plugin_filename(GType base_type, const gchar *name) -{ - gchar *ret, *name2, *plgbuf; - gchar *typename = (gchar *)g_type_name(base_type); - int retsize; - - - plgbuf = ascii_decapitalize_without_dashes(typename); - - - if(name) { - name2 = g_strdup(name); - } else { - name2 = hildon_plugin_default_name(typename); - } - - - retsize = strlen(PLUGIN_DIR) + strlen(plgbuf) + strlen(name2) + 6; - ret = (gchar *)g_malloc0(retsize); - g_snprintf(ret, retsize, "%s/%s_%s.so", PLUGIN_DIR, plgbuf, name2); - - - g_free(name2); - g_free(plgbuf); - - - return ret; -} - - /* possible speedup: pre-allocate more memory and ditch the first loop */ -static gchar *ascii_decapitalize_without_dashes(gchar *source) -{ - gchar *ptr, *ret = g_strdup (source); - - - for(ptr = ret; *ptr; ptr++) { - if(*ptr >= 'A' && *ptr <= 'Z') { - *ptr += 0x20; - } - } - - - return ret; -} - - -static gchar *hildon_plugin_default_name(gchar *typename) -{ - GtkSettings *settings; - gchar *ret, *val, *tmp; - int tmplen; - - - tmplen = strlen(typename) + strlen("-plugin") + 1; - tmp = (gchar *)g_malloc0(tmplen); - g_snprintf(tmp, tmplen, "%s-plugin", typename); - - - gtk_settings_install_property(g_param_spec_string(tmp, - tmp, - "Plugin for this pecific widget", - NULL, - G_PARAM_READWRITE)); - - settings = gtk_settings_get_default(); - - g_object_get(G_OBJECT(settings), tmp, &val, NULL); - - g_free(tmp); - - - if(val) { - ret = (gchar *)g_malloc0(strlen(val)+1); - memcpy(ret, val, strlen(val)); - g_free(val); - } else { - ret = (gchar *)g_malloc0(strlen("default")+1); - - - g_snprintf(ret, strlen("default")+1, "default"); - } - - - return ret; -} diff --git a/hildon-widgets/hildon-plugin-widget.h b/hildon-widgets/hildon-plugin-widget.h deleted file mode 100644 index a537bf5..0000000 --- a/hildon-widgets/hildon-plugin-widget.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Author: Kuisma Salonen - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - - -#ifndef __HILDON_PLUGIN_WIDGET_H__ -#define __HILDON_PLUGIN_WIDGET_H__ - - -#include - -#include - - -/** - * HildonPluginWidgetInfo: - * - * Contains information about the loaded module which has some widget - * inherited from some non-plugin widget. The struct should be considered - * private and should not be used directly. - */ -typedef struct HildonPluginWidgetInfo_ HildonPluginWidgetInfo; - - -HildonPluginWidgetInfo *hildon_plugin_info_initialize(GType base_type, const gchar *name); - - -GtkWidget *hildon_plugin_info_construct_widget(HildonPluginWidgetInfo *info); - - -void hildon_plugin_info_kill(HildonPluginWidgetInfo *info); - - - -#endif /* __HILDON_PLUGIN_WIDGET_H__ */ diff --git a/hildon-widgets/hildon-private.h b/hildon-widgets/hildon-private.h deleted file mode 100644 index 772080b..0000000 --- a/hildon-widgets/hildon-private.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - - -#ifndef __HILDON_PRIVATE_H__ -#define __HILDON_PRIVATE_H__ - -#include - -G_BEGIN_DECLS - -void -_hildon_time_editor_get_time_separators(GtkLabel *hm_sep_label, - GtkLabel *ms_sep_label); - -G_END_DECLS -#endif /* __HILDON_PRIVATE_H__ */ diff --git a/hildon-widgets/hildon-program.c b/hildon-widgets/hildon-program.c deleted file mode 100644 index 0aae6fc..0000000 --- a/hildon-widgets/hildon-program.c +++ /dev/null @@ -1,630 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/* - * @file hildon-program.c - * - * This file implements the HildonProgram object - * - */ - -#include "hildon-program.h" -#include "hildon-window-private.h" - -/*FIXME*/ -#include - - -#define HILDON_PROGRAM_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_PROGRAM, HildonProgramPriv)); - - -typedef struct _HildonProgramPriv HildonProgramPriv; - -struct _HildonProgramPriv -{ - gboolean killable; - gboolean is_topmost; - GdkWindow *group_leader; - guint window_count; - GtkWidget *common_menu; - GtkWidget *common_toolbar; - GSList *windows; - Window window_group; - gchar *name; -}; - -static void -hildon_program_init (HildonProgram *self); - -static void -hildon_program_finalize (GObject *self); - -static void -hildon_program_class_init (HildonProgramClass *self); - -static void -hildon_program_get_property(GObject * object, guint property_id, - GValue * value, GParamSpec * pspec); -static void -hildon_program_set_property (GObject * object, guint property_id, - const GValue * value, GParamSpec * pspec); - -enum -{ - PROP_0, - PROP_IS_TOPMOST, - PROP_KILLABLE -}; - - -GType -hildon_program_get_type (void) -{ - static GType program_type = 0; - - if (!program_type) - { - static const GTypeInfo program_info = - { - sizeof(HildonProgramClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_program_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonProgram), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_program_init, - }; - program_type = g_type_register_static(G_TYPE_OBJECT, - "HildonProgram", &program_info, 0); - } - return program_type; -} - -static void -hildon_program_init (HildonProgram *self) -{ - HildonProgramPriv *priv = HILDON_PROGRAM_GET_PRIVATE (self); - - priv->killable = FALSE; - priv->window_count = 0; - priv->is_topmost = FALSE; - priv->window_group = GDK_WINDOW_XID (gdk_display_get_default_group - (gdk_display_get_default())); - priv->common_toolbar = NULL; - priv->name = NULL; -} - -static void -hildon_program_finalize (GObject *self) -{ - HildonProgramPriv *priv = HILDON_PROGRAM_GET_PRIVATE (HILDON_PROGRAM (self)); - - if (priv->common_toolbar) - { - g_object_unref (priv->common_toolbar); - priv->common_toolbar = NULL; - } - - if (priv->common_menu) - { - g_object_unref (priv->common_menu); - priv->common_menu = NULL; - } - - g_free (priv->name); - -} - -static void -hildon_program_class_init (HildonProgramClass *self) -{ - GObjectClass *object_class = G_OBJECT_CLASS(self); - - g_type_class_add_private (self, sizeof(HildonProgramPriv)); - - /* Set up object virtual functions */ - object_class->finalize = hildon_program_finalize; - object_class->set_property = hildon_program_set_property; - object_class->get_property = hildon_program_get_property; - - /* Install properties */ - g_object_class_install_property (object_class, PROP_IS_TOPMOST, - g_param_spec_boolean ("is-topmost", - "Is top-most", - "Whether one of the program's window or dialog currently " - "is activated by window manager", - FALSE, - G_PARAM_READABLE)); - - g_object_class_install_property (object_class, PROP_KILLABLE, - g_param_spec_boolean ("can-hibernate", - "Can hibernate", - "Whether the program should be set to hibernate by the Task " - "Navigator in low memory situation", - FALSE, - G_PARAM_READWRITE)); - return; -} - - -static void -hildon_program_set_property (GObject * object, guint property_id, - const GValue * value, GParamSpec * pspec) -{ - switch (property_id){ - case PROP_KILLABLE: - hildon_program_set_can_hibernate (HILDON_PROGRAM (object), - g_value_get_boolean (value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } - -} - -static void -hildon_program_get_property (GObject * object, guint property_id, - GValue * value, GParamSpec * pspec) -{ - HildonProgramPriv *priv = HILDON_PROGRAM_GET_PRIVATE (object); - - switch (property_id) - { - case PROP_KILLABLE: - g_value_set_boolean (value, priv->killable); - break; - case PROP_IS_TOPMOST: - g_value_set_boolean (value, priv->is_topmost); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } - -} - -/* Utilities */ -static gint -hildon_program_window_list_compare (gconstpointer window_a, - gconstpointer window_b) -{ - g_return_val_if_fail (1, HILDON_IS_WINDOW(window_a) && - HILDON_IS_WINDOW(window_b)); - - return window_a != window_b; -} - -/* - * foreach function, checks if a window is topmost and acts consequently - */ -static void -hildon_program_window_list_is_is_topmost (gpointer data, gpointer window_id_) -{ - if (data && HILDON_IS_WINDOW (data)) - { - HildonWindow *window = HILDON_WINDOW (data); - Window window_id = * (Window*)window_id_; - - hildon_window_update_topmost (window, window_id); - } -} - -/* - * Check the _MB_CURRENT_APP_WINDOW on the root window, and update - * the top_most status accordingly - */ -static void -hildon_program_update_top_most (HildonProgram *program) -{ - XWMHints *wm_hints; - Window active_window; - HildonProgramPriv *priv; - - priv = HILDON_PROGRAM_GET_PRIVATE (program); - - active_window = hildon_window_get_active_window(); - - if (active_window) - { - wm_hints = XGetWMHints (GDK_DISPLAY (), active_window); - - if (wm_hints) - { - - if (wm_hints->window_group == priv->window_group) - { - if (!priv->is_topmost) - { - priv->is_topmost = TRUE; - g_object_notify (G_OBJECT (program), "is-topmost"); - } - } - else if (priv->is_topmost) - { - priv->is_topmost = FALSE; - g_object_notify (G_OBJECT (program), "is-topmost"); - } - } - XFree (wm_hints); - } - - /* Check each window if it was is_topmost */ - g_slist_foreach (priv->windows, - (GFunc)hildon_program_window_list_is_is_topmost, &active_window); -} - - -/* Event filter */ - -/* - * We keep track of the _MB_CURRENT_APP_WINDOW property on the root window, - * to detect when a window belonging to this program was is_topmost. This - * is based on the window group WM hint. - */ -static GdkFilterReturn -hildon_program_root_window_event_filter (GdkXEvent *xevent, - GdkEvent *event, - gpointer data) -{ - XAnyEvent *eventti = xevent; - HildonProgram *program = HILDON_PROGRAM (data); - Atom active_app_atom = - XInternAtom (GDK_DISPLAY (), "_MB_CURRENT_APP_WINDOW", False); - - if (eventti->type == PropertyNotify) - { - XPropertyEvent *pevent = xevent; - - if (pevent->atom == active_app_atom) - { - hildon_program_update_top_most (program); - } - } - - return GDK_FILTER_CONTINUE; -} - - -/** - * hildon_program_common_toolbar_topmost_window: - * @window: A @HildonWindow to be informed about its new common toolbar - * @data: Not used, it is here just to respect the API - * - * Checks if the window is the topmost window of the program and in - * that case forces the window to take the common toolbar. - **/ -static void -hildon_program_common_toolbar_topmost_window (gpointer window, gpointer data) -{ - if (HILDON_IS_WINDOW (window) && - hildon_window_get_is_topmost (HILDON_WINDOW (window))) - { - hildon_window_take_common_toolbar (HILDON_WINDOW (window)); - } -} - -/* Public methods */ - -/** - * hildon_program_get_instance: - * - * Return value: Returns the #HildonProgram for the current process. - * The object is created on the first call. - **/ -HildonProgram * -hildon_program_get_instance () -{ - static HildonProgram *program = NULL; - - if (!program) - { - program = g_object_new (HILDON_TYPE_PROGRAM, NULL); - } - - return program; -} - -/** - * hildon_program_add_window: - * @program: The @HildonProgram to which the window should be registered - * @window: A @HildonWindow to be added - * - * Registers a @HildonWindow as belonging to a given @HildonProgram. This - * allows to apply program-wide settings as all the registered windows, - * such as hildon_program_set_common_menu() and - * hildon_pogram_set_common_toolbar() - **/ -void -hildon_program_add_window (HildonProgram *self, HildonWindow *window) -{ - HildonProgramPriv *priv; - - g_return_if_fail (self && HILDON_IS_PROGRAM (self)); - - priv = HILDON_PROGRAM_GET_PRIVATE (self); - - if (g_slist_find_custom (priv->windows, window, - hildon_program_window_list_compare) ) - { - /* We already have that window */ - return; - } - - if (!priv->window_count) - { - hildon_program_update_top_most (self); - - /* Now that we have a window we should start keeping track of - * the root window */ - gdk_window_set_events (gdk_get_default_root_window (), - gdk_window_get_events (gdk_get_default_root_window ()) | GDK_PROPERTY_CHANGE_MASK); - gdk_window_add_filter (gdk_get_default_root_window (), - hildon_program_root_window_event_filter, self ); - } - - hildon_window_set_can_hibernate_property (window, &priv->killable); - - hildon_window_set_program (window, G_OBJECT (self)); - - priv->windows = g_slist_append (priv->windows, window); - priv->window_count ++; -} - -/** - * hildon_program_remove_window: - * @self: The #HildonProgram to which the window should be unregistered - * @window: The @HildonWindow to unregister - * - * Used to unregister a window from the program. Subsequent calls to - * hildon_program_set_common_menu() and hildon_pogram_set_common_toolbar() - * will not affect the window - **/ -void -hildon_program_remove_window (HildonProgram *self, HildonWindow *window) -{ - HildonProgramPriv *priv; - - g_return_if_fail (self && HILDON_IS_PROGRAM (self)); - - priv = HILDON_PROGRAM_GET_PRIVATE (self); - - hildon_window_unset_program (window); - - priv->windows = g_slist_remove (priv->windows, window); - - priv->window_count --; - - if (!priv->window_count) - { - gdk_window_remove_filter (gdk_get_default_root_window(), - hildon_program_root_window_event_filter, - self); - } -} - -/** - * hildon_program_set_can_hibernate: - * @self: The #HildonProgram which can hibernate or not - * @can_hibernate: whether or not the #HildonProgram can hibernate - * - * Used to set whether or not the Hildon task navigator should - * be able to set the program to hibernation in case of low memory - **/ -void -hildon_program_set_can_hibernate (HildonProgram *self, gboolean killable) -{ - HildonProgramPriv *priv; - - g_return_if_fail (self && HILDON_IS_PROGRAM (self)); - - priv = HILDON_PROGRAM_GET_PRIVATE (self); - - if (priv->killable != killable) - { - g_slist_foreach (priv->windows, - (GFunc)hildon_window_set_can_hibernate_property, &killable); - } - - priv->killable = killable; - -} - -/** - * hildon_program_get_can_hibernate: - * @self: The #HildonProgram which can hibernate or not - * - * Return value: Whether or not this #HildonProgram is set to be - * support hibernation from the Hildon task navigator - **/ -gboolean -hildon_program_get_can_hibernate (HildonProgram *self) -{ - HildonProgramPriv *priv; - - g_return_val_if_fail (self && HILDON_IS_PROGRAM (self), FALSE); - - priv = HILDON_PROGRAM_GET_PRIVATE (self); - - return priv->killable; - -} - -/** - * hildon_program_set_common_menu: - * @self: The #HildonProgram in which the common menu should be used - * @menu: A GtkMenu to use as common menu for the program - * - * Sets a GtkMenu that will appear in all the @HildonWindow registered - * to the #HildonProgram. Only one common GtkMenu can be set, further - * call will detach the previous common GtkMenu. A @HildonWindow - * can use it's own GtkMenu with @hildon_window_set_menu - **/ -void -hildon_program_set_common_menu (HildonProgram *self, GtkMenu *menu) -{ - HildonProgramPriv *priv; - - g_return_if_fail (self && HILDON_IS_PROGRAM (self)); - - priv = HILDON_PROGRAM_GET_PRIVATE (self); - - if (priv->common_menu) - { - if (GTK_WIDGET_VISIBLE (priv->common_menu)) - { - gtk_menu_popdown (GTK_MENU(priv->common_menu)); - gtk_menu_shell_deactivate (GTK_MENU_SHELL (priv->common_menu)); - } - - if (gtk_menu_get_attach_widget (GTK_MENU (priv->common_menu))) - { - gtk_menu_detach (GTK_MENU (priv->common_menu)); - } - else - { - g_object_unref (priv->common_menu); - } - } - - priv->common_menu = GTK_WIDGET (menu); - - if (priv->common_menu) - { - g_object_ref (menu); - gtk_object_sink (GTK_OBJECT (menu)); - gtk_widget_show_all (GTK_WIDGET (menu)); - } -} - -/** - * hildon_program_get_common_menu: - * @self: The #HildonProgram from which to retrieve the common menu - * - * Return value: the GtkMenu that was set as common menu for this - * #HildonProgram, or NULL of no common menu was set. - **/ -GtkMenu * -hildon_program_get_common_menu (HildonProgram *self) -{ - HildonProgramPriv *priv; - - g_return_val_if_fail (self && HILDON_IS_PROGRAM (self), NULL); - - priv = HILDON_PROGRAM_GET_PRIVATE (self); - - return GTK_MENU (priv->common_menu); -} - -/** - * hildon_program_set_common_toolbar: - * @self: The #HildonProgram in which the common toolbar should be used - * @toolbar: A GtkToolbar to use as common toolbar for the program - * - * Sets a GtkToolbar that will appear in all the @HildonWindow registered - * to the #HildonProgram. Only one common GtkToolbar can be set, further - * call will detach the previous common GtkToolbar. A @HildonWindow - * can use its own GtkToolbar with @hildon_window_set_toolbar. Both - * #HildonProgram and @HildonWindow specific toolbars will be shown - **/ -void -hildon_program_set_common_toolbar (HildonProgram *self, GtkToolbar *toolbar) -{ - HildonProgramPriv *priv; - - g_return_if_fail (self && HILDON_IS_PROGRAM (self)); - - priv = HILDON_PROGRAM_GET_PRIVATE (self); - - if (priv->common_toolbar) - { - if (priv->common_toolbar->parent) - { - gtk_container_remove (GTK_CONTAINER (priv->common_toolbar->parent), - priv->common_toolbar); - } - - g_object_unref (priv->common_toolbar); - } - - priv->common_toolbar = GTK_WIDGET (toolbar); - - if (priv->common_toolbar) - { - g_object_ref (priv->common_toolbar); - gtk_object_sink (GTK_OBJECT (priv->common_toolbar) ); - } - - /* if the program is the topmost we have to update the common - toolbar right now for the topmost window */ - if (priv->is_topmost) - { - g_slist_foreach (priv->windows, - (GFunc) hildon_program_common_toolbar_topmost_window, NULL); - } -} - -/** - * hildon_program_get_common_toolbar: - * @self: The #HildonProgram from which to retrieve the common toolbar - * - * Return value: the GtkToolbar that was set as common toolbar for this - * #HildonProgram, or NULL of no common menu was set. - **/ -GtkToolbar * -hildon_program_get_common_toolbar (HildonProgram *self) -{ - HildonProgramPriv *priv; - - g_return_val_if_fail (self && HILDON_IS_PROGRAM (self), NULL); - - priv = HILDON_PROGRAM_GET_PRIVATE (self); - - return priv->common_toolbar ? GTK_TOOLBAR (priv->common_toolbar) : NULL; -} - -/** - * hildon_program_get_is_topmost: - * @self: A #HildonWindow - * - * Return value: Whether or not one of the program's window or dialog is - * currenltly activated by the window manager. - **/ -gboolean -hildon_program_get_is_topmost (HildonProgram *self) -{ - HildonProgramPriv *priv; - - g_return_val_if_fail (self && HILDON_IS_PROGRAM (self), FALSE); - - priv = HILDON_PROGRAM_GET_PRIVATE (self); - - return priv->is_topmost; -} - - diff --git a/hildon-widgets/hildon-program.h b/hildon-widgets/hildon-program.h deleted file mode 100644 index 1b021f2..0000000 --- a/hildon-widgets/hildon-program.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_PROGRAM_H__ -#define __HILDON_PROGRAM_H__ - -#include -#include"hildon-window.h" - -G_BEGIN_DECLS -typedef struct _HildonProgram HildonProgram; -typedef struct _HildonProgramClass HildonProgramClass; - -#define HILDON_TYPE_PROGRAM (hildon_program_get_type()) -#define HILDON_PROGRAM(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, \ - HILDON_TYPE_PROGRAM, \ - HildonProgram)) -#define HILDON_IS_PROGRAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, \ - HILDON_TYPE_PROGRAM)) - -/* deprecated */ -#define hildon_program_new hildon_program_get_instance - - - -struct _HildonProgram -{ - GObject parent; -}; - -struct _HildonProgramClass -{ - GObjectClass parent; - - /* Padding for future extension */ - void (*_hildon_reserved1)(void); - void (*_hildon_reserved2)(void); - void (*_hildon_reserved3)(void); - void (*_hildon_reserved4)(void); - -}; - -GType -hildon_program_get_type (void); - -/* Public methods */ - -HildonProgram * -hildon_program_get_instance (void); - -void -hildon_program_add_window (HildonProgram *self, HildonWindow *window); - -void -hildon_program_remove_window (HildonProgram *self, HildonWindow *window); - -void -hildon_program_set_can_hibernate (HildonProgram *self, gboolean killable); - -gboolean -hildon_program_get_can_hibernate (HildonProgram *self); - -void -hildon_program_set_common_menu (HildonProgram *self, GtkMenu *menu); - -GtkMenu * -hildon_program_get_common_menu (HildonProgram *self); - -void -hildon_program_set_common_toolbar (HildonProgram *self, GtkToolbar *toolbar); - -GtkToolbar * -hildon_program_get_common_toolbar (HildonProgram *self); - -gboolean -hildon_program_get_is_topmost (HildonProgram *self); - -G_END_DECLS -#endif /* __HILDON_PROGRAM_H__ */ diff --git a/hildon-widgets/hildon-range-editor.c b/hildon-widgets/hildon-range-editor.c deleted file mode 100644 index 253ee5e..0000000 --- a/hildon-widgets/hildon-range-editor.c +++ /dev/null @@ -1,1023 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-range-editor - * @short_description: A widget is used to ask bounds of a range - * - * HidlonRangeEditor allows entering a pair of integers, e.g. the lower - * and higher bounds of a range. A minimum and maximum can also be set - * for the bounds. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hildon-range-editor.h" - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#define _(string) dgettext(PACKAGE, string) - -/* Alignment in entry box ( 0 = left, 1 = right ) */ -#define DEFAULT_ALIGNMENT 1 -/* Amount of padding to add to each side of the separator */ -#define DEFAULT_PADDING 3 - -#define DEFAULT_START -999 -#define DEFAULT_END 999 -#define DEFAULT_LENGTH 4 - -#define HILDON_RANGE_EDITOR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_RANGE_EDITOR, HildonRangeEditorPrivate)); - -typedef struct _HildonRangeEditorPrivate HildonRangeEditorPrivate; - -/* Property indices */ -enum -{ - PROP_LOWER = 1, - PROP_HIGHER, - PROP_MIN, - PROP_MAX, - PROP_SEPARATOR -}; - -static GtkContainerClass *parent_class = NULL; - -/*Init functions*/ -static void -hildon_range_editor_class_init (HildonRangeEditorClass *editor_class); -static void -hildon_range_editor_init (HildonRangeEditor *editor); -static void -hildon_range_editor_forall (GtkContainer *container, - gboolean include_internals, GtkCallback callback, - gpointer callback_data); -static void -hildon_range_editor_destroy (GtkObject *self); - -/*size and font functions */ -static void -hildon_range_editor_size_request (GtkWidget *widget, - GtkRequisition *requisition); -static void -hildon_range_editor_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); -static gboolean -hildon_range_editor_entry_focus_in (GtkEditable *editable, - GdkEventFocus *event, - HildonRangeEditor *editor); -static gboolean -hildon_range_editor_entry_focus_out (GtkEditable *editable, - GdkEventFocus *event, - HildonRangeEditor *editor); -static gboolean -hildon_range_editor_entry_keypress (GtkWidget *widget, GdkEventKey *event, - HildonRangeEditor *editor); -static gboolean -hildon_range_editor_released (GtkEditable *editable, GdkEventButton *event, - HildonRangeEditor *editor); -static gboolean -hildon_range_editor_press (GtkEditable *editable, GdkEventButton *event, - HildonRangeEditor *editor); - -static void hildon_range_editor_set_property( GObject *object, guint param_id, - const GValue *value, GParamSpec *pspec ); -static void hildon_range_editor_get_property( GObject *object, guint param_id, - GValue *value, GParamSpec *pspec ); -static void hildon_range_editor_entry_changed(GtkWidget *widget, - HildonRangeEditor *editor); - -/* Private struct */ -struct _HildonRangeEditorPrivate -{ - GtkWidget *start_entry; /* Entry for lower value */ - GtkWidget *end_entry; /* Entry for higher value */ - - GtkWidget *label; - - gint range_limits_start; /* Minimum value allowed for range start/end */ - gint range_limits_end; /* Maximum value allowed for range start/end */ - - gboolean bp; /* Button pressed, don't overwrite selection */ -}; - -/* Private functions */ -static void -hildon_range_editor_class_init (HildonRangeEditorClass *editor_class) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(editor_class); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(editor_class); - GtkContainerClass *container_class = GTK_CONTAINER_CLASS(editor_class); - - parent_class = g_type_class_peek_parent(editor_class); - - g_type_class_add_private(editor_class, - sizeof(HildonRangeEditorPrivate)); - - gobject_class->set_property = hildon_range_editor_set_property; - gobject_class->get_property = hildon_range_editor_get_property; - widget_class->size_request = hildon_range_editor_size_request; - widget_class->size_allocate = hildon_range_editor_size_allocate; - - container_class->forall = hildon_range_editor_forall; - GTK_OBJECT_CLASS(editor_class)->destroy = hildon_range_editor_destroy; - - gtk_widget_class_install_style_property(widget_class, - g_param_spec_int("hildon_range_editor_entry_alignment", - "Hildon RangeEditor entry alignment", - "Hildon RangeEditor entry alignment", 0, 1, - DEFAULT_ALIGNMENT, - G_PARAM_READABLE)); - - gtk_widget_class_install_style_property(widget_class, - g_param_spec_int("hildon_range_editor_separator_padding", - "Hildon RangeEditor separator padding", - "Hildon RangeEditor separaror padding", - G_MININT, G_MAXINT, - DEFAULT_PADDING, - G_PARAM_READABLE)); - - /** - * HildonRangeEditor:min: - * - * Minimum value in a range. - * Default: -999 - */ - g_object_class_install_property( gobject_class, PROP_MIN, - g_param_spec_int("min", - "Minimum value", - "Minimum value in a range", - G_MININT, G_MAXINT, - DEFAULT_START, G_PARAM_CONSTRUCT | - G_PARAM_READABLE | G_PARAM_WRITABLE) ); - - /** - * HildonRangeEditor:max: - * - * Maximum value in a range. - * Default: 999 - */ - g_object_class_install_property( gobject_class, PROP_MAX, - g_param_spec_int("max", - "Maximum value", - "Maximum value in a range", - G_MININT, G_MAXINT, - DEFAULT_END, G_PARAM_CONSTRUCT | - G_PARAM_READABLE | G_PARAM_WRITABLE) ); - - /** - * HildonRangeEditor:lower: - * - * Current value in the entry presenting lower end of selected range. - * Default: -999 - */ - g_object_class_install_property( gobject_class, PROP_LOWER, - g_param_spec_int("lower", - "Current lower value", - "Current value in the entry presenting lower end of selected range", - G_MININT, G_MAXINT, - DEFAULT_START, G_PARAM_CONSTRUCT | - G_PARAM_READABLE | G_PARAM_WRITABLE) ); - - /** - * HildonRangeEditor:higher: - * - * Current value in the entry presenting higher end of selected range. - * Default: 999 - */ - g_object_class_install_property( gobject_class, PROP_HIGHER, - g_param_spec_int("higher", - "Current higher value", - "Current value in the entry presenting higher end of selected range", - G_MININT, G_MAXINT, - DEFAULT_END, G_PARAM_CONSTRUCT | - G_PARAM_READABLE | G_PARAM_WRITABLE) ); - - /** - * HildonRangeEditor:separator: - * - * Separator string to separate range editor entries. - * Default: "-" - */ - g_object_class_install_property( gobject_class, PROP_SEPARATOR, - g_param_spec_string("separator", - "Separator", - "Separator string to separate entries", - _("ckct_wi_range_separator"), - G_PARAM_CONSTRUCT | - G_PARAM_READABLE | G_PARAM_WRITABLE) ); -} - -static void -hildon_range_editor_init (HildonRangeEditor *editor) -{ - HildonRangeEditorPrivate *priv; - - gint range_editor_entry_alignment; - gint range_editor_separator_padding; - - priv = HILDON_RANGE_EDITOR_GET_PRIVATE(editor); - - GTK_WIDGET_SET_FLAGS(editor, GTK_NO_WINDOW); - - gtk_widget_push_composite_child(); - - priv->start_entry = gtk_entry_new(); - priv->end_entry = gtk_entry_new(); - priv->label = gtk_label_new(_("ckct_wi_range_separator")); - priv->bp = FALSE; - - /* Get values from gtkrc (or use defaults) */ - /* FIXME: This is broken, styles are not yet attached */ - gtk_widget_style_get(GTK_WIDGET(editor), - "hildon_range_editor_entry_alignment", - &range_editor_entry_alignment, - "hildon_range_editor_separator_padding", - &range_editor_separator_padding, NULL); - - /* Add padding to separator */ - gtk_misc_set_padding (GTK_MISC(priv->label), - range_editor_separator_padding, 0); - - /* Align the text to right in entry box */ - gtk_entry_set_alignment(GTK_ENTRY(priv->start_entry), - range_editor_entry_alignment); - gtk_entry_set_alignment(GTK_ENTRY(priv->end_entry), - range_editor_entry_alignment); - - gtk_widget_set_composite_name(priv->start_entry, "start_entry"); - gtk_widget_set_composite_name(priv->end_entry, "end_entry"); - gtk_widget_set_composite_name(priv->label, "separator_label"); - gtk_widget_set_parent(priv->start_entry, GTK_WIDGET(editor)); - gtk_widget_set_parent(priv->end_entry, GTK_WIDGET(editor)); - gtk_widget_set_parent(priv->label, GTK_WIDGET(editor)); - - g_signal_connect(G_OBJECT(priv->start_entry), "button-release-event", - G_CALLBACK(hildon_range_editor_released), editor); - g_signal_connect(G_OBJECT(priv->end_entry), "button-release-event", - G_CALLBACK(hildon_range_editor_released), editor); - - g_signal_connect(G_OBJECT(priv->start_entry), "button-press-event", - G_CALLBACK(hildon_range_editor_press), editor); - g_signal_connect(G_OBJECT(priv->end_entry), "button-press-event", - G_CALLBACK(hildon_range_editor_press), editor); - - g_signal_connect(G_OBJECT(priv->start_entry), "key-press-event", - G_CALLBACK(hildon_range_editor_entry_keypress), editor); - g_signal_connect(G_OBJECT(priv->end_entry), "key-press-event", - G_CALLBACK(hildon_range_editor_entry_keypress), editor); - - g_signal_connect(G_OBJECT(priv->start_entry), "focus-in-event", - G_CALLBACK(hildon_range_editor_entry_focus_in), editor); - g_signal_connect(G_OBJECT(priv->end_entry), "focus-in-event", - G_CALLBACK(hildon_range_editor_entry_focus_in), editor); - - g_signal_connect(G_OBJECT(priv->start_entry), "focus-out-event", - G_CALLBACK(hildon_range_editor_entry_focus_out), editor); - g_signal_connect(G_OBJECT(priv->end_entry), "focus-out-event", - G_CALLBACK(hildon_range_editor_entry_focus_out), editor); - g_signal_connect(priv->start_entry, "changed", - G_CALLBACK(hildon_range_editor_entry_changed), editor); - g_signal_connect(priv->end_entry, "changed", - G_CALLBACK(hildon_range_editor_entry_changed), editor); - - g_object_set( G_OBJECT(priv->start_entry), - "input-mode", HILDON_INPUT_MODE_HINT_NUMERIC, NULL ); - g_object_set( G_OBJECT(priv->end_entry), - "input-mode", HILDON_INPUT_MODE_HINT_NUMERIC, NULL ); - - gtk_widget_show(priv->start_entry); - gtk_widget_show(priv->end_entry); - gtk_widget_show(priv->label); - - gtk_widget_pop_composite_child(); -} - -static void hildon_range_editor_set_property (GObject *object, guint param_id, - const GValue *value, GParamSpec *pspec) -{ - HildonRangeEditor *editor = HILDON_RANGE_EDITOR(object); - switch (param_id) - { - case PROP_LOWER: - hildon_range_editor_set_lower (editor, g_value_get_int (value)); - break; - - case PROP_HIGHER: - hildon_range_editor_set_higher (editor, g_value_get_int (value)); - break; - - case PROP_MIN: - hildon_range_editor_set_min (editor, g_value_get_int (value)); - break; - - case PROP_MAX: - hildon_range_editor_set_max (editor, g_value_get_int (value)); - break; - - case PROP_SEPARATOR: - hildon_range_editor_set_separator (editor, - g_value_get_string (value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); - break; - } -} - -static void hildon_range_editor_get_property( GObject *object, guint param_id, - GValue *value, GParamSpec *pspec ) -{ - HildonRangeEditor *editor = HILDON_RANGE_EDITOR(object); - switch (param_id) - { - case PROP_LOWER: - g_value_set_int (value, hildon_range_editor_get_lower (editor)); - break; - - case PROP_HIGHER: - g_value_set_int (value, hildon_range_editor_get_higher (editor)); - break; - - case PROP_MIN: - g_value_set_int (value, hildon_range_editor_get_min (editor)); - break; - - case PROP_MAX: - g_value_set_int (value, hildon_range_editor_get_max (editor)); - break; - - case PROP_SEPARATOR: - g_value_set_string (value, hildon_range_editor_get_separator (editor)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); - break; - } -} - -static void -hildon_range_editor_entry_validate(HildonRangeEditor *editor, - GtkWidget *edited_entry, gboolean allow_intermediate) -{ - HildonRangeEditorPrivate *priv; - const gchar *text; - long value; - gint min, max, fixup; - gchar *tail; - gchar buffer[256]; - gboolean error = FALSE; - - g_assert(HILDON_IS_RANGE_EDITOR(editor)); - g_assert(GTK_IS_ENTRY(edited_entry)); - - priv = HILDON_RANGE_EDITOR_GET_PRIVATE(editor); - - /* Find the valid range for the modified component */ - if (edited_entry == priv->start_entry) { - min = hildon_range_editor_get_min(editor); - max = hildon_range_editor_get_higher(editor); - } else { - min = hildon_range_editor_get_lower(editor); - max = hildon_range_editor_get_max(editor); - } - - text = gtk_entry_get_text(edited_entry); - - if (text && text[0]) - { - /* Try to convert entry text to number */ - value = strtol(text, &tail, 10); - - /* Check if conversion succeeded */ - if (tail[0] == 0) - { - /* Check if value is in allowed range. This is tricky in those - cases when user is editing a value. - For example: Range = [100, 500] and user have just inputted "4". - This should not lead into error message. Otherwise value is - resetted back to "100" and next "4" press will reset it back - and so on. */ - if (allow_intermediate) - { - /* We now have the following error cases: - * If inputted value as above maximum and - maximum is either positive or then maximum - negative and value is positive. - * If inputted value is below minimum and minimum - is negative or minumum positive and value - negative. - In all other cases situation can be fixed just by - adding new numbers to the string. - */ - if (value > max && (max >= 0 || (max < 0 && value >= 0))) - { - error = TRUE; - fixup = max; - g_snprintf(buffer, sizeof(buffer), _("ckct_ib_maximum_value"), max); - } - else if (value < min && (min < 0 || (min >= 0 && value < 0))) - { - error = TRUE; - fixup = min; - g_snprintf(buffer, sizeof(buffer), _("ckct_ib_minimum_value"), min); - } - } - else - { - if (value > max) { - error = TRUE; - fixup = max; - g_snprintf(buffer, sizeof(buffer), _("ckct_ib_maximum_value"), max); - } - else if (value < min) { - error = TRUE; - fixup = min; - g_snprintf(buffer, sizeof(buffer), _("ckct_ib_minimum_value"), min); - } - } - - if (error) { - if (edited_entry == priv->start_entry) - hildon_range_editor_set_lower(editor, fixup); - else - hildon_range_editor_set_higher(editor, fixup); - } - } - /* The only valid case when conversion can fail is when we - have plain '-', intermediate forms are allowed AND - minimum bound is negative */ - else if (!allow_intermediate || strcmp(text, "-") != 0 || min >= 0) { - error = TRUE; - g_snprintf(buffer, sizeof(buffer), _("ckct_ib_set_a_value_within_range"), min, max); - } - } - else if (!allow_intermediate) { - error = TRUE; - g_snprintf(buffer, sizeof(buffer), _("ckct_ib_set_a_value_within_range"), min, max); - } - - if (error) - { - hildon_banner_show_information(edited_entry, NULL, buffer); - gtk_widget_grab_focus(edited_entry); - } -} - -static gboolean -hildon_range_editor_entry_focus_in (GtkEditable *editable, - GdkEventFocus *event, - HildonRangeEditor *editor) -{ - HildonRangeEditorPrivate *priv = HILDON_RANGE_EDITOR_GET_PRIVATE(editor); - if(priv->bp) - { - priv->bp = FALSE; - return FALSE; - } - if (GTK_WIDGET(editable) == priv->start_entry) - gtk_editable_select_region(editable, -1, 0); - else - gtk_editable_select_region(editable, 0, -1); - return FALSE; -} - -/* Gets and sets the current range. This has two usefull side effects: - * Values are now sorted to the correct order - * Out of range values are clamped to range */ -static void hildon_range_editor_apply_current_range(HildonRangeEditor *editor) -{ - g_assert(HILDON_IS_RANGE_EDITOR(editor)); - - hildon_range_editor_set_range(editor, - hildon_range_editor_get_lower(editor), - hildon_range_editor_get_higher(editor)); -} - -static void hildon_range_editor_entry_changed(GtkWidget *widget, HildonRangeEditor *editor) -{ - g_assert(HILDON_IS_RANGE_EDITOR(editor)); - hildon_range_editor_entry_validate(editor, widget, TRUE); -} - -static gboolean -hildon_range_editor_entry_focus_out (GtkEditable *editable, - GdkEventFocus *event, - HildonRangeEditor *editor) -{ - g_assert(HILDON_IS_RANGE_EDITOR(editor)); - hildon_range_editor_entry_validate(editor, GTK_WIDGET(editable), FALSE); - return FALSE; -} - -static gboolean -hildon_range_editor_press (GtkEditable *editable, GdkEventButton *event, - HildonRangeEditor *editor) -{ - HildonRangeEditorPrivate *priv = HILDON_RANGE_EDITOR_GET_PRIVATE(editor); - priv->bp = TRUE; - return FALSE; -} - -static void -hildon_range_editor_forall (GtkContainer *container, - gboolean include_internals, - GtkCallback callback, gpointer callback_data) -{ - HildonRangeEditorPrivate *priv; - - g_assert(HILDON_IS_RANGE_EDITOR(container)); - g_assert(callback != NULL); - - priv = HILDON_RANGE_EDITOR_GET_PRIVATE(container); - - if (!include_internals) - return; - - (*callback) (priv->start_entry, callback_data); - (*callback) (priv->end_entry, callback_data); - (*callback) (priv->label, callback_data); -} - -static void -hildon_range_editor_destroy(GtkObject *self) -{ - HildonRangeEditorPrivate *priv = HILDON_RANGE_EDITOR_GET_PRIVATE(self); - - if (priv->start_entry) - { - gtk_widget_unparent(priv->start_entry); - priv->start_entry = NULL; - } - if (priv->end_entry) - { - gtk_widget_unparent(priv->end_entry); - priv->end_entry = NULL; - } - if (priv->label) - { - gtk_widget_unparent(priv->label); - priv->label = NULL; - } - - if (GTK_OBJECT_CLASS(parent_class)->destroy) - GTK_OBJECT_CLASS(parent_class)->destroy(self); -} - - -static void -hildon_range_editor_size_request(GtkWidget *widget, - GtkRequisition *requisition) -{ - HildonRangeEditorPrivate *priv = NULL; - GtkRequisition lab_req, mreq; - - priv = HILDON_RANGE_EDITOR_GET_PRIVATE(widget); - - gtk_entry_get_width_chars(GTK_ENTRY(priv->end_entry)); - - gtk_widget_size_request(priv->start_entry, &mreq); - gtk_widget_size_request(priv->end_entry, &mreq); - gtk_widget_size_request(priv->label, &lab_req); - - /* Width for entries and separator label and border */ - requisition->width = mreq.width * 2 + lab_req.width + - widget->style->xthickness * 2; - /* Add vertical border */ - requisition->height = mreq.height + widget->style->ythickness * 2; - /* Fit label height */ - requisition->height = MAX (requisition->height, lab_req.height); -} - -static void -hildon_range_editor_size_allocate(GtkWidget *widget, - GtkAllocation *allocation) -{ - HildonRangeEditorPrivate *priv; - GtkAllocation child1_allocation, child2_allocation, child3_allocation; - - priv = HILDON_RANGE_EDITOR_GET_PRIVATE(widget); - - widget->allocation = *allocation; - - /* Allocate entries, left-to-right */ - if (priv->start_entry && GTK_WIDGET_VISIBLE(priv->start_entry)) - { - GtkRequisition child_requisition; - - gtk_widget_get_child_requisition(priv->start_entry, - &child_requisition); - - child1_allocation.x = allocation->x; - child1_allocation.y = allocation->y; - - child1_allocation.width = child_requisition.width; - child1_allocation.height = allocation->height; - - gtk_widget_size_allocate(priv->start_entry, &child1_allocation); - } - - if (priv->label && GTK_WIDGET_VISIBLE(priv->label)) - { - GtkRequisition child_requisition; - - gtk_widget_get_child_requisition(priv->label, &child_requisition); - - child2_allocation.x = child1_allocation.x + child1_allocation.width; - child2_allocation.y = allocation->y; - /* Add spacing */ - child2_allocation.width = child_requisition.width + 4; - child2_allocation.height = allocation->height; - - gtk_widget_size_allocate (priv->label, &child2_allocation); - } - - if (priv->end_entry && GTK_WIDGET_VISIBLE(priv->end_entry)) - { - GtkRequisition child_requisition; - - gtk_widget_get_child_requisition (priv->end_entry, &child_requisition); - - child3_allocation.x = child2_allocation.x + child2_allocation.width; - child3_allocation.y = allocation->y; - - child3_allocation.width = child_requisition.width; - child3_allocation.height = allocation->height; - - gtk_widget_size_allocate(priv->end_entry, &child3_allocation); - } -} - -/* Button released inside entries */ -static gboolean -hildon_range_editor_released(GtkEditable *editable, GdkEventButton *event, - HildonRangeEditor *editor) -{ - HildonRangeEditorPrivate *priv = HILDON_RANGE_EDITOR_GET_PRIVATE(editor); - if (GTK_WIDGET(editable) == priv->start_entry) - gtk_editable_select_region(editable, -1, 0); - else - gtk_editable_select_region(editable, 0, -1); - return FALSE; -} - -static gboolean -hildon_range_editor_entry_keypress(GtkWidget *widget, GdkEventKey *event, - HildonRangeEditor *editor) -{ - const gchar *text; - gint cursor_pos; - - g_assert(HILDON_IS_RANGE_EDITOR(editor)); - - text = gtk_entry_get_text(GTK_ENTRY(widget)); - cursor_pos = gtk_editable_get_position(GTK_EDITABLE(widget)); - - switch (event->keyval) - { - case GDK_Left: - /* If we are on the first character and press left, - try to move to previous field */ - if (cursor_pos == 0) { - (void) gtk_widget_child_focus(GTK_WIDGET(editor), GTK_DIR_LEFT); - return TRUE; - } - break; - - case GDK_Right: - /* If the cursor is on the right, try to move to the next field */ - if (cursor_pos >= g_utf8_strlen(text, -1)) { - (void) gtk_widget_child_focus(GTK_WIDGET(editor), GTK_DIR_RIGHT); - return TRUE; - } - break; - - default: - break; - }; - - return FALSE; -} - -static void hildon_range_editor_refresh_widths(HildonRangeEditorPrivate *priv) -{ - gchar start_range[32], end_range[32]; - gint length; - - /* Calculate length of entry so extremes would fit */ - g_snprintf(start_range, sizeof(start_range), "%d", priv->range_limits_start); - g_snprintf(end_range, sizeof(end_range), "%d", priv->range_limits_end); - length = MAX(g_utf8_strlen(start_range, -1), g_utf8_strlen(end_range, -1)); - - gtk_entry_set_width_chars(GTK_ENTRY(priv->start_entry), length); - gtk_entry_set_max_length(GTK_ENTRY(priv->start_entry), length); - gtk_entry_set_width_chars(GTK_ENTRY (priv->end_entry), length); - gtk_entry_set_max_length(GTK_ENTRY (priv->end_entry), length); -} - -/* Public functions */ - -/** - * hildon_range_editor_get_type: - * - * Initializes, and returns the type of a hildon range editor. - * - * @Returns : GType of #HildonRangeEditor - * - */ -GType -hildon_range_editor_get_type (void) -{ - static GType editor_type = 0; - - if (!editor_type) - { - static const GTypeInfo editor_info = - { - sizeof(HildonRangeEditorClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_range_editor_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonRangeEditor), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_range_editor_init, - }; - editor_type = g_type_register_static(GTK_TYPE_CONTAINER, - "HildonRangeEditor", - &editor_info, 0); - } - return editor_type; -} - -/** - * hildon_range_editor_new: - * - * HildonRangeEditor contains two GtkEntrys that accept numbers and minus. - * - * Returns: pointer to a new @HildonRangeEditor widget - */ -GtkWidget * -hildon_range_editor_new (void) -{ - return GTK_WIDGET(g_object_new(HILDON_TYPE_RANGE_EDITOR, NULL)); -} - - -/** - * hildon_range_editor_new_with_separator: - * @separator: a string that is shown between the numbers - * - * HildonRangeEditor contains two Gtk entries that accept numbers. - * A separator is displayed between two entries. - * CHECKME: Use '-' as a separator in the case of null separator? - * - * Returns: pointer to a new @HildonRangeEditor widget - */ -GtkWidget * -hildon_range_editor_new_with_separator (const gchar *separator) -{ - return GTK_WIDGET (g_object_new (HILDON_TYPE_RANGE_EDITOR, - "separator", separator, NULL)); -} - - -/** - * hildon_range_editor_set_range: - * @editor: the #HildonRangeEditor widget - * @start: range's start value - * @end: range's end value - * - * Sets a range to the editor. (The current value) - * - * Sets the range of the @HildonRangeEditor widget. - */ -void -hildon_range_editor_set_range (HildonRangeEditor *editor, gint start, gint end) -{ - g_return_if_fail (HILDON_IS_RANGE_EDITOR (editor)); - - /* Make sure that the start/end appear in the correct order */ - hildon_range_editor_set_lower (editor, MIN(start, end)); - hildon_range_editor_set_higher (editor, MAX(start, end)); -} - - -/** - * hildon_range_editor_get_range: - * @editor: the #HildonRangeEditor widget - * @start: ranges start value - * @end: ranges end value - * - * Gets the range of the @HildonRangeEditor widget. - */ -void -hildon_range_editor_get_range (HildonRangeEditor *editor, gint *start, - gint *end) -{ - HildonRangeEditorPrivate *priv; - - g_return_if_fail (HILDON_IS_RANGE_EDITOR (editor) && start && end); - priv = HILDON_RANGE_EDITOR_GET_PRIVATE (editor); - - *start = hildon_range_editor_get_lower (editor); - *end = hildon_range_editor_get_higher (editor); -} - - -/** - * hildon_range_editor_set_limits: - * @editor: the #HildonRangeEditor widget - * @start: minimum acceptable value (default: no limit) - * @end: maximum acceptable value (default: no limit) - * - * Sets the range of the @HildonRangeEditor widget. - */ -void -hildon_range_editor_set_limits (HildonRangeEditor *editor, gint start, - gint end) -{ - /* FIXME: Setting start/end as separate steps can modify - the inputted range unneedlesly */ - hildon_range_editor_set_min (editor, start); - hildon_range_editor_set_max (editor, end); -} - -void -hildon_range_editor_set_lower (HildonRangeEditor *editor, gint value) -{ - HildonRangeEditorPrivate *priv; - gchar buffer[32]; - - g_return_if_fail (HILDON_IS_RANGE_EDITOR (editor)); - priv = HILDON_RANGE_EDITOR_GET_PRIVATE (editor); - - g_snprintf(buffer, sizeof(buffer), "%d", CLAMP(value, - priv->range_limits_start, priv->range_limits_end)); - - /* Update entry text with new value */ - gtk_entry_set_text (GTK_ENTRY (priv->start_entry), buffer); - g_object_notify (G_OBJECT (editor), "lower"); -} - -void -hildon_range_editor_set_higher (HildonRangeEditor *editor, gint value) -{ - HildonRangeEditorPrivate *priv; - gchar buffer[32]; - - g_return_if_fail (HILDON_IS_RANGE_EDITOR (editor)); - priv = HILDON_RANGE_EDITOR_GET_PRIVATE (editor); - - g_snprintf(buffer, sizeof(buffer), "%d", CLAMP(value, - priv->range_limits_start, priv->range_limits_end)); - - /* Update entry text with new value */ - gtk_entry_set_text (GTK_ENTRY (priv->end_entry), buffer); - g_object_notify (G_OBJECT (editor), "higher"); -} - -gint -hildon_range_editor_get_lower (HildonRangeEditor *editor) -{ - HildonRangeEditorPrivate *priv; - g_return_val_if_fail (HILDON_IS_RANGE_EDITOR (editor), 0); - priv = HILDON_RANGE_EDITOR_GET_PRIVATE (editor); - return atoi(gtk_entry_get_text(GTK_ENTRY(priv->start_entry))); -} - -gint -hildon_range_editor_get_higher (HildonRangeEditor *editor) -{ - HildonRangeEditorPrivate *priv; - g_return_val_if_fail (HILDON_IS_RANGE_EDITOR (editor), 0); - priv = HILDON_RANGE_EDITOR_GET_PRIVATE (editor); - return atoi(gtk_entry_get_text(GTK_ENTRY (priv->end_entry))); -} - -void -hildon_range_editor_set_min (HildonRangeEditor *editor, gint value) -{ - HildonRangeEditorPrivate *priv; - - g_return_if_fail (HILDON_IS_RANGE_EDITOR (editor)); - - /* We can cause many properties to change */ - g_object_freeze_notify(G_OBJECT(editor)); - priv = HILDON_RANGE_EDITOR_GET_PRIVATE (editor); - priv->range_limits_start = value; - - if (priv->range_limits_end < value) - hildon_range_editor_set_max (editor, value); - /* Setting maximum applies widths and range in this case */ - else { - hildon_range_editor_refresh_widths(priv); - hildon_range_editor_apply_current_range(editor); - } - - g_object_notify (G_OBJECT (editor), "min"); - g_object_thaw_notify(G_OBJECT(editor)); -} - -void -hildon_range_editor_set_max (HildonRangeEditor *editor, gint value) -{ - HildonRangeEditorPrivate *priv; - - g_return_if_fail (HILDON_IS_RANGE_EDITOR (editor)); - - /* We can cause many properties to change */ - g_object_freeze_notify(G_OBJECT(editor)); - priv = HILDON_RANGE_EDITOR_GET_PRIVATE (editor); - priv->range_limits_end = value; - - if (priv->range_limits_start > value) - hildon_range_editor_set_min (editor, value); - /* Setting minimum applies widths and range in this case */ - else { - hildon_range_editor_refresh_widths(priv); - hildon_range_editor_apply_current_range(editor); - } - - g_object_notify (G_OBJECT (editor), "max"); - g_object_thaw_notify(G_OBJECT(editor)); -} - -gint -hildon_range_editor_get_min (HildonRangeEditor *editor) -{ - HildonRangeEditorPrivate *priv; - g_return_val_if_fail (HILDON_IS_RANGE_EDITOR (editor), 0); - priv = HILDON_RANGE_EDITOR_GET_PRIVATE (editor); - - return priv->range_limits_start; -} - -gint -hildon_range_editor_get_max (HildonRangeEditor *editor) -{ - HildonRangeEditorPrivate *priv; - g_return_val_if_fail (HILDON_IS_RANGE_EDITOR (editor), 0); - priv = HILDON_RANGE_EDITOR_GET_PRIVATE (editor); - - return priv->range_limits_end; -} - -void -hildon_range_editor_set_separator (HildonRangeEditor *editor, - const gchar *separator) -{ - HildonRangeEditorPrivate *priv; - g_return_if_fail (HILDON_IS_RANGE_EDITOR (editor)); - priv = HILDON_RANGE_EDITOR_GET_PRIVATE (editor); - - gtk_label_set_text (GTK_LABEL (priv->label), separator); - g_object_notify (G_OBJECT(editor), "separator"); -} - -const gchar * -hildon_range_editor_get_separator (HildonRangeEditor *editor) -{ - HildonRangeEditorPrivate *priv; - g_return_val_if_fail (HILDON_IS_RANGE_EDITOR (editor), NULL); - priv = HILDON_RANGE_EDITOR_GET_PRIVATE (editor); - - return gtk_label_get_text (GTK_LABEL (priv->label)); -} diff --git a/hildon-widgets/hildon-range-editor.h b/hildon-widgets/hildon-range-editor.h deleted file mode 100644 index dbbf424..0000000 --- a/hildon-widgets/hildon-range-editor.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_RANGE_EDITOR_H__ -#define __HILDON_RANGE_EDITOR_H__ - -#include - -G_BEGIN_DECLS -/** - * HILDON_TYPE_RANGE_EDITOR - * - * Macro for getting type of range editor. - * Since: 0.12.10 - */ -#define HILDON_TYPE_RANGE_EDITOR (hildon_range_editor_get_type()) - -/** - * HILDON_RANGE_EDITOR_TYPE - * - * Deprecated: use #HILDON_TYPE_RANGE_EDITOR instead - */ -#define HILDON_RANGE_EDITOR_TYPE HILDON_TYPE_RANGE_EDITOR - -#define HILDON_RANGE_EDITOR(obj) \ - (GTK_CHECK_CAST (obj, HILDON_TYPE_RANGE_EDITOR, HildonRangeEditor)) -#define HILDON_RANGE_EDITOR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass),\ - HILDON_TYPE_RANGE_EDITOR, HildonRangeEditorClass)) -#define HILDON_IS_RANGE_EDITOR(obj) \ - (GTK_CHECK_TYPE (obj, HILDON_TYPE_RANGE_EDITOR)) -#define HILDON_IS_RANGE_EDITOR_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_RANGE_EDITOR)) -/** - * HildonRangeEditor: - * - * Internal struct for range editor. - */ -typedef struct _HildonRangeEditor HildonRangeEditor; -typedef struct _HildonRangeEditorClass HildonRangeEditorClass; - - -struct _HildonRangeEditor { - GtkContainer parent; -}; - -struct _HildonRangeEditorClass { - GtkContainerClass parent_class; -}; - -GType hildon_range_editor_get_type(void) G_GNUC_CONST; - -GtkWidget *hildon_range_editor_new_with_separator(const gchar * separator); -GtkWidget *hildon_range_editor_new(void); - -void hildon_range_editor_set_range(HildonRangeEditor * editor, - gint start, gint end); -void hildon_range_editor_get_range(HildonRangeEditor * editor, - gint * start, gint * end); -void hildon_range_editor_set_limits(HildonRangeEditor * editor, - gint start, gint end); - -void hildon_range_editor_set_lower (HildonRangeEditor *editor, gint value); -void hildon_range_editor_set_higher (HildonRangeEditor *editor, gint value); -gint hildon_range_editor_get_lower (HildonRangeEditor *editor); -gint hildon_range_editor_get_higher (HildonRangeEditor *editor); -void hildon_range_editor_set_min (HildonRangeEditor *editor, gint value); -void hildon_range_editor_set_max (HildonRangeEditor *editor, gint value); -gint hildon_range_editor_get_min (HildonRangeEditor *editor); -gint hildon_range_editor_get_max (HildonRangeEditor *editor); -void hildon_range_editor_set_separator (HildonRangeEditor *editor, - const gchar *separator); -const gchar *hildon_range_editor_get_separator (HildonRangeEditor *editor); - -G_END_DECLS -#endif /* __HILDON_RANGE_EDITOR_H__ */ diff --git a/hildon-widgets/hildon-scroll-area.c b/hildon-widgets/hildon-scroll-area.c deleted file mode 100644 index ff484be..0000000 --- a/hildon-widgets/hildon-scroll-area.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-scroll-area - * @short_description: A helper to create Maemo specific views, - * which are using scrollable area - * - * #GtkScrollArea combines a large widget that needs scrolling (like a - * text editor or a tree view) and other widgets that wouldn't fit one - * the screen normally without scrolling (like entries, toolbars etc.) - * into one scrollable area. - */ - -#include "hildon-scroll-area.h" -#include -#include -#include -#include -#include - -typedef struct - { - GtkWidget *fixed; - - /* Scrolled windows */ - GtkWidget *swouter; - GtkWidget *swinner; - - /* Widget that's being contained */ - GtkWidget *child; - - /* Vertical adjustment for scrolled windows */ - GtkAdjustment *outadj; - GtkAdjustment *inadj; - - } HildonScrollArea; - - -static void hildon_scroll_area_outer_value_changed (GtkAdjustment *adjustment, - HildonScrollArea *sc); -static void hildon_scroll_area_inner_value_changed (GtkAdjustment *adjustment, - HildonScrollArea *sc); -static void hildon_scroll_area_size_allocate (GtkWidget *widget, - GtkAllocation *allocation, - HildonScrollArea *sc); -static void hildon_scroll_area_child_requisition (GtkWidget *widget, - GtkRequisition *req, - HildonScrollArea *sc); -static void hildon_scroll_area_fixed_allocate (GtkWidget *widget, - GtkAllocation *allocation, - HildonScrollArea *sc); - -static int calculate_size (GtkWidget *widget); - -/** - * hildon_scroll_area_new: - * @sw: #GtkWidget - #GtkScrolledWindow - * @child: #GtkWidget - child to be place inside the sw - * - * This is not a widget. It's a helper function to create - * hildon-specific scrolling methods. - * A common situation where the scroll area should be used - * might be following. A view containing @GtkTreeView based widget, - * (or any similar widget which has built-in @GtkScrolledWindow support) - * and eg. couple buttons. Normaly @GtkScrolledWindow can not handle - * the situation so that the @GtkTreeView built-in support - * would work. The scroll area is connecting this built-in system to - * the scrolled window and also noticing the buttons. To use, one should - * create a box to which pack the buttons and the scroll area. - * The scroll area then contains the problematic widget eg. the @GtkTreeView. - * Then the box should be placed in the @GtkScrolledWindow. - * The function is currently assuming that the newly created scroll area - * hierarchy is not modified in anyway. Or if it is, it may lead to - * unwanted problems. Also assumed, that the @child will be packed - * to the @sw. - * - * Returns: a @GtkFixed - */ -GtkWidget *hildon_scroll_area_new (GtkWidget *sw, GtkWidget *child) -{ - GtkWidget *swi; - GtkWidget *fixed; - HildonScrollArea *sc; - - g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (sw) - && GTK_IS_WIDGET (child), NULL); - - swi = gtk_scrolled_window_new (NULL, NULL); - fixed = gtk_fixed_new (); - sc = g_malloc (sizeof (HildonScrollArea)); - memset (sc, 0, sizeof (HildonScrollArea)); - - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swi), - GTK_POLICY_NEVER, GTK_POLICY_NEVER); - - gtk_container_add (GTK_CONTAINER (swi), child); - gtk_fixed_put (GTK_FIXED (fixed), swi, 0, 0); - - sc->fixed = fixed; - sc->swouter = sw; - sc->swinner = swi; - sc->child = child; - sc->outadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (sw)); - sc->inadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (swi)); - - g_signal_connect_after (G_OBJECT (child), "size-request", - G_CALLBACK (hildon_scroll_area_child_requisition), sc); - - g_signal_connect_after (G_OBJECT (sc->outadj), "value_changed", - G_CALLBACK (hildon_scroll_area_outer_value_changed), sc); - g_signal_connect_after (G_OBJECT (sc->inadj), "value_changed", - G_CALLBACK (hildon_scroll_area_inner_value_changed), sc); - - g_signal_connect_after (G_OBJECT (sw), "size-allocate", - G_CALLBACK (hildon_scroll_area_size_allocate), sc); - g_signal_connect (G_OBJECT (sc->fixed), "size-allocate", - G_CALLBACK (hildon_scroll_area_fixed_allocate), sc); - g_signal_connect_swapped (G_OBJECT (sw), "destroy", - G_CALLBACK (g_free), sc); - - gtk_widget_show_all (sw); - return fixed; -} - -static void hildon_scroll_area_fixed_allocate (GtkWidget *widget, - GtkAllocation *allocation, - HildonScrollArea *sc) -{ - gtk_widget_set_size_request (sc->swinner, -1, - MIN (sc->outadj->page_size, allocation->height)); -} - - -static int calculate_size (GtkWidget *widget) -{ - int size = 0; - - if (GTK_IS_TEXT_VIEW (widget)) - return 0; - - if (GTK_IS_CONTAINER (widget)) { - GList *children = gtk_container_get_children (GTK_CONTAINER (widget)); - while (children != NULL) { - GtkWidget *wid = GTK_WIDGET (children->data); - gint sz = calculate_size (wid); - if ((GTK_WIDGET_VISIBLE (wid))) { - size += sz; - } - - children = g_list_next (children); - } - } else { - size = widget->allocation.height; - } - - return size; -} - -static void hildon_scroll_area_child_requisition (GtkWidget *widget, - GtkRequisition *req, - HildonScrollArea *sc) -{ - /* Limit height to fixed height */ - gint new_req = MAX (req->height, sc->fixed->allocation.height); - gint adjust_factor = calculate_size (sc->swouter) * 0.7; - - adjust_factor = MAX (0, adjust_factor - sc->outadj->value); - new_req = MIN (sc->outadj->page_size - adjust_factor, new_req); - - gtk_widget_set_size_request (sc->fixed, -1, req->height); - /* Request inner scrolled window at most page size */ - gtk_widget_set_size_request (sc->swinner, -1, new_req); -} - -static void hildon_scroll_area_outer_value_changed (GtkAdjustment *adjustment, - HildonScrollArea *sc) -{ - GtkRequisition req; - gtk_widget_size_request (sc->child, &req); - - /* Update inner adjustment position based on outer one, update fixed position */ - if ((sc->outadj->value + sc->outadj->page_size) > sc->fixed->allocation.y - && sc->outadj->value < (sc->fixed->allocation.y + req.height)) - { - gdouble new_pos = 0; - - new_pos = MAX (sc->outadj->value - sc->fixed->allocation.y, 0); - new_pos = MIN (new_pos, req.height - sc->inadj->page_size); - new_pos = MAX (new_pos, 0); - - gtk_fixed_move (GTK_FIXED (sc->fixed), sc->swinner, 0, new_pos); - gtk_adjustment_set_value (sc->inadj, new_pos); - } -} - -static void hildon_scroll_area_inner_value_changed (GtkAdjustment *adjustment, - HildonScrollArea *sc) -{ - /* Update outer adjustment based on inner adjustment position */ - if (sc->outadj->value != sc->fixed->allocation.y + adjustment->value) - gtk_adjustment_set_value (sc->outadj, - sc->fixed->allocation.y + adjustment->value); -} - -__inline__ static gint calculate_width (HildonScrollArea *sc) -{ - GtkScrolledWindow *scwin = GTK_SCROLLED_WINDOW (sc->swouter); - return (scwin->hscrollbar_visible * scwin->hscrollbar->allocation.width); -} - -static void hildon_scroll_area_size_allocate (GtkWidget *widget, - GtkAllocation *allocation, - HildonScrollArea *sc) -{ - gtk_widget_set_size_request (sc->fixed, calculate_width (sc), sc->fixed->allocation.height); - gtk_widget_set_size_request (sc->child, sc->fixed->allocation.width, -1); -} diff --git a/hildon-widgets/hildon-scroll-area.h b/hildon-widgets/hildon-scroll-area.h deleted file mode 100644 index ce1c725..0000000 --- a/hildon-widgets/hildon-scroll-area.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/* - * The reason why this is not made as a widget: - * We can not create a widget which could return the correct child. - * (ie. by gtk_bin_get_child) - */ - -#ifndef __HILDON_SCROLL_AREA_H__ -#define __HILDON_SCROLL_AREA_H__ - -#include - -G_BEGIN_DECLS - GtkWidget * hildon_scroll_area_new(GtkWidget * sw, GtkWidget * child); - -G_END_DECLS -#endif /* __HILDON_SCROLL_AREA_H__ */ diff --git a/hildon-widgets/hildon-seekbar.c b/hildon-widgets/hildon-seekbar.c deleted file mode 100644 index 34d3b50..0000000 --- a/hildon-widgets/hildon-seekbar.c +++ /dev/null @@ -1,601 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-seekbar - * @short_description: A widget used to identify a place from a content - * - * HildonSeekbar allows seeking in media with a range widget. It - * supports for setting or getting the length (total time) of the media, - * the position within it and the fraction (maximum position in a - * stream/the amount currently downloaded). The position is clamped - * between zero and the total time, or zero and the fraction in case of - * a stream. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "hildon-seekbar.h" - -#define HILDON_SEEKBAR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_SEEKBAR, HildonSeekbarPrivate)); - -typedef struct _HildonSeekbarPrivate HildonSeekbarPrivate; - -/* our parent class */ -static GtkScaleClass *parent_class = NULL; - -/* Init functions */ -static void hildon_seekbar_class_init(HildonSeekbarClass * seekbar_class); -static void hildon_seekbar_init(HildonSeekbar * seekbar); - -/* property functions */ -static void hildon_seekbar_set_property(GObject * object, guint prop_id, - const GValue * value, - GParamSpec * pspec); - -static void hildon_seekbar_get_property(GObject * object, guint prop_id, - GValue * value, - GParamSpec * pspec); - -/* virtual functions */ -static void hildon_seekbar_size_request(GtkWidget * widget, - GtkRequisition * event); -static void hildon_seekbar_size_allocate(GtkWidget * widget, - GtkAllocation * allocation); -static gboolean hildon_seekbar_expose(GtkWidget * widget, - GdkEventExpose * event); -static gboolean hildon_seekbar_button_press_event(GtkWidget * widget, - GdkEventButton * event); -static gboolean hildon_seekbar_button_release_event(GtkWidget * widget, - GdkEventButton * event); -static gboolean hildon_seekbar_keypress(GtkWidget * widget, - GdkEventKey * event); - - -#define MINIMUM_WIDTH 115 -#define DEFAULT_HEIGHT 58 - -/* Toolbar width and height defines */ -#define TOOL_MINIMUM_WIDTH 75 -#define TOOL_DEFAULT_HEIGHT 40 - -#define DEFAULT_DISPLAYC_BORDER 10 -#define BUFFER_SIZE 32 -#define EXTRA_SIDE_BORDER 20 -#define TOOL_EXTRA_SIDE_BORDER 0 - -/* the number of steps it takes to move from left to right */ -#define NUM_STEPS 20 - -#define SECONDS_PER_MINUTE 60 - -/* the number of digits precision for the internal range. - * note, this needs to be enough so that the step size for - * small total_times doesn't get rounded off. Currently set to 3 - * this is because for the smallest total time ( i.e 1 ) and the current - * num steps ( 20 ) is: 1/20 = 0.05. 0.05 is 2 digits, and we - * add one for safety */ -#define MAX_ROUND_DIGITS 3 - -/* - * FIXME HildonSeekbar introduced major changes in GtkRange mostly related - * to stream_indicator. These changes should be minimized. - */ - -/* Property indices */ -enum { - PROP_TOTAL_TIME = 1, - PROP_POSITION, - PROP_FRACTION -}; - -/* private variables */ -struct _HildonSeekbarPrivate { - gboolean is_toolbar; /* TRUE if this widget is inside a toolbar */ - guint fraction; /* This is the amount of time that has progressed from - the beginning. It should be an integer between the - minimum and maximum values of the corresponding - adjustment, ie. adjument->lower and ->upper.. */ -}; - -/** - * Initialises, and returns the type of a hildon seekbar. - */ -GType hildon_seekbar_get_type(void) -{ - static GType seekbar_type = 0; - - if (!seekbar_type) { - static const GTypeInfo seekbar_info = { - sizeof(HildonSeekbarClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_seekbar_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonSeekbar), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_seekbar_init, - }; - seekbar_type = g_type_register_static(GTK_TYPE_SCALE, - "HildonSeekbar", - &seekbar_info, 0); - } - return seekbar_type; -} - -/** - * Initialises the seekbar class. - */ -static void hildon_seekbar_class_init(HildonSeekbarClass * seekbar_class) -{ - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(seekbar_class); - GObjectClass *object_class = G_OBJECT_CLASS(seekbar_class); - - parent_class = g_type_class_peek_parent(seekbar_class); - - g_type_class_add_private(seekbar_class, sizeof(HildonSeekbarPrivate)); - - widget_class->size_request = hildon_seekbar_size_request; - widget_class->size_allocate = hildon_seekbar_size_allocate; - widget_class->expose_event = hildon_seekbar_expose; - widget_class->button_press_event = hildon_seekbar_button_press_event; - widget_class->button_release_event = - hildon_seekbar_button_release_event; - widget_class->key_press_event = hildon_seekbar_keypress; - - object_class->set_property = hildon_seekbar_set_property; - object_class->get_property = hildon_seekbar_get_property; - - g_object_class_install_property(object_class, PROP_TOTAL_TIME, - g_param_spec_double("total_time", - "total time", - "Total playing time of this media file", - 0, /* min value */ - G_MAXDOUBLE, /* max value */ - 0, /* default */ - G_PARAM_READWRITE)); - - g_object_class_install_property(object_class, PROP_POSITION, - g_param_spec_double("position", - "position", - "Current position in this media file", - 0, /* min value */ - G_MAXDOUBLE, /* max value */ - 0, /* default */ - G_PARAM_READWRITE)); - - g_object_class_install_property(object_class, PROP_FRACTION, - g_param_spec_double("fraction", - "Fraction", - "current fraction related to the" - "progress indicator", - 0, /* min value */ - G_MAXDOUBLE, /* max value */ - 0, /* default */ - G_PARAM_READWRITE)); -} - - -static void hildon_seekbar_init(HildonSeekbar * seekbar) -{ - HildonSeekbarPrivate *priv; - GtkRange *range = GTK_RANGE(seekbar); - - priv = HILDON_SEEKBAR_GET_PRIVATE(seekbar); - - /* Initialize range widget */ - range->orientation = GTK_ORIENTATION_HORIZONTAL; - range->flippable = TRUE; - range->has_stepper_a = TRUE; - range->has_stepper_d = TRUE; - range->round_digits = MAX_ROUND_DIGITS; - - gtk_scale_set_draw_value (GTK_SCALE (seekbar), FALSE); -} - -/* - * Purpose of this function is to prevent Up and Down keys from - * changing the widget's value (like Left and Right). Instead they - * are used for changing focus to other widgtes. - */ -static gboolean hildon_seekbar_keypress(GtkWidget * widget, - GdkEventKey * event) -{ - if (event->keyval == GDK_Up || event->keyval == GDK_Down) - return FALSE; - return ((GTK_WIDGET_CLASS(parent_class)->key_press_event) (widget, - event)); -} - -static void -hildon_seekbar_set_property(GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - HildonSeekbar *seekbar = HILDON_SEEKBAR(object); - - switch (prop_id) { - case PROP_TOTAL_TIME: - hildon_seekbar_set_total_time(seekbar, g_value_get_double(value)); - break; - case PROP_POSITION: - hildon_seekbar_set_position(seekbar, g_value_get_double(value)); - break; - case PROP_FRACTION: - hildon_seekbar_set_fraction(seekbar, g_value_get_double(value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/* handle getting of seekbar properties */ -static void -hildon_seekbar_get_property(GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GtkRange *range = GTK_RANGE(object); - - switch (prop_id) { - case PROP_TOTAL_TIME: - g_value_set_double(value, range->adjustment->upper); - break; - case PROP_POSITION: - g_value_set_double(value, range->adjustment->value); - break; - case PROP_FRACTION: - g_value_set_double(value, - hildon_seekbar_get_fraction(HILDON_SEEKBAR(object))); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/** - * hildon_seekbar_new: - * - * Create a new #HildonSeekbar widget. - * - * Returns: a #GtkWidget pointer of #HildonSeekbar widget - */ -GtkWidget *hildon_seekbar_new(void) -{ - return g_object_new(HILDON_TYPE_SEEKBAR, NULL); -} - -/** - * hildon_seekbar_get_total_time: - * @seekbar: pointer to #HildonSeekbar widget - * - * Returns: total playing time of media in seconds. - */ -gint hildon_seekbar_get_total_time(HildonSeekbar *seekbar) -{ - GtkWidget *widget; - widget = GTK_WIDGET (seekbar); - g_return_val_if_fail(HILDON_IS_SEEKBAR(seekbar), 0); - g_return_val_if_fail(GTK_RANGE(widget)->adjustment, 0); - return GTK_RANGE(widget)->adjustment->upper; -} - -/** - * hildon_seekbar_set_total_time: - * @seekbar: pointer to #HildonSeekbar widget - * @time: integer greater than zero - * - * Set total playing time of media in seconds. - */ -void hildon_seekbar_set_total_time(HildonSeekbar *seekbar, gint time) -{ - GtkAdjustment *adj; - GtkWidget *widget; - gboolean value_changed = FALSE; - - g_return_if_fail(HILDON_IS_SEEKBAR(seekbar)); - widget = GTK_WIDGET (seekbar); - - if (time <= 0) { - return; - } - - g_return_if_fail(GTK_RANGE(widget)->adjustment); - - adj = GTK_RANGE(widget)->adjustment; - adj->upper = time; - - /* Clamp position to total time */ - if (adj->value > time) { - adj->value = time; - value_changed = TRUE; - } - - /* Calculate new step value */ - adj->step_increment = adj->upper / NUM_STEPS; - adj->page_increment = adj->step_increment; - - gtk_adjustment_changed(adj); - - /* Update range widget position/fraction */ - if (value_changed) { - gtk_adjustment_value_changed(adj); - hildon_seekbar_set_fraction(seekbar, - MIN(hildon_seekbar_get_fraction(seekbar), - time)); - - g_object_freeze_notify (G_OBJECT(seekbar)); - - hildon_seekbar_set_position(seekbar, - MIN(hildon_seekbar_get_position(seekbar), - time)); - - g_object_notify(G_OBJECT (seekbar), "total-time"); - - g_object_thaw_notify (G_OBJECT(seekbar)); - } -} - -/** - * hildon_seekbar_get_fraction: - * @seekbar: pointer to #HildonSeekbar widget - * - * Get current fraction value of the rage. - * - * Returns: current fraction - */ -guint hildon_seekbar_get_fraction( HildonSeekbar *seekbar ) -{ - g_return_val_if_fail( HILDON_IS_SEEKBAR( seekbar ), 0 ); - - return osso_gtk_range_get_stream_position (GTK_RANGE(seekbar)); -} - -/** - * hildon_seekbar_set_fraction: - * @seekbar: pointer to #HildonSeekbar widget - * @fraction: the new position of the progress indicator - * - * Set current fraction value of the range. - * It should be between the minimal and maximal values of the range in seekbar. - */ -void hildon_seekbar_set_fraction( HildonSeekbar *seekbar, guint fraction ) -{ - GtkRange *range = NULL; - g_return_if_fail( HILDON_IS_SEEKBAR( seekbar ) ); - - range = GTK_RANGE(GTK_WIDGET(seekbar)); - - g_return_if_fail(fraction <= range->adjustment->upper && - fraction >= range->adjustment->lower); - - /* Set to show stream indicator. */ - g_object_set (G_OBJECT (seekbar), "stream_indicator", TRUE, NULL); - - fraction = CLAMP(fraction, range->adjustment->lower, - range->adjustment->upper); - - /* Update stream position of range widget */ - osso_gtk_range_set_stream_position( range, fraction ); - - if (fraction < hildon_seekbar_get_position(seekbar)) - hildon_seekbar_set_position(seekbar, fraction); - - g_object_notify (G_OBJECT (seekbar), "fraction"); -} - -/** - * hildon_seekbar_get_position: - * @seekbar: pointer to #HildonSeekbar widget - * - * Get current position in stream in seconds. - * - * Returns: current position in stream in seconds - */ -gint hildon_seekbar_get_position(HildonSeekbar *seekbar) -{ - g_return_val_if_fail(HILDON_IS_SEEKBAR(seekbar), 0); - g_return_val_if_fail(GTK_RANGE(seekbar)->adjustment, 0); - - return GTK_RANGE(seekbar)->adjustment->value; -} - -/** - * hildon_seekbar_set_position: - * @seekbar: pointer to #HildonSeekbar widget - * @time: time within range of >= 0 && < G_MAXINT - * - * Set current position in stream in seconds. - */ -void hildon_seekbar_set_position(HildonSeekbar *seekbar, gint time) -{ - GtkRange *range; - GtkAdjustment *adj; - gint value; - - g_return_if_fail(time >= 0); - g_return_if_fail(HILDON_IS_SEEKBAR(seekbar)); - range = GTK_RANGE(seekbar); - adj = range->adjustment; - g_return_if_fail(adj); - - /* only change value if it is a different int. this allows us to have - smooth scrolls for small total_times */ - value = floor(adj->value); - if (time != value) { - value = (time < adj->upper) ? time : adj->upper; - if (value <= osso_gtk_range_get_stream_position (range)) { - adj->value = value; - gtk_adjustment_value_changed(adj); - - g_object_notify(G_OBJECT(seekbar), "position"); - } - } -} - -static void hildon_seekbar_size_request(GtkWidget * widget, - GtkRequisition * req) -{ - HildonSeekbar *self = NULL; - HildonSeekbarPrivate *priv = NULL; - GtkWidget *parent = NULL; - - self = HILDON_SEEKBAR(widget); - priv = HILDON_SEEKBAR_GET_PRIVATE(self); - - parent = gtk_widget_get_ancestor(GTK_WIDGET(self), GTK_TYPE_TOOLBAR); - - priv->is_toolbar = parent ? TRUE : FALSE; - - if (GTK_WIDGET_CLASS(parent_class)->size_request) - GTK_WIDGET_CLASS(parent_class)->size_request(widget, req); - - /* Request minimum size, depending on whether the widget is in a - * toolbar or not */ - req->width = priv->is_toolbar ? TOOL_MINIMUM_WIDTH : MINIMUM_WIDTH; - req->height = priv->is_toolbar ? TOOL_DEFAULT_HEIGHT : DEFAULT_HEIGHT; -} - -static void hildon_seekbar_size_allocate(GtkWidget * widget, - GtkAllocation * allocation) -{ - HildonSeekbarPrivate *priv; - - priv = HILDON_SEEKBAR_GET_PRIVATE(HILDON_SEEKBAR(widget)); - - if (priv->is_toolbar == TRUE) - { - /* Center vertically */ - if (allocation->height > TOOL_DEFAULT_HEIGHT) - { - allocation->y += - (allocation->height - TOOL_DEFAULT_HEIGHT) / 2; - allocation->height = TOOL_DEFAULT_HEIGHT; - } - /* Add space for border */ - allocation->x += TOOL_EXTRA_SIDE_BORDER; - allocation->width -= 2 * TOOL_EXTRA_SIDE_BORDER; - } - else - { - /* Center vertically */ - if (allocation->height > DEFAULT_HEIGHT) - { - allocation->y += (allocation->height - DEFAULT_HEIGHT) / 2; - allocation->height = DEFAULT_HEIGHT; - } - - /* Add space for border */ - allocation->x += EXTRA_SIDE_BORDER; - allocation->width -= 2 * EXTRA_SIDE_BORDER; - } - - if (GTK_WIDGET_CLASS(parent_class)->size_allocate) - GTK_WIDGET_CLASS(parent_class)->size_allocate(widget, allocation); -} - -static gboolean hildon_seekbar_expose(GtkWidget * widget, - GdkEventExpose * event) -{ - HildonSeekbarPrivate *priv; - gint extra_side_borders = 0; - - priv = HILDON_SEEKBAR_GET_PRIVATE(HILDON_SEEKBAR(widget)); - - extra_side_borders = priv->is_toolbar ? TOOL_EXTRA_SIDE_BORDER : - EXTRA_SIDE_BORDER; - - if (GTK_WIDGET_DRAWABLE(widget)) { - /* Paint border */ - gtk_paint_box(widget->style, widget->window, - GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, - NULL, widget, "seekbar", - widget->allocation.x - extra_side_borders, - widget->allocation.y, - widget->allocation.width + 2 * extra_side_borders, - widget->allocation.height); - - (*GTK_WIDGET_CLASS(parent_class)->expose_event) (widget, event); - } - - return FALSE; -} - -/* - * Event handler for button press. Changes button1 to button2. - */ -static gboolean -hildon_seekbar_button_press_event(GtkWidget * widget, - GdkEventButton * event) -{ - gint result = FALSE; - - /* We change here the button id because we want to use button2 - * functionality for button1: jump to mouse position - * instead of slowly incrementing to it */ - if (event->button == 1) event->button = 2; - - /* call the parent handler */ - if (GTK_WIDGET_CLASS(parent_class)->button_press_event) - result = GTK_WIDGET_CLASS(parent_class)->button_press_event(widget, - event); - - return result; -} -/* - * Event handler for button release. Changes button1 to button2. - */ -static gboolean -hildon_seekbar_button_release_event(GtkWidget * widget, - GdkEventButton * event) -{ - gboolean result = FALSE; - - /* We change here the button id because we want to use button2 - * functionality for button1: jump to mouse position - * instead of slowly incrementing to it */ - event->button = event->button == 1 ? 2 : event->button; - - /* call the parent handler */ - if (GTK_WIDGET_CLASS(parent_class)->button_release_event) - result = GTK_WIDGET_CLASS(parent_class)->button_release_event(widget, - event); - return result; -} diff --git a/hildon-widgets/hildon-seekbar.h b/hildon-widgets/hildon-seekbar.h deleted file mode 100644 index 47c7548..0000000 --- a/hildon-widgets/hildon-seekbar.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_SEEKBAR_H__ -#define __HILDON_SEEKBAR_H__ - -#include - -G_BEGIN_DECLS -#define HILDON_TYPE_SEEKBAR ( hildon_seekbar_get_type() ) -#define HILDON_SEEKBAR(obj) (GTK_CHECK_CAST (obj,\ - HILDON_TYPE_SEEKBAR, HildonSeekbar)) -#define HILDON_SEEKBAR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass),\ - HILDON_TYPE_SEEKBAR, HildonSeekbarClass)) -#define HILDON_IS_SEEKBAR(obj) (GTK_CHECK_TYPE (obj, HILDON_TYPE_SEEKBAR)) -#define HILDON_IS_SEEKBAR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass),\ - HILDON_TYPE_SEEKBAR)) -/** - * HildonSeekbar: - * - * Contains only private data. - */ -typedef struct _HildonSeekbar HildonSeekbar; -typedef struct _HildonSeekbarClass HildonSeekbarClass; - -struct _HildonSeekbar { - GtkScale scale; -}; - -struct _HildonSeekbarClass { - GtkScaleClass parent_class; -}; - -GType hildon_seekbar_get_type(void) G_GNUC_CONST; -GtkWidget *hildon_seekbar_new(void); -gint hildon_seekbar_get_total_time(HildonSeekbar *seekbar); -void hildon_seekbar_set_total_time(HildonSeekbar *seekbar, gint time); -gint hildon_seekbar_get_position(HildonSeekbar *seekbar); -void hildon_seekbar_set_position(HildonSeekbar *seekbar, gint time); -void hildon_seekbar_set_fraction(HildonSeekbar *seekbar, guint fraction); -guint hildon_seekbar_get_fraction(HildonSeekbar *seekbar); - -G_END_DECLS -#endif /* __HILDON_SEEKBAR_H__ */ diff --git a/hildon-widgets/hildon-set-password-dialog.c b/hildon-widgets/hildon-set-password-dialog.c deleted file mode 100644 index 527fc30..0000000 --- a/hildon-widgets/hildon-set-password-dialog.c +++ /dev/null @@ -1,666 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-set-password-dialog - * @short_description: A dialog used to set, change or remove a password - * @see_also: #HildonGetPasswordDialog - * - * HildonSetPasswordDialog allows setting and changing a password. - * - * In Change mode: Dialog is used to change or remove an existing - * password. Unselecting the check box dims the password fields below - * it. If the dialog is accepted with 'OK' while the check box is - * unselected, a Confirmation Note is shown. If the Confirmation Note - * Dialog is accepted with 'Remove', the password protection is removed. - * - * In Set mode: Set Password Dialog is used to define a password, or - * change a password that cannot be removed. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#define _(String) dgettext(PACKAGE, String) -#define c_(String) dgettext("hildon-common-strings", String) - -static GtkDialogClass *parent_class; - -#define HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(obj)\ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_SET_PASSWORD_DIALOG, HildonSetPasswordDialogPrivate)); - -typedef struct -_HildonSetPasswordDialogPrivate HildonSetPasswordDialogPrivate; - -static void -hildon_set_password_dialog_class_init(HildonSetPasswordDialogClass * - class); -static void hildon_set_password_dialog_init(HildonSetPasswordDialog * - dialog); -static void hildon_checkbox_toggled(GtkWidget * widget, gpointer dialog); - -static void -hildon_set_password_response_change(GtkDialog * d, gint arg1, gpointer unused); -static void -hildon_set_password_response_set(GtkDialog * d, gint arg1, gpointer unused); - -static void create_contents(HildonSetPasswordDialog *dialog); -static void hildon_set_password_set_property(GObject * object, - guint prop_id, - const GValue * value, - GParamSpec * pspec); -static void hildon_set_password_get_property(GObject * object, - guint prop_id, GValue * value, - GParamSpec * pspec); - -/* Private struct */ -struct _HildonSetPasswordDialogPrivate { - GtkWidget *checkboxCaption; - GtkWidget *checkbox; - - GtkLabel *domainLabel; - - GtkWidget *pwd1stEntry; - GtkWidget *pwd1stCaption; - gchar *pwd1stCaption_string; - - GtkWidget *pwd2ndEntry; - GtkWidget *pwd2ndCaption; - gchar *pwd2ndCaption_string; - - GtkWidget *okButton; - GtkWidget *cancelButton; - - gboolean protection; -}; - -enum { - PROP_NONE = 0, - PROP_DOMAIN, - PROP_PASSWORD, - PROP_HILDON_PASSWORD_DIALOG -}; - -/* Private functions */ -static void -hildon_set_password_set_property(GObject * object, - guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - HildonSetPasswordDialog *dialog = HILDON_SET_PASSWORD_DIALOG(object); - HildonSetPasswordDialogPrivate *priv; - - priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(dialog); - - switch (prop_id) { - case PROP_DOMAIN: - /* Update domain label to display new value */ - gtk_label_set_text(priv->domainLabel, g_value_get_string(value)); - break; - case PROP_PASSWORD: - /* Update password entry to display new value */ - gtk_entry_set_text(GTK_ENTRY(priv->pwd1stEntry), g_value_get_string(value)); - break; - case PROP_HILDON_PASSWORD_DIALOG: - /* Note this is a G_PARAM_CONSTRUCT_ONLY type property */ - priv->protection = g_value_get_boolean(value); - - /* We now have the necessary information to populate the dialog */ - create_contents(dialog); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -hildon_set_password_get_property(GObject * object, - guint prop_id, - GValue * value, - GParamSpec * pspec) -{ - HildonSetPasswordDialogPrivate *priv = NULL; - - priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_DOMAIN: - g_value_set_string(value, gtk_label_get_text(priv->domainLabel)); - break; - case PROP_PASSWORD: - g_value_set_string(value, - gtk_entry_get_text(GTK_ENTRY(priv->pwd1stEntry))); - break; - case PROP_HILDON_PASSWORD_DIALOG: - g_value_set_boolean(value, priv->protection); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - - -static void -create_contents(HildonSetPasswordDialog *dialog) -{ - HildonSetPasswordDialogPrivate *priv = NULL; - - GtkSizeGroup *group; - - priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(dialog); - priv->checkbox = NULL; - - /* Size group for labels */ - group = GTK_SIZE_GROUP(gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL)); - - gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); - - /* Setup and pack domain label */ - priv->domainLabel = GTK_LABEL(gtk_label_new(NULL)); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), - GTK_WIDGET(priv->domainLabel), FALSE, FALSE, 0); - gtk_widget_show(GTK_WIDGET(priv->domainLabel)); - - if (priv->protection == TRUE) { - /* Use Change Password Dialog strings */ - priv->pwd1stCaption_string = _(HILDON_SET_MODIFY_PASSWORD_DIALOG_PASSWORD); - priv->pwd2ndCaption_string = _(HILDON_SET_MODIFY_PASSWORD_DIALOG_VERIFY_PASSWORD); - - /* Setup checkbox to enable/disable password protection */ - priv->checkbox = gtk_check_button_new(); - gtk_widget_show(priv->checkbox); - priv->checkboxCaption = hildon_caption_new - (group, - _(HILDON_SET_MODIFY_PASSWORD_DIALOG_LABEL), - priv->checkbox, - NULL, HILDON_CAPTION_OPTIONAL); - hildon_caption_set_separator(HILDON_CAPTION(priv->checkboxCaption), ""); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), - priv->checkboxCaption, TRUE, TRUE, 0); - gtk_widget_show(priv->checkboxCaption); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbox), - TRUE); - gtk_signal_connect(GTK_OBJECT(priv->checkbox), "toggled", - G_CALLBACK(hildon_checkbox_toggled), dialog); - - /* Setup appropriate response handler */ - g_signal_connect(G_OBJECT(dialog), "response", - G_CALLBACK(hildon_set_password_response_change), - NULL); - } else { - /* Use Set Password Dialog strings */ - priv->pwd1stCaption_string = _(HILDON_SET_PASSWORD_DIALOG_PASSWORD); - priv->pwd2ndCaption_string = _(HILDON_SET_PASSWORD_DIALOG_VERIFY_PASSWORD); - - /* Setup appropriate response handler */ - g_signal_connect(G_OBJECT(dialog), "response", - G_CALLBACK(hildon_set_password_response_set), - NULL); - } - - /* Create the password field */ - priv->pwd1stEntry = gtk_entry_new(); - g_object_set (priv->pwd1stEntry, "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL); - gtk_entry_set_visibility(GTK_ENTRY(priv->pwd1stEntry), FALSE); - gtk_widget_show(priv->pwd1stEntry); - priv->pwd1stCaption = hildon_caption_new(group, - priv->pwd1stCaption_string, - priv->pwd1stEntry, - NULL, HILDON_CAPTION_OPTIONAL); - hildon_caption_set_separator(HILDON_CAPTION(priv->pwd1stCaption), ""); - gtk_entry_set_visibility(GTK_ENTRY(priv->pwd1stEntry), FALSE); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), - priv->pwd1stCaption, TRUE, TRUE, 0); - gtk_widget_show(priv->pwd1stCaption); - - /* Create the password verify field */ - priv->pwd2ndEntry = gtk_entry_new(); - g_object_set (priv->pwd2ndEntry, "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL); - gtk_widget_show(priv->pwd2ndEntry); - priv->pwd2ndCaption = hildon_caption_new(group, - priv->pwd2ndCaption_string, - priv->pwd2ndEntry, - NULL, HILDON_CAPTION_OPTIONAL); - hildon_caption_set_separator(HILDON_CAPTION(priv->pwd2ndCaption), ""); - gtk_entry_set_visibility(GTK_ENTRY(priv->pwd2ndEntry), FALSE); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), - priv->pwd2ndCaption, TRUE, TRUE, 0); - gtk_widget_show(priv->pwd2ndCaption); - - /* Set dialog title */ - gtk_window_set_title(GTK_WINDOW(dialog), - _(priv->protection - ? HILDON_SET_MODIFY_PASSWORD_DIALOG_TITLE - : HILDON_SET_PASSWORD_DIALOG_TITLE)); - - /* Create the OK/CANCEL buttons */ - priv->okButton = gtk_dialog_add_button - (GTK_DIALOG(dialog), _(priv->protection - ? HILDON_SET_MODIFY_PASSWORD_DIALOG_OK - : HILDON_SET_PASSWORD_DIALOG_OK), - GTK_RESPONSE_OK); - priv->cancelButton = gtk_dialog_add_button - (GTK_DIALOG(dialog), _(priv->protection - ? HILDON_SET_MODIFY_PASSWORD_DIALOG_CANCEL - : HILDON_SET_PASSWORD_DIALOG_CANCEL), - GTK_RESPONSE_CANCEL); - - gtk_widget_show(priv->okButton); - gtk_widget_show(priv->cancelButton); - - /* Ensure group is freed when all its contents have been removed */ - g_object_unref(group); -} - -static void -hildon_set_password_dialog_class_init(HildonSetPasswordDialogClass * class) -{ - GObjectClass *object_class = G_OBJECT_CLASS(class); - - parent_class = g_type_class_peek_parent(class); - - /* Override virtual methods */ - object_class->set_property = hildon_set_password_set_property; - object_class->get_property = hildon_set_password_get_property; - - /* Install new properties */ - g_object_class_install_property(object_class, - PROP_DOMAIN, - g_param_spec_string ("domain", - "Domain", - "Set Domain (content) for domain label.", - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property(object_class, - PROP_HILDON_PASSWORD_DIALOG, - g_param_spec_boolean ("modify_protection", - "Password type", - "Set type to dialog", - TRUE, - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_READWRITE)); - - g_object_class_install_property(object_class, - PROP_PASSWORD, - g_param_spec_string ("password", - "Password content", - "Set content to dialog", - "DEFAULT", - G_PARAM_READWRITE)); - - /* Install private structure */ - g_type_class_add_private(class, - sizeof(HildonSetPasswordDialogPrivate)); -} - -static void -hildon_set_password_dialog_init(HildonSetPasswordDialog * dialog) -{ - /* Most of the initializations are done in create_contents() - after the 'modify_protection' property has been set */ - - gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); -} - - -/* We come here when response button is clicked and dialog - is used to change existing password. */ -static void -hildon_set_password_response_change(GtkDialog * dialog, gint arg1, - gpointer unused) -{ - GtkEntry *pwd1stEntry; - GtkEntry *pwd2ndEntry; - gchar *text1; - gchar *text2; - HildonNote *note; - gint i; - HildonSetPasswordDialogPrivate *priv; - - priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(dialog); - - /* Password and verification */ - pwd1stEntry = GTK_ENTRY(gtk_bin_get_child - (GTK_BIN(priv->pwd1stCaption))); - pwd2ndEntry = GTK_ENTRY(gtk_bin_get_child - (GTK_BIN(priv->pwd2ndCaption))); - text1 = GTK_ENTRY(pwd1stEntry)->text; - text2 = GTK_ENTRY(pwd2ndEntry)->text; - - /* User accepted the dialog */ - if (arg1 == GTK_RESPONSE_OK){ - /* Is the checkbox marked, so password protection is still in use? */ - if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->checkbox))){ - /* Yes, Something is given as password as well? */ - if (text1[0] != '\0') { - if (strcmp (text1, text2) == 0) { - /* Passwords match, so accept change password */ - priv->protection = TRUE; - } else if (text2[0] == '\0') { - /* Second field is empty, so show error, but don't clear fields */ - g_signal_stop_emission_by_name(G_OBJECT(dialog), - "response"); - gtk_infoprint (NULL, - c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH)); - gtk_widget_grab_focus(GTK_WIDGET(pwd2ndEntry)); - } else { - /* Error: Passwords don't match, so start over */ - g_signal_stop_emission_by_name(G_OBJECT(dialog), - "response"); - gtk_entry_set_text(pwd1stEntry, ""); - gtk_entry_set_text(pwd2ndEntry, ""); - gtk_infoprint (NULL, - c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH)); - gtk_widget_grab_focus(GTK_WIDGET(pwd1stEntry)); - } - } else { - /* No, the password is empty */ - g_signal_stop_emission_by_name(G_OBJECT(dialog), "response"); - if (text2[0] == '\0') { - /* Error: Both fields are empty */ - gtk_infoprint (NULL, c_(HILDON_SET_PASSWORD_DIALOG_EMPTY)); - } else { - /* Error: Second field doesn't match - the empty first field, so start over */ - gtk_infoprint (NULL, c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH)); - gtk_entry_set_text(pwd2ndEntry, ""); - } - gtk_widget_grab_focus(GTK_WIDGET(pwd1stEntry)); - } - } else { - /* No, user wants to remove password protection. - Confirm remove password protection */ - note = HILDON_NOTE(hildon_note_new_confirmation - (GTK_WINDOW(dialog), - c_(HILDON_SET_PASSWORD_DIALOG_REMOVE_PROTECTION - ))); - - hildon_note_set_button_texts - (HILDON_NOTE(note), - c_(HILDON_REMOVE_PROTECTION_CONFIRMATION_REMOVE), - c_(HILDON_REMOVE_PROTECTION_CONFIRMATION_CANCEL)); - - /* Display confirmation note */ - i = gtk_dialog_run(GTK_DIALOG(note)); - - gtk_widget_destroy(GTK_WIDGET(note)); - - if (i == GTK_RESPONSE_OK) - /* Remove password protection */ - priv->protection = FALSE; - else { - /* Remove password protection cancelled */ - priv->protection = TRUE; - g_signal_stop_emission_by_name(G_OBJECT(dialog), "response"); - } - } - - } else { - /* Watch out for fading boolean values */ - priv->protection = TRUE; - } -} - -/* We come here when response button is clicked and dialog - is used to set new password. */ -static void -hildon_set_password_response_set(GtkDialog * dialog, gint arg1, - gpointer unused) -{ - GtkEntry *pwd1stEntry; - GtkEntry *pwd2ndEntry; - gchar *text1; - gchar *text2; - - HildonSetPasswordDialogPrivate *priv; - - priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(dialog); - - /* Password and confirmation */ - pwd1stEntry = GTK_ENTRY(gtk_bin_get_child - (GTK_BIN(priv->pwd1stCaption))); - pwd2ndEntry = GTK_ENTRY(gtk_bin_get_child - (GTK_BIN(priv->pwd2ndCaption))); - text1 = GTK_ENTRY(pwd1stEntry)->text; - text2 = GTK_ENTRY(pwd2ndEntry)->text; - - if (arg1 == GTK_RESPONSE_OK) { - /* User provided something for password? */ - if (text1[0] != '\0') { - if (strcmp (text1, text2) == 0) { - /* Passwords match, so accept set password */ - priv->protection = TRUE; - } else if (text2[0] == '\0') { - /* Second field is empty, so show error, - but don't clear the fields */ - g_signal_stop_emission_by_name(G_OBJECT(dialog), "response"); - gtk_infoprint (NULL, c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH)); - gtk_widget_grab_focus (GTK_WIDGET (priv->pwd2ndEntry)); - } else { - /* Error: Passwords don't match, so start over */ - g_signal_stop_emission_by_name(G_OBJECT(dialog), "response"); - gtk_entry_set_text(pwd1stEntry, ""); - gtk_entry_set_text(pwd2ndEntry, ""); - gtk_infoprint (NULL, c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH)); - gtk_widget_grab_focus(GTK_WIDGET(priv->pwd1stEntry)); - } - } else { - /* First field is empty */ - g_signal_stop_emission_by_name(G_OBJECT(dialog), "response"); - if (text2[0] == '\0') { - /* Error: Both fields are empty */ - gtk_infoprint (NULL, c_(HILDON_SET_PASSWORD_DIALOG_EMPTY)); - } else { - /* Error: Second field doesn't match - the empty first field, so start over */ - gtk_infoprint (NULL, c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH)); - gtk_entry_set_text(pwd2ndEntry, ""); - } - gtk_widget_grab_focus(GTK_WIDGET(pwd1stEntry)); - } - } else { - /* Watch out for fading boolean values */ - priv->protection = FALSE; - } -} - -static void hildon_checkbox_toggled(GtkWidget * widget, gpointer dialog) -{ - HildonSetPasswordDialogPrivate *priv = - HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(dialog); - gboolean active; - - /* If the user enabled/disabled the password protection feature - we enable/disable password entries accordingly */ - active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); - gtk_widget_set_sensitive(GTK_WIDGET(priv->pwd1stEntry), active); - gtk_widget_set_sensitive(GTK_WIDGET(priv->pwd2ndEntry), active); -} - -/* Public functions */ - -/** - * hildon_set_password_dialog_get_type: - * - * Returns GType for HildonPasswordDialog as produced by - * g_type_register_static(). - * - * Returns: HildonSetPasswordDialog type - */ -GType hildon_set_password_dialog_get_type(void) -{ - static GType dialog_type = 0; - - if (!dialog_type) { - static const GTypeInfo dialog_info = { - sizeof(HildonSetPasswordDialogClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_set_password_dialog_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonSetPasswordDialog), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_set_password_dialog_init - }; - - dialog_type = g_type_register_static(GTK_TYPE_DIALOG, - "HildonSetPasswordDialog", - &dialog_info, 0); - } - return dialog_type; -} - -/** - * hildon_set_password_dialog_new: - * @parent: parent window; can be NULL - * @modify_protection: TRUE creates a new change password dialog and FALSE - * creates a new set password dialog - * - * Constructs a new HildonSetPasswordDialog. - * - * Returns: a new #GtkWidget of type HildonSetPasswordDialog - */ - -GtkWidget *hildon_set_password_dialog_new(GtkWindow * parent, - gboolean modify_protection) -{ - return hildon_set_password_dialog_new_with_default(parent, "", - modify_protection); -} - -/** - * hildon_set_password_dialog_new_with_default: - * @parent: parent window; can be NULL - * @password: a default password to be shown in password field - * @modify_protection: TRUE creates a new change password dialog and FALSE - * creates a new set password dialog - * - * Same as #hildon_set_password_dialog_new, but with a default password - * in password field. - * - * Returns: a new #GtkWidget of type HildonSetPasswordDialog - */ - -GtkWidget *hildon_set_password_dialog_new_with_default - (GtkWindow *parent, - const gchar *password, - gboolean modify_protection) -{ - GtkWidget *dialog = g_object_new(HILDON_TYPE_SET_PASSWORD_DIALOG, - "modify_protection", modify_protection, - "password", password, NULL); - - if (parent != NULL) { - gtk_window_set_transient_for(GTK_WINDOW(dialog), parent); - } - - return dialog; -} - -/** - * hildon_set_password_dialog_get_password: - * @dialog: pointer to HildonSetPasswordDialog - * - * Returns current password. - * - * Returns: changed password ( if the dialog is successfully - * accepted with 'OK' ( and when the check box is 'ON' ( in Change Password - * Dialog )) - */ -const gchar - *hildon_set_password_dialog_get_password(HildonSetPasswordDialog * - dialog) -{ - HildonSetPasswordDialogPrivate *priv; - - g_return_val_if_fail(HILDON_IS_SET_PASSWORD_DIALOG(dialog), NULL); - - priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(dialog); - - return GTK_ENTRY(priv->pwd1stEntry)->text; -} - -/** - * hildon_set_password_dialog_get_protected: - * @dialog: pointer to HildonSetPasswordDialog - * - * Returns the protection mode. - * - * Returns: password protection mode ( TRUE when the protection is - * 'ON' and FALSE when the protection is 'OFF' ) - */ -gboolean -hildon_set_password_dialog_get_protected(HildonSetPasswordDialog * dialog) -{ - HildonSetPasswordDialogPrivate *priv; - - g_return_val_if_fail(HILDON_IS_SET_PASSWORD_DIALOG(dialog), FALSE); - - priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(dialog); - - return priv->protection; -} - -/** - * hildon_set_password_dialog_set_domain(GtkWidget *dialog, - * @dialog: the dialog - * @domain: the domain or some other descriptive text to be set - * - * Sets the optional descriptive text. - */ - -void hildon_set_password_dialog_set_domain(HildonSetPasswordDialog *dialog, - const gchar *domain) -{ - HildonSetPasswordDialogPrivate *priv = NULL; - - g_return_if_fail(HILDON_IS_SET_PASSWORD_DIALOG(dialog)); - - priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(dialog); - gtk_label_set_text(priv->domainLabel, domain); -} diff --git a/hildon-widgets/hildon-set-password-dialog.h b/hildon-widgets/hildon-set-password-dialog.h deleted file mode 100644 index 3e019f6..0000000 --- a/hildon-widgets/hildon-set-password-dialog.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_SET_PASSWORD_DIALOG_H__ -#define __HILDON_SET_PASSWORD_DIALOG_H__ - -#include - -G_BEGIN_DECLS - - -#define HILDON_TYPE_SET_PASSWORD_DIALOG \ - ( hildon_set_password_dialog_get_type() ) -#define HILDON_SET_PASSWORD_DIALOG(obj) \ - (GTK_CHECK_CAST (obj, HILDON_TYPE_SET_PASSWORD_DIALOG,\ - HildonSetPasswordDialog)) -#define HILDON_SET_PASSWORD_DIALOG_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), HILDON_TYPE_SET_PASSWORD_DIALOG, \ - HildonSetPasswordDialogClass)) -#define HILDON_IS_SET_PASSWORD_DIALOG(obj) \ - (GTK_CHECK_TYPE (obj, HILDON_TYPE_SET_PASSWORD_DIALOG)) -#define HILDON_IS_SET_PASSWORD_DIALOG_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_SET_PASSWORD_DIALOG)) - - - -#define HILDON_SET_PASSWORD_DIALOG_TITLE "ecdg_ti_set_password" -#define HILDON_SET_PASSWORD_DIALOG_PASSWORD "ecdg_fi_set_passwd_enter_pwd" -#define HILDON_SET_PASSWORD_DIALOG_VERIFY_PASSWORD "ecdg_fi_set_passwd_confirm" -#define HILDON_SET_PASSWORD_DIALOG_OK "ecdg_bd_set_password_dialog_ok" -#define HILDON_SET_PASSWORD_DIALOG_CANCEL "ecdg_bd_set_password_dialog_cancel" - -#define HILDON_SET_MODIFY_PASSWORD_DIALOG_TITLE "ckdg_ti_dialog_c_passwd_change_password" -#define HILDON_SET_MODIFY_PASSWORD_DIALOG_LABEL "ckdg_fi_dialog_c_passwd_pwd_protect" -#define HILDON_SET_MODIFY_PASSWORD_DIALOG_PASSWORD "ckdg_fi_dialog_c_passwd_new_pwd" -#define HILDON_SET_MODIFY_PASSWORD_DIALOG_VERIFY_PASSWORD "ckdg_fi_dialog_c_passwd_ver_pwd" -#define HILDON_SET_MODIFY_PASSWORD_DIALOG_OK "ckdg_bd_change_password_dialog_ok" -#define HILDON_SET_MODIFY_PASSWORD_DIALOG_CANCEL "ckdg_bd_change_password_dialog_cancel" - -#define HILDON_SET_PASSWORD_DIALOG_MISMATCH "ecdg_ib_passwords_do_not_match" -#define HILDON_SET_PASSWORD_DIALOG_EMPTY "ecdg_ib_password_is_empty" -#define HILDON_SET_PASSWORD_DIALOG_REMOVE_PROTECTION "ckdg_nc_dialog_c_passwd_remove_pwd" - -#define HILDON_REMOVE_PROTECTION_CONFIRMATION_REMOVE "ckdg_bd_dialog_c_passwd_remove_button" -#define HILDON_REMOVE_PROTECTION_CONFIRMATION_CANCEL "ckdg_bd_dialog_c_passwd_cancel_button" - - - -typedef struct _HildonSetPasswordDialog HildonSetPasswordDialog; -typedef struct _HildonSetPasswordDialogClass HildonSetPasswordDialogClass; - -struct _HildonSetPasswordDialog { - GtkDialog parent; -}; - -struct _HildonSetPasswordDialogClass { - GtkDialogClass parent_class; -}; - - - -GtkWidget * hildon_set_password_dialog_new (GtkWindow *parent, - gboolean modify_protection); - -GtkWidget * hildon_set_password_dialog_new_with_default (GtkWindow *parent, - const gchar *password, - gboolean modify_protection); - -GType hildon_set_password_dialog_get_type (void) G_GNUC_CONST; - -const gchar *hildon_set_password_dialog_get_password (HildonSetPasswordDialog *dialog); - -gboolean hildon_set_password_dialog_get_protected (HildonSetPasswordDialog *dialog); - -void hildon_set_password_dialog_set_domain (HildonSetPasswordDialog *dialog, - const gchar *domain); - - -G_END_DECLS - -#endif /* __HILDON_SET_PASSWORD_DIALOG_H__ */ diff --git a/hildon-widgets/hildon-sort-dialog.c b/hildon-widgets/hildon-sort-dialog.c deleted file mode 100644 index 2c28552..0000000 --- a/hildon-widgets/hildon-sort-dialog.c +++ /dev/null @@ -1,495 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-sort-dialog - * @short_description: A widget for defining the sorting order of items - * - * HildonSortDialog is used to define an order (ascending/descending) - * and a field by which items are sorted in a list. The combo boxes - * display the current value when the dialog is opened. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include "hildon-sort-dialog.h" - - -#define _(String) dgettext(PACKAGE, String) - -static GtkDialogClass *parent_class; - -#define HILDON_SORT_DIALOG_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), HILDON_TYPE_SORT_DIALOG, HildonSortDialogPrivate)); - -typedef struct _HildonSortDialogPrivate HildonSortDialogPrivate; - -static void hildon_sort_dialog_class_init(HildonSortDialogClass * class); -static void hildon_sort_dialog_init(HildonSortDialog * widget); -static void hildon_sort_dialog_set_property(GObject * object, - guint prop_id, - const GValue * value, - GParamSpec * pspec); -static void hildon_sort_dialog_get_property(GObject * object, - guint prop_id, - GValue * value, GParamSpec * pspec); -static void reconstruct_combo (HildonSortDialog * dialog, - gboolean remove, - gboolean reversed); -static gint hildon_sort_dialog_add_sort_key_with_sorting(HildonSortDialog * dialog, - const gchar * sort_key, - gboolean sorting); -static void sort_key_changed(GtkWidget * widget, - HildonSortDialog * dialog); -static void hildon_sort_dialog_finalize(GObject * object); - -enum { - PROP_0, - PROP_SORT_KEY, - PROP_SORT_ORDER -}; - -/* private data */ -struct _HildonSortDialogPrivate { - /* Sort category widgets */ - GtkWidget *combo_key; - GtkWidget *caption_key; - - /* Sort order widgets */ - GtkWidget *combo_order; - GtkWidget *caption_order; - - /* Index value counter */ - gint index_counter; - - /* If the current order displayed is reversed */ - gboolean reversed; - - /* An array for each key representing if a key should be reverse-sorted */ - gboolean *key_reversed; -}; - -/* Private functions */ - -static void sort_key_changed(GtkWidget * widget, HildonSortDialog * dialog) -{ - g_return_if_fail(HILDON_IS_SORT_DIALOG(dialog)); - - HildonSortDialogPrivate *priv = HILDON_SORT_DIALOG_GET_PRIVATE(dialog); - - gint index = gtk_combo_box_get_active(GTK_COMBO_BOX(widget)); - - if (priv->key_reversed [index] != priv->reversed) { - reconstruct_combo (dialog, TRUE, priv->key_reversed [index]); - gtk_combo_box_set_active(GTK_COMBO_BOX(priv->combo_order), 0); - } - - priv->reversed = priv->key_reversed [index]; -} - -/* - * Initialises the sort dialog class. - */ -static void hildon_sort_dialog_class_init(HildonSortDialogClass * class) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(class); - parent_class = g_type_class_peek_parent(class); - g_type_class_add_private(class, sizeof(HildonSortDialogPrivate)); - - gobject_class->set_property = hildon_sort_dialog_set_property; - gobject_class->get_property = hildon_sort_dialog_get_property; - gobject_class->finalize = (gpointer) hildon_sort_dialog_finalize; - - g_object_class_install_property(gobject_class, PROP_SORT_KEY, - g_param_spec_int("sort-key", - "Sort Key", - "The currently active sort key", - G_MININT, - G_MAXINT, - 0, G_PARAM_READWRITE)); - - g_object_class_install_property(gobject_class, PROP_SORT_ORDER, - g_param_spec_enum("sort-order", - "Sort Order", - "The current sorting order", - GTK_TYPE_SORT_TYPE, - GTK_SORT_ASCENDING, - G_PARAM_READWRITE)); -} - -static gint hildon_sort_dialog_add_sort_key_with_sorting(HildonSortDialog * dialog, const gchar * sort_key, gboolean sorting) -{ - HildonSortDialogPrivate *priv; - - g_return_val_if_fail(HILDON_IS_SORT_DIALOG(dialog), -1); - - priv = HILDON_SORT_DIALOG_GET_PRIVATE(dialog); - gboolean *new_array = g_malloc (sizeof (gboolean) * (priv->index_counter + 1)); - - /* Rewrite the old values */ - int i = 0; - for (i = 0; i < priv->index_counter; i++) - new_array [i] = priv->key_reversed [i]; - - new_array [priv->index_counter] = sorting; - gtk_combo_box_append_text(GTK_COMBO_BOX(priv->combo_key), sort_key); - - /* Free the old one and reassign */ - if (priv->key_reversed != NULL) - g_free (priv->key_reversed); - priv->key_reversed = new_array; - - return priv->index_counter++; -} - -static void reconstruct_combo (HildonSortDialog * dialog, gboolean remove, gboolean reversed) -{ - HildonSortDialogPrivate *priv; - priv = HILDON_SORT_DIALOG_GET_PRIVATE(dialog); - - if (remove) { - gtk_combo_box_remove_text(GTK_COMBO_BOX(priv->combo_order), 1); - gtk_combo_box_remove_text(GTK_COMBO_BOX(priv->combo_order), 0); - } - - if (reversed) { - gtk_combo_box_append_text(GTK_COMBO_BOX(priv->combo_order), _("ckdg_va_sort_descending")); - gtk_combo_box_append_text(GTK_COMBO_BOX(priv->combo_order), _("ckdg_va_sort_ascending")); - } else { - gtk_combo_box_append_text(GTK_COMBO_BOX(priv->combo_order), _("ckdg_va_sort_ascending")); - gtk_combo_box_append_text(GTK_COMBO_BOX(priv->combo_order), _("ckdg_va_sort_descending")); - } -} - -static void hildon_sort_dialog_init(HildonSortDialog * dialog) -{ - HildonSortDialogPrivate *priv; - GtkSizeGroup *group; - - g_assert(HILDON_IS_SORT_DIALOG(dialog)); - - priv = HILDON_SORT_DIALOG_GET_PRIVATE(dialog); - - priv->index_counter = 0; - priv->reversed = FALSE; - priv->key_reversed = NULL; - - group = GTK_SIZE_GROUP(gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL)); - - gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); - gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); - gtk_window_set_title(GTK_WINDOW(dialog), _("ckdg_ti_sort")); - - /* Tab one */ - priv->combo_key = gtk_combo_box_new_text(); - priv->caption_key = hildon_caption_new(group, _("ckdg_fi_sort_field"), priv->combo_key, - NULL, HILDON_CAPTION_OPTIONAL); - hildon_caption_set_separator(HILDON_CAPTION(priv->caption_key), ""); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), - priv->caption_key, FALSE, FALSE, 0); - - /* Tab two */ - priv->combo_order = gtk_combo_box_new_text(); - reconstruct_combo (dialog, FALSE, FALSE); - - priv->caption_order = hildon_caption_new(group, _("ckdg_fi_sort_order"), - priv->combo_order, - NULL, HILDON_CAPTION_OPTIONAL); - hildon_caption_set_separator(HILDON_CAPTION(priv->caption_order), ""); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), - priv->caption_order, FALSE, FALSE, 0); - - gtk_combo_box_set_active(GTK_COMBO_BOX(priv->combo_key), 0); - gtk_combo_box_set_active(GTK_COMBO_BOX(priv->combo_order), 0); - g_signal_connect (G_OBJECT (priv->combo_key), "changed", (gpointer) sort_key_changed, dialog); - - /* Create the OK/CANCEL buttons */ - (void) gtk_dialog_add_button(GTK_DIALOG(dialog), - _("ckdg_bd_sort_dialog_ok"), - GTK_RESPONSE_OK); - (void) gtk_dialog_add_button(GTK_DIALOG(dialog), - _("ckdg_bd_sort_dialog_cancel"), - GTK_RESPONSE_CANCEL); - /* FIXME: Hardcoded sizes are bad */ - gtk_window_resize(GTK_WINDOW(dialog), 370, 100); - gtk_widget_show_all(GTK_DIALOG(dialog)->vbox); - - g_object_unref(group); /* Captions now own their references to sizegroup */ -} - -/* Public functions */ - -/** - * hildon_sort_dialog_get_type: - * - * Returns GType for HildonSortDialog as produced by - * g_type_register_static(). - * - * Returns: HildonSortDialog type - */ -GType hildon_sort_dialog_get_type() -{ - static GType dialog_type = 0; - - if (!dialog_type) { - static const GTypeInfo dialog_info = { - sizeof(HildonSortDialogClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_sort_dialog_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonSortDialog), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_sort_dialog_init - }; - - dialog_type = g_type_register_static(GTK_TYPE_DIALOG, - "HildonSortDialog", - &dialog_info, 0); - } - return dialog_type; -} - -/** - * hildon_sort_dialog_new: - * @parent: widget to be transient for, or NULL if none - * - * HildonSortDialog contains two HildonCaptions with combo boxes. - * - * Returns: pointer to a new @HildonSortDialog widget - */ -GtkWidget *hildon_sort_dialog_new(GtkWindow * parent) -{ - GtkWidget *sort_dialog = g_object_new(HILDON_TYPE_SORT_DIALOG, NULL); - - if (parent) - gtk_window_set_transient_for(GTK_WINDOW(sort_dialog), parent); - - return sort_dialog; -} - -/** - * hildon_sort_dialog_get_sort_key: - * @dialog: the #HildonSortDialog widget - * - * Gets index to currently active sort key. - * - * Returns: an integer which is the index value of the "Sort by" - * field - */ -gint hildon_sort_dialog_get_sort_key(HildonSortDialog * dialog) -{ - GtkWidget *combo_key; - HildonSortDialogPrivate *priv; - - g_return_val_if_fail(HILDON_IS_SORT_DIALOG(dialog), -1); - - priv = HILDON_SORT_DIALOG_GET_PRIVATE(dialog); - - combo_key = gtk_bin_get_child(GTK_BIN(priv->caption_key)); - - return gtk_combo_box_get_active(GTK_COMBO_BOX(combo_key)); -} - -/** - * hildon_sort_dialog_get_sort_order: - * @dialog: the #HildonSortDialog widget - * - * Gets current sorting order from "Sort order" field. - * - * Returns: current sorting order as #GtkSortType - */ -GtkSortType hildon_sort_dialog_get_sort_order(HildonSortDialog * dialog) -{ - GtkWidget *combo_order; - HildonSortDialogPrivate *priv; - - g_return_val_if_fail(HILDON_IS_SORT_DIALOG(dialog), 0); - - priv = HILDON_SORT_DIALOG_GET_PRIVATE(dialog); - combo_order = gtk_bin_get_child(GTK_BIN(priv->caption_order)); - - gint sort_order = gtk_combo_box_get_active(GTK_COMBO_BOX(combo_order)); - - if (priv->reversed) - return (sort_order == 0) ? 1 : 0; - else - return sort_order; -} - -/** - * hildon_sort_dialog_set_sort_key: - * @dialog: the #HildonSortDialog widget - * @key: combo box's index value - * - * Sets the index value of the #HildonSortDialog widget. - */ -void hildon_sort_dialog_set_sort_key(HildonSortDialog * dialog, gint key) -{ - GtkWidget *combo_key; - HildonSortDialogPrivate *priv; - - g_return_if_fail(HILDON_IS_SORT_DIALOG(dialog)); - - priv = HILDON_SORT_DIALOG_GET_PRIVATE(dialog); - combo_key = gtk_bin_get_child(GTK_BIN(priv->caption_key)); - gtk_combo_box_set_active(GTK_COMBO_BOX(combo_key), key); - - g_object_notify (G_OBJECT (dialog), "sort-key"); -} - -/** - * hildon_sort_dialog_set_sort_order: - * @dialog: the #HildonSortDialog widget - * @order: combo box's index value - * - * Sets the index value of the #HildonSortDialog widget. - */ -void -hildon_sort_dialog_set_sort_order(HildonSortDialog * dialog, - GtkSortType order) -{ - GtkWidget *combo_order; - HildonSortDialogPrivate *priv; - - g_return_if_fail(HILDON_IS_SORT_DIALOG(dialog)); - - priv = HILDON_SORT_DIALOG_GET_PRIVATE(dialog); - combo_order = gtk_bin_get_child(GTK_BIN(priv->caption_order)); - - if (priv->reversed) - order = (order == 0) ? 1 : 0; - - gtk_combo_box_set_active(GTK_COMBO_BOX(combo_order), order); - - g_object_notify (G_OBJECT (dialog), "sort-order"); -} - -/** - * hildon_sort_dialog_add_sort_key: - * @dialog: the #HildonSortDialog widget - * @sort_key: combo box's index value - * - * Adds a new sort key and returns the respective index in - * sort key combobox. - * - * Returns: an integer which is the index of the added combo box's - * item - */ -gint -hildon_sort_dialog_add_sort_key(HildonSortDialog * dialog, - const gchar * sort_key) -{ - return hildon_sort_dialog_add_sort_key_with_sorting (dialog, sort_key, FALSE); -} - -/** - * hildon_sort_dialog_add_sort_key_reversed: - * @dialog: the #HildonSortDialog widget - * @sort_key: combo box's index value - * - * Adds a new sort key and returns the respective index in - * sort key combobox. The default sort order for this key is reversed (Descending first). - * - * Returns: an integer which is the index of the added combo box's - * item - * - * Since: 0.14.1 - */ -gint -hildon_sort_dialog_add_sort_key_reversed(HildonSortDialog * dialog, - const gchar * sort_key) -{ - return hildon_sort_dialog_add_sort_key_with_sorting (dialog, sort_key, TRUE); -} - -static void -hildon_sort_dialog_set_property(GObject * object, - guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - HildonSortDialog *dialog; - - dialog = HILDON_SORT_DIALOG(object); - - switch (prop_id) { - case PROP_SORT_KEY: - hildon_sort_dialog_set_sort_key(dialog, g_value_get_int(value)); - break; - case PROP_SORT_ORDER: - hildon_sort_dialog_set_sort_order(dialog, g_value_get_enum(value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -hildon_sort_dialog_get_property(GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec) -{ - HildonSortDialog *dialog; - - dialog = HILDON_SORT_DIALOG(object); - - switch (prop_id) { - case PROP_SORT_KEY: - g_value_set_int(value, hildon_sort_dialog_get_sort_key(dialog)); - break; - case PROP_SORT_ORDER: - g_value_set_enum(value, hildon_sort_dialog_get_sort_order(dialog)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -hildon_sort_dialog_finalize(GObject * object) -{ - HildonSortDialogPrivate *priv; - HildonSortDialog *dialog; - - g_return_if_fail (HILDON_IS_SORT_DIALOG (object)); - dialog = HILDON_SORT_DIALOG(object); - - priv = HILDON_SORT_DIALOG_GET_PRIVATE(dialog); - if (priv != NULL && priv->key_reversed != NULL) - g_free(priv->key_reversed); - - if (G_OBJECT_CLASS(parent_class)->finalize) - G_OBJECT_CLASS(parent_class)->finalize(object); -} - - diff --git a/hildon-widgets/hildon-sort-dialog.h b/hildon-widgets/hildon-sort-dialog.h deleted file mode 100644 index 5ef6bcf..0000000 --- a/hildon-widgets/hildon-sort-dialog.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_SORT_DIALOG_H__ -#define __HILDON_SORT_DIALOG_H__ - -#include - -G_BEGIN_DECLS -#define HILDON_TYPE_SORT_DIALOG \ - ( hildon_sort_dialog_get_type() ) -#define HILDON_SORT_DIALOG(obj) \ - (GTK_CHECK_CAST (obj, HILDON_TYPE_SORT_DIALOG, HildonSortDialog)) -#define HILDON_SORT_DIALOG_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), HILDON_TYPE_SORT_DIALOG, \ - HildonSortDialogClass)) -#define HILDON_IS_SORT_DIALOG(obj) \ - (GTK_CHECK_TYPE (obj, HILDON_TYPE_SORT_DIALOG)) -#define HILDON_IS_SORT_DIALOG_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_SORT_DIALOG)) -typedef struct _HildonSortDialog HildonSortDialog; -typedef struct _HildonSortDialogClass HildonSortDialogClass; - - - -struct _HildonSortDialog { - GtkDialog parent; -}; - -struct _HildonSortDialogClass { - GtkDialogClass parent_class; -}; - -GType hildon_sort_dialog_get_type(void) G_GNUC_CONST; - - -GtkWidget *hildon_sort_dialog_new(GtkWindow * parent); -gint hildon_sort_dialog_get_sort_key(HildonSortDialog * dialog); -GtkSortType hildon_sort_dialog_get_sort_order(HildonSortDialog * dialog); -void hildon_sort_dialog_set_sort_key(HildonSortDialog * dialog, gint key); -void hildon_sort_dialog_set_sort_order(HildonSortDialog * dialog, - GtkSortType order); -gint hildon_sort_dialog_add_sort_key(HildonSortDialog * dialog, - const gchar * sort_key); - -G_END_DECLS -#endif /* __HILDON_SORT_DIALOG_H__ */ diff --git a/hildon-widgets/hildon-system-sound.c b/hildon-widgets/hildon-system-sound.c deleted file mode 100644 index 38d29fd..0000000 --- a/hildon-widgets/hildon-system-sound.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-system-sound - * @short_description: An esd-based utility function for playing a sound - * - * HildonSystemSound is an esd-based utility function for playing a sound - * from the system sounds directory with volume taken from GConf. - */ - -#include -#include -#include "hildon-system-sound.h" - -#define ALARM_GCONF_PATH "/apps/osso/sound/system_alert_volume" - -/** - * hildon_play_system_sound: - * @sample: sound file to play - * - * Plays the given sample using esd sound daemon. - * Volume level is received from gconf. - */ -void hildon_play_system_sound(const gchar *sample) -{ - GConfClient *client; - GConfValue *value; - gint volume, scale, sock, sample_id; - - client = gconf_client_get_default(); - value = gconf_client_get(client, ALARM_GCONF_PATH, NULL); - - /* We want error cases to match full volume, not silence, so - we do not want to use gconf_client_get_int */ - if (!value || value->type != GCONF_VALUE_INT) - volume = 2; - else - volume = gconf_value_get_int(value); - - if (value) - gconf_value_free(value); - g_object_unref(client); - - switch (volume) - { - case 0: - return; - case 1: - scale = 0x80; - break; - case 2: - default: - scale = 0xff; - break; - }; - - sock = esd_open_sound(NULL); - if (sock <= 0) - return; - - sample_id = esd_file_cache(sock, g_get_prgname(), sample); - if (sample_id < 0) { - close(sock); - return; - } - - esd_set_default_sample_pan(sock, sample_id, scale, scale); - esd_sample_play(sock, sample_id); - esd_sample_free(sock, sample_id); - close(sock); -} diff --git a/hildon-widgets/hildon-system-sound.h b/hildon-widgets/hildon-system-sound.h deleted file mode 100644 index 666a8bb..0000000 --- a/hildon-widgets/hildon-system-sound.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ -#ifndef __HILDON_SYSTEM_SOUND_H__ -#define __HILDON_SYSTEM_SOUND_H__ - -G_BEGIN_DECLS - -void hildon_play_system_sound(const gchar *sample); - -G_END_DECLS -#endif /* __HILDON_SYSTEM_SOUND_H__ */ diff --git a/hildon-widgets/hildon-telephone-editor.c b/hildon-widgets/hildon-telephone-editor.c deleted file mode 100644 index a18acad..0000000 --- a/hildon-widgets/hildon-telephone-editor.c +++ /dev/null @@ -1,1436 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-telephone-editor.c - * @short_description: A widget which allows users to enter telephone numbers - * - * A single-line editor which allows user to enter a telephone number. - * There are two modes to choose from (coerce/free format). - * Coerce format has three fields which are placed horizontally. - * The fields are: country code, area code and number. When nothing is - * entered in the fields, assisting text is displayed. Tapping on the - * field highlights the field and allows users to input numbers. - * - * The widget is used where a user should enter a phone number. Free format - * should be used wherever possible as it enables the user to enter the - * phone number in the format she likes. Free format also supports DTMF - * strings as a part of the phone number. The format can not be changed - * at runtime. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include "hildon-telephone-editor.h" -#include "hildon-composite-widget.h" - -#define _(String) gettext (String) -#define HILDON_TELEPHONE_EDITOR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TELEPHONE_EDITOR_TYPE, HildonTelephoneEditorPriv)); - -#define AREA_LEN 4 -#define COUNTRY_LEN 7 -#define NUMBER_LEN 10 - -#define AREA_STR "Area" -#define COUNTRY_STR "Country" -#define NUMBER_STR "Number" - -typedef struct _HildonTelephoneEditorPriv HildonTelephoneEditorPriv; - -enum { - PROP_0, - PROP_COUNTRY_STR, - PROP_AREA_STR, - PROP_NUMBER_STR, - PROP_SHOW_BORDER, - PROP_SHOW_PLUS, - PROP_FORMAT -}; - -/*< private >*/ -struct _HildonTelephoneEditorPriv { - HildonTelephoneEditorFormat format; /* format of the editor */ - - gboolean edited_country; /* is the country edited */ - gboolean edited_area; /* is the area edited */ - gboolean edited_number; /* is the number edited */ - - gboolean editable_country; /* is the country editable */ - gboolean editable_area; /* is the area editable */ - gboolean editable_number; /* is the number editable */ - - gboolean show_plus; /* show '+' sign in country */ - gboolean show_border; /* show border around the widget */ - - GtkWidget *frame; /* frame for border lines */ - GtkWidget *plus; /* + in front of country code */ - GtkWidget *plus_event; /* event box for the + -label */ - GtkWidget *country; /* country code */ - GtkWidget *area; /* area code */ - GtkWidget *number; /* telephone number */ - - gint j; -}; - - -static GtkContainerClass *parent_class; - -static void -hildon_telephone_editor_class_init(HildonTelephoneEditorClass * - editor_class); - -static void -hildon_telephone_editor_init(HildonTelephoneEditor * editor); - -static void -hildon_telephone_editor_forall(GtkContainer * container, - gboolean include_internals, - GtkCallback callback, - gpointer callback_data); -static void -hildon_telephone_editor_destroy(GtkObject * self); - -static void -hildon_telephone_editor_size_allocate(GtkWidget * widget, - GtkAllocation * allocation); - -static void -hildon_telephone_editor_size_request(GtkWidget * widget, - GtkRequisition * requisition); - -static gboolean -hildon_telephone_editor_button_release(GtkWidget * widget, - GdkEventButton * event, - gpointer data); -static void -hildon_telephone_editor_focus_dest_entry(GtkWidget * widget, - gboolean edited, - gboolean move_left); -static gboolean -hildon_telephone_editor_entry_keypress(GtkWidget * widget, - GdkEventKey * event, gpointer data); - -static gboolean -hildon_telephone_editor_mnemonic_activate( GtkWidget *widget, - gboolean group_cycling); - -static void -hildon_telephone_editor_set_property(GObject * object, - guint prop_id, - const GValue * value, - GParamSpec * pspec); -static void -hildon_telephone_editor_get_property(GObject * object, - guint prop_id, - GValue * value, GParamSpec * pspec); - -GType hildon_telephone_editor_get_type(void) -{ - static GType editor_type = 0; - - if (!editor_type) { - static const GTypeInfo editor_info = { - sizeof(HildonTelephoneEditorClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_telephone_editor_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonTelephoneEditor), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_telephone_editor_init, - }; - editor_type = g_type_register_static(GTK_TYPE_CONTAINER, - "HildonTelephoneEditor", - &editor_info, 0); - } - return editor_type; -} - -static void -hildon_telephone_editor_class_init(HildonTelephoneEditorClass * - editor_class) -{ - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(editor_class); - GtkContainerClass *container_class = GTK_CONTAINER_CLASS(editor_class); - GObjectClass *object_class = G_OBJECT_CLASS(editor_class); - - parent_class = g_type_class_peek_parent(editor_class); - - g_type_class_add_private(editor_class, sizeof(HildonTelephoneEditorPriv)); - - widget_class->size_request = hildon_telephone_editor_size_request; - widget_class->size_allocate = hildon_telephone_editor_size_allocate; - container_class->forall = hildon_telephone_editor_forall; - widget_class->mnemonic_activate = hildon_telephone_editor_mnemonic_activate; - widget_class->focus = hildon_composite_widget_focus; - object_class->set_property = hildon_telephone_editor_set_property; - object_class->get_property = hildon_telephone_editor_get_property; - - GTK_OBJECT_CLASS(editor_class)->destroy = hildon_telephone_editor_destroy; - - /* Install properties */ - g_object_class_install_property(object_class, PROP_COUNTRY_STR, - g_param_spec_string("country", - ("Country string"), - ("Country string"), - COUNTRY_STR, G_PARAM_READWRITE)); - - g_object_class_install_property(object_class, PROP_AREA_STR, - g_param_spec_string("area", - ("Area string"), - ("Area string"), - AREA_STR, G_PARAM_READWRITE)); - - g_object_class_install_property(object_class, PROP_NUMBER_STR, - g_param_spec_string("number", - ("Number string"), - ("Number string"), - NUMBER_STR, G_PARAM_READWRITE)); - - g_object_class_install_property(object_class, PROP_SHOW_BORDER, - g_param_spec_boolean ("show-border", - "Show Border", - "Wether to show the border around the widget", - TRUE, G_PARAM_READWRITE)); - - g_object_class_install_property(object_class, PROP_SHOW_PLUS, - g_param_spec_boolean ("show-plus", - "Show Plus", - "Wether to show the plus sign in front of" - " coerce format's country field", - TRUE, G_PARAM_READWRITE)); - - g_object_class_install_property(object_class, PROP_FORMAT, - g_param_spec_int("set-format", - ("Format"), - ("Sets telephoneditor format"), - HILDON_TELEPHONE_EDITOR_FORMAT_FREE, - HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA, - 0, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); -} - -static void -hildon_telephone_editor_init(HildonTelephoneEditor * editor) -{ - HildonTelephoneEditorPriv *priv; - gboolean use_frames = FALSE; /* in entries, for debug purposes */ - - priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); - - priv->frame = gtk_frame_new(NULL); - priv->plus = gtk_label_new("+"); - priv->plus_event = gtk_event_box_new(); - priv->country = gtk_entry_new(); - priv->area = gtk_entry_new(); - priv->number = gtk_entry_new(); - priv->edited_country = FALSE; - priv->edited_area = FALSE; - priv->edited_number = FALSE; - priv->show_plus = TRUE; - priv->show_border = TRUE; - priv->editable_country = TRUE; - priv->editable_area = TRUE; - priv->editable_number = TRUE; - - gtk_container_add(GTK_CONTAINER(priv->plus_event), priv->plus); - - gtk_entry_set_has_frame(GTK_ENTRY(priv->country), use_frames); - gtk_entry_set_has_frame(GTK_ENTRY(priv->area), use_frames); - gtk_entry_set_has_frame(GTK_ENTRY(priv->number), use_frames); - - gtk_widget_set_parent(priv->frame, GTK_WIDGET(editor)); - gtk_widget_set_parent(priv->plus_event, GTK_WIDGET(editor)); - - hildon_telephone_editor_set_widths(editor, COUNTRY_LEN, AREA_LEN, - NUMBER_LEN); - - /* set signals for country entry */ - gtk_signal_connect(GTK_OBJECT(priv->country), "button_release_event", - G_CALLBACK(hildon_telephone_editor_button_release), - editor); - - gtk_signal_connect(GTK_OBJECT(priv->country), "key-press-event", - G_CALLBACK(hildon_telephone_editor_entry_keypress), - editor); - - /* set signals for plus label */ - gtk_signal_connect(GTK_OBJECT(priv->plus_event), "button_press_event", - G_CALLBACK(hildon_telephone_editor_button_release), - editor); - - /* set signals for area entry */ - gtk_signal_connect(GTK_OBJECT(priv->area), "button_release_event", - G_CALLBACK(hildon_telephone_editor_button_release), - editor); - - gtk_signal_connect(GTK_OBJECT(priv->area), "key-press-event", - G_CALLBACK(hildon_telephone_editor_entry_keypress), - editor); - - /* set signals for number entry */ - gtk_signal_connect(GTK_OBJECT(priv->number), "button_release_event", - G_CALLBACK(hildon_telephone_editor_button_release), - editor); - - gtk_signal_connect(GTK_OBJECT(priv->number), "key-press-event", - G_CALLBACK(hildon_telephone_editor_entry_keypress), - editor); - - GTK_WIDGET_SET_FLAGS(editor, GTK_NO_WINDOW); - - gtk_widget_show(priv->number); - gtk_widget_show(priv->area); - gtk_widget_show(priv->country); - gtk_widget_show_all(priv->frame); - gtk_widget_show_all(priv->plus_event); -} - -/** - * hildon_telephone_editor_new: - * @format: format of the editor - * - * Creates a new #HildonTelephoneEditor. The editor can be in a free - * format where the user can type in country code, area code and the - * phone number and can type in other characters than just digits. In - * coerse format the editor has fields where the user can input only - * digits. See #HildonTelephoneEditorFormat for the different coerse - * formats. - * - * Returns: new #HildonTelephoneEditor - */ -GtkWidget * -hildon_telephone_editor_new(HildonTelephoneEditorFormat format) -{ - - HildonTelephoneEditor *editor; - - editor = - g_object_new(HILDON_TELEPHONE_EDITOR_TYPE, "set-format", format, - "set-country", _(COUNTRY_STR), "set-area", - _(AREA_STR), "set-number", _(NUMBER_STR), NULL); - - return GTK_WIDGET(editor); -} - -/** - * hildon_telephone_editor_new_with_strings: - * @format: format of the editor - * @country: default text for the country field - * @area: default text for the area field - * @number: default text for the number field - * - * Creates a new #HildonTelephoneEditor. See hildon_telephone_editor_new - * for details. - * - * Returns: new #HildonTelephoneEditor - */ -GtkWidget * -hildon_telephone_editor_new_with_strings(HildonTelephoneEditorFormat - format, - const gchar * country, - const gchar * area, - const gchar * number) -{ - HildonTelephoneEditor *editor; - - editor = - g_object_new(HILDON_TELEPHONE_EDITOR_TYPE, "set-format", format, - "set-country", country, "set-area", area, - "set-number", number, NULL); - - return GTK_WIDGET(editor); -} - -static void -hildon_telephone_editor_get_property(GObject * object, - guint prop_id, - GValue * value, - GParamSpec * pspec) -{ - HildonTelephoneEditor *editor; - HildonTelephoneEditorPriv *priv; - - editor = HILDON_TELEPHONE_EDITOR (object); - priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_COUNTRY_STR: - g_value_set_string(value, - hildon_telephone_editor_get_country(editor)); - break; - case PROP_AREA_STR: - g_value_set_string(value, - hildon_telephone_editor_get_area(editor)); - break; - case PROP_NUMBER_STR: - g_value_set_string(value, - hildon_telephone_editor_get_number(editor)); - break; - case PROP_SHOW_BORDER: - g_value_set_boolean(value, - hildon_telephone_editor_get_show_border(editor)); - break; - case PROP_SHOW_PLUS: - g_value_set_boolean(value, - hildon_telephone_editor_get_show_plus(editor)); - break; - case PROP_FORMAT: - g_value_set_int(value, priv->format); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -hildon_telephone_editor_set_property(GObject * object, - guint prop_id, - const GValue * value, - GParamSpec * pspec) -{ - HildonTelephoneEditor *editor; - HildonTelephoneEditorPriv *priv; - - editor = HILDON_TELEPHONE_EDITOR (object); - priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_COUNTRY_STR: - hildon_telephone_editor_set_country(editor, - _(g_value_get_string(value))); - break; - case PROP_AREA_STR: - hildon_telephone_editor_set_area(editor, - _(g_value_get_string(value))); - break; - case PROP_NUMBER_STR: - hildon_telephone_editor_set_number(editor, - _(g_value_get_string(value))); - break; - case PROP_SHOW_BORDER: - hildon_telephone_editor_set_show_border( - editor, g_value_get_boolean(value)); - break; - case PROP_SHOW_PLUS: - hildon_telephone_editor_set_show_plus( - editor, g_value_get_boolean(value)); - break; - case PROP_FORMAT: - priv->format = g_value_get_int(value); - if (priv->format != HILDON_TELEPHONE_EDITOR_FORMAT_FREE) - gtk_entry_set_text(GTK_ENTRY(priv->number), _(NUMBER_STR)); - - /* set proper fields according to selected format */ - switch (priv->format) { - case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE: - gtk_widget_set_parent(priv->number, GTK_WIDGET(object)); - case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA: - gtk_widget_set_parent(priv->area, GTK_WIDGET(object)); - case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY: - gtk_widget_set_parent(priv->country, GTK_WIDGET(object)); - break; - case HILDON_TELEPHONE_EDITOR_FORMAT_FREE: - gtk_widget_set_parent(priv->number, GTK_WIDGET(object)); - break; - default: - g_assert_not_reached(); - } - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static gboolean -hildon_telephone_editor_mnemonic_activate( GtkWidget *widget, - gboolean group_cycling) -{ - HildonTelephoneEditorPriv *priv; - priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(widget); - - if (!GTK_CONTAINER(widget)->focus_child) - { - if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE) - { - gtk_widget_grab_focus(priv->number); - - if (priv->editable_number && !priv->edited_number) - gtk_editable_select_region(GTK_EDITABLE(priv->number), 0, -1); - } - else - { - if (priv->editable_country) - { - gtk_widget_grab_focus(priv->country); - if (!priv->edited_country) - gtk_editable_select_region(GTK_EDITABLE(priv->country), 0, -1); - } - else if ((priv->editable_area) && (priv->format != - HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY)) - { - gtk_widget_grab_focus(priv->area); - if (!priv->edited_area) - gtk_editable_select_region(GTK_EDITABLE(priv->area), 0, -1); - } - else if ((priv->editable_number) && (priv->format == - HILDON_TELEPHONE_EDITOR_FORMAT_COERCE)) - { - gtk_widget_grab_focus(priv->number); - if (!priv->edited_number) - gtk_editable_select_region(GTK_EDITABLE(priv->number), 0, -1); - } - else - gtk_widget_grab_focus(priv->country); - } - } - return TRUE; -} - -static void -hildon_telephone_editor_forall(GtkContainer * container, - gboolean include_internals, - GtkCallback callback, - gpointer callback_data) -{ - HildonTelephoneEditor *editor; - HildonTelephoneEditorPriv *priv; - - editor = HILDON_TELEPHONE_EDITOR(container); - priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); - - g_return_if_fail(container); - g_return_if_fail(callback); - - if (!include_internals) - return; - - switch (priv->format) { - case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE: - (*callback) (priv->number, callback_data); - case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA: - (*callback) (priv->area, callback_data); - case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY: - (*callback) (priv->country, callback_data); - break; - case HILDON_TELEPHONE_EDITOR_FORMAT_FREE: - (*callback) (priv->number, callback_data); - break; - default: - g_return_if_reached(); - } - - if (priv->show_plus) - (*callback) (priv->plus_event, callback_data); - - if (priv->show_border) - (*callback) (priv->frame, callback_data); - -} - -static void -hildon_telephone_editor_destroy(GtkObject * self) -{ - HildonTelephoneEditorPriv *priv; - - priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(self); - - switch (priv->format) { - case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE: - if (priv->number) { - gtk_widget_unparent(priv->number); - priv->number = NULL; - } - case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA: - if (priv->area) { - gtk_widget_unparent(priv->area); - priv->area = NULL; - } - case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY: - if (priv->country) { - gtk_widget_unparent(priv->country); - priv->country = NULL; - } - break; - case HILDON_TELEPHONE_EDITOR_FORMAT_FREE: - if (priv->number) { - gtk_widget_unparent(priv->number); - priv->number = NULL; - } - break; - default: - g_return_if_reached(); - } - - if (priv->plus_event) { - gtk_widget_unparent(priv->plus_event); - priv->plus_event = NULL; - } - if (priv->frame) { - gtk_widget_unparent(priv->frame); - priv->frame = NULL; - } - if (GTK_OBJECT_CLASS(parent_class)->destroy) - GTK_OBJECT_CLASS(parent_class)->destroy(self); -} - -static void -hildon_telephone_editor_size_request(GtkWidget *widget, - GtkRequisition *requisition) -{ - HildonTelephoneEditor *editor; - HildonTelephoneEditorPriv *priv; - GtkRequisition req; - - g_return_if_fail(requisition); - - editor = HILDON_TELEPHONE_EDITOR(widget); - priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); - - if (priv->show_border) - gtk_widget_size_request(priv->frame, requisition); - - requisition->width = 0; - requisition->height = 0; - - switch (priv->format) - { - case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE: - gtk_widget_size_request(priv->number, &req); - requisition->width += req.width; - if (requisition->height < req.height) - requisition->height = req.height; - - case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA: - gtk_widget_size_request(priv->area, &req); - requisition->width += req.width; - if (requisition->height < req.height) - requisition->height = req.height; - - case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY: - gtk_widget_size_request(priv->country, &req); - requisition->width += req.width; - if (requisition->height < req.height) - requisition->height = req.height; - - break; - case HILDON_TELEPHONE_EDITOR_FORMAT_FREE: - gtk_widget_size_request(priv->number, &req); - requisition->width += req.width; - if (requisition->height < req.height) - requisition->height = req.height; - - break; - default: - g_return_if_reached(); - } - - if (priv->show_plus) - { - gtk_widget_size_request(priv->plus_event, &req); - requisition->width += req.width; - if (requisition->height < req.height) - requisition->height = req.height; - } - - requisition->width += GTK_CONTAINER(priv->frame)->border_width * 2; - requisition->height += GTK_CONTAINER(priv->frame)->border_width * 2; -} - -static void -hildon_telephone_editor_size_allocate(GtkWidget *widget, - GtkAllocation *allocation) -{ - HildonTelephoneEditor *editor; - HildonTelephoneEditorPriv *priv; - gint header_x = 6, frame_w = 12; - GtkAllocation alloc, country_alloc, area_alloc, number_alloc; - GtkRequisition requisition, country_requisition, area_requisition, - number_requisition; - - g_return_if_fail(widget); - g_return_if_fail(allocation); - - if (allocation->height < 0 ) - allocation->height = 0; - - widget->allocation = *allocation; - - header_x += allocation->x; - editor = HILDON_TELEPHONE_EDITOR(widget); - priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); - - - if (priv->show_plus && - priv->format != HILDON_TELEPHONE_EDITOR_FORMAT_FREE) { - gtk_widget_get_child_requisition(priv->plus_event, &requisition); - - alloc.x = header_x; - alloc.y = allocation->y + 1; - alloc.width = requisition.width; - alloc.height = requisition.height; - - header_x += alloc.width; - gtk_widget_size_allocate(priv->plus_event, &alloc); - frame_w += alloc.width; - } - - gtk_widget_get_child_requisition(priv->number, &number_requisition); - - number_alloc.width = number_requisition.width; - - number_alloc.height = allocation->height - 4 - - GTK_CONTAINER(priv->frame)->border_width * 2; - - /* get sizes */ - switch (priv->format) { - case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE: - case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA: - gtk_widget_get_child_requisition(priv->area, &area_requisition); - - area_alloc.width = area_requisition.width; - area_alloc.height = number_alloc.height; - case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY: - gtk_widget_get_child_requisition(priv->country, &country_requisition); - - country_alloc.width = country_requisition.width; - country_alloc.height = number_alloc.height; - break; - case HILDON_TELEPHONE_EDITOR_FORMAT_FREE: - break; - default: - g_return_if_reached(); - } - - - /* allocate in coerce formats */ - switch (priv->format) { - case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE: - number_alloc.x = header_x + country_alloc.width + area_alloc.width; - number_alloc.y = allocation->y + 1; - - gtk_widget_size_allocate(priv->number, &number_alloc); - frame_w += number_alloc.width; - case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA: - area_alloc.x = header_x + country_alloc.width; - area_alloc.y = allocation->y + 1; - - gtk_widget_size_allocate(priv->area, &area_alloc); - frame_w += area_alloc.width; - case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY: - country_alloc.x = header_x; - country_alloc.y = allocation->y + 1; - - gtk_widget_size_allocate(priv->country, &country_alloc); - frame_w += country_alloc.width; - break; - case HILDON_TELEPHONE_EDITOR_FORMAT_FREE: - number_alloc.x = header_x; - number_alloc.y = allocation->y + 1; - - gtk_widget_size_allocate(priv->number, &number_alloc); - frame_w += number_alloc.width; - break; - default: - g_return_if_reached(); - } - - if (priv->show_border) - { - alloc.x = allocation->x; - alloc.y = allocation->y; - - alloc.width = frame_w - 4; - - alloc.height = allocation->height; - gtk_widget_size_allocate( GTK_WIDGET(priv->frame), &alloc ); - } -} - -static gboolean -hildon_telephone_editor_button_release(GtkWidget * widget, - GdkEventButton * event, gpointer data) -{ - gtk_editable_select_region(GTK_EDITABLE(widget), 0, -1); - return FALSE; -} - -static void -hildon_telephone_editor_focus_dest_entry(GtkWidget * widget, - gboolean edited, - gboolean move_left) -{ - /* full coerse mode, wrap to field */ - gtk_widget_grab_focus(widget); - - if (move_left) - gtk_editable_set_position(GTK_EDITABLE(widget), -1); - else - gtk_editable_set_position(GTK_EDITABLE(widget), 0); - /* new field not yet edited, select all */ - if (!edited) - gtk_editable_select_region(GTK_EDITABLE(widget), 0, -1); -} - -static gboolean -hildon_telephone_editor_entry_keypress(GtkWidget * widget, - GdkEventKey * event, gpointer data) -{ - HildonTelephoneEditor *editor; - HildonTelephoneEditorPriv *priv; - gint pos, width; - gint cpos, start, end; - - g_return_val_if_fail(widget, FALSE); - g_return_val_if_fail(event, FALSE); - g_return_val_if_fail(data, FALSE); - - editor = HILDON_TELEPHONE_EDITOR(data); - priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); - cpos = gtk_editable_get_position(GTK_EDITABLE(widget)); - gtk_editable_get_selection_bounds(GTK_EDITABLE(widget), &start, &end); - - if( event->keyval == GDK_Up || event->keyval == GDK_KP_Up || - event->keyval == GDK_Down || event->keyval == GDK_KP_Down ) - return FALSE; - - /* Wrap around should not happen; that's why following code */ - switch (priv->format) { - case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE: - if (((event->keyval == GDK_Left || event->keyval == GDK_KP_Left) && - (widget == priv->country) && ((cpos == 0) || - ((start == 0 && end == strlen(GTK_ENTRY(priv->country)->text))))) - || - ((event->keyval == GDK_Right || event->keyval == GDK_KP_Right) - && (widget == priv->number) - && (cpos >= strlen(GTK_ENTRY(priv->number)->text)))) - return TRUE; - break; - case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA: - if (((event->keyval == GDK_Left || event->keyval == GDK_KP_Left) && - (widget == priv->country) && ((cpos == 0) || - ((start == 0 - && end == - strlen(GTK_ENTRY - (priv->country)-> - text))))) - || - ((event->keyval == GDK_Right || event->keyval == GDK_KP_Right) - && (widget == priv->area) - && (cpos >= strlen(GTK_ENTRY(priv->area)->text)))) - return TRUE; - break; - case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY: - break; - case HILDON_TELEPHONE_EDITOR_FORMAT_FREE: - break; - } - - /* valid key pressed */ - if (event->keyval == GDK_Left || event->keyval == GDK_KP_Left || - event->keyval == GDK_Right || event->keyval == GDK_KP_Right || - event->keyval == GDK_BackSpace || event->keyval == GDK_Delete || - event->keyval == GDK_KP_Delete || - (event->keyval >= GDK_0 && event->keyval <= GDK_9) || - (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE && - (event->keyval == GDK_slash || event->keyval == GDK_space || - event->keyval == GDK_parenleft || event->keyval == GDK_parenright - || event->keyval == GDK_period || event->keyval == GDK_hyphen - || event->keyval == GDK_plus || event->keyval == GDK_asterisk - || event->keyval == GDK_KP_Multiply - || event->keyval == GDK_KP_Add || event->keyval == GDK_numbersign - || event->keyval == GDK_question || event->keyval == GDK_KP_Subtract - || event->keyval == GDK_minus))) - { - if ((event->keyval >= GDK_0 && event->keyval <= GDK_9) || - (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE && - (event->keyval == GDK_slash || event->keyval == GDK_space || - event->keyval == GDK_parenleft || - event->keyval == GDK_parenright || - event->keyval == GDK_period || event->keyval == GDK_hyphen || - event->keyval == GDK_plus || event->keyval == GDK_asterisk || - event->keyval == GDK_KP_Add || - event->keyval == GDK_KP_Multiply || - event->keyval == GDK_numbersign || - event->keyval == GDK_question || - event->keyval == GDK_KP_Subtract || - event->keyval == GDK_minus))) - { - if (widget == priv->country) - priv->edited_country = TRUE; - if (widget == priv->area) - priv->edited_area = TRUE; - if (widget == priv->number) - priv->edited_number = TRUE; - } - - pos = gtk_editable_get_position(GTK_EDITABLE(widget)); - - /* going left */ - if (event->keyval == GDK_Left || event->keyval == GDK_KP_Left) { - /* not yet on the left edge and the widget is edited */ - if (pos != 0 && - ((widget == priv->country && priv->edited_country == TRUE) - || (widget == priv->area && priv->edited_area == TRUE) - || (widget == priv->number - && priv->edited_number == TRUE))) - return FALSE; - - /* left edge of number field */ - if (widget == priv->number) { - /* Stop signal handler, if only number field exists */ - if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE) - return TRUE; - else { - /* Grab the focus to the area field, if it is editable - */ - if (priv->editable_area) { - hildon_telephone_editor_focus_dest_entry - (priv->area, priv->edited_area, TRUE); - } - /* Grab the focus to the country field, if it is - editable */ - else if (priv->editable_country) { - hildon_telephone_editor_focus_dest_entry - (priv->country, priv->edited_country, TRUE); - } else - return TRUE; - } - } - - /* left edge of area field */ - if (widget == priv->area) { /* grab the focus to the country - field, if it is editable */ - if (priv->editable_country) { - hildon_telephone_editor_focus_dest_entry - (priv->country, priv->edited_country, TRUE); - } else - return TRUE; - } - - /* left edge of country field, let's wrap */ - if (widget == priv->country) { - /* Stop the signal handler, if only country field exists */ - if (priv->format == - HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY) - return TRUE; - /* wrap to area, if in AREA mode */ - else if (priv->format == - HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA) { - hildon_telephone_editor_focus_dest_entry - (priv->area, priv->edited_area, TRUE); - } - - else { - hildon_telephone_editor_focus_dest_entry - (priv->number, priv->edited_number, TRUE); - } - } - } - /* going right */ - else if (event->keyval == GDK_Right || event->keyval == GDK_KP_Right) { - width = g_utf8_strlen(gtk_entry_get_text(GTK_ENTRY(widget)), -1); - - /* not yet on the rigth edge and the widget is edited */ - if (pos != width && - ((widget == priv->country && priv->edited_country == TRUE) - || (widget == priv->area && priv->edited_area == TRUE) - || (widget == priv->number - && priv->edited_number == TRUE))) - return FALSE; - - /* rigth edge of number field */ - if (widget == priv->number) { - /* Stop signal handler, if only number field exists */ - if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE) - return TRUE; - else { - hildon_telephone_editor_focus_dest_entry - (priv->country, priv->edited_country, FALSE); - } - } - - /* rigth edge of area field */ - if (widget == priv->area) { - /* area mode, wrap to country field */ - if (priv->format == - HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA) { - hildon_telephone_editor_focus_dest_entry - (priv->country, priv->edited_country, FALSE); - } - /* grab the focus to the number field, if it is editable */ - else if (priv->editable_number) { - hildon_telephone_editor_focus_dest_entry - (priv->number, priv->edited_number, FALSE); - } else - return TRUE; - } - - /* rigth edge of country field */ - if (widget == priv->country) { - /* wrap around, if only country field exists */ - if (priv->format == - HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY) - return TRUE; - - /* area mode, move to area field */ - else if (priv->format == - HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA || - priv->format == - HILDON_TELEPHONE_EDITOR_FORMAT_COERCE) { - /* grab the focus to the area field, if it is editable - */ - if (priv->editable_area) { - hildon_telephone_editor_focus_dest_entry - (priv->area, priv->edited_area, FALSE); - } - /* grab the focus to the area field, if it is editable - */ - else if ((priv->format == - HILDON_TELEPHONE_EDITOR_FORMAT_COERCE) && - priv->editable_number) { - hildon_telephone_editor_focus_dest_entry - (priv->number, priv->edited_number, FALSE); - } else - return TRUE; - } - - else { - hildon_telephone_editor_focus_dest_entry - (priv->number, priv->edited_number, FALSE); - } - } - } - return FALSE; - } - return TRUE; -} - -/** - * hildon_telephone_editor_set_editable: - * @hte: #HildonTelephoneEditor - * @country: set the editable status of the country field in coarce format - * @area: set the editable status of the area field in coarce format - * @number: set the editable status of the number field in coarce format - * - * Specify wheter the fields in coerse format are editable or - * not. This function is ignored if the editor is in free mode. The - * number or area and number parameters are ignored if the editor is - * in HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA or - * HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY formats, - * respectively. - */ -void -hildon_telephone_editor_set_editable(HildonTelephoneEditor * editor, - gboolean country, - gboolean area, gboolean number) -{ - HildonTelephoneEditorPriv *priv; - - g_return_if_fail(editor); - - priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); - - priv->editable_country = country; - priv->editable_area = area; - priv->editable_number = number; - - if (priv->country) - { - gtk_editable_set_editable(GTK_EDITABLE(priv->country), country); - gtk_widget_set_sensitive(GTK_WIDGET(priv->plus), country); - } - - if (priv->area) - gtk_editable_set_editable(GTK_EDITABLE(priv->area), area); - - if (priv->number) - gtk_editable_set_editable(GTK_EDITABLE(priv->number), number); -} - -/** - * hildon_telephone_editor_set_widths: - * @hte: #HildonTelephoneEditor - * @country: width (characters) of the country field in coarce mode - * @area: width (characters) of the area field in coarce mode - * @number: width (characters) of the number field in coarce mode - * - * Set widths of the fields in coecse format. Country and area parameters - * are ignored, if the editor is in free mode. The number or area and number - * parameters are ignored if the editor is in - * HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA or - * HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY mode, respectively. - */ -void -hildon_telephone_editor_set_widths(HildonTelephoneEditor * editor, - guint country, - guint area, guint number) -{ - HildonTelephoneEditorPriv *priv; - - g_return_if_fail(editor); - - priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); - - if (priv->country) { - /*gtk_entry_set_max_length(GTK_ENTRY(priv->country), country);*/ - gtk_entry_set_width_chars(GTK_ENTRY(priv->country), country); - } - - if (priv->area) { - /*gtk_entry_set_max_length(GTK_ENTRY(priv->area), area);*/ - gtk_entry_set_width_chars(GTK_ENTRY(priv->area), area); - } - - if (priv->number) { - /*gtk_entry_set_max_length(GTK_ENTRY(priv->number), number);*/ - gtk_entry_set_width_chars(GTK_ENTRY(priv->number), number); - } - -} - -/** - * hildon_telephone_editor_set_show_plus: - * @hte: #HildonTelephoneEditor - * @show: show the plus sign - * - * Show or hide the plus sign in front of coerce format's country field. - */ -void -hildon_telephone_editor_set_show_plus(HildonTelephoneEditor * editor, - gboolean show) -{ - HildonTelephoneEditorPriv *priv; - - g_return_if_fail(editor); - - priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); - - /* do nothing in FREE format */ - if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE) - return; - - if (show && !priv->show_plus) { - priv->show_plus = TRUE; - gtk_widget_set_parent(priv->plus_event, GTK_WIDGET(editor)); - gtk_widget_show(priv->plus_event); - } else if (!show && priv->show_plus) { - gtk_widget_hide(priv->plus_event); - gtk_widget_unparent(priv->plus_event); - priv->show_plus = FALSE; - } -} - -/** - * hildon_telephone_editor_get_show_plus: - * @hte: #HildonTelephoneEditor - * - * Get the visibility status of the plus sign in - * front of coerce format's country field. - * - * Returns: gboolean - */ -gboolean -hildon_telephone_editor_get_show_plus(HildonTelephoneEditor * - editor) -{ - HildonTelephoneEditorPriv *priv; - g_return_val_if_fail(editor, FALSE); - priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); - - /* no plus in FREE format */ - if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE) - return FALSE; - return priv->show_plus; -} - -/** - * hildon_telephone_editor_set_show_border: - * @hte: #HildonTelephoneEditor - * @show: show the border - * - * Show or hide the border around the widget - */ -void -hildon_telephone_editor_set_show_border(HildonTelephoneEditor * - editor, gboolean show) -{ - HildonTelephoneEditorPriv *priv; - g_return_if_fail(editor); - priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); - - if (show && !priv->show_border) { - priv->show_border = TRUE; - gtk_widget_set_parent(priv->frame, GTK_WIDGET(editor)); - gtk_widget_show(priv->frame); - } else if (!show && priv->show_border) { - gtk_widget_hide(priv->frame); - gtk_widget_unparent(priv->frame); - priv->show_border = FALSE; - } -} - -/** - * hildon_telephone_editor_get_show_border: - * @hte: #HildonTelephoneEditor - * - * Get the visibility status of the border around the widget. - * - * Returns: gboolean - */ -gboolean -hildon_telephone_editor_get_show_border(HildonTelephoneEditor * editor) -{ - HildonTelephoneEditorPriv *priv; - g_return_val_if_fail(editor, FALSE); - priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); - - return priv->show_border; -} - -/** - * hildon_telephone_editor_get_country: - * @hte: #HildonTelephoneEditor - * - * Get text in the country field in coarse format. This function must - * not be called if in free mode. - * - * Returns: pointer to the text in the country field. It must not - * be changed or freed. - */ -const gchar * -hildon_telephone_editor_get_country(HildonTelephoneEditor * - editor) -{ - HildonTelephoneEditorPriv *priv; - g_return_val_if_fail(editor, NULL); - priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); - - /* return NULL if in FREE format */ - if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE) - return NULL; - - return gtk_entry_get_text(GTK_ENTRY(priv->country)); -} - -/** - * hildon_telephone_editor_set_country: - * @hte: #HildonTelephoneEditor - * @country: text to be set in country field - * - * Set text in the country field in coarse format. This function must - * not be called if in free mode. - */ -void -hildon_telephone_editor_set_country(HildonTelephoneEditor * editor, - const gchar * country) -{ - HildonTelephoneEditorPriv *priv; - const gchar *p; - gunichar u; - - g_return_if_fail(editor); - g_return_if_fail(country); - - priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); - - /* do nothing in FREE format */ - if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE) - return; - - if (!priv->country) - return; - - p = country; - g_return_if_fail(g_utf8_validate(p, -1, NULL)); - - /* allow only digits */ - do { - u = g_utf8_get_char(p); - if (!g_unichar_isdigit(*p)) - return; - - p = g_utf8_next_char(p); - } while (*p); - - gtk_entry_set_text(GTK_ENTRY(priv->country), country); -} - -/** - * hildon_telephone_editor_get_area: - * @hte: #HildonTelephoneEditor - * - * Get text in the area field in coarse format. This function must not - * be called if in free mode or in - * HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY mode. - * - * Returns: pointer to the text in the area field. It must not be - * changed or freed. - */ -const gchar * -hildon_telephone_editor_get_area(HildonTelephoneEditor * - editor) -{ - HildonTelephoneEditorPriv *priv; - g_return_val_if_fail(editor, NULL); - priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); - - /* return NULL if in FREE format or if in COERCE_COUNTRY format */ - if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE) - return NULL; - if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY) - return NULL; - - return gtk_entry_get_text(GTK_ENTRY(priv->area)); -} - -/** - * hildon_telephone_editor_set_area: - * @hte: #HildonTelephoneEditor - * @area: text to be set in area field - * - * Set text in the area field in coarse format. This function must not - * be called if in free mode or in - * HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY mode. - */ -void -hildon_telephone_editor_set_area(HildonTelephoneEditor * editor, - const gchar * area) -{ - HildonTelephoneEditorPriv *priv; - const gchar *p; - gunichar u; - - g_return_if_fail(editor); - g_return_if_fail(area); - - priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); - - /* do nothing in FREE format */ - if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE) - return; - - if (!priv->area) - return; - - p = area; - g_return_if_fail(g_utf8_validate(p, -1, NULL)); - - /* allow only digits */ - do { - u = g_utf8_get_char(p); - if (!g_unichar_isdigit(u)) - return; - - p = g_utf8_next_char(p); - } while (*p); - - gtk_entry_set_text(GTK_ENTRY(priv->area), area); -} - -/** - * hildon_telephone_editor_get_number: - * @hte: #HildonTelephoneEditor - * - * Get text in the number field in all formats. In free mode, this - * functions returns the whole phone number. In coarce mode, it returns - * only the number field. This function must not be called if - * the editor is in HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA or - * HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY modes. - * - * Returns: pointer to text in the number field. It must not be - * changed or freed. - */ -const gchar * -hildon_telephone_editor_get_number(HildonTelephoneEditor * - editor) -{ - HildonTelephoneEditorPriv *priv; - g_return_val_if_fail(editor, NULL); - priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); - - return gtk_entry_get_text(GTK_ENTRY(priv->number)); -} - -/** - * hildon_telephone_editor_set_number: - * @hte: #HildonTelephoneEditor - * @number: text to be set to number field - * - * Set text in the number field in all formats. In free mode this - * functions sets the whole phone number. In coerce mode, it sets - * only the number field. This function must not be called if - * the editor is in HILDON_TELEPHONE_EDITOR_FORMAT_COERSE_AREA or - * HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY modes. - */ -void -hildon_telephone_editor_set_number(HildonTelephoneEditor * editor, - const gchar * number) -{ - HildonTelephoneEditorPriv *priv; - const gchar *p; - gunichar u; - - g_return_if_fail(editor); - g_return_if_fail(number); - - priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); - - if (!priv->number) - return; - - p = number; - g_return_if_fail(g_utf8_validate(p, -1, NULL)); - - /* allow only digits in coerce format or some other in free format */ - do { - u = g_utf8_get_char(p); - if (g_unichar_isdigit(u) || - (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE && - (u == '+' || - u == 'p' || - u == 'w' || - u == '(' || - u == ')' || - u == '/' || - u == ' ' || - u == '.' || u == '-' || u == '*' || u == '#' || u == '?'))) - p = g_utf8_next_char(p); - else - return; - - } while (*p); - - gtk_entry_set_text(GTK_ENTRY(priv->number), number); -} diff --git a/hildon-widgets/hildon-telephone-editor.h b/hildon-widgets/hildon-telephone-editor.h deleted file mode 100644 index 7cba96b..0000000 --- a/hildon-widgets/hildon-telephone-editor.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_TELEPHONE_EDITOR_H__ -#define __HILDON_TELEPHONE_EDITOR_H__ - -#include - -G_BEGIN_DECLS -/** - * HILDON_TELEPHONE_EDITOR_TYPE: - * - * Macro for getting type of telephone editor. - */ -#define HILDON_TELEPHONE_EDITOR_TYPE \ - ( hildon_telephone_editor_get_type() ) -#define HILDON_TELEPHONE_EDITOR(obj) \ - (GTK_CHECK_CAST (obj, HILDON_TELEPHONE_EDITOR_TYPE, \ - HildonTelephoneEditor)) -#define HILDON_TELEPHONE_EDITOR_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), HILDON_TELEPHONE_EDITOR_TYPE, \ - HildonTelephoneEditorClass)) -#define HILDON_IS_TELEPHONE_EDITOR(obj) \ - (GTK_CHECK_TYPE (obj, HILDON_TELEPHONE_EDITOR_TYPE)) -#define HILDON_IS_TELEPHONE_EDITOR_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TELEPHONE_EDITOR_TYPE)) -/** - * HildonTelephoneEditorFormat: - * @HILDON_TELEPHONE_EDITOR_FORMAT_FREE: Free format. - * @HILDON_TELEPHONE_EDITOR_FORMAT_COERCE: Coerce format, three fields. - * @HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY: Coerce format, only - * country field. - * @HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA: Coerce format, country - * and area fields. - * - * Define all possible format modes for the HildonTelephoneEditor. - * - */ - typedef enum { - HILDON_TELEPHONE_EDITOR_FORMAT_FREE = 0, - HILDON_TELEPHONE_EDITOR_FORMAT_COERCE, - HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY, - HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA -} HildonTelephoneEditorFormat; - - -/** - * HildonTelephoneEditor: - * - * Internal struct for telephone editor. - */ -typedef struct _HildonTelephoneEditor HildonTelephoneEditor; -typedef struct _HildonTelephoneEditorClass HildonTelephoneEditorClass; - -/*< private >*/ -struct _HildonTelephoneEditor { - GtkContainer parent; -}; - -struct _HildonTelephoneEditorClass { - GtkContainerClass parent_class; -}; - -GType hildon_telephone_editor_get_type(void); - -GtkWidget *hildon_telephone_editor_new(HildonTelephoneEditorFormat format); -GtkWidget - *hildon_telephone_editor_new_with_strings(HildonTelephoneEditorFormat - format, - const gchar * country, - const gchar * area, - const gchar * number); -void hildon_telephone_editor_set_editable(HildonTelephoneEditor * hte, - gboolean country, gboolean area, - gboolean number); - -void hildon_telephone_editor_set_show_plus(HildonTelephoneEditor * hte, - gboolean show); - -gboolean hildon_telephone_editor_get_show_plus(HildonTelephoneEditor * - hte); - -void hildon_telephone_editor_set_show_border(HildonTelephoneEditor * hte, - gboolean show); - -gboolean hildon_telephone_editor_get_show_border(HildonTelephoneEditor * - hte); - - -void hildon_telephone_editor_set_widths(HildonTelephoneEditor * hte, - guint country, - guint area, guint number); - -const gchar *hildon_telephone_editor_get_country(HildonTelephoneEditor * - hte); - -void hildon_telephone_editor_set_country(HildonTelephoneEditor * hte, - const gchar * country); - -const gchar *hildon_telephone_editor_get_area(HildonTelephoneEditor * hte); - -void hildon_telephone_editor_set_area(HildonTelephoneEditor * hte, - const gchar * area); - -const gchar *hildon_telephone_editor_get_number(HildonTelephoneEditor * - hte); - -void hildon_telephone_editor_set_number(HildonTelephoneEditor * hte, - const gchar * number); - -G_END_DECLS -#endif /* __HILDON_TELEPHONE_EDITOR_H__ */ diff --git a/hildon-widgets/hildon-time-editor.c b/hildon-widgets/hildon-time-editor.c deleted file mode 100644 index 31bada1..0000000 --- a/hildon-widgets/hildon-time-editor.c +++ /dev/null @@ -1,1902 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-time-editor - * @short_description: A widget used to enter time or duration in hours, minutes, - * and optional seconds - * @see_also: #HildonTimePicker - * - * HildonTimeEditor is used to edit time or duration. Time mode is - * restricted to normal 24 hour cycle, but Duration mode can select any - * amount of time up to 99 hours. It consists of entries for hours, - * minutes and seconds, and pm/am indicator as well as a button which - * popups a #HildonTimePicker dialog. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include "hildon-composite-widget.h" -#include "hildon-marshalers.h" -#include "hildon-libs-enum-types.h" - -#define _(String) dgettext(PACKAGE, String) - -#define HILDON_TIME_EDITOR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_TIME_EDITOR, HildonTimeEditorPrivate)); - -#define TICKS(h,m,s) ((h) * 3600 + (m) * 60 + (s)) - -#define TIME_EDITOR_HEIGHT 30 -#define ICON_PRESSED 4 -#define ICON_NAME "qgn_widg_timedit" -#define ICON_SIZE "timepicker-size" -#define MIN_DURATION 0 -#define MAX_DURATION TICKS(99, 59, 59) - -/* Default values for properties */ -#define HILDON_TIME_EDITOR_TICKS_VALUE 0 -#define HILDON_TIME_EDITOR_DURATION_MODE FALSE -#define HILDON_TIME_EDITOR_DURATION_LOWER_VALUE 0 -#define HILDON_TIME_EDITOR_DURATION_UPPER_VALUE TICKS(99, 59, 59) - -#define HOURS_MAX_24 23 -#define HOURS_MAX_12 12 -#define HOURS_MIN_24 0 -#define HOURS_MIN_12 1 -#define MINUTES_MAX 59 -#define SECONDS_MAX 59 -#define MINUTES_MIN 0 -#define SECONDS_MIN 0 - -static GtkContainerClass *parent_class; - -typedef struct _HildonTimeEditorPrivate HildonTimeEditorPrivate; - -enum -{ - PROP_TICKS = 1, - PROP_DURATION_MODE, - PROP_DURATION_MIN, - PROP_DURATION_MAX, - PROP_SHOW_SECONDS, - PROP_SHOW_HOURS -}; - -/* Indices for h/m/s entries in priv->entries */ -enum { - ENTRY_HOURS, - ENTRY_MINS, - ENTRY_SECS, - - ENTRY_COUNT -}; - -/* Signals */ -enum { - TIME_ERROR, - LAST_SIGNAL -}; - -/* Error codes categories */ -enum { - MAX_VALUE, - MIN_VALUE, - WITHIN_RANGE, - NUM_ERROR_CODES -}; - -static guint time_editor_signals[LAST_SIGNAL] = { 0 }; -static guint hour_errors[NUM_ERROR_CODES] = { MAX_HOURS, MIN_HOURS, EMPTY_HOURS }; -static guint min_errors[NUM_ERROR_CODES] = { MAX_MINS, MIN_MINS, EMPTY_MINS }; -static guint sec_errors[NUM_ERROR_CODES] = { MAX_SECS, MIN_SECS, EMPTY_SECS }; - -struct _HildonTimeEditorPrivate { - guint ticks; /* Current duration in seconds */ - - gchar *am_symbol; - gchar *pm_symbol; - - GtkWidget *iconbutton; /* button for icon */ - - GtkWidget *frame; /* frame around the entries */ - GtkWidget *entries[ENTRY_COUNT]; /* h, m, s entries */ - GtkWidget *hm_label; /* between hour and minute */ - GtkWidget *sec_label; /* between minute and second */ - GtkWidget *ampm_label; /* label for showing am or pm */ - - GtkWidget *error_widget; /* field to highlight in idle */ - GtkWidget *ampm_button; /* am/pm change button */ - - - gboolean duration_mode; /* In HildonDurationEditor mode */ - gboolean show_seconds; /* show seconds */ - gboolean show_hours; /* show hours */ - - gboolean ampm_pos_after; /* is am/pm shown after others */ - gboolean clock_24h; /* whether to show a 24h clock */ - gboolean am; /* TRUE == am, FALSE == pm */ - - guint duration_min; /* duration editor ranges */ - guint duration_max; /* duration editor ranges */ - - guint highlight_idle; - gboolean skipper; /* FIXME (MDK): To prevent us from looping inside the validation events. - When set to TRUE further validations (that can happen from-inside other validations) - are being skipped. Nasty hack to cope with a bad design. */ -}; - -/*** - * Widget functions - */ - -static void hildon_time_editor_class_init (HildonTimeEditorClass *editor_class); -static void hildon_time_editor_init (HildonTimeEditor *editor); - -static void hildon_time_editor_finalize (GObject *obj_self); - -static void hildon_time_editor_set_property(GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec); - -static void hildon_time_editor_get_property(GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec); - -static void hildon_time_editor_forall(GtkContainer *container, - gboolean include_internals, - GtkCallback callback, - gpointer callback_data); - -static void hildon_time_editor_destroy(GtkObject * self); - -/*** - * Signal handlers - */ - -static gboolean hildon_time_editor_entry_focusout(GtkWidget *widget, - GdkEventFocus *event, - gpointer data); - -static gboolean hildon_time_editor_entry_focusin(GtkWidget *widget, - GdkEventFocus *event, - gpointer data); - -static gboolean hildon_time_editor_time_error(HildonTimeEditor *editor, - HildonTimeEditorErrorType type); - -static gboolean hildon_time_editor_ampm_clicked(GtkWidget *widget, - gpointer data); - -static gboolean hildon_time_editor_icon_clicked(GtkWidget *widget, - gpointer data); - -static void hildon_time_editor_size_request(GtkWidget *widget, - GtkRequisition *requisition); - -static void hildon_time_editor_size_allocate(GtkWidget *widget, - GtkAllocation *allocation); - -static gboolean hildon_time_editor_entry_keypress(GtkWidget *widget, - GdkEventKey *event, - gpointer data); - -/*** - * Internal functions - */ - -static gboolean hildon_time_editor_check_locale(HildonTimeEditor * editor); - -static -void hildon_time_editor_tap_and_hold_setup(GtkWidget * widget, - GtkWidget * menu, - GtkCallback func, - GtkWidgetTapAndHoldFlags flags); -static void -hildon_time_editor_validate (HildonTimeEditor *editor, gboolean allow_intermediate); - -static void hildon_time_editor_set_to_current_time (HildonTimeEditor * editor); - -static gboolean -_hildon_time_editor_entry_select_all(GtkWidget *widget); - - -/*** - * Utility functions - */ - -static void convert_to_12h (guint *h, gboolean *am); -static void convert_to_24h (guint *h, gboolean am); - -static void ticks_to_time (guint ticks, - guint *hours, - guint *minutes, - guint *seconds); - -static void -hildon_time_editor_inserted_text (GtkEditable * editable, - gchar * new_text, - gint new_text_length, - gint * position, - gpointer user_data); - -GType hildon_time_editor_get_type(void) -{ - static GType editor_type = 0; - - if (!editor_type) { - static const GTypeInfo editor_info = { - sizeof(HildonTimeEditorClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_time_editor_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonTimeEditor), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_time_editor_init, - }; - editor_type = g_type_register_static(GTK_TYPE_CONTAINER, - "HildonTimeEditor", - &editor_info, 0); - } - return editor_type; -} - -static void hildon_time_editor_forall(GtkContainer * container, - gboolean include_internals, - GtkCallback callback, - gpointer callback_data) -{ - HildonTimeEditor *editor; - HildonTimeEditorPrivate *priv; - - g_assert(HILDON_IS_TIME_EDITOR(container)); - g_assert(callback != NULL); - - editor = HILDON_TIME_EDITOR(container); - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - - if (!include_internals) - return; - - /* widget that are always shown */ - (*callback) (priv->iconbutton, callback_data); - (*callback) (priv->frame, callback_data); -} - -static void hildon_time_editor_destroy(GtkObject * self) -{ - HildonTimeEditorPrivate *priv; - - priv = HILDON_TIME_EDITOR_GET_PRIVATE(self); - - if (priv->iconbutton) { - gtk_widget_unparent(priv->iconbutton); - priv->iconbutton = NULL; - } - if (priv->frame) { - gtk_widget_unparent(priv->frame); - priv->frame = NULL; - } - - if (GTK_OBJECT_CLASS(parent_class)->destroy) - GTK_OBJECT_CLASS(parent_class)->destroy(self); - -} - -static void -hildon_time_editor_class_init(HildonTimeEditorClass * editor_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS(editor_class); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(editor_class); - GtkContainerClass *container_class = GTK_CONTAINER_CLASS(editor_class); - - parent_class = g_type_class_peek_parent(editor_class); - - g_type_class_add_private(editor_class, - sizeof(HildonTimeEditorPrivate)); - - object_class->get_property = hildon_time_editor_get_property; - object_class->set_property = hildon_time_editor_set_property; - widget_class->size_request = hildon_time_editor_size_request; - widget_class->size_allocate = hildon_time_editor_size_allocate; - widget_class->tap_and_hold_setup = - hildon_time_editor_tap_and_hold_setup; - widget_class->focus = hildon_composite_widget_focus; - - container_class->forall = hildon_time_editor_forall; - GTK_OBJECT_CLASS(editor_class)->destroy = hildon_time_editor_destroy; - - object_class->finalize = hildon_time_editor_finalize; - - editor_class->time_error = hildon_time_editor_time_error; - - time_editor_signals[TIME_ERROR] = - g_signal_new("time-error", - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET(HildonTimeEditorClass, time_error), - g_signal_accumulator_true_handled, NULL, - _hildon_marshal_BOOLEAN__ENUM, - G_TYPE_BOOLEAN, 1, HILDON_TYPE_TIME_EDITOR_ERROR_TYPE); - - /** - * HildonTimeEditor:ticks: - * - * If editor is in duration mode, contains the duration seconds. - * If not, contains seconds since midnight. - */ - g_object_class_install_property( object_class, PROP_TICKS, - g_param_spec_uint("ticks", - "Duration value", - "Current value of duration", - 0, G_MAXUINT, - HILDON_TIME_EDITOR_TICKS_VALUE, - G_PARAM_READABLE | G_PARAM_WRITABLE) ); - - /** - * HildonTimeEditor:show_seconds: - * - * Controls whether seconds are shown in the editor - */ - g_object_class_install_property( object_class, PROP_SHOW_SECONDS, - g_param_spec_boolean("show_seconds", - "Show seconds property", - "Controls whether the seconds are shown in the editor", - FALSE, - G_PARAM_READABLE | G_PARAM_WRITABLE) ); - - /** - * HildonTimeEditor:show_hours: - * - * Controls whether hours are shown in the editor - */ - g_object_class_install_property( object_class, PROP_SHOW_HOURS, - g_param_spec_boolean("show_hours", - "Show hours field", - "Controls whether the hours field is shown in the editor", - TRUE, - G_PARAM_READABLE | G_PARAM_WRITABLE) ); - - /** - * HildonTimeEditor:duration_mode: - * - * Controls whether the TimeEditor is in duration mode - */ - g_object_class_install_property( object_class, PROP_DURATION_MODE, - g_param_spec_boolean("duration_mode", - "Duration mode", - "Controls whether the TimeEditor is in duration mode", - HILDON_TIME_EDITOR_DURATION_MODE, - G_PARAM_READABLE | G_PARAM_WRITABLE) ); - - /** - * HildonTimeEditor:duration_min: - * - * Minimum allowed duration value. - */ - g_object_class_install_property( object_class, PROP_DURATION_MIN, - g_param_spec_uint("duration_min", - "Minumum duration value", - "Smallest possible duration value", - MIN_DURATION, MAX_DURATION, - HILDON_TIME_EDITOR_DURATION_LOWER_VALUE, - G_PARAM_READABLE | G_PARAM_WRITABLE) ); - - /** - * HildonTimeEditor:duration_max: - * - * Maximum allowed duration value. - */ - g_object_class_install_property( object_class, PROP_DURATION_MAX, - g_param_spec_uint("duration_max", - "Maximum duration value", - "Largest possible duration value", - 0, G_MAXUINT, - HILDON_TIME_EDITOR_DURATION_UPPER_VALUE, - G_PARAM_READABLE | G_PARAM_WRITABLE) ); -} - -static -void hildon_time_editor_tap_and_hold_setup(GtkWidget * widget, - GtkWidget * menu, - GtkCallback func, - GtkWidgetTapAndHoldFlags flags) -{ - HildonTimeEditorPrivate *priv = HILDON_TIME_EDITOR_GET_PRIVATE(widget); - gint i; - - /* Forward this tap_and_hold_setup signal to all our child widgets */ - for (i = 0; i < ENTRY_COUNT; i++) - { - gtk_widget_tap_and_hold_setup(priv->entries[i], menu, func, - GTK_TAP_AND_HOLD_NO_SIGNALS); - } - gtk_widget_tap_and_hold_setup(priv->ampm_button, menu, func, - GTK_TAP_AND_HOLD_NO_SIGNALS); - gtk_widget_tap_and_hold_setup(priv->iconbutton, menu, func, - GTK_TAP_AND_HOLD_NONE); -} - -static void hildon_time_editor_entry_changed(GtkWidget *widget, gpointer data) -{ - g_assert(HILDON_IS_TIME_EDITOR(data)); - hildon_time_editor_validate(HILDON_TIME_EDITOR(data), TRUE); -} - -static void hildon_time_editor_init(HildonTimeEditor * editor) -{ - HildonTimeEditorPrivate *priv; - GtkWidget *hbox, *icon; - gint i; - - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - - gtk_widget_push_composite_child(); - - /* Setup defaults and create widgets */ - priv->ticks = 0; - priv->show_seconds = FALSE; - priv->show_hours = TRUE; - priv->ampm_pos_after = TRUE; - priv->clock_24h = TRUE; - priv->duration_mode = FALSE; - priv->iconbutton = gtk_button_new(); - priv->ampm_label = gtk_label_new(NULL); - priv->hm_label = gtk_label_new(NULL); - priv->sec_label = gtk_label_new(NULL); - priv->frame = gtk_frame_new(NULL); - priv->ampm_button = gtk_button_new(); - priv->skipper = FALSE; - - icon = gtk_image_new_from_icon_name(ICON_NAME, HILDON_ICON_SIZE_WIDG); - hbox = gtk_hbox_new(FALSE, 0); - - GTK_WIDGET_SET_FLAGS(editor, GTK_NO_WINDOW); - GTK_WIDGET_UNSET_FLAGS(priv->iconbutton, GTK_CAN_FOCUS | GTK_CAN_DEFAULT); - - gtk_container_set_border_width(GTK_CONTAINER(priv->frame), 0); - - gtk_container_add(GTK_CONTAINER(priv->iconbutton), icon); - gtk_container_add(GTK_CONTAINER(priv->ampm_button), priv->ampm_label); - gtk_button_set_relief(GTK_BUTTON(priv->ampm_button), GTK_RELIEF_NONE); - gtk_button_set_focus_on_click(GTK_BUTTON(priv->ampm_button), FALSE); - - /* Create hour, minute and second entries */ - for (i = 0; i < ENTRY_COUNT; i++) - { - priv->entries[i] = gtk_entry_new(); - - /* No frames for entries, so that they all appear to be inside one long entry */ - gtk_entry_set_has_frame(GTK_ENTRY(priv->entries[i]), FALSE); - - /* Set the entries to accept only numeric characters */ - g_object_set (priv->entries[i], "input-mode", - HILDON_INPUT_MODE_HINT_NUMERIC, NULL); - - /* The entry fields all take exactly two characters */ - gtk_entry_set_max_length (GTK_ENTRY(priv->entries[i]), 2); - gtk_entry_set_width_chars (GTK_ENTRY(priv->entries[i]), 2); - - g_signal_connect(priv->entries[i], "focus-in-event", - G_CALLBACK(hildon_time_editor_entry_focusin), editor); - g_signal_connect(priv->entries[i], "focus-out-event", - G_CALLBACK(hildon_time_editor_entry_focusout), editor); - g_signal_connect(priv->entries[i], "key-press-event", - G_CALLBACK(hildon_time_editor_entry_keypress), editor); - g_signal_connect(priv->entries[i], "changed", - G_CALLBACK(hildon_time_editor_entry_changed), editor); - - /* inserted signal sets time */ - g_signal_connect_after (G_OBJECT(priv->entries[i]), "insert_text", - G_CALLBACK (hildon_time_editor_inserted_text), - editor); - } - - /* clicked signal for am/pm label */ - g_signal_connect(G_OBJECT(priv->ampm_button), "clicked", - G_CALLBACK(hildon_time_editor_ampm_clicked), editor); - - /* clicked signal for icon */ - g_signal_connect(G_OBJECT(priv->iconbutton), "clicked", - G_CALLBACK(hildon_time_editor_icon_clicked), editor); - - /* Set ourself as the parent of all the widgets we created */ - gtk_widget_set_parent(priv->iconbutton, GTK_WIDGET(editor)); - gtk_box_pack_start(GTK_BOX(hbox), priv->entries[ENTRY_HOURS], FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(hbox), priv->hm_label, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(hbox), priv->entries[ENTRY_MINS], FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(hbox), priv->sec_label, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(hbox), priv->entries[ENTRY_SECS], FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(hbox), priv->ampm_button, FALSE, FALSE, 0); - gtk_misc_set_padding(GTK_MISC(priv->ampm_label), 0, 0); - - gtk_container_add(GTK_CONTAINER(priv->frame), hbox); - - /* Show created widgets */ - gtk_widget_set_parent(priv->frame, GTK_WIDGET(editor)); - gtk_widget_show_all(priv->frame); - gtk_widget_show_all(priv->iconbutton); - - /* Update AM/PM and time separators settings from locale */ - if (!hildon_time_editor_check_locale(editor)) { - /* Using 12h clock */ - priv->clock_24h = FALSE; - } else { - gtk_widget_hide(priv->ampm_button); - } - - if (!priv->show_seconds) { - gtk_widget_hide(priv->sec_label); - gtk_widget_hide(priv->entries[ENTRY_SECS]); - } - - /* set the default time to current time. */ - hildon_time_editor_set_to_current_time (editor); - - gtk_widget_pop_composite_child(); -} - -static void hildon_time_editor_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec) -{ - HildonTimeEditor *time_editor = HILDON_TIME_EDITOR(object); - switch (param_id) - { - case PROP_TICKS: - hildon_time_editor_set_ticks (time_editor, g_value_get_uint(value)); - break; - - case PROP_SHOW_SECONDS: - hildon_time_editor_set_show_seconds (time_editor, g_value_get_boolean(value)); - break; - - case PROP_SHOW_HOURS: - hildon_time_editor_set_show_hours (time_editor, g_value_get_boolean(value)); - break; - - case PROP_DURATION_MODE: - hildon_time_editor_set_duration_mode (time_editor, g_value_get_boolean(value)); - break; - - case PROP_DURATION_MIN: - hildon_time_editor_set_duration_min (time_editor, g_value_get_uint(value)); - break; - - case PROP_DURATION_MAX: - hildon_time_editor_set_duration_max (time_editor, g_value_get_uint(value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); - break; - } -} - -static void hildon_time_editor_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - HildonTimeEditor *time_editor = HILDON_TIME_EDITOR(object); - switch (param_id) - { - - case PROP_TICKS: - g_value_set_uint (value, hildon_time_editor_get_ticks (time_editor)); - break; - - case PROP_SHOW_SECONDS: - g_value_set_boolean (value, hildon_time_editor_get_show_seconds (time_editor)); - break; - - case PROP_SHOW_HOURS: - g_value_set_boolean (value, hildon_time_editor_get_show_hours (time_editor)); - break; - - case PROP_DURATION_MODE: - g_value_set_boolean (value, hildon_time_editor_get_duration_mode (time_editor)); - break; - - case PROP_DURATION_MIN: - g_value_set_uint (value, hildon_time_editor_get_duration_min (time_editor)); - break; - - case PROP_DURATION_MAX: - g_value_set_uint (value, hildon_time_editor_get_duration_max (time_editor)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); - break; - } -} - -/** - * hildon_time_editor_new: - * - * This function creates a new time editor. - * - * Returns: pointer to a new #HildonTimeEditor widget - */ - -GtkWidget *hildon_time_editor_new(void) -{ - return GTK_WIDGET(g_object_new(HILDON_TYPE_TIME_EDITOR, NULL)); -} - -static void hildon_time_editor_finalize(GObject * obj_self) -{ - HildonTimeEditorPrivate *priv = HILDON_TIME_EDITOR_GET_PRIVATE(obj_self); - - g_free(priv->am_symbol); - g_free(priv->pm_symbol); - - if (priv->highlight_idle) - g_source_remove(priv->highlight_idle); - - if (G_OBJECT_CLASS(parent_class)->finalize) - G_OBJECT_CLASS(parent_class)->finalize(obj_self); -} - -/** - * _hildon_time_editor_get_time_separators: - * @editor: the #HildonTimeEditor - * @hm_sep_label: the label that will show the hour:minutes separator - * @ms_sep_label: the label that will show the minutes:seconds separator - * - * Gets hour-minute separator and minute-second separator from current - * locale and sets then to the labels we set as parameters. Both - * parameters can be NULL if you just want to assing one separator. - * - */ -void -_hildon_time_editor_get_time_separators(GtkLabel *hm_sep_label, - GtkLabel *ms_sep_label) -{ - gchar buffer[256]; - gchar *separator; - GDate locale_test_date; - gchar *iter, *endp = NULL; - - /* Get localized time string */ - g_date_set_dmy(&locale_test_date, 1, 2, 1970); - (void) g_date_strftime(buffer, sizeof(buffer), "%X", &locale_test_date); - - if (hm_sep_label != NULL) - { - /* Find h-m separator */ - iter = buffer; - while (*iter && g_ascii_isdigit(*iter)) iter++; - - /* Extract h-m separator*/ - endp = iter; - while (*endp && !g_ascii_isdigit(*endp)) endp++; - separator = g_strndup(iter, endp - iter); - gtk_label_set_label(hm_sep_label, separator); - g_free(separator); - } - - if (ms_sep_label != NULL) - { - /* Find m-s separator */ - iter = endp; - while (*iter && g_ascii_isdigit(*iter)) iter++; - - /* Extract m-s separator*/ - endp = iter; - while (*endp && !g_ascii_isdigit(*endp)) endp++; - separator = g_strndup(iter, endp - iter); - gtk_label_set_label(ms_sep_label, separator); - g_free(separator); - } - -} - -/* Convert ticks to H:M:S. Ticks = seconds since 00:00:00. */ -static void ticks_to_time (guint ticks, - guint *hours, - guint *minutes, - guint *seconds) -{ - guint left; - - *hours = ticks / 3600; - left = ticks % 3600; - *minutes = left / 60; - *seconds = left % 60; -} - -/** - * hildon_time_editor_set_ticks: - * @editor: the #HildonTimeEditor widget - * @ticks: the duration to set, in seconds - * - * Sets the current duration in seconds. This means seconds from - * midnight, if not in duration mode. In case of any errors, it tries - * to fix it. - */ - -void hildon_time_editor_set_ticks (HildonTimeEditor * editor, - guint ticks) -{ - HildonTimeEditorPrivate *priv; - guint i, h, m, s; - gchar str[3]; - - g_assert(HILDON_IS_TIME_EDITOR(editor)); - - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - - /* Validate ticks. If it's too low or too high, set it to - min/max value for the current mode. */ - if (priv->duration_mode) - priv->ticks = CLAMP(ticks, priv->duration_min, priv->duration_max); - else { - /* Check that ticks value is valid. We only need to check that hours - don't exceed 23. */ - ticks_to_time (ticks, &h, &m, &s); - if (h > HOURS_MAX_24) - ticks = TICKS(HOURS_MAX_24, m, s); - - priv->ticks = ticks; - } - - /* Get the time in H:M:S. */ - ticks_to_time (priv->ticks, &h, &m, &s); - - if (!priv->clock_24h && !priv->duration_mode) - { - /* Convert 24h H:M:S values to 12h mode, and update AM/PM state */ - convert_to_12h (&h, &priv->am); - } - - /* Set H:M:S values to entries. We do not want to invoke validation - callbacks (since they can cause new call to this function), so we - block signals while setting values. */ - for (i = 0; i < ENTRY_COUNT; i++) - { - g_signal_handlers_block_by_func(priv->entries[i], - (gpointer) hildon_time_editor_entry_changed, editor); - - g_signal_handlers_block_by_func(priv->entries[i], - (gpointer) hildon_time_editor_inserted_text, editor); - - g_signal_handlers_block_by_func(priv->entries[i], - (gpointer) hildon_time_editor_entry_focusout, editor); - - } - - g_snprintf(str, sizeof(str), "%02u", h); - gtk_entry_set_text(GTK_ENTRY(priv->entries[ENTRY_HOURS]), str); - - g_snprintf(str, sizeof(str), "%02u", m); - gtk_entry_set_text(GTK_ENTRY(priv->entries[ENTRY_MINS]), str); - - g_snprintf(str, sizeof(str), "%02u", s); - gtk_entry_set_text(GTK_ENTRY(priv->entries[ENTRY_SECS]), str); - - for (i = 0; i < ENTRY_COUNT; i++) - { - g_signal_handlers_unblock_by_func(priv->entries[i], - (gpointer) hildon_time_editor_entry_changed, editor); - - g_signal_handlers_unblock_by_func(priv->entries[i], - (gpointer) hildon_time_editor_inserted_text, editor); - - g_signal_handlers_unblock_by_func(priv->entries[i], - (gpointer) hildon_time_editor_entry_focusout, editor); - - } - - /* Update AM/PM label in case we're in 12h mode */ - gtk_label_set_label(GTK_LABEL(priv->ampm_label), - priv->am ? priv->am_symbol : priv->pm_symbol); - - g_object_notify (G_OBJECT (editor), "ticks"); -} - -static void -hildon_time_editor_set_to_current_time (HildonTimeEditor * editor) -{ - time_t now; - const struct tm *tm; - - now = time(NULL); - tm = localtime(&now); - - if (tm != NULL) - hildon_time_editor_set_time(editor, tm->tm_hour, tm->tm_min, tm->tm_sec); -} - -/** - * hildon_time_editor_get_ticks: - * @editor: the #HildonTimeEditor widget - * - * This function returns the current duration, in seconds. - * This means seconds from midnight, if not in duration mode. - * - * Returns: current duration in seconds - */ - -guint hildon_time_editor_get_ticks (HildonTimeEditor * editor) -{ - HildonTimeEditorPrivate *priv; - - g_return_val_if_fail(editor, 0); - g_return_val_if_fail(HILDON_IS_TIME_EDITOR(editor), 0); - - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - - return (priv->ticks); -} - -/** - * hildon_time_editor_set_show_seconds: - * @editor: the #HildonTimeEditor - * @show_seconds: enable or disable showing of seconds - * - * This function shows or hides the seconds field. - */ - -void hildon_time_editor_set_show_seconds (HildonTimeEditor * editor, - gboolean show_seconds) -{ - HildonTimeEditorPrivate *priv; - - g_return_if_fail(HILDON_IS_TIME_EDITOR(editor)); - - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - - if (show_seconds != priv->show_seconds) { - priv->show_seconds = show_seconds; - - /* show/hide seconds field and its ':' label if the value changed. */ - if (show_seconds) { - gtk_widget_show(priv->entries[ENTRY_SECS]); - gtk_widget_show(priv->sec_label); - } else { - gtk_widget_hide(priv->entries[ENTRY_SECS]); - gtk_widget_hide(priv->sec_label); - } - - g_object_notify (G_OBJECT (editor), "show_seconds"); - } -} - -/** - * hildon_time_editor_get_show_seconds: - * @editor: the #HildonTimeEditor widget - * - * This function returns a boolean indicating the visibility of - * seconds in the #HildonTimeEditor - * - * Returns: TRUE if the seconds are visible - */ - -gboolean hildon_time_editor_get_show_seconds (HildonTimeEditor * editor) -{ - HildonTimeEditorPrivate *priv; - - g_return_val_if_fail (HILDON_IS_TIME_EDITOR (editor), FALSE); - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - - return (priv->show_seconds); -} - -/** - * hildon_time_editor_set_duration_mode: - * @editor: the #HildonTimeEditor - * @duration_mode: enable or disable duration editor mode - * - * This function sets the duration editor mode in which the maximum hours - * is 99. - */ - -void hildon_time_editor_set_duration_mode (HildonTimeEditor * editor, - gboolean duration_mode) -{ - HildonTimeEditorPrivate *priv; - - g_return_if_fail(HILDON_IS_TIME_EDITOR(editor)); - - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - - if (duration_mode != priv->duration_mode) { - priv->duration_mode = duration_mode; - - if (duration_mode) { - /* FIXME: Why do we reset the duration range here? - Would change API, so won't touch this for now. */ - hildon_time_editor_set_duration_range(editor, MIN_DURATION, - MAX_DURATION); - /* There's no AM/PM label or time picker icon in duration mode. - Make sure they're hidden. */ - gtk_widget_hide(GTK_WIDGET(priv->ampm_label)); - gtk_widget_hide(GTK_WIDGET(priv->ampm_button)); - gtk_widget_hide(GTK_WIDGET(priv->iconbutton)); - /* Duration mode has seconds by default. */ - hildon_time_editor_set_show_seconds(editor, TRUE); - } else { - /* Make sure AM/PM label and time picker icons are visible if needed */ - if (!priv->clock_24h) - gtk_widget_show(GTK_WIDGET(priv->ampm_label)); - - gtk_widget_show(GTK_WIDGET(priv->ampm_button)); - gtk_widget_show(GTK_WIDGET(priv->iconbutton)); - - /* Reset the ticks to current time. Anything set in duration mode - * is bound to be invalid or useless in time mode. - */ - hildon_time_editor_set_to_current_time (editor); - } - - g_object_notify (G_OBJECT (editor), "duration_mode"); - } -} - -/** - * hildon_time_editor_get_duration_mode: - * @editor: the #HildonTimeEditor widget - * - * This function returns a boolean indicating whether the #HildonTimeEditor - * is in the duration mode. - * - * Returns: TRUE if the #HildonTimeEditor is in duration mode - */ - -gboolean hildon_time_editor_get_duration_mode (HildonTimeEditor * editor) -{ - HildonTimeEditorPrivate *priv; - - g_return_val_if_fail (HILDON_IS_TIME_EDITOR (editor), FALSE); - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - - return (priv->duration_mode); -} - -/** - * hildon_time_editor_set_duration_min: - * @editor: the #HildonTimeEditor widget - * @duration_min: mimimum allowed duration - * - * Sets the minimum allowed duration for the duration mode. - * Note: Has no effect in time mode - */ - -void hildon_time_editor_set_duration_min (HildonTimeEditor * editor, - guint duration_min) -{ - HildonTimeEditorPrivate *priv; - - g_return_if_fail(HILDON_IS_TIME_EDITOR(editor)); - g_return_if_fail(duration_min >= MIN_DURATION); - - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - - if( !priv->duration_mode ) - return; - - priv->duration_min = duration_min; - - /* Clamp the current value to the minimum if necessary */ - if (priv->ticks < duration_min) - { - hildon_time_editor_set_ticks (editor, duration_min); - } - - g_object_notify (G_OBJECT (editor), "duration_min"); -} - -/** - * hildon_time_editor_get_duration_min: - * @editor: the #HildonTimeEditor widget - * - * This function returns the smallest duration the #HildonTimeEditor - * allows in the duration mode. - * - * Returns: minimum allowed duration in seconds - */ - -guint hildon_time_editor_get_duration_min (HildonTimeEditor * editor) -{ - HildonTimeEditorPrivate *priv; - - g_return_val_if_fail(HILDON_IS_TIME_EDITOR(editor), 0); - - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - - if( !priv->duration_mode ) - return (0); - - return (priv->duration_min); -} - -/** - * hildon_time_editor_set_duration_max: - * @editor: the #HildonTimeEditor widget - * @duration_max: maximum allowed duration in seconds - * - * Sets the maximum allowed duration in seconds for the duration mode. - * Note: Has no effect in time mode - */ - -void hildon_time_editor_set_duration_max (HildonTimeEditor * editor, - guint duration_max) -{ - HildonTimeEditorPrivate *priv; - - g_return_if_fail(HILDON_IS_TIME_EDITOR(editor)); - g_return_if_fail(duration_max <= MAX_DURATION); - - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - - if( !priv->duration_mode ) - return; - - priv->duration_max = duration_max; - - /* Clamp the current value to the maximum if necessary */ - if (priv->ticks > duration_max) - { - hildon_time_editor_set_ticks (editor, duration_max); - } - - g_object_notify (G_OBJECT (editor), "duration_max"); -} - -/** - * hildon_time_editor_get_duration_max: - * @editor: the #HildonTimeEditor widget - * - * This function returns the longest duration the #HildonTimeEditor - * allows in the duration mode. - * - * Returns: maximum allowed duration in seconds - */ - -guint hildon_time_editor_get_duration_max (HildonTimeEditor * editor) -{ - HildonTimeEditorPrivate *priv; - - g_return_val_if_fail(HILDON_IS_TIME_EDITOR(editor), 0); - - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - - if( !priv->duration_mode ) - return (0); - - return (priv->duration_max); -} - - -/** - * hildon_time_editor_set_time: - * @editor: the #HildonTimeEditor widget - * @hours: hours - * @minutes: minutes - * @seconds: seconds - * - * This function sets the time on an existing time editor. If the - * time specified by the arguments is invalid, it's fixed. - * The time is assumed to be in 24h format. - */ - -void hildon_time_editor_set_time(HildonTimeEditor * editor, guint hours, - guint minutes, guint seconds) -{ - g_return_if_fail(HILDON_IS_TIME_EDITOR(editor)); - - hildon_time_editor_set_ticks (editor, TICKS(hours, minutes, seconds)); -} - -/** - * hildon_time_editor_get_time: - * @editor: the #HildonTimeEditor widget - * @hours: hours - * @minutes: minutes - * @seconds: seconds - * - * Gets the time of the #HildonTimeEditor widget. The time returned is - * always in 24h format. - */ - -void hildon_time_editor_get_time(HildonTimeEditor * editor, - guint * hours, - guint * minutes, guint * seconds) -{ - HildonTimeEditorPrivate *priv; - - g_return_if_fail(HILDON_IS_TIME_EDITOR(editor)); - - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - - ticks_to_time (hildon_time_editor_get_ticks (editor), - hours, minutes, seconds); -} - -/** - * hildon_time_editor_set_duration_range: - * @editor: the #HildonTimeEditor widget - * @min_seconds: minimum allowed time in seconds - * @max_seconds: maximum allowed time in seconds - * - * Sets the duration editor time range of the #HildonTimeEditor widget. - */ - -void hildon_time_editor_set_duration_range(HildonTimeEditor * editor, - guint min_seconds, - guint max_seconds) -{ - HildonTimeEditorPrivate *priv; - guint tmp; - - g_return_if_fail(HILDON_IS_TIME_EDITOR(editor)); - - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - /* Swap values if reversed */ - if (min_seconds > max_seconds) - { - tmp = max_seconds; - max_seconds = min_seconds; - min_seconds = tmp; - } - - hildon_time_editor_set_duration_max (editor, max_seconds); - hildon_time_editor_set_duration_min (editor, min_seconds); - - if (priv->duration_mode) { - /* Set minimum allowed value for duration editor. - FIXME: Shouldn't it be changed only if it's not in range? - Would change API, so won't touch this for now. */ - hildon_time_editor_set_ticks(editor, min_seconds); - } -} - -/** - * hildon_time_editor_get_duration_range: - * @editor: the #HildonTimeEditor widget - * @min_seconds: pointer to guint - * @max_seconds: pointer to guint - * - * Gets the duration editor time range of the #HildonTimeEditor widget. - */ - -void hildon_time_editor_get_duration_range(HildonTimeEditor * editor, - guint * min_seconds, - guint * max_seconds) -{ - HildonTimeEditorPrivate *priv; - - g_return_if_fail(HILDON_IS_TIME_EDITOR(editor)); - - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - - *min_seconds = priv->duration_min; - *max_seconds = priv->duration_max; -} - -static gboolean hildon_time_editor_check_locale(HildonTimeEditor * editor) -{ - HildonTimeEditorPrivate *priv; - - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - - /* Update time separator symbols */ - _hildon_time_editor_get_time_separators(GTK_LABEL(priv->hm_label), GTK_LABEL(priv->sec_label)); - - /* Get AM/PM symbols. */ - priv->am_symbol = g_strdup(nl_langinfo(AM_STR)); - priv->pm_symbol = g_strdup(nl_langinfo(PM_STR)); - - if (priv->am_symbol[0] == '\0') - return TRUE; - else { - /* 12h clock mode. Check if AM/PM should be before or after time. - %p is the AM/PM string, so we assume that if the format string - begins with %p it's in the beginning, and in any other case it's - in the end (although that's not necessarily the case). */ - if (strncmp(nl_langinfo(T_FMT_AMPM), "%p", 2) == 0) - priv->ampm_pos_after = FALSE; - return FALSE; - } -} - -static gboolean hildon_time_editor_entry_focusin(GtkWidget * widget, - GdkEventFocus * event, - gpointer data) -{ - g_idle_add((GSourceFunc) _hildon_time_editor_entry_select_all, - GTK_ENTRY(widget)); - - return FALSE; -} - -static gboolean -hildon_time_editor_time_error(HildonTimeEditor *editor, - HildonTimeEditorErrorType type) -{ - return TRUE; -} - -/* Returns negative if we didn't get value, - * and should stop further validation - */ -static gint validated_conversion(HildonTimeEditorPrivate *priv, - GtkWidget *field, - gint min, - gint max, - gint def_value, - gboolean allow_intermediate, - guint *error_code, - GString *error_string) -{ - const gchar *text; - gchar *tail; - long value; - - text = gtk_entry_get_text(GTK_ENTRY(field)); - - if (text && text[0]) - { - /* Try to convert entry text to number */ - value = strtol(text, &tail, 10); - - /* Check if conversion succeeded */ - if ((tail[0] == 0) && !(text[0] == '-')) - { - if (value > max) { - g_string_printf(error_string, _("ckct_ib_maximum_value"), max); - priv->error_widget = field; - *error_code = MAX_VALUE; - return max; - } - if (value < min && !allow_intermediate) { - g_string_printf(error_string, _("ckct_ib_minimum_value"), min); - priv->error_widget = field; - *error_code = MIN_VALUE; - return min; - } - - return value; - } - /* We'll handle failed conversions soon */ - else - { - if ((tail[0] == '-') || (text[0] == '-')) - { - g_string_printf(error_string, _("ckct_ib_minimum_value"), min); - priv->error_widget = field; - *error_code = MIN_VALUE; - return min; - } - } - } - else if (allow_intermediate) - return -1; /* Empty field while user is still editing. No error, but - cannot validate either... */ - else /* Empty field: show error and set value to minimum allowed */ - { - g_string_printf(error_string, _("ckct_ib_set_a_value_within_range"), min, max); - priv->error_widget = field; - *error_code = WITHIN_RANGE; - return def_value; - } - - /* Empty field and not allowed intermediated OR failed conversion */ - g_string_printf(error_string, _("ckct_ib_set_a_value_within_range"), min, max); - priv->error_widget = field; - *error_code = WITHIN_RANGE; - return -1; -} - -static void -hildon_time_editor_real_validate(HildonTimeEditor *editor, - gboolean allow_intermediate, GString *error_string) -{ - HildonTimeEditorPrivate *priv; - guint h, m, s, ticks; - guint error_code; - guint max_hours, min_hours, def_hours; - guint max_minutes, min_minutes, def_minutes; - guint max_seconds, min_seconds, def_seconds; - gboolean r; - - g_assert(HILDON_IS_TIME_EDITOR(editor)); - - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - - /* Find limits for field based validation. */ - if (priv->duration_mode) - { - ticks_to_time(priv->duration_min, &min_hours, &min_minutes, &min_seconds); - ticks_to_time(priv->duration_max, &max_hours, &max_minutes, &max_seconds); - } else { - if (priv->clock_24h) { - max_hours = HOURS_MAX_24; - min_hours = HOURS_MIN_24; - } else { - max_hours = HOURS_MAX_12; - min_hours = HOURS_MIN_12; - } - } - - hildon_time_editor_get_time(editor, &def_hours, &def_minutes, &def_seconds); - - /* Get time components from fields and validate them... */ - if (priv->show_hours) { - h = validated_conversion(priv, priv->entries[ENTRY_HOURS], min_hours, max_hours, def_hours, - allow_intermediate, &error_code, error_string); - if (priv->error_widget == priv->entries[ENTRY_HOURS]) - g_signal_emit (editor, time_editor_signals [TIME_ERROR], 0, hour_errors[error_code], &r); - if ((gint) h < 0) return; - } - else h = 0; - m = validated_conversion(priv, priv->entries[ENTRY_MINS], MINUTES_MIN, MINUTES_MAX, def_minutes, - allow_intermediate, &error_code, error_string); - if (priv->error_widget == priv->entries[ENTRY_MINS]) - g_signal_emit (editor, time_editor_signals [TIME_ERROR], 0, min_errors[error_code], &r); - if ((gint) m < 0) return; - if (priv->show_seconds) { - s = validated_conversion(priv, priv->entries[ENTRY_SECS], SECONDS_MIN, SECONDS_MAX, def_seconds, - allow_intermediate, &error_code, error_string); - if (priv->error_widget == priv->entries[ENTRY_SECS]) - g_signal_emit (editor, time_editor_signals [TIME_ERROR], 0, sec_errors[error_code], &r); - if ((gint) s < 0) return; - } - else s = 0; - - /* Ok, we now do separate check that tick count is valid for duration mode */ - if (priv->duration_mode) - { - ticks = TICKS(h, m, s); - - if (ticks < priv->duration_min && !allow_intermediate) - { - g_string_printf(error_string, - _("ckct_ib_min_allowed_duration_hts"), - min_hours, min_minutes, min_seconds); - hildon_time_editor_set_ticks (editor, priv->duration_min); - priv->error_widget = priv->show_hours ? priv->entries[ENTRY_HOURS] : priv->entries[ENTRY_MINS]; - g_signal_emit (editor, time_editor_signals[TIME_ERROR], 0, MIN_DUR, &r); - return; - } - else if (ticks > priv->duration_max) - { - g_string_printf(error_string, - _("ckct_ib_max_allowed_duration_hts"), - max_hours, max_minutes, max_seconds); - hildon_time_editor_set_ticks (editor, priv->duration_max); - priv->error_widget = priv->show_hours ? priv->entries[ENTRY_HOURS] : priv->entries[ENTRY_MINS]; - g_signal_emit (editor, time_editor_signals[TIME_ERROR], 0, MAX_DUR, &r); - return; - } - } - else if (!priv->clock_24h) - convert_to_24h (&h, priv->am); - - /* The only case when we do not want to refresh the - time display, is when the user is editing a value - (unless the value was out of bounds and we have to fix it) */ - if (!allow_intermediate || priv->error_widget) - hildon_time_editor_set_time (editor, h, m, s); -} - -/* Setting text to entries causes entry to recompute itself - in idle callback, which remove selection. Because of this - we need to do selection in idle as well. */ -static gboolean highlight_callback(gpointer data) -{ - HildonTimeEditorPrivate *priv; - GtkWidget *widget; - gint i; - - g_assert(HILDON_IS_TIME_EDITOR(data)); - priv = HILDON_TIME_EDITOR_GET_PRIVATE(data); - - GDK_THREADS_ENTER (); - - widget = priv->error_widget; - priv->error_widget = NULL; - - if (GTK_IS_WIDGET(widget) == FALSE) - goto Done; - - /* Avoid revalidation because it will issue the date_error signal - twice when there is an empty field. We must block the signal - for all the entries because we do not know where the focus - comes from */ - for (i = 0; i < ENTRY_COUNT; i++) - g_signal_handlers_block_by_func(priv->entries[i], - (gpointer) hildon_time_editor_entry_focusout, data); - gtk_editable_select_region(GTK_EDITABLE(widget), 0, -1); - gtk_widget_grab_focus(widget); - for (i = 0; i < ENTRY_COUNT; i++) - g_signal_handlers_unblock_by_func(priv->entries[i], - (gpointer) hildon_time_editor_entry_focusout, data); - -Done: - priv->highlight_idle = 0; - GDK_THREADS_LEAVE (); - - return FALSE; -} - -/* Update ticks from current H:M:S entries. If they're invalid, show an - infoprint and update the fields unless they're empty. */ -static void -hildon_time_editor_validate (HildonTimeEditor *editor, gboolean allow_intermediate) -{ - HildonTimeEditorPrivate *priv; - GString *error_message; - - g_assert(HILDON_IS_TIME_EDITOR(editor)); - - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - - /* if there is already an error we do nothing until it will be managed by the idle */ - if (priv->highlight_idle == 0 && priv->skipper == FALSE) - { - priv->skipper = TRUE; - error_message = g_string_new(NULL); - hildon_time_editor_real_validate(editor, - allow_intermediate, error_message); - - if (priv->error_widget) - { - hildon_banner_show_information(priv->error_widget, NULL, - error_message->str); - - priv->highlight_idle = g_idle_add(highlight_callback, editor); - } - - priv->skipper = FALSE; - g_string_free(error_message, TRUE); - } -} - -/* on inserted text, if entry has two digits, jumps to the next field. */ -static void -hildon_time_editor_inserted_text (GtkEditable * editable, - gchar * new_text, - gint new_text_length, - gint * position, - gpointer user_data) -{ - HildonTimeEditor *editor; - GtkEntry *entry; - gchar *value; - HildonTimeEditorPrivate *priv; - - entry = GTK_ENTRY(editable); - editor = HILDON_TIME_EDITOR(user_data); - - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - - /* if there is already an error we don't have to do anything */ - if (!priv->error_widget) - { - - value = (gchar *) gtk_entry_get_text(entry); - - if (strlen(value) == 2) - { - if (GTK_WIDGET(editable) == priv->entries[ENTRY_HOURS]) - { - /* We already checked the input in changed signal, but - * now we will re-check it again in focus-out we - * intermediate flag set to FALSE */ - gtk_widget_grab_focus(priv->entries[ENTRY_MINS]); - *position = -1; - } - else if (GTK_WIDGET(editable) == priv->entries[ENTRY_MINS] && - GTK_WIDGET_VISIBLE (priv->entries[ENTRY_SECS])) - { - /* See above */ - gtk_widget_grab_focus(priv->entries[ENTRY_SECS]); - *position = -1; - } - } - } -} - -static gboolean hildon_time_editor_entry_focusout(GtkWidget * widget, - GdkEventFocus * event, - gpointer data) -{ - g_assert(HILDON_IS_TIME_EDITOR(data)); - - /* Validate the given time and update ticks. */ - hildon_time_editor_validate(HILDON_TIME_EDITOR(data), FALSE); - - return FALSE; -} - -static gboolean -hildon_time_editor_ampm_clicked(GtkWidget * widget, - gpointer data) -{ - HildonTimeEditor *editor; - HildonTimeEditorPrivate *priv; - - g_assert(GTK_IS_WIDGET(widget)); - g_assert(HILDON_IS_TIME_EDITOR(data)); - - editor = HILDON_TIME_EDITOR(data); - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - - /* First validate the given time and update ticks. */ - hildon_time_editor_validate (editor, FALSE); - - /* Apply the AM/PM change by moving the current time by 12 hours */ - if (priv->am) { - /* 00:00 .. 11:59 -> 12:00 .. 23:59 */ - hildon_time_editor_set_ticks (editor, priv->ticks + 12*3600); - } else { - /* 12:00 .. 23:59 -> 00:00 .. 11:59 */ - hildon_time_editor_set_ticks (editor, priv->ticks - 12*3600); - } - return FALSE; -} - -static gboolean -hildon_time_editor_icon_clicked(GtkWidget * widget, gpointer data) -{ - HildonTimeEditor *editor; - GtkWidget *picker; - GtkWidget *parent; - guint h, m, s, result; - HildonTimeEditorPrivate *priv; - - g_assert(HILDON_IS_TIME_EDITOR(data)); - - editor = HILDON_TIME_EDITOR(data); - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - - /* icon is passive in duration editor mode */ - if (hildon_time_editor_get_duration_mode(editor)) - return FALSE; - - /* Validate and do not launch if broken */ - hildon_time_editor_validate(HILDON_TIME_EDITOR(data), FALSE); - if (priv->error_widget != NULL) - return FALSE; - - /* Launch HildonTimePicker dialog */ - parent = gtk_widget_get_ancestor(GTK_WIDGET(editor), GTK_TYPE_WINDOW); - picker = hildon_time_picker_new(GTK_WINDOW(parent)); - - hildon_time_editor_get_time(editor, &h, &m, &s); - hildon_time_picker_set_time(HILDON_TIME_PICKER(picker), h, m); - - result = gtk_dialog_run(GTK_DIALOG(picker)); - switch (result) { - case GTK_RESPONSE_OK: - case GTK_RESPONSE_ACCEPT: - /* Use the selected time */ - hildon_time_picker_get_time(HILDON_TIME_PICKER(picker), &h, &m); - hildon_time_editor_set_time(editor, h, m, 0); - break; - default: - break; - } - - gtk_widget_destroy(picker); - return FALSE; -} - -static void hildon_time_editor_size_request(GtkWidget * widget, - GtkRequisition * requisition) -{ - HildonTimeEditor *editor; - HildonTimeEditorPrivate *priv; - GtkRequisition req; - - editor = HILDON_TIME_EDITOR(widget); - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - - /* Get frame's size */ - gtk_widget_size_request(priv->frame, requisition); - - if (GTK_WIDGET_VISIBLE(priv->iconbutton)) - { - gtk_widget_size_request(priv->iconbutton, &req); - /* Reserve space for icon */ - requisition->width += req.width + ICON_PRESSED + - HILDON_MARGIN_DEFAULT; - } - - /* FIXME: It's evil to use hardcoded TIME_EDITOR_HEIGHT. For now we'll - want to force this since themes might have varying thickness values - which cause the height to change. */ - requisition->height = TIME_EDITOR_HEIGHT; -} - -static void hildon_time_editor_size_allocate(GtkWidget * widget, - GtkAllocation * allocation) -{ - HildonTimeEditorPrivate *priv = HILDON_TIME_EDITOR_GET_PRIVATE(widget); - GtkAllocation alloc; - GtkRequisition req, max_req; - - widget->allocation = *allocation; - gtk_widget_get_child_requisition(widget, &max_req); - - /* Center horizontally */ - alloc.x = allocation->x + MAX(allocation->width - max_req.width, 0) / 2; - /* Center vertically */ - alloc.y = allocation->y + MAX(allocation->height - max_req.height, 0) / 2; - - /* allocate frame */ - gtk_widget_get_child_requisition(priv->frame, &req); - - alloc.width = req.width; - alloc.height = max_req.height; - gtk_widget_size_allocate(priv->frame, &alloc); - - /* allocate icon */ - if (GTK_WIDGET_VISIBLE(priv->iconbutton)) { - gtk_widget_get_child_requisition(priv->iconbutton, &req); - - alloc.x += alloc.width + HILDON_MARGIN_DEFAULT; - alloc.width = req.width; - gtk_widget_size_allocate(priv->iconbutton, &alloc); - } - - /* FIXME: ugly way to move labels up. They just don't seem move up - otherwise. This is likely because we force the editor to be - smaller than it otherwise would be. */ - alloc = priv->ampm_label->allocation; - alloc.y = allocation->y - 2; - alloc.height = max_req.height + 2; - gtk_widget_size_allocate(priv->ampm_label, &alloc); - - alloc = priv->hm_label->allocation; - alloc.y = allocation->y - 2; - alloc.height = max_req.height + 2; - gtk_widget_size_allocate(priv->hm_label, &alloc); - - alloc = priv->sec_label->allocation; - alloc.y = allocation->y - 2; - alloc.height = max_req.height + 2; - gtk_widget_size_allocate(priv->sec_label, &alloc); -} - -static gboolean hildon_time_editor_entry_keypress(GtkWidget * widget, - GdkEventKey * event, - gpointer data) -{ - HildonTimeEditor *editor; - HildonTimeEditorPrivate *priv; - gint cursor_pos; - gboolean r; - - g_assert(GTK_IS_ENTRY(widget)); - g_assert(event != NULL); - g_assert(HILDON_IS_TIME_EDITOR(data)); - - editor = HILDON_TIME_EDITOR(data); - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - cursor_pos = gtk_editable_get_position(GTK_EDITABLE(widget)); - - /* Show error message in case the key pressed is not allowed - (only digits and control characters are allowed )*/ - if (!g_unichar_isdigit(event->keyval) && !(event->keyval & 0xF000)) { - g_signal_emit(editor, time_editor_signals[TIME_ERROR], 0, INVALID_CHAR, &r); - hildon_banner_show_information(widget, NULL, _("ckct_ib_illegal_character")); - return TRUE; - } - - switch (event->keyval) - { - case GDK_Return: - /* Return key popups up time picker dialog. Visually it looks as if - the time picker icon was clicked. Before opening the time picker - the fields are first validated and fixed. */ - hildon_time_editor_validate (editor, FALSE); - hildon_gtk_button_set_depressed(GTK_BUTTON(priv->iconbutton), TRUE); - hildon_time_editor_icon_clicked(widget, data); - hildon_gtk_button_set_depressed(GTK_BUTTON(priv->iconbutton), FALSE); - return TRUE; - - case GDK_Left: - /* left arrow pressed in the entry. If we are on first position, try to - move to the previous field. */ - if (cursor_pos == 0) { - (void) gtk_widget_child_focus(GTK_WIDGET(editor), GTK_DIR_LEFT); - return TRUE; - } - break; - - case GDK_Right: - /* right arrow pressed in the entry. If we are on last position, try to - move to the next field. */ - if (cursor_pos >= g_utf8_strlen(gtk_entry_get_text(GTK_ENTRY(widget)), -1)) { - (void) gtk_widget_child_focus(GTK_WIDGET(editor), GTK_DIR_RIGHT); - return TRUE; - } - break; - - default: - break; - }; - - return FALSE; -} - -/*** - * Utility functions - */ - -static void -convert_to_12h (guint *h, gboolean *am) -{ - g_assert(0 <= *h && *h < 24); - - /* 00:00 to 00:59 add 12 hours */ - /* 01:00 to 11:59 straight to am */ - /* 12:00 to 12:59 straight to pm */ - /* 13:00 to 23:59 subtract 12 hours */ - - if ( *h == 0 ) { *am = TRUE; *h += 12;} - else if ( 1 <= *h && *h < 12 ) { *am = TRUE; } - else if ( 12 <= *h && *h < 13 ) { *am = FALSE; } - else { *am = FALSE; *h -= 12;} -} - -static void -convert_to_24h (guint *h, gboolean am) -{ - if (*h == 12 && am) /* 12 midnight - 12:59 AM subtract 12 hours */ - { - *h -= 12; - } - else if (!am && 1 <= *h && *h < 12) /* 1:00 PM - 11:59 AM add 12 hours */ - { - *h += 12; - } -} - -/** - * hildon_time_editor_set_show_hours: - * @editor: The #HildonTimeEditor. - * @enable: Enable or disable showing of hours. - * - * This function shows or hides the hours field. - * - * Since: 0.12.4 - **/ -void hildon_time_editor_set_show_hours(HildonTimeEditor * editor, - gboolean show_hours) -{ - HildonTimeEditorPrivate *priv; - - g_return_if_fail(HILDON_IS_TIME_EDITOR(editor)); - - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - - if (show_hours != priv->show_hours) { - priv->show_hours = show_hours; - - /* show/hide hours field and its ':' label if the value changed. */ - if (show_hours) { - gtk_widget_show(priv->entries[ENTRY_HOURS]); - gtk_widget_show(priv->hm_label); - } else { - gtk_widget_hide(priv->entries[ENTRY_HOURS]); - gtk_widget_hide(priv->hm_label); - } - - g_object_notify (G_OBJECT (editor), "show_hours"); - } -} - -/** - * hildon_time_editor_get_show_hours: - * @self: the @HildonTimeEditor widget. - * - * This function returns a boolean indicating the visibility of - * hours in the @HildonTimeEditor - * - * Return value: TRUE if hours are visible. - * - * Since: 0.12.4-1 - **/ -gboolean hildon_time_editor_get_show_hours(HildonTimeEditor *editor) -{ - HildonTimeEditorPrivate *priv; - - g_return_val_if_fail (HILDON_IS_TIME_EDITOR (editor), FALSE); - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - - return priv->show_hours; -} - -/*** - * Deprecated functions - */ - -/** - * hildon_time_editor_show_seconds: - * @editor: the #HildonTimeEditor - * @enable: enable or disable showing of seconds - * - * This function is deprecated, - * use #hildon_time_editor_set_show_seconds instead. - */ -void hildon_time_editor_show_seconds(HildonTimeEditor * editor, - gboolean enable) -{ - hildon_time_editor_set_show_seconds (editor, enable); -} -/** - * hildon_time_editor_enable_duration_mode: - * @editor: the #HildonTimeEditor - * @enable: enable or disable duration editor mode - * - * This function is deprecated, - * use #hildon_time_editor_set_duration_mode instead. - */ -void hildon_time_editor_enable_duration_mode(HildonTimeEditor * editor, - gboolean enable) -{ - hildon_time_editor_set_duration_mode (editor, enable); -} - -/* Idle callback */ -static gboolean -_hildon_time_editor_entry_select_all (GtkWidget *widget) -{ - GDK_THREADS_ENTER (); - gtk_editable_select_region(GTK_EDITABLE(widget), 0, -1); - GDK_THREADS_LEAVE (); - return FALSE; -} diff --git a/hildon-widgets/hildon-time-editor.h b/hildon-widgets/hildon-time-editor.h deleted file mode 100644 index 7169fa0..0000000 --- a/hildon-widgets/hildon-time-editor.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_TIME_EDITOR_H__ -#define __HILDON_TIME_EDITOR_H__ - -#include - -G_BEGIN_DECLS - -#define HILDON_TYPE_TIME_EDITOR (hildon_time_editor_get_type()) - -#define HILDON_TIME_EDITOR(obj) (GTK_CHECK_CAST (obj, HILDON_TYPE_TIME_EDITOR, HildonTimeEditor)) -#define HILDON_TIME_EDITOR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), HILDON_TYPE_TIME_EDITOR, HildonTimeEditorClass)) - -#define HILDON_IS_TIME_EDITOR(obj) (GTK_CHECK_TYPE (obj, HILDON_TYPE_TIME_EDITOR)) -#define HILDON_IS_TIME_EDITOR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_TIME_EDITOR)) - - -typedef enum -{ - NO_TIME_ERROR = -1, - MAX_HOURS, - MAX_MINS, - MAX_SECS, - MIN_HOURS, - MIN_MINS, - MIN_SECS, - EMPTY_HOURS, - EMPTY_MINS, - EMPTY_SECS, - MIN_DUR, - MAX_DUR, - INVALID_TIME, - INVALID_CHAR -} HildonTimeEditorErrorType; - -typedef struct _HildonTimeEditor HildonTimeEditor; -typedef struct _HildonTimeEditorClass HildonTimeEditorClass; - -struct _HildonTimeEditor { - GtkContainer parent; -}; - -struct _HildonTimeEditorClass { - GtkContainerClass parent_class; - - gboolean (*time_error) (HildonTimeEditor *editor, - HildonTimeEditorErrorType type); -}; - -GType hildon_time_editor_get_type(void) G_GNUC_CONST; -GtkWidget *hildon_time_editor_new(void); - - -void hildon_time_editor_set_time (HildonTimeEditor * editor, - guint hours, - guint minutes, - guint seconds); - -void hildon_time_editor_get_time (HildonTimeEditor * editor, - guint * hours, - guint * minutes, - guint * seconds); - -#ifndef HILDON_DISABLE_DEPRECATED -void hildon_time_editor_show_seconds (HildonTimeEditor * editor, gboolean enable); -void hildon_time_editor_enable_duration_mode (HildonTimeEditor * editor, gboolean enable); -#endif /* HILDON_DISABLE_DEPRECATED */ - - -void hildon_time_editor_set_duration_range (HildonTimeEditor * editor, - guint min_seconds, - guint max_seconds); - -void hildon_time_editor_get_duration_range (HildonTimeEditor * editor, - guint * min_seconds, - guint * max_seconds); - -void hildon_time_editor_set_ticks (HildonTimeEditor * editor, guint ticks); -guint hildon_time_editor_get_ticks (HildonTimeEditor * editor); - -void hildon_time_editor_set_show_seconds (HildonTimeEditor * editor, gboolean show_seconds); -gboolean hildon_time_editor_get_show_seconds (HildonTimeEditor * editor); - -void hildon_time_editor_set_show_hours (HildonTimeEditor * editor, gboolean show_hours); -gboolean hildon_time_editor_get_show_hours (HildonTimeEditor * editor); - -void hildon_time_editor_set_duration_mode (HildonTimeEditor * editor, gboolean duration_mode); -gboolean hildon_time_editor_get_duration_mode (HildonTimeEditor * editor); - -void hildon_time_editor_set_duration_min (HildonTimeEditor * editor, guint duration_min); -guint hildon_time_editor_get_duration_min (HildonTimeEditor * editor); - -void hildon_time_editor_set_duration_max (HildonTimeEditor * editor, guint duration_max); -guint hildon_time_editor_get_duration_max (HildonTimeEditor * editor); - - -G_END_DECLS -#endif /* __HILDON_TIME_EDITOR_H__ */ diff --git a/hildon-widgets/hildon-time-picker.c b/hildon-widgets/hildon-time-picker.c deleted file mode 100644 index bdf6fba..0000000 --- a/hildon-widgets/hildon-time-picker.c +++ /dev/null @@ -1,933 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-time-picker - * @short_description: A dialog popup widget which lets the user set the time - * @see_also: #HildonTimeEditor - * - * #HildonTimePicker is a dialog popup widget which lets the user set the time, - * using up/down arrows on hours and minutes. There are two arrows for minutes, - * so that minutes can be added also in 10 min increments.This widget is mainly - * used as a part of #HildonTimeEditor implementation. - */ - -#include "hildon-time-picker.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_CONFIG_H -#include -#endif - -#define _(String) dgettext(PACKAGE, String) - -#define HILDON_TIME_PICKER_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_TIME_PICKER, HildonTimePickerPrivate)) - -#define DEFAULT_HOURS 1 -#define DEFAULT_MINUTES 1 -#define DEFAULT_ARROW_WIDTH 26 -#define DEFAULT_ARROW_HEIGHT 26 - -#define MINS_IN_1H (60) -#define MINS_IN_24H (MINS_IN_1H * 24) -#define MINS_IN_12H (MINS_IN_1H * 12) - -#define HILDON_TIME_PICKER_LABEL_X_PADDING 0 -#define HILDON_TIME_PICKER_LABEL_Y_PADDING 1 - - -/* Indices for grouped labels in priv->widgets */ -enum -{ - WIDGET_GROUP_HOURS, - WIDGET_GROUP_10_MINUTES, - WIDGET_GROUP_1_MINUTES, - WIDGET_GROUP_AMPM, - - WIDGET_GROUP_COUNT -}; - -/* Indices for up/down buttons in group->buttons */ -enum -{ - BUTTON_UP, - BUTTON_DOWN, - - BUTTON_COUNT -}; - -typedef struct -{ - GtkWidget *frame; - GtkWidget *eventbox; - GtkLabel *label; - - /* buttons are used for hours and minutes, but not for am/pm */ - GtkWidget *buttons[BUTTON_COUNT]; - -} HildonTimePickerWidgetGroup; - -static GtkDialogClass *parent_class; - -struct _HildonTimePickerPrivate -{ - HildonTimePickerWidgetGroup widgets[WIDGET_GROUP_COUNT]; - - gchar *am_symbol; - gchar *pm_symbol; - - guint key_repeat; - guint minutes; /* time in minutes since midnight */ - gint mul; /* for key repeat handling */ - guint timer_id; - - guint show_ampm : 1; /* 12 hour clock, show AM/PM */ - guint ampm_left : 1; - guint button_press : 1; - guint start_key_repeat : 1; -}; - -enum -{ - PROP_MINUTES = 1 -}; - - -static const gint button_multipliers[WIDGET_GROUP_COUNT][2] = -{ - { MINS_IN_1H, -MINS_IN_1H }, - { 10, -10 }, - { 1, -1 }, - { 0, 0 } -}; - -static void -hildon_time_picker_class_init( HildonTimePickerClass *klass ); - -static void -hildon_time_picker_init( HildonTimePicker *picker ); - -static gboolean -hildon_time_picker_key_repeat_timeout( gpointer tpicker ); - -static void -hildon_time_picker_change_time( HildonTimePicker *picker, guint minutes ); - -static gboolean -hildon_time_picker_ampm_release( GtkWidget *widget, GdkEvent *event, - HildonTimePicker *picker ); - -static gboolean -hildon_time_picker_arrow_press( GtkWidget *widget, GdkEvent *event, - HildonTimePicker *picker ); -static gboolean -hildon_time_picker_arrow_release( GtkWidget *widget, GdkEvent *event, - HildonTimePicker *picker ); - -static void -hildon_time_picker_finalize( GObject *object ); - -static void -hildon_time_picker_get_property( GObject *object, guint param_id, - GValue *value, GParamSpec *pspec ); - -static void -hildon_time_picker_set_property( GObject *object, guint param_id, - const GValue *value, GParamSpec *pspec ); - -static gboolean -hildon_time_picker_event_box_focus_in( GtkWidget *widget, GdkEvent *event, - gpointer unused ); - -static gboolean -hildon_time_picker_event_box_focus_out( GtkWidget *widget, GdkEvent *event, - gpointer unused ); - -static gboolean -hildon_time_picker_event_box_key_press( GtkWidget *widget, GdkEventKey *event, - HildonTimePicker *picker ); - -static gboolean -hildon_time_picker_event_box_key_release( GtkWidget *widget, GdkEventKey *event, - HildonTimePicker *picker ); - -static gboolean -hildon_time_picker_event_box_button_press( GtkWidget *widget, GdkEventKey *event, - gpointer unused ); - -static void -hildon_time_picker_map( GtkWidget *widget ); - -static void -frame_size_request (GtkWidget *widget, GtkRequisition *requistion); - -GType hildon_time_picker_get_type( void ) -{ - static GType picker_type = 0; - - if( !picker_type ) - { - static const GTypeInfo picker_info = - { - sizeof(HildonTimePickerClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc)hildon_time_picker_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonTimePicker), - 0, /* n_preallocs */ - (GInstanceInitFunc)hildon_time_picker_init, - }; - picker_type = g_type_register_static( GTK_TYPE_DIALOG, "HildonTimePicker", - &picker_info, 0 ); - } - return picker_type; -} - - -static void -hildon_time_picker_class_init( HildonTimePickerClass *klass ) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); - parent_class = g_type_class_peek_parent( klass ); - - gobject_class->finalize = hildon_time_picker_finalize; - gobject_class->get_property = hildon_time_picker_get_property; - gobject_class->set_property = hildon_time_picker_set_property; - widget_class->map = hildon_time_picker_map; - - /** - * HildonTimePicker:minutes: - * - * Currently selected time in minutes since midnight. - */ - g_object_class_install_property( gobject_class, PROP_MINUTES, - g_param_spec_uint("minutes", - "Current minutes", - "The selected time in minutes " - "since midnight", - 0, MINS_IN_24H, 0, - G_PARAM_READABLE | G_PARAM_WRITABLE) ); - - gtk_widget_class_install_style_property( widget_class, - g_param_spec_uint("arrow-width", - "Arrow width", - "Increase/decrease arrows width.", - 0, G_MAXUINT, - DEFAULT_ARROW_WIDTH, - G_PARAM_READABLE) ); - - gtk_widget_class_install_style_property( widget_class, - g_param_spec_uint("arrow-height", - "Arrow height", - "Increase/decrease arrows height.", - 0, G_MAXUINT, - DEFAULT_ARROW_HEIGHT, - G_PARAM_READABLE) ); - - g_type_class_add_private( klass, sizeof(HildonTimePickerPrivate) ); -} - -/* Okay, this is really bad. We make the requisition of the frames a bit larger - * so that it doesn't "change" when digits are changed (see #37489). It's a - * really bad solution to a problem, but the whole layout of the time picker is - * on crack anyways */ -static void frame_size_request (GtkWidget *widget, GtkRequisition *requistion) -{ - int framed = requistion->width / 10; - requistion->width = (framed + 1) * 10; -} - -static void hildon_time_picker_init( HildonTimePicker *picker ) -{ - HildonTimePickerPrivate *priv = HILDON_TIME_PICKER_GET_PRIVATE(picker); - gint widget_group_table_column_pos[WIDGET_GROUP_COUNT]; - GtkSettings *settings = NULL; - GtkDialog *dialog = GTK_DIALOG(picker); - GtkTable *table = NULL; - GtkWidget *maintocenter, *colon_label; - const struct tm *local = NULL; - time_t stamp; - gint i = 0; - GtkSizeGroup *size_group; - - picker->priv = priv; - - widget_group_table_column_pos[WIDGET_GROUP_HOURS] = 1; - widget_group_table_column_pos[WIDGET_GROUP_10_MINUTES] = 3; - widget_group_table_column_pos[WIDGET_GROUP_1_MINUTES] = 4; - widget_group_table_column_pos[WIDGET_GROUP_AMPM] = 5; - - /* Get AM/PM strings from locale. If they're set, the time is wanted - in 12 hour mode. */ - priv->am_symbol = g_strdup(nl_langinfo(AM_STR)); - priv->pm_symbol = g_strdup(nl_langinfo(PM_STR)); - - priv->show_ampm = priv->am_symbol[0] != '\0'; - if (priv->show_ampm) - { - /* Check if AM/PM should be before or after time. - %p is the AM/PM string, so we assume that if the format string - begins with %p it's in the beginning, and in any other case it's - in the end (although that's not necessarily the case). */ - if (strncmp(nl_langinfo(T_FMT_AMPM), "%p", 2) == 0) - { - /* Before time. Update column position. */ - priv->ampm_left = TRUE; - widget_group_table_column_pos[WIDGET_GROUP_AMPM] = 0; - } - } - - gtk_widget_push_composite_child(); - - /* Pack all our internal widgets into a table */ - table = GTK_TABLE(gtk_table_new(3, 6, FALSE)); - - /* Put everything centered into window */ - maintocenter = gtk_alignment_new( 0.5, 0, 0, 0 ); - - /* Create our internal widgets */ - for (i = 0; i < WIDGET_GROUP_COUNT; i++) - { - HildonTimePickerWidgetGroup *group = &priv->widgets[i]; - gint table_column = widget_group_table_column_pos[i]; - - /* Create frame and attach to table. With AM/PM label we're attaching - it later. */ - group->frame = gtk_frame_new(NULL); - if (i != WIDGET_GROUP_AMPM) - { - gtk_table_attach(table, group->frame, table_column, table_column + 1, - 1, 2, GTK_EXPAND, GTK_EXPAND, 0, 0); - - - } - /* FIXME: is it needed to force it to 0 here? */ - gtk_container_set_border_width(GTK_CONTAINER(group->frame), 0); - - /* Create eventbox inside frame */ - group->eventbox = gtk_event_box_new(); - gtk_container_add(GTK_CONTAINER(group->frame), group->eventbox); - - g_object_set(group->eventbox, "can-focus", TRUE, NULL); - gtk_widget_set_events(group->eventbox, - GDK_FOCUS_CHANGE_MASK | GDK_BUTTON_PRESS_MASK ); - - /* Connect signals to eventbox */ - g_signal_connect(group->eventbox, "key-release-event", - G_CALLBACK(hildon_time_picker_event_box_key_release), - picker); - g_signal_connect(group->eventbox, "key-press-event", - G_CALLBACK(hildon_time_picker_event_box_key_press), - picker); - g_signal_connect(group->eventbox, "focus-in-event", - G_CALLBACK(hildon_time_picker_event_box_focus_in), - picker); - g_signal_connect(group->eventbox, "focus-out-event", - G_CALLBACK(hildon_time_picker_event_box_focus_out), - picker); - g_signal_connect(group->eventbox, "button-press-event", - G_CALLBACK(hildon_time_picker_event_box_button_press), - picker); - - /* Create label inside eventbox */ - group->label = GTK_LABEL(gtk_label_new(NULL)); - g_signal_connect(group->frame, "size-request", - G_CALLBACK(frame_size_request), - NULL); - gtk_misc_set_alignment (GTK_MISC (group->label), 0.5, 0.5); - gtk_container_add(GTK_CONTAINER(group->eventbox), GTK_WIDGET(group->label)); - - if (i != WIDGET_GROUP_AMPM) - { - gint button; - - /* Add some padding to hour and minute labels, and make them bigger */ - gtk_misc_set_padding(GTK_MISC(group->label), - HILDON_TIME_PICKER_LABEL_X_PADDING, - HILDON_TIME_PICKER_LABEL_Y_PADDING); - gtk_widget_set_name(GTK_WIDGET(group->label), "osso-LargeFont"); - - /* Create up and down buttons for hours and mins */ - for (button = 0; button < BUTTON_COUNT; button++) - { - gint table_row = button == BUTTON_UP ? 0 : 2; - - group->buttons[button] = gtk_button_new(); - gtk_table_attach(table, group->buttons[button], - table_column, table_column + 1, - table_row, table_row + 1, - GTK_SHRINK, GTK_SHRINK, 0, 0); - g_object_set(group->buttons[button], "can-focus", FALSE, NULL); - - /* Connect signals */ - g_signal_connect(group->buttons[button], "button-press-event", - G_CALLBACK(hildon_time_picker_arrow_press), picker); - g_signal_connect(group->buttons[button], "button-release-event", - G_CALLBACK(hildon_time_picker_arrow_release), picker); - } - - gtk_widget_set_name(group->buttons[BUTTON_UP], - "hildon-time-picker-up"); - gtk_widget_set_name(group->buttons[BUTTON_DOWN], - "hildon-time-picker-down"); - } - } - - /* Label between hour and minutes */ - colon_label = gtk_label_new(NULL); - _hildon_time_editor_get_time_separators(GTK_LABEL(colon_label), NULL); - - gtk_table_attach(table, colon_label, 2, 3, 1, 2, - GTK_SHRINK, GTK_SHRINK, 6, 0); /* FIXME: magic */ - gtk_widget_set_name(colon_label, "osso-LargeFont" ); - - priv->minutes = 0; - priv->mul = 0; - priv->key_repeat = 0; - priv->start_key_repeat = FALSE; - priv->timer_id = 0; - priv->button_press = FALSE; - - gtk_table_set_row_spacing( table, 0, 6 ); - gtk_table_set_row_spacing( table, 1, 6 ); - - if (priv->show_ampm) - { - gint table_column = widget_group_table_column_pos[WIDGET_GROUP_AMPM]; - GtkWidget *ampmtotop = NULL; - - /* Show the AM/PM label centered vertically */ - ampmtotop = gtk_alignment_new( 0, 0.5, 0, 0 ); - gtk_table_attach(table, ampmtotop, table_column, table_column + 1, - 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); - gtk_container_add(GTK_CONTAINER(ampmtotop), - priv->widgets[WIDGET_GROUP_AMPM].frame); - - if (table_column != 0) - gtk_table_set_col_spacing(table, table_column - 1, 9); - - /* Connect AM/PM signal handlers */ - g_signal_connect(priv->widgets[WIDGET_GROUP_AMPM].eventbox, - "button-release-event", - G_CALLBACK(hildon_time_picker_ampm_release), picker); - } - - gtk_widget_pop_composite_child(); - - /* Get button press repeater timeout from settings (in milliseconds) */ - settings = gtk_settings_get_default(); - g_object_get( settings, "gtk-update-timeout", &priv->key_repeat, NULL ); - - /* This dialog isn't modal */ - gtk_window_set_modal( GTK_WINDOW(dialog), FALSE ); - /* And final dialog packing */ - gtk_dialog_set_has_separator( dialog, FALSE ); - gtk_dialog_add_button( dialog, _("ecdg_bd_time_picker_close"), - GTK_RESPONSE_OK ); - - gtk_container_add( GTK_CONTAINER(maintocenter), GTK_WIDGET(table) ); - gtk_box_pack_start( GTK_BOX(dialog->vbox), maintocenter, TRUE, FALSE, 0 ); - - /* Set default time to current time */ - stamp = time( NULL ); - local = localtime( &stamp ); - hildon_time_picker_set_time( picker, local->tm_hour, local->tm_min ); - - gtk_widget_show_all( maintocenter ); -} - -static void -hildon_time_picker_set_property( GObject *object, guint param_id, - const GValue *value, GParamSpec *pspec ) -{ - HildonTimePicker *picker = HILDON_TIME_PICKER(object); - - switch( param_id ) - { - case PROP_MINUTES: - hildon_time_picker_change_time( picker, g_value_get_uint(value) ); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); - break; - } -} - -static void -hildon_time_picker_finalize( GObject *object ) -{ - HildonTimePicker *picker = HILDON_TIME_PICKER(object); - - /* Make sure the timer is stopped */ - if (picker->priv->timer_id) - g_source_remove(picker->priv->timer_id); - - g_free(picker->priv->am_symbol); - g_free(picker->priv->pm_symbol); - - if (G_OBJECT_CLASS(parent_class)->finalize) - G_OBJECT_CLASS(parent_class)->finalize(object); -} - -static void -hildon_time_picker_get_property( GObject *object, guint param_id, - GValue *value, GParamSpec *pspec ) -{ - HildonTimePickerPrivate *priv = HILDON_TIME_PICKER(object)->priv; - - switch( param_id ) - { - case PROP_MINUTES: - g_value_set_uint( value, priv->minutes ); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); - break; - } -} - -static void -hildon_time_picker_map( GtkWidget *widget ) -{ - guint width, height; - gint i, button; - HildonTimePickerPrivate *priv = HILDON_TIME_PICKER(widget)->priv; - - /* Widget is now mapped. Set border for the dialog. */ - gdk_window_set_decorations( widget->window, GDK_DECOR_BORDER ); - - /* Update hour/minute up/down buttons sizes from style properties */ - gtk_widget_style_get( widget, - "arrow-width", &width, - "arrow-height", &height, NULL ); - for (i = 0; i < WIDGET_GROUP_COUNT; i++) - { - if (priv->widgets[i].buttons[0] != NULL) - { - for (button = 0; button < BUTTON_COUNT; button++) - { - gtk_widget_set_size_request(priv->widgets[i].buttons[button], - width, height); - } - } - } - - GTK_WIDGET_CLASS(parent_class)->map( widget ); -} - - -static gboolean -hildon_time_picker_event_box_button_press( GtkWidget *widget, - GdkEventKey *event, gpointer unused ) -{ - /* Clicked hour/minute field. Move focus to it. */ - gtk_widget_grab_focus( widget ); - return FALSE; -} - -static gboolean -hildon_time_picker_ampm_release( GtkWidget *widget, GdkEvent *event, - HildonTimePicker *picker ) -{ - /* Clicked AM/PM label. Move focus to it and move the time by 12 hours. */ - gtk_widget_grab_focus( widget ); - hildon_time_picker_change_time( picker, picker->priv->minutes > MINS_IN_12H ? - picker->priv->minutes - MINS_IN_12H : - picker->priv->minutes + MINS_IN_12H ); - return FALSE; -} - -static gboolean -hildon_time_picker_arrow_press( GtkWidget *widget, GdkEvent *event, - HildonTimePicker *picker ) -{ - HildonTimePickerPrivate *priv = picker->priv; - gint i, button; - gint newval = 0; - - /* Make sure we don't add repeat timer twice. Normally it shouldn't - happen but WM can cause button release to be lost. */ - if( priv->button_press ) - return FALSE; - - priv->start_key_repeat = priv->button_press = TRUE; - - /* Find the widget which was clicked */ - priv->mul = 0; - for (i = 0; i < WIDGET_GROUP_COUNT; i++) - { - for (button = 0; button < BUTTON_COUNT; button++) - { - if (priv->widgets[i].buttons[button] == widget) - { - /* Update multiplier and move the focus to the clicked field */ - priv->mul = button_multipliers[i][button]; - gtk_widget_grab_focus(priv->widgets[i].eventbox); - break; - } - } - } - g_assert(priv->mul != 0); - - /* Change the time now, wrapping if needed. */ - newval = priv->minutes + priv->mul; - if( newval < 0 ) - newval += MINS_IN_24H; - - hildon_time_picker_change_time( picker, newval ); - - /* Keep changing the time as long as button is being pressed. - The first repeat takes 3 times longer to start than the rest. */ - priv->timer_id = g_timeout_add(priv->key_repeat * 3, - hildon_time_picker_key_repeat_timeout, - picker); - return FALSE; -} - -static gboolean -hildon_time_picker_arrow_release( GtkWidget *widget, GdkEvent *event, - HildonTimePicker *picker ) -{ - HildonTimePickerPrivate *priv = picker->priv; - if( priv->timer_id ) - { - /* Stop repeat timer */ - g_source_remove( priv->timer_id ); - priv->timer_id = 0; - } - priv->button_press = FALSE; - return FALSE; -} - -static gboolean -hildon_time_picker_event_box_focus_in( GtkWidget *widget, GdkEvent *event, - gpointer unused ) -{ - /* Draw the widget in selected state so focus shows clearly. */ - gtk_widget_set_state( widget, GTK_STATE_SELECTED ); - return FALSE; -} - -static gboolean -hildon_time_picker_event_box_focus_out( GtkWidget *widget, GdkEvent *event, - gpointer unused ) -{ - /* Draw the widget in normal state */ - gtk_widget_set_state( widget, GTK_STATE_NORMAL ); - return FALSE; -} - -static gint -hildon_time_picker_lookup_eventbox_group(HildonTimePicker *picker, - GtkWidget *widget) -{ - gint i; - - for (i = 0; i < WIDGET_GROUP_COUNT; i++) - { - if (picker->priv->widgets[i].eventbox == widget) - return i; - } - return -1; -} - -static gboolean -hildon_time_picker_event_box_key_press( GtkWidget *widget, GdkEventKey *event, - HildonTimePicker *picker ) -{ - HildonTimePickerPrivate *priv = picker->priv; - HildonTimePickerWidgetGroup *group; - gint group_idx; - - /* If mouse button is already being pressed, ignore this keypress */ - if( priv->timer_id ) - return TRUE; - - group_idx = hildon_time_picker_lookup_eventbox_group(picker, widget); - group = group_idx < 0 ? NULL : &picker->priv->widgets[group_idx]; - - /* Handle keypresses in hour/minute/AMPM fields */ - switch( event->keyval ) - { - case GDK_Up: - case GDK_Down: - if (group != NULL) - { - gint button = event->keyval == GDK_Up ? BUTTON_UP : BUTTON_DOWN; - - if (group->buttons[button] != NULL) - { - /* Fake a button up/down press */ - hildon_time_picker_arrow_press(group->buttons[button], NULL, picker); - gtk_widget_set_state(group->buttons[button], GTK_STATE_SELECTED); - } - else - { - /* Fake a AM/PM button release */ - g_assert(group_idx == WIDGET_GROUP_AMPM); - hildon_time_picker_ampm_release(group->eventbox, NULL, picker); - } - } - return TRUE; - - case GDK_Left: - /* If we're in leftmost field, stop this keypress signal. - Otherwise let the default key handler move focus to field in left. */ - if (priv->show_ampm && priv->ampm_left) - { - /* AM/PM is the leftmost field */ - if (group_idx == WIDGET_GROUP_AMPM) - return TRUE; - } - else - { - /* Hours is the leftmost field */ - if (group_idx == WIDGET_GROUP_HOURS) - return TRUE; - } - break; - - case GDK_Right: - /* If we're in rightmost field, stop this keypress signal. - Otherwise let the default key handler move focus to field in right. */ - if (priv->show_ampm && !priv->ampm_left) - { - /* AM/PM is the rightmost field */ - if (group_idx == WIDGET_GROUP_AMPM) - return TRUE; - } - else - { - /* 1-minutes is the leftmost field */ - if (group_idx == WIDGET_GROUP_1_MINUTES) - return TRUE; - } - break; - - case GDK_Escape: - gtk_dialog_response (GTK_DIALOG (picker), GTK_RESPONSE_CANCEL); - return TRUE; - - case GDK_Return: - gtk_dialog_response (GTK_DIALOG (picker), GTK_RESPONSE_OK); - return TRUE; - } - - return FALSE; -} - -static gboolean -hildon_time_picker_event_box_key_release( GtkWidget *widget, GdkEventKey *event, - HildonTimePicker *picker ) -{ - HildonTimePickerWidgetGroup *group; - gint group_idx; - - /* Fake a button release if in key-press handler we faked a button press. */ - switch( event->keyval ) - { - case GDK_Up: - case GDK_Down: - group_idx = hildon_time_picker_lookup_eventbox_group(picker, widget); - if (group_idx >= 0) - { - gint button = event->keyval == GDK_Up ? BUTTON_UP : BUTTON_DOWN; - - group = &picker->priv->widgets[group_idx]; - if (group->buttons[button] != NULL) - { - /* Fake a button up/down press */ - gtk_widget_set_state(group->buttons[button], GTK_STATE_NORMAL); - hildon_time_picker_arrow_release(group->buttons[button], - NULL, picker); - } - } - break; - } - return FALSE; -} - -/* Button up/down is being pressed. Update the time. */ -static gboolean -hildon_time_picker_key_repeat_timeout( gpointer tpicker ) -{ - HildonTimePicker *picker; - HildonTimePickerPrivate *priv = NULL; - gint newval = 0; - - GDK_THREADS_ENTER (); - - picker = HILDON_TIME_PICKER(tpicker); - g_assert(picker != NULL); - - priv = picker->priv; - - /* Change the time, wrapping if needed */ - newval = priv->minutes + priv->mul; - if( newval < 0 ) - newval += MINS_IN_24H; - - hildon_time_picker_change_time( picker, newval ); - - if( priv->start_key_repeat ) - { - /* This is the first repeat. Shorten the timeout to key_repeat - (instead of the first time's 3*key_repeat) */ - priv->timer_id = g_timeout_add(priv->key_repeat, - hildon_time_picker_key_repeat_timeout, - picker); - priv->start_key_repeat = FALSE; - - GDK_THREADS_LEAVE (); - return FALSE; - } - - GDK_THREADS_LEAVE (); - return TRUE; -} - - - -static void -hildon_time_picker_change_time( HildonTimePicker *picker, guint minutes ) -{ - HildonTimePickerPrivate *priv = picker->priv; - gchar str[3] = "00"; - guint hours = 0; - gboolean ampm = TRUE; - - /* If the minutes isn't in valid range, wrap them. */ - minutes %= MINS_IN_24H; - - if( priv->minutes == minutes ) - return; - - /* Minutes changed. Update widgets to show the new time. */ - priv->minutes = minutes; - - if (priv->show_ampm) - { - /* am < 12:00 <= pm */ - ampm = !((guint)(minutes / MINS_IN_12H)); - /* 12:00 - 23:59 -> 00:00 - 11:59 */ - minutes %= MINS_IN_12H; - if( minutes < MINS_IN_1H ) - /* 00:mm is always shown as 12:mm */ - minutes += MINS_IN_12H; - - /* Update the AM/PM label */ - gtk_label_set_text(priv->widgets[WIDGET_GROUP_AMPM].label, - ampm ? priv->am_symbol : priv->pm_symbol); - } - - /* Update hour and minute fields */ - hours = minutes / MINS_IN_1H; - minutes %= MINS_IN_1H; - - snprintf(str, sizeof(str), "%02d", hours); - gtk_label_set_text(priv->widgets[WIDGET_GROUP_HOURS].label, str); - - snprintf(str, sizeof(str), "%d", minutes / 10); - gtk_label_set_text(priv->widgets[WIDGET_GROUP_10_MINUTES].label, str); - - snprintf(str, sizeof(str), "%d", minutes % 10); - gtk_label_set_text(priv->widgets[WIDGET_GROUP_1_MINUTES].label, str); - - g_object_notify( G_OBJECT(picker), "minutes" ); -} - -/** - * hildon_time_picker_new: - * @parent: parent window - * - * #HildonTimePicker shows time picker dialog. The close button is placed - * in the dialog's action area and time picker is placed in dialogs vbox. - * The actual time picker consists of two #GtkLabel fields - one for hours - * and one for minutes - and an AM/PM button. A colon (:) is placed - * between hour and minute fields. - * - * Returns: pointer to a new #HildonTimePicker widget. - */ -GtkWidget *hildon_time_picker_new( GtkWindow *parent ) -{ - GtkWidget *widget = g_object_new( HILDON_TYPE_TIME_PICKER, - "minutes", 360, NULL ); - - if( parent ) - gtk_window_set_transient_for( GTK_WINDOW(widget), parent ); - - return GTK_WIDGET(widget); -} - -/** - * hildon_time_picker_set_time: - * @picker: the #HildonTimePicker widget - * @hours: hours - * @minutes: minutes - * - * Sets the time of the #HildonTimePicker widget. - */ -void hildon_time_picker_set_time( HildonTimePicker *picker, - guint hours, guint minutes ) -{ - g_return_if_fail( HILDON_IS_TIME_PICKER(picker) ); - hildon_time_picker_change_time( picker, hours * MINS_IN_1H + minutes ); -} - -/** - * hildon_time_picker_get_time: - * @picker: the #HildonTimePicker widget - * @hours: hours - * @minutes: minutes - * - * Gets the time of the #HildonTimePicker widget. - */ -void hildon_time_picker_get_time( HildonTimePicker *picker, - guint *hours, guint *minutes ) -{ - guint current; - g_return_if_fail( HILDON_IS_TIME_PICKER(picker) ); - - current = picker->priv->minutes; - *hours = current / MINS_IN_1H; - *minutes = current % MINS_IN_1H; -} diff --git a/hildon-widgets/hildon-time-picker.h b/hildon-widgets/hildon-time-picker.h deleted file mode 100644 index dcf79cf..0000000 --- a/hildon-widgets/hildon-time-picker.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ -#ifndef __HILDON_TIME_PICKER_H__ -#define __HILDON_TIME_PICKER_H__ - -#include - -G_BEGIN_DECLS - - -#define HILDON_TYPE_TIME_PICKER (hildon_time_picker_get_type()) -#define HILDON_TIME_PICKER(obj) (GTK_CHECK_CAST (obj, \ - HILDON_TYPE_TIME_PICKER, \ - HildonTimePicker)) -#define HILDON_TIME_PICKER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), \ - HILDON_TYPE_TIME_PICKER,\ - HildonTimePickerClass)) -#define HILDON_IS_TIME_PICKER(obj) (GTK_CHECK_TYPE (obj, \ - HILDON_TYPE_TIME_PICKER)) -#define HILDON_IS_TIME_PICKER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass),\ - HILDON_TYPE_TIME_PICKER)) - - -typedef struct _HildonTimePicker HildonTimePicker; -typedef struct _HildonTimePickerClass HildonTimePickerClass; -typedef struct _HildonTimePickerPrivate HildonTimePickerPrivate; - - -struct _HildonTimePicker -{ - GtkDialog parent; - HildonTimePickerPrivate *priv; -}; - -struct _HildonTimePickerClass -{ - GtkDialogClass parent_class; -}; - - -GType hildon_time_picker_get_type( void ) G_GNUC_CONST; - -GtkWidget *hildon_time_picker_new( GtkWindow *parent ); - -void hildon_time_picker_set_time( HildonTimePicker *picker, - guint hours, guint minutes ); - -void hildon_time_picker_get_time( HildonTimePicker *picker, - guint *hours, guint *minutes ); - - -G_END_DECLS -#endif /* __HILDON_TIME_PICKER_H__ */ diff --git a/hildon-widgets/hildon-volumebar-private.h b/hildon-widgets/hildon-volumebar-private.h deleted file mode 100644 index d93700f..0000000 --- a/hildon-widgets/hildon-volumebar-private.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ -#ifndef __HILDON_VOLUMEBAR_PRIVATE__ -#define __HILDON_VOLUMEBAR_PRIVATE__ - -#include -#include - -G_BEGIN_DECLS -#define HILDON_VOLUMEBAR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_VOLUMEBAR, HildonVolumebarPrivate)); - -typedef struct _HildonVolumebarPrivate HildonVolumebarPrivate; - -struct _HildonVolumebarPrivate { - HildonVolumebarRange *volumebar; - GtkToggleButton *tbutton; - gboolean is_toolbar; /* is inside toolbar (for horizontal volumebar) */ - GdkWindow *event_window; /* input-only window to catch insensitive presses */ -}; - -void _hildon_volumebar_mute_toggled(HildonVolumebar * self); - -G_END_DECLS -#endif /* __HILDON_VOLUMEBAR_PRIVATE__ */ diff --git a/hildon-widgets/hildon-volumebar-range.c b/hildon-widgets/hildon-volumebar-range.c deleted file mode 100644 index ef4b152..0000000 --- a/hildon-widgets/hildon-volumebar-range.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/* - * @file hildon-volumebar-range.c - * - * This file contains the implementation of the HildonVolumebarRange. - * This widget is an "workhorse" for #HildonVolumebar widget. - * It is not designed to be used as a standalone widget. - * - * Purpose of this widget is to act as an "container" for GtkScale - * widget. #HildonVolumebarRange changes some event parameters so - * that #HildonVolumebar can meet its specifications. - * - * Currently #HildonVolumebarRange models range of [0..100]. - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include "hildon-volumebar-range.h" - -#define VOLUMEBAR_RANGE_INITIAL_VALUE 50.0 -#define VOLUMEBAR_RANGE_MINIMUM_VALUE 0.0 -#define VOLUMEBAR_RANGE_MAXIMUM_VALUE 100.0 -#define VOLUMEBAR_RANGE_STEP_INCREMENT_VALUE 5.0 -#define VOLUMEBAR_RANGE_PAGE_INCREMENT_VALUE 5.0 -#define VOLUMEBAR_RANGE_PAGE_SIZE_VALUE 0.0 - -#define CHANGE_THRESHOLD 0.001 - -static GtkScaleClass *parent_class; - -static void hildon_volumebar_range_class_init(HildonVolumebarRangeClass * - volumerange_class); -static void hildon_volumebar_range_init(HildonVolumebarRange * - volumerange); -static void hildon_volumebar_range_set_property(GObject * object, - guint prop_id, - const GValue * value, - GParamSpec * pspec); -static void hildon_volumebar_range_get_property(GObject * object, - guint prop_id, - GValue * value, - GParamSpec * pspec); -static gint hildon_volumebar_range_button_press_event(GtkWidget * widget, - GdkEventButton * - event); -static gint hildon_volumebar_range_button_release_event(GtkWidget * widget, - GdkEventButton * - event); -static gboolean hildon_volumebar_range_keypress(GtkWidget * widget, - GdkEventKey * event); - -enum { - PROP_NONE = 0, - PROP_LEVEL -}; - -GType -hildon_volumebar_range_get_type(void) -{ - static GType volumerange_type = 0; - - if (!volumerange_type) { - static const GTypeInfo volumerange_info = { - sizeof(HildonVolumebarRangeClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_volumebar_range_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonVolumebarRange), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_volumebar_range_init, - }; - volumerange_type = g_type_register_static(GTK_TYPE_SCALE, - "HildonVolumebarRange", - &volumerange_info, 0); - } - return volumerange_type; -} - -static void -hildon_volumebar_range_class_init(HildonVolumebarRangeClass * - volumerange_class) -{ - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(volumerange_class); - GObjectClass *object_class = G_OBJECT_CLASS(volumerange_class); - - parent_class = g_type_class_peek_parent(volumerange_class); - - widget_class->button_press_event = - hildon_volumebar_range_button_press_event; - widget_class->button_release_event = - hildon_volumebar_range_button_release_event; - widget_class->key_press_event = hildon_volumebar_range_keypress; - - object_class->set_property = hildon_volumebar_range_set_property; - object_class->get_property = hildon_volumebar_range_get_property; - - g_object_class_install_property(object_class, - PROP_LEVEL, - g_param_spec_double("level", - "Level", - "Current volume level", - VOLUMEBAR_RANGE_MINIMUM_VALUE, - VOLUMEBAR_RANGE_MAXIMUM_VALUE, - VOLUMEBAR_RANGE_INITIAL_VALUE, - G_PARAM_READWRITE)); - return; -} - -static void -hildon_volumebar_range_init(HildonVolumebarRange * volumerange) -{ - /* stepper_a = "less", stepper_d = "more" */ - GTK_RANGE(volumerange)->has_stepper_a = TRUE; - GTK_RANGE(volumerange)->has_stepper_d = TRUE; -} - -static void -hildon_volumebar_range_set_property(GObject * object, - guint prop_id, - const GValue * value, - GParamSpec * pspec) -{ - HildonVolumebarRange *range = HILDON_VOLUMEBAR_RANGE(object); - - switch (prop_id) { - case PROP_LEVEL: - hildon_volumebar_range_set_level(range, g_value_get_double(value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -hildon_volumebar_range_get_property(GObject * object, - guint prop_id, - GValue * value, - GParamSpec * pspec) -{ - HildonVolumebarRange *range = HILDON_VOLUMEBAR_RANGE(object); - - switch (prop_id) { - case PROP_LEVEL: - g_value_set_double(value, hildon_volumebar_range_get_level(range)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static -gboolean hildon_volumebar_range_keypress(GtkWidget * widget, - GdkEventKey * event) -{ - /* Accept arrow keys only if they match the orientation of the widget */ - if (GTK_RANGE (widget)->orientation == GTK_ORIENTATION_HORIZONTAL) - { - if (event->keyval == GDK_Up || event->keyval == GDK_Down) { - return FALSE; - } - } - else - { - if (event->keyval == GDK_Left || event->keyval == GDK_Right) { - return FALSE; - } - } - - return ((GTK_WIDGET_CLASS(parent_class)->key_press_event) (widget, - event)); -} - -GtkWidget * -hildon_volumebar_range_new(GtkOrientation orientation) -{ - GtkAdjustment * adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (VOLUMEBAR_RANGE_INITIAL_VALUE, - VOLUMEBAR_RANGE_MINIMUM_VALUE, - VOLUMEBAR_RANGE_MAXIMUM_VALUE, - VOLUMEBAR_RANGE_STEP_INCREMENT_VALUE, - VOLUMEBAR_RANGE_PAGE_INCREMENT_VALUE, - VOLUMEBAR_RANGE_PAGE_SIZE_VALUE)); - HildonVolumebarRange *self = - g_object_new(HILDON_TYPE_VOLUMEBAR_RANGE, - "adjustment", adjustment, - NULL); - - GTK_RANGE(self)->orientation = orientation; - - /* Default vertical range is upside down for purposes of this widget */ - gtk_range_set_inverted(GTK_RANGE(self), - (orientation == GTK_ORIENTATION_VERTICAL)); - - return GTK_WIDGET(self); -} - -gdouble -hildon_volumebar_range_get_level(HildonVolumebarRange * self) -{ - g_return_val_if_fail(HILDON_IS_VOLUMEBAR_RANGE(self), -1.0); - - return gtk_adjustment_get_value(gtk_range_get_adjustment(GTK_RANGE(self))); -} - -void -hildon_volumebar_range_set_level(HildonVolumebarRange * self, - gdouble level) -{ - GtkAdjustment *adjustment; - - g_return_if_fail(HILDON_IS_VOLUMEBAR_RANGE(self)); - - adjustment = gtk_range_get_adjustment(GTK_RANGE(self)); - - /* Check that value has actually changed. Note that it's not safe to - * just compare if floats are equivalent or not */ - if (ABS(gtk_adjustment_get_value(adjustment) - level) > CHANGE_THRESHOLD) { - gtk_adjustment_set_value(adjustment, level); - } -} - -static gint -hildon_volumebar_range_button_press_event(GtkWidget * widget, - GdkEventButton * - event) -{ - gboolean result = FALSE; - - /* FIXME: By default, clicking left mouse button on GtkRange moves the - slider by one step towards the click location. However, we want stylus - taps to move the slider to the position of the tap, which by default - is the middle button behaviour. To avoid breaking default GtkRange - behaviour, this has been implemented by faking a middle button press. */ - event->button = (event->button == 1) ? 2 : event->button; - if (GTK_WIDGET_CLASS(parent_class)->button_press_event) { - result = - GTK_WIDGET_CLASS(parent_class)->button_press_event(widget, - event); - } - return result; -} - -static gint -hildon_volumebar_range_button_release_event(GtkWidget * widget, - GdkEventButton * - event) -{ - gboolean result = FALSE; - - /* FIXME: By default, clicking left mouse button on GtkRange moves the - slider by one step towards the click location. However, we want stylus - taps to move the slider to the position of the tap, which by default - is the middle button behaviour. To avoid breaking default GtkRange - behaviour, this has been implemented by faking a middle button press. */ - event->button = event->button == 1 ? 2 : event->button; - if (GTK_WIDGET_CLASS(parent_class)->button_release_event) { - result = - GTK_WIDGET_CLASS(parent_class)->button_release_event(widget, - event); - } - return result; -} diff --git a/hildon-widgets/hildon-volumebar-range.h b/hildon-widgets/hildon-volumebar-range.h deleted file mode 100644 index 545ff9d..0000000 --- a/hildon-widgets/hildon-volumebar-range.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_VOLUMEBAR_RANGE_H__ -#define __HILDON_VOLUMEBAR_RANGE_H__ - -#include - -G_BEGIN_DECLS - -/** - * HILDON_VOLUMEBAR_RANGE_TYPE - * - * Macro for getting type of volumebar range. - * Since: 0.12.10 - */ -#define HILDON_TYPE_VOLUMEBAR_RANGE ( hildon_volumebar_range_get_type() ) - -/** - * HILDON_VOLUMEBAR_RANGE_TYPE - * - * Deprecated: use #HILDON_VOLUMEBAR_RANGE_TYPE instead - */ -#define HILDON_VOLUMEBAR_RANGE_TYPE HILDON_TYPE_VOLUMEBAR_RANGE - - -#define HILDON_VOLUMEBAR_RANGE(obj) (GTK_CHECK_CAST (obj,\ - HILDON_TYPE_VOLUMEBAR_RANGE, HildonVolumebarRange)) -#define HILDON_VOLUMEBAR_RANGE_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass),\ - HILDON_TYPE_VOLUMEBAR_RANGE, HildonVolumebarRangeClass)) -#define HILDON_IS_VOLUMEBAR_RANGE(obj) (GTK_CHECK_TYPE (obj,\ - HILDON_TYPE_VOLUMEBAR_RANGE)) -#define HILDON_IS_VOLUMEBAR_RANGE_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_VOLUMEBAR_RANGE)) - -typedef struct _HildonVolumebarRange HildonVolumebarRange; -typedef struct _HildonVolumebarRangeClass HildonVolumebarRangeClass; - -struct _HildonVolumebarRange { - GtkScale scale; -}; - -struct _HildonVolumebarRangeClass { - GtkScaleClass parent_class; -}; - -GType hildon_volumebar_range_get_type (void) G_GNUC_CONST; -GtkWidget * hildon_volumebar_range_new (GtkOrientation orientation); -gdouble hildon_volumebar_range_get_level (HildonVolumebarRange *self); -void hildon_volumebar_range_set_level (HildonVolumebarRange *self, - gdouble level); - - -G_END_DECLS - -#endif /* __HILDON_VOLUMEBAR_RANGE_H__ */ diff --git a/hildon-widgets/hildon-volumebar.c b/hildon-widgets/hildon-volumebar.c deleted file mode 100644 index 8f6f635..0000000 --- a/hildon-widgets/hildon-volumebar.c +++ /dev/null @@ -1,622 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-volumebar - * @short_description: Base class for widgets that display a volume bar - * @see_also: #HildonHVolumebar, #HildonVVolumebar - * - * #HildonVolumebar is a base class for widgets that display a volume bar that - * allows increasing or decreasing volume within a predefined range, and muting - * the volume when users click the mute icon. - */ - -#include -#include -#include - -#include "hildon-volumebar.h" -#include "hildon-volumebar-range.h" -#include "hildon-volumebar-private.h" - -static GtkContainerClass *parent_class; - -static void -hildon_volumebar_class_init(HildonVolumebarClass * volumebar_class); -static void -hildon_volumebar_init(HildonVolumebar * volumebar); - -static void -hildon_child_forall(GtkContainer * container, - gboolean include_internals, - GtkCallback callback, - gpointer callback_data); -static void -hildon_volumebar_destroy(GtkObject * self); - -static void hildon_volumebar_set_property(GObject * object, - guint prop_id, - const GValue * value, - GParamSpec * pspec); -static void hildon_volumebar_get_property(GObject * object, - guint prop_id, - GValue * value, - GParamSpec * pspec); - -static void mute_toggled (HildonVolumebar *self); - -static gboolean -hildon_volumebar_key_press(GtkWidget * widget, - GdkEventKey * event); - -static void hildon_volumebar_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); -static void hildon_volumebar_realize (GtkWidget *widget); -static void hildon_volumebar_unrealize (GtkWidget *widget); -static void hildon_volumebar_map (GtkWidget *widget); -static void hildon_volumebar_unmap (GtkWidget *widget); -static void hildon_volumebar_notify (GObject *self, GParamSpec *param); - - -enum -{ - MUTE_TOGGLED_SIGNAL, - LEVEL_CHANGED_SIGNAL, - LAST_SIGNAL -}; - -enum { - PROP_NONE = 0, - PROP_HILDON_HAS_MUTE, - PROP_HILDON_FOCUSABLE, - PROP_HILDON_LEVEL, - PROP_HILDON_MUTE -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -GType -hildon_volumebar_get_type(void) -{ - static GType volumebar_type = 0; - - if (!volumebar_type) { - static const GTypeInfo volumebar_info = { - sizeof(HildonVolumebarClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_volumebar_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonVolumebar), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_volumebar_init, - }; - volumebar_type = g_type_register_static(GTK_TYPE_CONTAINER, - "HildonVolumebar", - &volumebar_info, 0); - } - return volumebar_type; -} - -static void -hildon_volumebar_class_init(HildonVolumebarClass *volumebar_class) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (volumebar_class); - GtkObjectClass *object_class = GTK_OBJECT_CLASS(volumebar_class); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(volumebar_class); - GtkContainerClass *container_class = GTK_CONTAINER_CLASS(volumebar_class); - - parent_class = g_type_class_peek_parent(volumebar_class); - - g_type_class_add_private(volumebar_class, - sizeof(HildonVolumebarPrivate)); - - /* Because we derived our widget from GtkContainer, we should also - override forall method */ - volumebar_class->mute_toggled = mute_toggled; - container_class->forall = hildon_child_forall; - widget_class->size_allocate = hildon_volumebar_size_allocate; - widget_class->realize = hildon_volumebar_realize; - widget_class->unrealize = hildon_volumebar_unrealize; - widget_class->map = hildon_volumebar_map; - widget_class->unmap = hildon_volumebar_unmap; - widget_class->key_press_event = hildon_volumebar_key_press; - object_class->destroy = hildon_volumebar_destroy; - - signals[MUTE_TOGGLED_SIGNAL] = g_signal_new("mute_toggled", - G_OBJECT_CLASS_TYPE - (object_class), - G_SIGNAL_RUN_LAST | - G_SIGNAL_ACTION, - G_STRUCT_OFFSET - (HildonVolumebarClass, - mute_toggled), NULL, NULL, - gtk_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - signals[LEVEL_CHANGED_SIGNAL] = g_signal_new("level_changed", - G_OBJECT_CLASS_TYPE - (object_class), - G_SIGNAL_RUN_LAST | - G_SIGNAL_ACTION, - G_STRUCT_OFFSET - (HildonVolumebarClass, - level_changed), NULL, - NULL, - gtk_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - gobject_class->notify = hildon_volumebar_notify; - gobject_class->set_property = hildon_volumebar_set_property; - gobject_class->get_property = hildon_volumebar_get_property; - - /*This kind of property could be usefull in the gtkcontainer*/ - g_object_class_install_property(gobject_class, - PROP_HILDON_FOCUSABLE, - g_param_spec_boolean("can-focus", - "The widget focusablility", - "The widget focusablility. TRUE is focusable", - TRUE, - G_PARAM_CONSTRUCT | G_PARAM_READWRITE)); - - g_object_class_install_property(gobject_class, - PROP_HILDON_HAS_MUTE, - g_param_spec_boolean("has_mute", - "Show/Hide the mute button", - "Whether the mute button is visible. Default value: TRUE", - TRUE, - G_PARAM_CONSTRUCT | G_PARAM_READWRITE)); - - g_object_class_install_property(gobject_class, - PROP_HILDON_LEVEL, - g_param_spec_double("level", - "Level", - "Current volume level", - 0.0, - 100.0, - 50.0, - G_PARAM_READWRITE)); - - g_object_class_install_property(gobject_class, - PROP_HILDON_MUTE, - g_param_spec_boolean("mute", - "Mute", - "Whether volume is muted", - FALSE, - G_PARAM_READWRITE)); -} - -static void -hildon_volumebar_init(HildonVolumebar * volumebar) -{ - HildonVolumebarPrivate *priv; - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(volumebar); - - /* Should set GTK_NO_WINDOW flag, because widget is derived from - GtkContainer */ - GTK_WIDGET_SET_FLAGS(GTK_WIDGET(volumebar), GTK_NO_WINDOW); - GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(volumebar), GTK_CAN_FOCUS); - - /* Initialize mute button */ - priv->tbutton = GTK_TOGGLE_BUTTON(gtk_toggle_button_new()); - g_object_set (G_OBJECT (priv->tbutton), "can-focus", FALSE, NULL); -} - -static void -hildon_volumebar_size_allocate (GtkWidget *widget, GtkAllocation *allocation) -{ - HildonVolumebarPrivate *priv; - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget); - - if (GTK_WIDGET_CLASS (parent_class)->size_allocate) - GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation); - - if (GTK_WIDGET_REALIZED (widget)) - gdk_window_move_resize (priv->event_window, - allocation->x, allocation->y, - allocation->width, allocation->height); -} - -static void -hildon_volumebar_realize (GtkWidget *widget) -{ - HildonVolumebarPrivate *priv; - GdkWindowAttr attributes; - gint attributes_mask; - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget); - - GTK_WIDGET_CLASS(parent_class)->realize(widget); - - 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_ONLY; - attributes.event_mask = GDK_BUTTON_PRESS_MASK; - - attributes_mask = GDK_WA_X | GDK_WA_Y; - - priv->event_window = gdk_window_new (widget->window, - &attributes, attributes_mask); - gdk_window_set_user_data (priv->event_window, widget); -} - -static void -hildon_volumebar_unrealize (GtkWidget *widget) -{ - HildonVolumebarPrivate *priv; - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget); - - if (priv->event_window) { - gdk_window_set_user_data (priv->event_window, NULL); - gdk_window_destroy (priv->event_window); - priv->event_window = NULL; - } - - GTK_WIDGET_CLASS(parent_class)->unrealize(widget); -} - -static void -hildon_volumebar_map (GtkWidget *widget) -{ - HildonVolumebarPrivate *priv; - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget); - - GTK_WIDGET_CLASS(parent_class)->map(widget); - - /* the event window must be on top of all other widget windows, so show it - * last */ - if (!GTK_WIDGET_SENSITIVE (widget)) - gdk_window_show (priv->event_window); -} - -static void hildon_volumebar_unmap (GtkWidget *widget) -{ - HildonVolumebarPrivate *priv; - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget); - - gdk_window_hide (priv->event_window); - - GTK_WIDGET_CLASS(parent_class)->unmap(widget); -} - -static void -hildon_child_forall(GtkContainer * container, - gboolean include_internals, - GtkCallback callback, gpointer callback_data) -{ - HildonVolumebarPrivate *priv; - - g_assert(HILDON_IS_VOLUMEBAR(container)); - g_assert(callback != NULL); - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(container); - - /* No external children */ - if (!include_internals) - return; - - /* Execute callback for both internals */ - (*callback) (GTK_WIDGET(priv->tbutton), callback_data); - (*callback) (GTK_WIDGET(priv->volumebar), callback_data); -} - -static void -hildon_volumebar_notify (GObject *self, GParamSpec *param) -{ - HildonVolumebarPrivate *priv; - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(self); - - if (GTK_WIDGET_MAPPED (self)) { - /* show/hide the event window on sensitivity change */ - if (g_str_equal (param->name, "sensitive")) { - if (GTK_WIDGET_SENSITIVE (self)) - gdk_window_hide (priv->event_window); - else - gdk_window_show (priv->event_window); - } - } - - if (G_OBJECT_CLASS(parent_class)->notify) - G_OBJECT_CLASS(parent_class)->notify (self, param); -} - -static void -hildon_volumebar_destroy(GtkObject * self) -{ - HildonVolumebarPrivate *priv; - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(self); - - if (priv->tbutton) { - gtk_widget_unparent(GTK_WIDGET(priv->tbutton)); - priv->tbutton = NULL; - } - if (priv->volumebar) { - gtk_widget_unparent(GTK_WIDGET(priv->volumebar)); - priv->volumebar = NULL; - } - - if (GTK_OBJECT_CLASS(parent_class)->destroy) - GTK_OBJECT_CLASS(parent_class)->destroy(self); -} - -static void -hildon_volumebar_set_property(GObject * object, - guint prop_id, - const GValue * value, - GParamSpec * pspec) -{ - HildonVolumebarPrivate *priv; - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(object); - - switch (prop_id) { - case PROP_HILDON_HAS_MUTE: - /* Mute button always exists, but might be hidden */ - if (g_value_get_boolean(value)) - gtk_widget_show(GTK_WIDGET(priv->tbutton)); - else - gtk_widget_hide(GTK_WIDGET(priv->tbutton)); - break; - case PROP_HILDON_FOCUSABLE: - g_object_set( G_OBJECT(priv->volumebar), "can-focus", - g_value_get_boolean(value), NULL ); - break; - case PROP_HILDON_LEVEL: - hildon_volumebar_set_level(HILDON_VOLUMEBAR(priv->volumebar), - g_value_get_double(value)); - break; - case PROP_HILDON_MUTE: - hildon_volumebar_set_mute(HILDON_VOLUMEBAR(priv->volumebar), - g_value_get_boolean(value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - - break; - } -} - -static void -hildon_volumebar_get_property(GObject * object, - guint prop_id, GValue * value, - GParamSpec * pspec) -{ - HildonVolumebar *vb = HILDON_VOLUMEBAR(object); - HildonVolumebarPrivate *priv = HILDON_VOLUMEBAR_GET_PRIVATE(vb); - - switch (prop_id) { - case PROP_HILDON_HAS_MUTE: - g_value_set_boolean(value, GTK_WIDGET_VISIBLE(priv->tbutton)); - break; - case PROP_HILDON_FOCUSABLE: - g_value_set_boolean(value, GTK_WIDGET_CAN_FOCUS(priv->volumebar)); - break; - case PROP_HILDON_LEVEL: - g_value_set_double(value, hildon_volumebar_get_level(vb)); - break; - case PROP_HILDON_MUTE: - g_value_set_boolean(value, hildon_volumebar_get_mute(vb)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -/** - * hildon_volumebar_level_change: - * @self: a #HildonVolumebar widget - * - * Emits "level_changed" signal to the given volume bar. This function - * is mainly used by derived classes. - */ -void -hildon_volumebar_level_change(HildonVolumebar * self) -{ - g_return_if_fail(HILDON_IS_VOLUMEBAR(self)); - g_signal_emit_by_name(GTK_WIDGET(self), "level_changed"); -} - -/** - * hildon_volumebar_set_level: - * @self: volume bar to change level on - * @level: new level - * - * Sets new volume level for this #HildonVolumebar. - */ -void -hildon_volumebar_set_level(HildonVolumebar * self, gdouble level) -{ - HildonVolumebarPrivate *priv; - - g_return_if_fail(HILDON_IS_VOLUMEBAR(self)); - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(self); - - hildon_volumebar_range_set_level(priv->volumebar, level); -} - -/** - * hildon_volumebar_get_level: - * @self: volume bar to query level on - * - * Gets the volume level of this #HildonVolumebar. - * - * Returns: volume level or -1 on error - */ -gdouble -hildon_volumebar_get_level(HildonVolumebar * self) -{ - HildonVolumebarPrivate *priv; - - g_return_val_if_fail(HILDON_IS_VOLUMEBAR(self), -1); - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(self); - - return hildon_volumebar_range_get_level(priv->volumebar); -} - -/** - * hildon_volumebar_set_mute: - * @self: volume bar to work on - * @mute: mute ON/OFF - * - * Sets mute status for this #HildonVolumebar. - */ -void -hildon_volumebar_set_mute(HildonVolumebar * self, gboolean mute) -{ - HildonVolumebarPrivate *priv; - gboolean focusable = TRUE; - - g_return_if_fail(HILDON_IS_VOLUMEBAR(self)); - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(self); - - /* Slider should be insensitive when mute is on */ - gtk_widget_set_sensitive(GTK_WIDGET(priv->volumebar), !mute); - - focusable = GTK_WIDGET_CAN_FOCUS (GTK_WIDGET (priv->volumebar)); - - if (mute){ - if (focusable){ - /* Make mute button focusable since the slider isn't anymore */ - g_object_set (G_OBJECT (priv->tbutton), "can-focus", TRUE, NULL); - gtk_widget_grab_focus (GTK_WIDGET(priv->tbutton)); - } - } - else - { - g_object_set (G_OBJECT (priv->tbutton), "can-focus", FALSE, NULL); - - /* Mute off grabs focus */ - if (focusable){ - gtk_widget_grab_focus (GTK_WIDGET (self)); - } - else{ - /* If volumebar is not focusable, focus the parent window instead */ - GtkWidget *win = gtk_widget_get_ancestor (GTK_WIDGET (self), - GTK_TYPE_WINDOW); - gtk_window_set_focus (GTK_WINDOW (win), NULL); - } - } - - /* Update mute button state and redraw */ - gtk_toggle_button_set_active(priv->tbutton, mute); - - gtk_widget_queue_draw (GTK_WIDGET (self)); -} - -/** - * hildon_volumebar_get_mute: - * @self: volume bar to query mute status - * - * Gets mute status of this #HildonVolumebar (ON/OFF). - * - * Returns: Mute status as #gboolean value. - */ -gboolean -hildon_volumebar_get_mute(HildonVolumebar * self) -{ - HildonVolumebarPrivate *priv; - - g_return_val_if_fail(HILDON_IS_VOLUMEBAR(self), TRUE); - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(self); - - return gtk_toggle_button_get_active(priv->tbutton); -} - -/** - * hildon_volumebar_get_adjustment - * @self : a #HildonVolumebar - * - * Gets the GtkAdjustment used in volume bar. This can be handy - * to give to hildon_appview_set_connected_adjustment which - * will allow changing the volume with increase / decrease - * hardware buttons. - * - * This is a temporary solution until volume bar is restructured to - * be a child class of GtkRange. - * - * Returns: a #GtkAdjustment used by volume bar. - */ -GtkAdjustment * -hildon_volumebar_get_adjustment (HildonVolumebar * self) -{ - HildonVolumebarPrivate *priv; - - g_return_val_if_fail(HILDON_IS_VOLUMEBAR(self), NULL); - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(self); - - return gtk_range_get_adjustment (GTK_RANGE (priv->volumebar)); -} - -static void -mute_toggled (HildonVolumebar *self) -{ - /* This looks like no-op, but it still does something meaningfull! - set_mute also updates the ui to match new state that - is already reported by get_mute */ - hildon_volumebar_set_mute (self, hildon_volumebar_get_mute(self)); -} - -static gboolean -hildon_volumebar_key_press (GtkWidget * widget, - GdkEventKey * event) -{ - HildonVolumebarPrivate *priv; - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget); - - /* Enter key toggles mute button (unless it is hidden) */ - if (event->keyval == GDK_Return && GTK_WIDGET_VISIBLE(priv->tbutton)) { - gtk_toggle_button_set_active(priv->tbutton, - !hildon_volumebar_get_mute(HILDON_VOLUMEBAR(widget))); - return TRUE; - } - - return GTK_WIDGET_CLASS(parent_class)->key_press_event(widget, event); -} - -/* Sends mute-toggled signal to widget, used as a callback in derived classes - Just keep this "protected" in order to avoid introducing new API. */ -void -_hildon_volumebar_mute_toggled(HildonVolumebar * self) -{ - g_return_if_fail(HILDON_IS_VOLUMEBAR(self)); - g_signal_emit_by_name(self, "mute_toggled"); -} diff --git a/hildon-widgets/hildon-volumebar.h b/hildon-widgets/hildon-volumebar.h deleted file mode 100644 index 10e0694..0000000 --- a/hildon-widgets/hildon-volumebar.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ -#ifndef __HILDON_VOLUMEBAR_H__ -#define __HILDON_VOLUMEBAR_H__ - -#include -#include - -G_BEGIN_DECLS - -#define HILDON_TYPE_VOLUMEBAR ( hildon_volumebar_get_type() ) -#define HILDON_VOLUMEBAR(obj) (GTK_CHECK_CAST (obj,\ - HILDON_TYPE_VOLUMEBAR, HildonVolumebar)) -#define HILDON_VOLUMEBAR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass),\ - HILDON_TYPE_VOLUMEBAR, HildonVolumebarClass)) -#define HILDON_IS_VOLUMEBAR(obj) (GTK_CHECK_TYPE (obj,\ - HILDON_TYPE_VOLUMEBAR)) -#define HILDON_IS_VOLUMEBAR_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_VOLUMEBAR)) - -typedef struct _HildonVolumebar HildonVolumebar; -typedef struct _HildonVolumebarClass HildonVolumebarClass; - -struct _HildonVolumebar { - GtkContainer par; -}; - -struct _HildonVolumebarClass { - GtkContainerClass parent_class; - - /* signals */ - void (*mute_toggled) (HildonVolumebar * self); - void (*level_changed) (HildonVolumebar * self); -}; - - -GType hildon_volumebar_get_type (void) G_GNUC_CONST; - -double hildon_volumebar_get_level (HildonVolumebar *self); -void hildon_volumebar_set_level (HildonVolumebar *self, - gdouble level); - -gboolean hildon_volumebar_get_mute (HildonVolumebar *self); -void hildon_volumebar_set_mute (HildonVolumebar *self, - gboolean mute); - -void hildon_volumebar_level_change (HildonVolumebar *self); - -GtkAdjustment * hildon_volumebar_get_adjustment (HildonVolumebar *self); - - -G_END_DECLS -#endif /* __HILDON_VOLUMEBAR_H__ */ diff --git a/hildon-widgets/hildon-vvolumebar.c b/hildon-widgets/hildon-vvolumebar.c deleted file mode 100644 index 17fde14..0000000 --- a/hildon-widgets/hildon-vvolumebar.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/* - * SECTION:hildon-vvolumebar - * @short_description: A widget that displays a vertical volume bar - * @see_also: #HildonVolumebar, #HildonHVolumebar - * - * #HildonVVolumebar is a subclass of #HildonVolumebar. It displays a - * vertical volume bar that allows increasing or decreasing volume - * within a predefined range, and muting when users click the mute icon. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include "hildon-vvolumebar.h" -#include "hildon-volumebar-range.h" -#include "hildon-volumebar-private.h" - -/* Volume bar */ -#define DEFAULT_BAR_WIDTH 58 -#define MINIMUM_BAR_HEIGHT 165 -/* Toggle button */ -#define DEFAULT_VERTICAL_TBUTTON_WIDTH 26 -#define DEFAULT_VERTICAL_TBUTTON_HEIGHT 26 -#define DEFAULT_ENDING_SIZE 20 -/* Gap to leave for mute button */ -#define HORIZONTAL_MUTE_GAP 16 -#define VERTICAL_MUTE_GAP 6 - -static HildonVolumebarClass *parent_class; -static void hildon_vvolumebar_class_init(HildonVVolumebarClass * klass); -static void hildon_vvolumebar_init(HildonVVolumebar * vvolumebar); -static gboolean hildon_vvolumebar_expose(GtkWidget * widget, - GdkEventExpose * event); -static void hildon_vvolumebar_size_request(GtkWidget * widget, - GtkRequisition * requisition); -static void hildon_vvolumebar_size_allocate(GtkWidget * widget, - GtkAllocation * allocation); - -GType hildon_vvolumebar_get_type(void) -{ - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof(HildonVVolumebarClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_vvolumebar_class_init, /* class_init */ - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonVVolumebar), - 0, - (GInstanceInitFunc) hildon_vvolumebar_init, - }; - type = - g_type_register_static(HILDON_TYPE_VOLUMEBAR, - "HildonVVolumebar", &info, 0); - } - return type; -} - -static void hildon_vvolumebar_class_init(HildonVVolumebarClass * klass) -{ - GtkWidgetClass *volumebar_class = GTK_WIDGET_CLASS(klass); - - parent_class = g_type_class_peek_parent(klass); - - volumebar_class->size_request = hildon_vvolumebar_size_request; - volumebar_class->size_allocate = hildon_vvolumebar_size_allocate; - volumebar_class->expose_event = hildon_vvolumebar_expose; -} - -static void hildon_vvolumebar_init(HildonVVolumebar * vvolumebar) -{ - HildonVolumebarPrivate *priv; - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(vvolumebar); - - priv->volumebar = - HILDON_VOLUMEBAR_RANGE(hildon_volumebar_range_new - (GTK_ORIENTATION_VERTICAL)); - - GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(vvolumebar), GTK_CAN_FOCUS); - - gtk_widget_set_parent(GTK_WIDGET(priv->tbutton), GTK_WIDGET(vvolumebar)); - gtk_widget_set_parent(GTK_WIDGET(priv->volumebar), GTK_WIDGET(vvolumebar)); - - gtk_scale_set_draw_value(GTK_SCALE(priv->volumebar), FALSE); - - /* Signals */ - g_signal_connect_swapped(G_OBJECT(priv->volumebar), "value-changed", - G_CALLBACK(hildon_volumebar_level_change), - vvolumebar); - g_signal_connect_swapped(priv->tbutton, "toggled", - G_CALLBACK(_hildon_volumebar_mute_toggled), vvolumebar); - - gtk_widget_show(GTK_WIDGET(priv->volumebar)); -} - -/** - * hildon_vvolumebar_new: - * - * Creates a new #HildonVVolumebar widget. - * - * Returns: a new #HildonVVolumebar - */ -GtkWidget *hildon_vvolumebar_new(void) -{ - return GTK_WIDGET(g_object_new(HILDON_TYPE_VVOLUMEBAR, NULL)); -} - -static gboolean hildon_vvolumebar_expose(GtkWidget * widget, - GdkEventExpose * event) -{ - HildonVolumebarPrivate *priv; - - g_assert(HILDON_IS_VVOLUMEBAR(widget)); - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(HILDON_VOLUMEBAR(widget)); - - if (GTK_WIDGET_DRAWABLE(widget)) { - /* Paint background */ - gtk_paint_box(widget->style, widget->window, - GTK_WIDGET_STATE(priv->volumebar), GTK_SHADOW_OUT, - NULL, widget, "background", - widget->allocation.x, - widget->allocation.y, - widget->allocation.width, - widget->allocation.height); - - /* The contents of the widget can paint themselves */ - (*GTK_WIDGET_CLASS(parent_class)->expose_event) (widget, event); - } - - return FALSE; -} - -static void -hildon_vvolumebar_size_request(GtkWidget * widget, - GtkRequisition * requisition) -{ - g_assert(HILDON_IS_VVOLUMEBAR(widget)); - - requisition->height = MINIMUM_BAR_HEIGHT; - requisition->width = DEFAULT_BAR_WIDTH; -} - -static void -hildon_vvolumebar_size_allocate(GtkWidget * widget, - GtkAllocation * allocation) -{ - HildonVolumebarPrivate *priv; - - GtkAllocation range_allocation, button_allocation; - - g_assert(HILDON_IS_VVOLUMEBAR(widget)); - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget); - - /* Center the widget horizontally */ - if (allocation->width > DEFAULT_BAR_WIDTH) { - allocation->x += - (allocation->width - DEFAULT_BAR_WIDTH) / 2; - allocation->width = DEFAULT_BAR_WIDTH; - } - - GTK_WIDGET_CLASS(parent_class)->size_allocate(widget, allocation); - - if (priv->volumebar && GTK_WIDGET_VISIBLE(priv->volumebar)) { - /* Allocate space for the slider */ - range_allocation.x = allocation->x; - range_allocation.y = allocation->y + DEFAULT_ENDING_SIZE; - - range_allocation.width = DEFAULT_BAR_WIDTH; - - if (priv->tbutton && GTK_WIDGET_VISIBLE(priv->tbutton)) - { - /* Leave room for the mute button */ - range_allocation.height = MAX(0, - allocation->height - - 2 * DEFAULT_ENDING_SIZE - - DEFAULT_VERTICAL_TBUTTON_HEIGHT - - VERTICAL_MUTE_GAP); - } - - else - { - range_allocation.height = MAX(0, - allocation->height - - 2 * DEFAULT_ENDING_SIZE); - } - - gtk_widget_size_allocate(GTK_WIDGET(priv->volumebar), - &range_allocation); - } - - if (priv->tbutton && GTK_WIDGET_VISIBLE(priv->tbutton)) { - /* Allocate space for the mute button */ - button_allocation.x = allocation->x + HORIZONTAL_MUTE_GAP; - button_allocation.y = allocation->y + allocation->height - - VERTICAL_MUTE_GAP - 2 * DEFAULT_ENDING_SIZE; - button_allocation.width = DEFAULT_VERTICAL_TBUTTON_WIDTH; - button_allocation.height = DEFAULT_VERTICAL_TBUTTON_HEIGHT; - gtk_widget_size_allocate(GTK_WIDGET(priv->tbutton), - &button_allocation); - } -} diff --git a/hildon-widgets/hildon-vvolumebar.h b/hildon-widgets/hildon-vvolumebar.h deleted file mode 100644 index 5807aee..0000000 --- a/hildon-widgets/hildon-vvolumebar.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_VVOLUMEBAR_H__ -#define __HILDON_VVOLUMEBAR_H__ - -#include - -G_BEGIN_DECLS - -#define HILDON_TYPE_VVOLUMEBAR ( hildon_vvolumebar_get_type() ) - -#define HILDON_VVOLUMEBAR(obj) (GTK_CHECK_CAST (obj, HILDON_TYPE_VVOLUMEBAR, HildonVVolumebar)) - -#define HILDON_VVOLUMEBAR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass),\ - HILDON_TYPE_VVOLUMEBAR, HildonVVolumebarClass)) - -#define HILDON_IS_VVOLUMEBAR(obj) (GTK_CHECK_TYPE (obj, HILDON_TYPE_VVOLUMEBAR)) - -#define HILDON_IS_VVOLUMEBAR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_VVOLUMEBAR)) - - -typedef struct _HildonVVolumebar HildonVVolumebar; -typedef struct _HildonVVolumebarClass HildonVVolumebarClass; - -struct _HildonVVolumebar { - HildonVolumebar volumebar; /* this is our parent class */ -}; - -struct _HildonVVolumebarClass { - HildonVolumebarClass parent_class; -}; - -GType hildon_vvolumebar_get_type (void) G_GNUC_CONST; -GtkWidget * hildon_vvolumebar_new (void); - - -G_END_DECLS -#endif /* __HILDON_VVOLUMEBAR_H__ */ diff --git a/hildon-widgets/hildon-weekday-picker.c b/hildon-widgets/hildon-weekday-picker.c deleted file mode 100644 index 5f25fd1..0000000 --- a/hildon-widgets/hildon-weekday-picker.c +++ /dev/null @@ -1,502 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-weekday-picker - * @short_description: A widget for picking days on which a certain event - * should take place - * @see_also: #HildonWeekdayPicker - * - * #HildonWeekdayPicker supports non-mutually exclusive selection of days of - * the week. Selected days of the week are shown with a pushed-in effect. - * - * #HildonWeekdayPicker is used where users are required to pick days on which - * a certain event should take place, for example, which days a Calendar event - * should be repeated on. It is used in Calendar in the Repeat dialog, in Tasks - * in the Repeat dialog and in the Email set-up wizard. - */ - - /* GDate numbers days from 1 to 7 and G_DATE_MONDAY is 1st day. However - according to locale settings first day is sunday. To get around this - problem, we addjust GDate days numbering to be same as locale - numbering */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "hildon-weekday-picker.h" -#include "hildon-composite-widget.h" - -#define HILDON_WEEKDAY_PICKER_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_WEEKDAY_PICKER, HildonWeekdayPickerPrivate)); - -static GtkContainerClass *parent_class; - -typedef struct _HildonWeekdayPickerPrivate HildonWeekdayPickerPrivate; - -static void -hildon_weekday_picker_class_init(HildonWeekdayPickerClass * picker_class); -static void -hildon_weekday_picker_init(HildonWeekdayPicker * picker); -static void -hildon_weekday_picker_size_allocate(GtkWidget * widget, - GtkAllocation * allocation); -static void -hildon_weekday_picker_size_request(GtkWidget * widget, - GtkRequisition * requisition); -static void -hildon_weekday_picker_forall(GtkContainer * container, - gboolean include_internals, - GtkCallback callback, gpointer callback_data); -static void -hildon_weekday_picker_destroy(GtkObject * self); - -static void -button_toggle(GtkToggleButton * togglebutton, gpointer wpicker); - -struct _HildonWeekdayPickerPrivate { - GtkWidget *buttons[8]; /* weekday buttons in show order */ - GtkWidget *day_order_buttons[8]; /* weekday buttons in glib day order */ -}; - -enum { - SELECTION_CHANGED_SIGNAL, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -GType hildon_weekday_picker_get_type(void) -{ - static GType picker_type = 0; - - if (!picker_type) { - static const GTypeInfo picker_info = { - sizeof(HildonWeekdayPickerClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_weekday_picker_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonWeekdayPicker), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_weekday_picker_init, - }; - picker_type = g_type_register_static(GTK_TYPE_CONTAINER, - "HildonWeekdayPicker", - &picker_info, 0); - } - return picker_type; -} - -static void -hildon_weekday_picker_class_init(HildonWeekdayPickerClass * picker_class) -{ - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(picker_class); - GtkContainerClass *container_class = GTK_CONTAINER_CLASS(picker_class); - GObjectClass *object_class = G_OBJECT_CLASS(picker_class); - - parent_class = g_type_class_peek_parent(picker_class); - - g_type_class_add_private(picker_class, - sizeof(HildonWeekdayPickerPrivate)); - - /* Override virtual methods */ - widget_class->size_request = hildon_weekday_picker_size_request; - widget_class->size_allocate = hildon_weekday_picker_size_allocate; - widget_class->focus = hildon_composite_widget_focus; - container_class->forall = hildon_weekday_picker_forall; - GTK_OBJECT_CLASS(picker_class)->destroy = - hildon_weekday_picker_destroy; - - /* Create a signal for reporting user actions */ - signals[SELECTION_CHANGED_SIGNAL] = g_signal_new("selection_changed", - G_OBJECT_CLASS_TYPE - (object_class), - G_SIGNAL_RUN_LAST | - G_SIGNAL_ACTION, - G_STRUCT_OFFSET - (HildonWeekdayPickerClass, - selection_changed), NULL, NULL, - gtk_marshal_VOID__INT, - G_TYPE_NONE, 1, G_TYPE_INT); -} - -static void -hildon_weekday_picker_init(HildonWeekdayPicker * picker) -{ - HildonWeekdayPickerPrivate *priv; - gint i, day; - /* weekday indexes to be used with nl_langinfo. These are shifted - * by one for glib compability */ - int wdays[] = { - -1, /* 0 = invalid date */ - ABDAY_2, /* 1 = monday in glib */ - ABDAY_3, /* 2 = tuesday in glib */ - ABDAY_4, /* 3 = wednesday in glib */ - ABDAY_5, /* 4 = thursday in glib */ - ABDAY_6, /* 5 = friday in glib */ - ABDAY_7, /* 6 = saturday in glib */ - ABDAY_1 }; /* 7 = sunday in glib */ - GtkSizeGroup *sgroup; - - sgroup = gtk_size_group_new(GTK_SIZE_GROUP_BOTH); - - /* Check our first weekday */ - day = *nl_langinfo(_NL_TIME_FIRST_WEEKDAY); - - priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker); - - /* Shift the days by one. This is done because GDateWeekday - * starts with Monday(1) and langinfo's first day is Sunday */ - day--; - if (day < 1) - day = 7; - - /* Initialize and pack day buttons */ - for (i = 1; i <= 7; i++) { - priv->buttons[i] = - gtk_toggle_button_new_with_label(nl_langinfo(wdays[day])); - priv->day_order_buttons[day] = priv->buttons[i]; - day++; - - if (day > 7) - day = 1; - - g_signal_connect(GTK_WIDGET(priv->buttons[i]), - "toggled", G_CALLBACK(button_toggle), picker); - - gtk_size_group_add_widget(sgroup, priv->buttons[i]); - - gtk_widget_set_parent(priv->buttons[i], GTK_WIDGET(picker)); - gtk_widget_show(priv->buttons[i]); - } - - GTK_WIDGET_SET_FLAGS(picker, GTK_NO_WINDOW); - - g_object_unref( sgroup ); -} - -/** - * hildon_weekday_picker_new: - * - * Creates a new #HildonWeekdayPicker. - * - * Returns: pointer to a new #HildonWeekdayPicker widget. - */ -GtkWidget *hildon_weekday_picker_new(void) -{ - return g_object_new(HILDON_TYPE_WEEKDAY_PICKER, NULL); -} - -static void -hildon_weekday_picker_forall(GtkContainer * container, - gboolean include_internals, GtkCallback callback, - gpointer callback_data) -{ - HildonWeekdayPicker *picker; - HildonWeekdayPickerPrivate *priv; - gint i; - - g_assert(container); - g_assert(callback); - - picker = HILDON_WEEKDAY_PICKER(container); - priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker); - - /* We only have internal children */ - if (!include_internals) - return; - - /* Activate callback for each day button */ - for (i = 1; i <= 7; ++i) { - (*callback) (priv->buttons[i], callback_data); - } - -} - -static void -hildon_weekday_picker_destroy(GtkObject * self) -{ - HildonWeekdayPickerPrivate *priv; - gint i; - - priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(self); - - /* Destroy internal children... */ - for (i = 1; i <= 7; ++i) { - if (priv->buttons[i]) - { - gtk_widget_unparent(priv->buttons[i]); - priv->buttons[i] = NULL; - } - } - - /* ... and chain to parent. */ - if (GTK_OBJECT_CLASS(parent_class)->destroy) - GTK_OBJECT_CLASS(parent_class)->destroy(self); - -} - -static void -hildon_weekday_picker_size_request(GtkWidget * widget, - GtkRequisition *requisition) -{ - HildonWeekdayPicker *picker; - HildonWeekdayPickerPrivate *priv; - gint i; - GtkRequisition req; - - picker = HILDON_WEEKDAY_PICKER(widget); - priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker); - requisition->width = 0; - requisition->height = 0; - - /* Request an area that is as wide as all of the buttons - together and tall enough to hold heightest button */ - for (i = 1; i <= 7; ++i) { - gtk_widget_size_request(priv->buttons[i], &req); - requisition->width += req.width; - if (req.height > requisition->height) - requisition->height = req.height; - - } -} - -static void -hildon_weekday_picker_size_allocate(GtkWidget * widget, - GtkAllocation * allocation) -{ - HildonWeekdayPicker *picker; - HildonWeekdayPickerPrivate *priv; - gint i; - GtkAllocation alloc; - GtkRequisition child_requisition; - gint header_x; - guint sval; - GtkTextDirection direction; - - g_assert(widget); - g_assert(allocation); - - /* Check orientation */ - direction = gtk_widget_get_direction(widget); - - picker = HILDON_WEEKDAY_PICKER(widget); - priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker); - header_x = allocation->x; - widget->allocation = *allocation; - - if (direction == GTK_TEXT_DIR_LTR || direction == GTK_TEXT_DIR_NONE) - sval = 1; - else - sval = 7; - - /* Allocate day buttons side by side honouring the text direction */ - for (i = 1; i <= 7; ++i) { - gtk_widget_get_child_requisition(priv->buttons[sval], - &child_requisition); - - alloc.x = header_x; - alloc.y = allocation->y; - alloc.width = child_requisition.width; - alloc.height = child_requisition.height; - header_x += alloc.width; - gtk_widget_size_allocate(priv->buttons[sval], &alloc); - if (direction == GTK_TEXT_DIR_RTL) - sval--; - else - sval++; - } -} - -static void -button_toggle(GtkToggleButton * button, gpointer wpicker) -{ - HildonWeekdayPicker *picker; - HildonWeekdayPickerPrivate *priv; - gint i; - - g_assert(button); - g_assert(wpicker); - - picker = HILDON_WEEKDAY_PICKER(wpicker); - priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker); - - for (i = 1; i <= 7; ++i) { - if (GTK_WIDGET(button) == priv->day_order_buttons[i]) { - g_signal_emit (GTK_WIDGET(picker), - signals[SELECTION_CHANGED_SIGNAL], 0, i); - break; - } - } -} - -/** - * hildon_weekday_picker_set_day: - * @picker: the #HildonWeekdayPicker widget - * @day: day to be set active - * - * Sets specified weekday active. - */ -void -hildon_weekday_picker_set_day(HildonWeekdayPicker * picker, - GDateWeekday day) -{ - HildonWeekdayPickerPrivate *priv; - - g_return_if_fail(picker); - g_return_if_fail(g_date_valid_weekday(day)); - - priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker); - - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON - (priv->day_order_buttons[day]), TRUE); -} - -/** - * hildon_weekday_picker_unset_day: - * @picker: the #HildonWeekdayPicker widget - * @day: day to be set inactive - * - * Sets specified weekday inactive. - */ -void -hildon_weekday_picker_unset_day(HildonWeekdayPicker * picker, - GDateWeekday day) -{ - HildonWeekdayPickerPrivate *priv; - - g_return_if_fail(picker); - g_return_if_fail(g_date_valid_weekday(day)); - - priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker); - - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON - (priv->day_order_buttons[day]), FALSE); -} - -/** - * hildon_weekday_picker_toggle_day: - * @picker: the #HildonWeekdayPicker widget - * @day: day to be toggled - * - * Toggles current status of the specified weekday. - */ -void -hildon_weekday_picker_toggle_day(HildonWeekdayPicker * picker, - GDateWeekday day) -{ - HildonWeekdayPickerPrivate *priv; - - g_return_if_fail(picker); - g_return_if_fail(g_date_valid_weekday(day)); - - priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker); - - gtk_toggle_button_set_active( - GTK_TOGGLE_BUTTON(priv->day_order_buttons[day]), - !gtk_toggle_button_get_active( - GTK_TOGGLE_BUTTON(priv->day_order_buttons[day]))); -} - -/** - * hildon_weekday_picker_set_all: - * @picker: the #HildonWeekdayPicker widget - * - * Sets all weekdays active. - */ -void -hildon_weekday_picker_set_all(HildonWeekdayPicker * picker) -{ - HildonWeekdayPickerPrivate *priv; - gint i; - - g_return_if_fail(picker); - - priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker); - - for (i = 1; i <= 7; i++) - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->buttons[i]), - TRUE); -} - -/** - * hildon_weekday_picker_unset_all: - * @picker: the #HildonWeekdayPicker widget - * - * Sets all weekdays inactive. - */ -void -hildon_weekday_picker_unset_all(HildonWeekdayPicker * picker) -{ - HildonWeekdayPickerPrivate *priv; - gint i; - - g_return_if_fail(picker); - - priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker); - - for (i = 1; i <= 7; i++) - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->buttons[i]), - FALSE); -} - -/** - * hildon_weekday_picker_isset_day: - * @picker: the #HildonWeekdayPicker widget - * @day: day to be checked. - * - * Checks if the specified weekday is set active. - * - * Returns: TRUE if the day is set, FALSE if the day is not set - */ -gboolean -hildon_weekday_picker_isset_day(HildonWeekdayPicker * picker, - GDateWeekday day) -{ - HildonWeekdayPickerPrivate *priv; - - g_return_val_if_fail(picker, FALSE); - g_return_val_if_fail(g_date_valid_weekday(day), FALSE); - - priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker); - - return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON( - priv->day_order_buttons[day])); -} diff --git a/hildon-widgets/hildon-weekday-picker.h b/hildon-widgets/hildon-weekday-picker.h deleted file mode 100644 index feb0db6..0000000 --- a/hildon-widgets/hildon-weekday-picker.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_WEEKDAY_PICKER_H__ -#define __HILDON_WEEKDAY_PICKER_H__ - -#include - -G_BEGIN_DECLS -/** - * HILDON_TYPE_WEEKDAY_PICKER: - * - * Macro for getting type of weekday picker. - * Since: 0.12.10 - */ -#define HILDON_TYPE_WEEKDAY_PICKER ( hildon_weekday_picker_get_type() ) - -/** - * HILDON_WEEKDAY_PICKER_TYPE: - * - * Deprecated: use #HILDON_TYPE_WEEKDAY_PICKER instead. - */ -#define HILDON_WEEKDAY_PICKER_TYPE HILDON_TYPE_WEEKDAY_PICKER - -#define HILDON_WEEKDAY_PICKER(obj) \ - (GTK_CHECK_CAST (obj, HILDON_TYPE_WEEKDAY_PICKER, \ - HildonWeekdayPicker)) -#define HILDON_WEEKDAY_PICKER_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), \ - HILDON_TYPE_WEEKDAY_PICKER, HildonWeekdayPickerClass)) -#define HILDON_IS_WEEKDAY_PICKER(obj) \ - (GTK_CHECK_TYPE (obj, HILDON_TYPE_WEEKDAY_PICKER)) -#define HILDON_IS_WEEKDAY_PICKER_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_WEEKDAY_PICKER)) -/** - * HildonWeekdayPicker: - * - * Internal struct for weekday picker. - */ -typedef struct _HildonWeekdayPicker HildonWeekdayPicker; -typedef struct _HildonWeekdayPickerClass HildonWeekdayPickerClass; - -struct _HildonWeekdayPicker { - GtkContainer parent; -}; - -struct _HildonWeekdayPickerClass { - GtkContainerClass parent_class; - - void (*selection_changed) (HildonWeekdayPicker * self); -}; - -GType hildon_weekday_picker_get_type(void) G_GNUC_CONST; - -/** - * hildon_weekday_picker_new: - * - * Creates a new #HildonWeekdayPicker. - * - * Return value: New #HildonWeekdayPicker. - **/ -GtkWidget *hildon_weekday_picker_new(void); - -/** - * hildon_weekday_picker_set_day: - * @picker: #HildonWeekdayPicker. - * @day: #GDateWeekday. - * - * Select specified weekday. - * - **/ -void hildon_weekday_picker_set_day(HildonWeekdayPicker * picker, - GDateWeekday day); - -/** - * hildon_weekday_picker_unset_day: - * @picker: #HildonWeekdayPicker. - * @day: #GDateWeekday. - * - * Unselect specified weekday. - * - **/ -void hildon_weekday_picker_unset_day(HildonWeekdayPicker * picker, - GDateWeekday day); - -/** - * hildon_weekday_picker_toggle_day: - * @picker: #HildonWeekdayPicker. - * @day: #GDateWeekday. - * - * Toggle current status of the specified weekday. - * - **/ -void hildon_weekday_picker_toggle_day(HildonWeekdayPicker * picker, - GDateWeekday day); - -/** - * hildon_weekday_picker_set_all: - * @picker: #HildonWeekdayPicker. - * - * Select all weekdays. - * - **/ -void hildon_weekday_picker_set_all(HildonWeekdayPicker * picker); - -/** - * hildon_weekday_picker_unset_all: - * @picker: #HildonWeekdayPicker. - * - * Unselect all weekdays. - * - **/ -void hildon_weekday_picker_unset_all(HildonWeekdayPicker * picker); - -/** - * hildon_weekday_picker_isset_day: - * @picker: #HildonWeekdayPicker. - * @day: #GDateWeekday. - * - * Check if the specified weekday is set. - * - * Return value: Set/not set. - **/ -gboolean hildon_weekday_picker_isset_day(HildonWeekdayPicker * picker, - GDateWeekday day); - -G_END_DECLS -#endif /* __HILDON_WEEKDAY_PICKER_H__ */ diff --git a/hildon-widgets/hildon-window-private.h b/hildon-widgets/hildon-window-private.h deleted file mode 100644 index 92ea85e..0000000 --- a/hildon-widgets/hildon-window-private.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - - -#ifndef __HILDON_WINDOW_PRIVATE_H__ -#define __HILDON_WINDOW_PRIVATE_H__ - -G_BEGIN_DECLS - -void -hildon_window_set_program (HildonWindow *self, GObject *program); - -void -hildon_window_unset_program (HildonWindow *self); - -void -hildon_window_set_can_hibernate_property (HildonWindow *self, - gpointer can_hibernate); - -void -hildon_window_take_common_toolbar (HildonWindow *self); - -void -hildon_window_update_topmost (HildonWindow *self, Window window_id); - -Window -hildon_window_get_active_window (void); - -void -hildon_window_update_title (HildonWindow *window); - -G_END_DECLS -#endif /* __HILDON_WINDOW_PRIVATE_H__ */ diff --git a/hildon-widgets/hildon-window.c b/hildon-widgets/hildon-window.c deleted file mode 100644 index faf9e0e..0000000 --- a/hildon-widgets/hildon-window.c +++ /dev/null @@ -1,1707 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - - -#include -#include -#include -#include -#include "hildon-app.h" -#include -#include "hildon-program.h" -#include "hildon-window-private.h" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - - -#include -#define _(String) gettext(String) - -/*The size of screen*/ -#define WINDOW_HEIGHT 480 -#define WINDOW_WIDTH 800 - -#define NAVIGATOR_HEIGHT WINDOW_HEIGHT - -#define APPVIEW_HEIGHT 396 -#define APPVIEW_WIDTH 672 - -#define TOOLBAR_HEIGHT 40 -#define TOOLBAR_MIDDLE 10 -#define TOOLBAR_WIDTH APPVIEW_WIDTH - -/*FIXME*/ -#define CAN_HIBERNATE "CANKILL" -#define CAN_HIBERNATE_LENGTH 7 - -#define CAN_HIBERNATE_PROPERTY "_HILDON_ABLE_TO_HIBERNATE" - -#define TITLE_SEPARATOR " - " - - -#define HILDON_WINDOW_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ - HILDON_TYPE_WINDOW, HildonWindowPrivate)) - -static GtkWindowClass *parent_class; - -static void -hildon_window_init (HildonWindow * self); - -static void -hildon_window_class_init (HildonWindowClass * window_class); - -static void -hildon_window_menupopupfunc (GtkMenu *menu, gint *x, gint *y, - gboolean *push_in, - GtkWidget *widget); -static void -hildon_window_menupopupfuncfull (GtkMenu *menu, gint *x, gint *y, - gboolean *push_in, - GtkWidget *widget); -static gboolean -hildon_window_expose (GtkWidget * widget, GdkEventExpose * event); -static void -hildon_window_forall (GtkContainer * container, - gboolean include_internals, - GtkCallback callback, - gpointer callback_data); -static void -hildon_window_show_all (GtkWidget *widget); - -static void -hildon_window_size_allocate (GtkWidget * widget, - GtkAllocation * allocation); -static void -hildon_window_size_request (GtkWidget * widget, - GtkRequisition * requisition); -static void -hildon_window_finalize (GObject * obj_self); -static void -hildon_window_set_property (GObject * object, guint property_id, - const GValue * value, GParamSpec * pspec); -static void -hildon_window_get_property (GObject * object, guint property_id, - GValue * value, GParamSpec * pspec); -static void -hildon_window_destroy (GtkObject *obj); -static void -hildon_window_realize (GtkWidget *widget); -static void -hildon_window_unrealize (GtkWidget *widget); -static gboolean -hildon_window_key_press_event (GtkWidget *widget, - GdkEventKey *event); -static gboolean -hildon_window_key_release_event (GtkWidget *widget, - GdkEventKey *event); -static gboolean -hildon_window_window_state_event (GtkWidget *widget, - GdkEventWindowState *event); - - -static void -hildon_window_notify (GObject *gobject, GParamSpec *param); - -static void -hildon_window_is_topmost_notify (HildonWindow *window); - -static gboolean -hildon_window_toggle_menu (HildonWindow * self); - -static gboolean -hildon_window_escape_timeout (gpointer data); - -static GdkFilterReturn -hildon_window_event_filter (GdkXEvent *xevent, GdkEvent *event, gpointer data ); - -static GdkFilterReturn -hildon_window_root_window_event_filter (GdkXEvent *xevent, - GdkEvent *event, - gpointer data ); - -static void -hildon_window_get_borders (HildonWindow *window); - -static void -visible_toolbar (gpointer data, gpointer user_data); -static void -paint_toolbar (GtkWidget *widget, GtkBox *box, - GdkEventExpose * event, - gboolean fullscreen); - -typedef void (*HildonWindowSignal) (HildonWindow *, gint, gpointer); - - - -enum -{ - PROP_0, - PROP_IS_TOPMOST -}; - -enum -{ - WIN_TYPE = 0, - WIN_TYPE_MESSAGE, - MAX_WIN_MESSAGES -}; - -struct _HildonWindowPrivate -{ - GtkWidget *menu; - GtkWidget *vbox; - - GtkBorder *borders; - GtkBorder *toolbar_borders; - - GtkAllocation allocation; - - guint fullscreen; - guint is_topmost; - guint escape_timeout; - gint visible_toolbars; - gint previous_vbox_y; - - HildonProgram *program; -}; - -GType -hildon_window_get_type (void) -{ - static GType window_type = 0; - - if (!window_type) { - static const GTypeInfo window_info = { - sizeof(HildonWindowClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_window_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonWindow), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_window_init, - }; - window_type = g_type_register_static(GTK_TYPE_WINDOW, - "HildonWindow", - &window_info, 0); - } - return window_type; -} - -/* Virtual methods */ - -static void -hildon_window_class_init (HildonWindowClass * window_class) -{ - /* Get convenience variables */ - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (window_class); - GObjectClass *object_class = G_OBJECT_CLASS (window_class); - GtkContainerClass *container_class = GTK_CONTAINER_CLASS (window_class); - - /* Set the global parent_class here */ - parent_class = g_type_class_peek_parent (window_class); - - object_class->set_property = hildon_window_set_property; - object_class->get_property = hildon_window_get_property; - object_class->notify = hildon_window_notify; - - /* Set the widgets virtual functions */ - widget_class->size_allocate = hildon_window_size_allocate; - widget_class->size_request = hildon_window_size_request; - widget_class->expose_event = hildon_window_expose; - widget_class->show_all = hildon_window_show_all; - widget_class->realize = hildon_window_realize; - widget_class->unrealize = hildon_window_unrealize; - widget_class->key_press_event = hildon_window_key_press_event; - widget_class->key_release_event = hildon_window_key_release_event; - widget_class->window_state_event = hildon_window_window_state_event; - - /* now the object stuff */ - object_class->finalize = hildon_window_finalize; - - /* To the container */ - container_class->forall = hildon_window_forall; - - /* gtkobject stuff*/ - GTK_OBJECT_CLASS (window_class)->destroy = hildon_window_destroy; - - g_type_class_add_private (window_class, - sizeof (struct _HildonWindowPrivate)); - - /* Install properties */ - g_object_class_install_property (object_class, PROP_IS_TOPMOST, - g_param_spec_boolean ("is-topmost", - "Is top-most", - "Whether the window is currently activated by the window " - "manager", - FALSE, - G_PARAM_READABLE)); - - gtk_widget_class_install_style_property (widget_class, - g_param_spec_boxed ("borders", - "Graphical borders", - "Size of graphical window borders", - GTK_TYPE_BORDER, - G_PARAM_READABLE)); - - gtk_widget_class_install_style_property (widget_class, - g_param_spec_boxed ("toolbar-borders", - "Graphical toolbar borders", - "Size of graphical toolbar borders", - GTK_TYPE_BORDER, - G_PARAM_READABLE)); - - /* opera hack, install clip operation signal */ - g_signal_new ("clipboard_operation", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (HildonWindowClass, clipboard_operation), - NULL, NULL, - g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, - GTK_TYPE_INT); -} - -static void -hildon_window_init (HildonWindow * self) -{ - HildonWindowPrivate *priv = self->priv = HILDON_WINDOW_GET_PRIVATE(self); - - self->priv->vbox = gtk_vbox_new (TRUE, TOOLBAR_MIDDLE); - gtk_widget_set_parent (self->priv->vbox, GTK_WIDGET(self)); - priv->menu = NULL; - priv->visible_toolbars = 0; - priv->is_topmost = FALSE; - priv->borders = NULL; - priv->toolbar_borders = NULL; - priv->escape_timeout = 0; - - priv->fullscreen = FALSE; - - priv->program = NULL; - - /* We need to track the root window _MB_CURRENT_APP_WINDOW property */ - gdk_window_set_events (gdk_get_default_root_window (), - gdk_window_get_events (gdk_get_default_root_window ()) | GDK_PROPERTY_CHANGE_MASK); - - gdk_window_add_filter (gdk_get_default_root_window (), - hildon_window_root_window_event_filter, self); -} - -static void -hildon_window_finalize (GObject * obj_self) -{ - HildonWindow *self; - g_return_if_fail (HILDON_WINDOW (obj_self)); - self = HILDON_WINDOW (obj_self); - - g_free (self->priv->borders); - g_free (self->priv->toolbar_borders); - - if (G_OBJECT_CLASS (parent_class)->finalize) - G_OBJECT_CLASS (parent_class)->finalize (obj_self); - -} - -static void -hildon_window_realize (GtkWidget *widget) -{ - Atom *old_atoms, *new_atoms; - Display *disp; - Window window; - gint atom_count; - Window active_window; - - GTK_WIDGET_CLASS (parent_class)->realize (widget); - - gtk_widget_realize (GTK_WIDGET (HILDON_WINDOW (widget)->priv->vbox)); - - - /* catch the custom button signal from mb to display the menu */ - gdk_window_add_filter (widget->window, hildon_window_event_filter, widget ); - - window = GDK_WINDOW_XID ( widget->window ); - disp = GDK_WINDOW_XDISPLAY ( widget->window ); - - /* Enable custom button that is used for menu */ - XGetWMProtocols (disp, window, &old_atoms, &atom_count); - new_atoms = g_new (Atom, atom_count + 1); - - memcpy (new_atoms, old_atoms, sizeof(Atom) * atom_count); - - new_atoms[atom_count++] = - XInternAtom (disp, "_NET_WM_CONTEXT_CUSTOM", False); - - XSetWMProtocols (disp, window, new_atoms, atom_count); - - XFree(old_atoms); - g_free(new_atoms); - - /* rely on GDK to set the window group to its default */ - gdk_window_set_group (widget->window, NULL); - - if (HILDON_WINDOW (widget)->priv->program) - { - gboolean can_hibernate = hildon_program_get_can_hibernate ( - HILDON_WINDOW (widget)->priv->program); - - hildon_window_set_can_hibernate_property (HILDON_WINDOW (widget), - &can_hibernate); - } - - /* Update the topmost status */ - active_window = hildon_window_get_active_window(); - hildon_window_update_topmost (HILDON_WINDOW (widget), active_window); - - /* Update the window title */ - hildon_window_update_title(HILDON_WINDOW (widget)); - -} - -static void -hildon_window_unrealize (GtkWidget *widget) -{ - - gdk_window_remove_filter (widget->window, hildon_window_event_filter, - widget); - - gtk_widget_unrealize (GTK_WIDGET (HILDON_WINDOW (widget)->priv->vbox)); - GTK_WIDGET_CLASS(parent_class)->unrealize(widget); -} - -static void -hildon_window_set_property (GObject * object, guint property_id, - const GValue * value, GParamSpec * pspec) -{ - /*HildonWindow *window = HILDON_WINDOW (object);*/ - - switch (property_id) { - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -hildon_window_get_property (GObject * object, guint property_id, - GValue * value, GParamSpec * pspec) -{ - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (object); - - switch (property_id) { - - case PROP_IS_TOPMOST: - g_value_set_boolean (value, priv->is_topmost); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; - } -} - -/* - * Retrieve the graphical borders size used by the themes - */ -static void -hildon_window_get_borders (HildonWindow *window) -{ - - g_free (window->priv->borders); - g_free (window->priv->toolbar_borders); - - gtk_widget_style_get (GTK_WIDGET (window), "borders",&window->priv->borders, - "toolbar-borders", &window->priv->toolbar_borders, - NULL); - - if (!window->priv->borders) - { - window->priv->borders = (GtkBorder *)g_malloc0 (sizeof (GtkBorder)); - } - - if (!window->priv->toolbar_borders) - { - window->priv->toolbar_borders = - (GtkBorder *)g_malloc0 (sizeof (GtkBorder)); - } -} - -static void -visible_toolbars (gpointer data, gpointer user_data) -{ - if (GTK_WIDGET_VISIBLE (GTK_WIDGET (((GtkBoxChild *)data)->widget))) - (*((gint *)user_data)) ++; -} - -static gboolean -hildon_window_expose (GtkWidget * widget, GdkEventExpose * event) -{ - HildonWindowPrivate *priv = HILDON_WINDOW (widget)->priv; - GtkWidget *bx = HILDON_WINDOW(widget)->priv->vbox; - GtkBox *box = GTK_BOX(bx); - GtkBorder *b = HILDON_WINDOW(widget)->priv->borders; - GtkBorder *tb = HILDON_WINDOW(widget)->priv->toolbar_borders; - gint tb_height = 0; - gint currently_visible_toolbars = 0; - - if (!priv->borders) - { - hildon_window_get_borders (HILDON_WINDOW (widget)); - b = HILDON_WINDOW(widget)->priv->borders; - tb = HILDON_WINDOW(widget)->priv->toolbar_borders; - } - - tb_height = bx->allocation.height + tb->top + tb->bottom; - - g_list_foreach (box->children, visible_toolbars, - ¤tly_visible_toolbars); - - paint_toolbar (widget, box, - event, priv->fullscreen); - - if (!HILDON_WINDOW (widget)->priv->fullscreen) - { - - /* Draw the left and right window border */ - gint side_borders_height = widget->allocation.height - b->top; - - if (currently_visible_toolbars) - side_borders_height -= tb_height; - else - side_borders_height -= b->bottom; - - if (b->left > 0) - { - gtk_paint_box (widget->style, widget->window, - GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, - &event->area, widget, "left-border", - widget->allocation.x, widget->allocation.y + - b->top, b->left, side_borders_height); - } - - if (b->right > 0) - { - gtk_paint_box (widget->style, widget->window, - GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, - &event->area, widget, "right-border", - widget->allocation.x + widget->allocation.width - - b->right, widget->allocation.y + b->top, - b->right, side_borders_height); - } - - /* If no toolbar, draw the bottom window border */ - if (!currently_visible_toolbars && b->bottom > 0) - { - gtk_paint_box (widget->style, widget->window, - GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, - &event->area, widget, "bottom-border", - widget->allocation.x, widget->allocation.y + - (widget->allocation.height - b->bottom), - widget->allocation.width, b->bottom); - } - - /* Draw the top border */ - if (b->top > 0) - { - gtk_paint_box (widget->style, widget->window, - GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, - &event->area, widget, "top-border", - widget->allocation.x, widget->allocation.y, - widget->allocation.width, b->top); - } - - - } - - /* don't draw the window stuff as it overwrites our borders with a blank - * rectangle. Instead start with the drawing of the GtkBin */ - GTK_WIDGET_CLASS (g_type_class_peek_parent (parent_class))-> - expose_event (widget, event); - /*GTK_WIDGET_CLASS (parent_class))-> - expose_event (widget, event);*/ - - return FALSE; - -} - -static void -hildon_window_size_request (GtkWidget * widget, GtkRequisition * requisition) -{ - HildonWindowPrivate *priv = HILDON_WINDOW (widget)->priv; - GtkWidget *child = GTK_BIN (widget)->child; - GtkRequisition req2; - gint border_width = GTK_CONTAINER(widget)->border_width; - - if (!priv->borders) - { - hildon_window_get_borders (HILDON_WINDOW (widget)); - } - - if (child) - gtk_widget_size_request (child, requisition); - - if (HILDON_WINDOW (widget)->priv->vbox != NULL) - gtk_widget_size_request (HILDON_WINDOW (widget)->priv->vbox, - &req2); - - requisition->height += req2.height; - requisition->width = (requisition->width < req2.width) ? - req2.width : requisition->width; - - - requisition->width += 2 * border_width; - requisition->height += 2 * border_width; - - if (!priv->fullscreen) - { - requisition->height += priv->borders->top; - if (req2.height == 0) - requisition->height += priv->borders->bottom; - requisition->width += priv->borders->left + priv->borders->right; - } -} - -static void -hildon_window_size_allocate (GtkWidget * widget, GtkAllocation * allocation) -{ - HildonWindowPrivate *priv = HILDON_WINDOW (widget)->priv; - GtkAllocation box_alloc; - GtkAllocation alloc = *allocation; - GtkRequisition req; - gint border_width = GTK_CONTAINER(widget)->border_width; - - GtkWidget *box = HILDON_WINDOW(widget)->priv->vbox; - GtkBin *bin = GTK_BIN(widget); - GtkBorder *b = HILDON_WINDOW (widget)->priv->borders; - GtkBorder *tb = HILDON_WINDOW (widget)->priv->toolbar_borders; - - if (!priv->borders) - { - hildon_window_get_borders (HILDON_WINDOW (widget)); - b = HILDON_WINDOW (widget)->priv->borders; - tb = HILDON_WINDOW (widget)->priv->toolbar_borders; - } - - widget->allocation = *allocation; - - gtk_widget_get_child_requisition (box, &req); - - box_alloc.width = allocation->width - tb->left - tb->right; - box_alloc.height = ( (req.height < allocation->height) ? - req.height : allocation->height ); - box_alloc.x = allocation->x + tb->left; - box_alloc.y = allocation->y + allocation->height - box_alloc.height - tb->bottom; - - if (bin->child != NULL && GTK_IS_WIDGET (bin->child) - && GTK_WIDGET_VISIBLE (bin->child)) - { - alloc.x += border_width; - alloc.y += border_width; - alloc.width -= (border_width * 2); - alloc.height -= (border_width * 2) + box_alloc.height; - - if (!(HILDON_WINDOW (widget)->priv->fullscreen)) - { - alloc.x += b->left; - alloc.width -= (b->left + b->right); - alloc.y += b->top; - - alloc.height -= b->top; - - if (box_alloc.height <= 0) - alloc.height -= b->bottom; - else - alloc.height -= (tb->top + tb->bottom); - } - else - { - if (!(box_alloc.height <= 0)) - alloc.height -= (tb->top + tb->bottom); - } - - gtk_widget_size_allocate (bin->child, &alloc); - } - - - gtk_widget_size_allocate (box, &box_alloc); - - if (priv->previous_vbox_y != box_alloc.y) - { - /* The size of the VBox has changed, we need to redraw part - * of the window borders */ - gint draw_from_y = priv->previous_vbox_y < box_alloc.y? - priv->previous_vbox_y - tb->top: - box_alloc.y - tb->top; - - gtk_widget_queue_draw_area (widget, 0, draw_from_y, - widget->allocation.width, - widget->allocation.height - draw_from_y); - - priv->previous_vbox_y = box_alloc.y; - } - -} - -static void -hildon_window_forall (GtkContainer * container, gboolean include_internals, - GtkCallback callback, gpointer callback_data) -{ - HildonWindow *self = HILDON_WINDOW (container); - - g_return_if_fail (callback != NULL); - - GTK_CONTAINER_CLASS (parent_class)->forall (container, include_internals, - callback, callback_data); - if (include_internals && self->priv->vbox != NULL) - (* callback)(GTK_WIDGET (self->priv->vbox), callback_data); -} - -static void -hildon_window_show_all (GtkWidget *widget) -{ - HildonWindow *self = HILDON_WINDOW (widget); - - GTK_WIDGET_CLASS (parent_class)->show_all (widget); - gtk_widget_show_all (self->priv->vbox); - -} - -static void -hildon_window_destroy (GtkObject *obj) -{ - HildonWindow *self = HILDON_WINDOW (obj); - GList *menu_list; - - if (self->priv->vbox != NULL) - { - if (self->priv->program) - { - GtkWidget * common_toolbar = GTK_WIDGET ( - hildon_program_get_common_toolbar (self->priv->program)); - if (common_toolbar && common_toolbar->parent == self->priv->vbox) - { - gtk_container_remove (GTK_CONTAINER (self->priv->vbox), - common_toolbar); - } - } - - gtk_widget_unparent (self->priv->vbox); - self->priv->vbox = NULL; - - } - - menu_list = g_list_copy (gtk_menu_get_for_attach_widget (GTK_WIDGET (obj))); - - while (menu_list) - { - if (GTK_IS_MENU(menu_list->data)) - { - if (GTK_WIDGET_VISIBLE (GTK_WIDGET (menu_list->data))) - { - gtk_menu_popdown (GTK_MENU (menu_list->data)); - gtk_menu_shell_deactivate (GTK_MENU_SHELL (menu_list->data)); - } - gtk_menu_detach (GTK_MENU (menu_list->data)); - } - menu_list = menu_list->next; - } - - g_list_free (menu_list); - - if (self->priv->program) - { - hildon_program_remove_window (self->priv->program, self); - } - - gdk_window_remove_filter (gdk_get_default_root_window(), - hildon_window_root_window_event_filter, - obj); - - gtk_widget_set_events (GTK_WIDGET(obj), 0); - - GTK_OBJECT_CLASS (parent_class)->destroy (obj); -} - - -static void -hildon_window_notify (GObject *gobject, GParamSpec *param) -{ - HildonWindow *window = HILDON_WINDOW (gobject); - - if (strcmp (param->name, "title") == 0) - { - - hildon_window_update_title (window); - } - else if (strcmp (param->name, "is-topmost")) - { - hildon_window_is_topmost_notify (window); - } - - if (G_OBJECT_CLASS(parent_class)->notify) - G_OBJECT_CLASS(parent_class)->notify (gobject, param); -} - -/* Utilities */ - -static void -visible_toolbar (gpointer data, gpointer user_data) -{ - if (GTK_WIDGET_VISIBLE (((GtkBoxChild *)data)->widget)) - (*((gint *)user_data))++; -} - -static void -find_findtoolbar_index (gpointer data, gpointer user_data) -{ - gint *pass_bundle = (gint *)user_data; - - if(((GtkBoxChild *)data)->widget->allocation.y < pass_bundle[0] - && GTK_WIDGET_VISIBLE (((GtkBoxChild *)data)->widget)) - pass_bundle[1]++; -} - -static void -find_findtoolbar (gpointer data, gpointer user_data) -{ - if(HILDON_IS_FIND_TOOLBAR (((GtkBoxChild *)data)->widget) - && GTK_WIDGET_VISIBLE (((GtkBoxChild *)data)->widget)) - (*((GtkWidget **)user_data)) = ((GtkBoxChild *)data)->widget; -} - -static void -paint_toolbar (GtkWidget *widget, GtkBox *box, - GdkEventExpose * event, - gboolean fullscreen) -{ - gint toolbar_num = 0; - gint ftb_index = 0; - gint count; - GtkWidget *findtoolbar = NULL; - gchar toolbar_mode[40]; - GtkBorder *tb = HILDON_WINDOW (widget)->priv->toolbar_borders; - - /* collect info to help on painting the boxes */ - g_list_foreach (box->children, visible_toolbar, - (gpointer) &toolbar_num); - - if(toolbar_num <= 0) - return; - - g_list_foreach (box->children, find_findtoolbar, (gpointer) &findtoolbar); - - if (findtoolbar != NULL) - { - gint pass_bundle[2];/* an array for convient data passing - the first member contains the y allocation - of the find toolbar, and the second allocation - contains the index(how many toolbars are above - find toolbar) */ - pass_bundle[0] = findtoolbar->allocation.y; - pass_bundle[1] = ftb_index; - g_list_foreach(box->children, find_findtoolbar_index, - (gpointer) pass_bundle); - ftb_index = pass_bundle[1]; - } - - /*upper border*/ - sprintf (toolbar_mode, "toolbar%sframe-top", - fullscreen ? "-fullscreen-" : "-"); - gtk_paint_box (widget->style, widget->window, - GTK_WIDGET_STATE (widget), GTK_SHADOW_OUT, - &event->area, widget, toolbar_mode, - widget->allocation.x, - GTK_WIDGET (box)->allocation.y - tb->top, - widget->allocation.width, tb->top); - - /*top most toolbar painting*/ - if (findtoolbar != NULL && ftb_index == 0 ) - { - sprintf (toolbar_mode, "findtoolbar%s", - fullscreen ? "-fullscreen" : ""); - - gtk_paint_box (widget->style, widget->window, - GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, - &event->area, widget, toolbar_mode, - widget->allocation.x, - GTK_WIDGET(box)->allocation.y, - widget->allocation.width, - TOOLBAR_HEIGHT); - } - else - { - sprintf (toolbar_mode, "toolbar%s", - fullscreen ? "-fullscreen" : ""); - - gtk_paint_box (widget->style, widget->window, - GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, - &event->area, widget, toolbar_mode, - widget->allocation.x, - GTK_WIDGET(box)->allocation.y, - widget->allocation.width, - TOOLBAR_HEIGHT); - } - /*multi toolbar painting*/ - for (count = 0; count < toolbar_num - 1; count++) - { - sprintf (toolbar_mode, "toolbar%sframe-middle", - fullscreen ? "-fullscreen-" : "-"); - - gtk_paint_box (widget->style, widget->window, - GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, - &event->area, widget, toolbar_mode, - widget->allocation.x, - GTK_WIDGET(box)->allocation.y + - (1 + count) * TOOLBAR_HEIGHT + - count * TOOLBAR_MIDDLE, - widget->allocation.width, - TOOLBAR_MIDDLE); - - if (findtoolbar != NULL && count + 1 == ftb_index) - { - - sprintf (toolbar_mode, "findtoolbar%s", - fullscreen ? "-fullscreen" : ""); - - gtk_paint_box (widget->style, widget->window, - GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, - &event->area, widget, toolbar_mode, - widget->allocation.x, - GTK_WIDGET(box)->allocation.y + - (1 + count) * (TOOLBAR_HEIGHT + TOOLBAR_MIDDLE), - widget->allocation.width, - TOOLBAR_HEIGHT); - } - else - { - sprintf (toolbar_mode, "toolbar%s", - fullscreen ? "-fullscreen" : ""); - - gtk_paint_box (widget->style, widget->window, - GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, - &event->area, widget, toolbar_mode, - widget->allocation.x, - GTK_WIDGET(box)->allocation.y + - (1 + count) * (TOOLBAR_HEIGHT + TOOLBAR_MIDDLE), - widget->allocation.width, - TOOLBAR_HEIGHT); - } - } - sprintf (toolbar_mode, "toolbar%sframe-bottom", - fullscreen ? "-fullscreen-" : "-"); - - gtk_paint_box (widget->style, widget->window, - GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, - &event->area, widget, toolbar_mode, - widget->allocation.x, - GTK_WIDGET(box)->allocation.y + - GTK_WIDGET(box)->allocation.height, - widget->allocation.width, tb->bottom); - -} - -/* - * Checks the root window to know which is the topped window - */ -Window -hildon_window_get_active_window (void) -{ - Atom realtype; - int format; - int status; - Window ret; - unsigned long n; - unsigned long extra; - union - { - Window *win; - unsigned char *char_pointer; - } win; - Atom active_app_atom = - XInternAtom (GDK_DISPLAY (), "_MB_CURRENT_APP_WINDOW", False); - - win.win = NULL; - - status = XGetWindowProperty (GDK_DISPLAY(), GDK_ROOT_WINDOW(), - active_app_atom, 0L, 16L, - 0, XA_WINDOW, &realtype, &format, - &n, &extra, &win.char_pointer); - if (!(status == Success && realtype == XA_WINDOW && format == 32 - && n == 1 && win.win != NULL)) - { - if (win.win != NULL) - XFree (win.char_pointer); - return None; - } - - ret = win.win[0]; - - if (win.win != NULL) - XFree(win.char_pointer); - - return ret; -} - -static int -xclient_message_type_check (XClientMessageEvent *cm, const gchar *name) -{ - return cm->message_type == XInternAtom(GDK_DISPLAY(), name, FALSE); -} - -/*****************/ -/* Event filters */ -/*****************/ - -/* - * Handle the window border custom button, which toggles the menu, - * and the Hildon input method copy paste messages - */ -static GdkFilterReturn -hildon_window_event_filter (GdkXEvent *xevent, GdkEvent *event, gpointer data) -{ - XAnyEvent *eventti = xevent; - - if (eventti->type == ClientMessage) - { - XClientMessageEvent *cm = xevent; - - if (xclient_message_type_check (cm, "_MB_GRAB_TRANSFER")) - { - hildon_window_toggle_menu (HILDON_WINDOW ( data )); - return GDK_FILTER_REMOVE; - } - /* opera hack clipboard client message */ - else if (xclient_message_type_check (cm, "_HILDON_IM_CLIPBOARD_COPY")) - { - g_signal_emit_by_name(G_OBJECT(data), "clipboard_operation", - HILDON_WINDOW_CO_COPY); - return GDK_FILTER_REMOVE; - } - else if (xclient_message_type_check(cm, "_HILDON_IM_CLIPBOARD_CUT")) - { - g_signal_emit_by_name(G_OBJECT(data), "clipboard_operation", - HILDON_WINDOW_CO_CUT); - return GDK_FILTER_REMOVE; - } - else if (xclient_message_type_check(cm, "_HILDON_IM_CLIPBOARD_PASTE")) - { - g_signal_emit_by_name(G_OBJECT(data), "clipboard_operation", - HILDON_WINDOW_CO_PASTE); - return GDK_FILTER_REMOVE; - } - } - - return GDK_FILTER_CONTINUE; -} - -/* - * Here we keep track of changes in the _MB_CURRENT_APP_WINDOW, - * to know when we acquire/lose topmost status - */ -static GdkFilterReturn -hildon_window_root_window_event_filter (GdkXEvent *xevent, - GdkEvent *event, - gpointer data) -{ - XAnyEvent *eventti = xevent; - HildonWindow *hwindow = HILDON_WINDOW (data); - - - if (eventti->type == PropertyNotify) - { - XPropertyEvent *pevent = xevent; - Atom active_app_atom = - XInternAtom (GDK_DISPLAY (), "_MB_CURRENT_APP_WINDOW", False); - - if (pevent->atom == active_app_atom) - { - Window active_window = hildon_window_get_active_window(); - - hildon_window_update_topmost (hwindow, active_window); - } - } - - return GDK_FILTER_CONTINUE; -} - -/***************************/ -/* Signal handlers */ -/***************************/ - -/* - * Handle the menu hardware key here - */ -static gboolean -hildon_window_key_press_event (GtkWidget *widget, GdkEventKey *event) -{ - HildonWindowPrivate *priv; - - g_return_val_if_fail (HILDON_IS_WINDOW (widget),FALSE); - - priv = HILDON_WINDOW (widget)->priv; - - switch (event->keyval) - { - case HILDON_HARDKEY_MENU: - if (hildon_window_toggle_menu (HILDON_WINDOW (widget))) - return TRUE; - break; - case HILDON_HARDKEY_ESC: - if (!priv->escape_timeout) - { - priv->escape_timeout = g_timeout_add - (HILDON_WINDOW_LONG_PRESS_TIME, - hildon_window_escape_timeout, widget); - } - break; - } - - return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event); - -} - -static gboolean -hildon_window_key_release_event (GtkWidget *widget, GdkEventKey *event) -{ - HildonWindowPrivate *priv; - - g_return_val_if_fail (HILDON_IS_WINDOW (widget),FALSE); - - priv = HILDON_WINDOW (widget)->priv; - - switch (event->keyval) - { - case HILDON_HARDKEY_ESC: - if (priv->escape_timeout) - { - g_source_remove (priv->escape_timeout); - priv->escape_timeout = 0; - } - break; - } - - return GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event); - -} - -/* - * We keep track of the window state changes, because the drawing - * (borders) differs whether we are in fullscreen mode or not - */ -static gboolean -hildon_window_window_state_event (GtkWidget *widget, - GdkEventWindowState *event) -{ - if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) - { - HILDON_WINDOW (widget)->priv->fullscreen = - event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN; - } - - if (GTK_WIDGET_CLASS (parent_class)->window_state_event) - { - return GTK_WIDGET_CLASS (parent_class)->window_state_event ( - widget, - event); - } - else - { - return FALSE; - } -} - -static void -hildon_window_title_notify (GObject *gobject, - GParamSpec *arg1, - gpointer user_data) -{ - HildonWindow *window = HILDON_WINDOW (gobject); - - hildon_window_update_title (window); - -} - -/*******************/ -/* General */ -/*******************/ - -/*The menu popuping needs a menu popup-function*/ -static void -hildon_window_menupopupfunc (GtkMenu *menu, gint *x, gint *y, - gboolean *push_in, GtkWidget *widget) -{ - gint window_x = 0; - gint window_y = 0; - GdkWindow *window = GTK_WIDGET(widget)->window; - - if (window) - { - gdk_window_get_origin (window, &window_x, &window_y); - } - - gtk_widget_style_get (GTK_WIDGET (menu), "horizontal-offset", x, - "vertical-offset", y, NULL); - - *x += window_x; - *y += window_y; - -} - -static void -hildon_window_menupopupfuncfull ( GtkMenu *menu, gint *x, gint *y, - gboolean *push_in, - GtkWidget *widget ) -{ - gtk_widget_style_get (GTK_WIDGET (menu), "horizontal-offset", x, - "vertical-offset", y, NULL); - - *x = MAX (0, *x); - *y = MAX (0, *y); -} - - -/********************/ -/* Private methods */ -/********************/ - - -/* - * Takes the common toolbar when we acquire the top-most status - */ -static void -hildon_window_is_topmost_notify (HildonWindow *window) -{ - if (window->priv->is_topmost) - { - hildon_window_take_common_toolbar (window); - } - - else - { - /* If the window lost focus while the user started to press - * the ESC key, we won't get the release event. We need to - * stop the timeout*/ - if (window->priv->escape_timeout) - { - g_source_remove (window->priv->escape_timeout); - window->priv->escape_timeout = 0; - } - } -} - -/* - * Sets the program to which the window belongs. This should only be called - * by hildon_program_add_window - */ -void -hildon_window_set_program (HildonWindow *self, GObject *program) -{ - if (self->priv->program) - { - g_object_unref (self->priv->program); - } - - /* Now that we are bound to a program, we can rely on it to track the - * root window */ - gdk_window_remove_filter (gdk_get_default_root_window(), - hildon_window_root_window_event_filter, - self); - - self->priv->program = HILDON_PROGRAM (program); - g_object_ref (program); -} - -/* - * Unsets the program to which the window belongs. This should only be called - * by hildon_program_add_window - */ -void -hildon_window_unset_program (HildonWindow *self) -{ - g_return_if_fail(self && HILDON_IS_WINDOW (self)); - - if (self->priv->program) - { - g_object_unref (self->priv->program); - self->priv->program = NULL; - - /* We need to start tacking the root window again */ - gdk_window_set_events (gdk_get_default_root_window (), - gdk_window_get_events (gdk_get_default_root_window ()) - | GDK_PROPERTY_CHANGE_MASK); - - gdk_window_add_filter (gdk_get_default_root_window (), - hildon_window_root_window_event_filter, self ); - } - - self->priv->program = NULL; -} - -/* - * Sets whether or not the program to which this window belongs is - * killable. This is used by the HildonProgram to signify to the - * Task Navigator whether or not it can hibernate in memory-low situations - **/ -void -hildon_window_set_can_hibernate_property (HildonWindow *self, - gpointer _can_hibernate) -{ - GdkAtom killable_atom; - gboolean can_hibernate; - - g_return_if_fail(self && HILDON_IS_WINDOW (self)); - - if (!GTK_WIDGET_REALIZED ((GTK_WIDGET (self)))) - { - return; - } - - can_hibernate = * ((gboolean *)_can_hibernate); - - killable_atom = gdk_atom_intern (CAN_HIBERNATE_PROPERTY, FALSE); - - if (can_hibernate) - { - gdk_property_change (GTK_WIDGET (self)->window, killable_atom, - (GdkAtom)31/* XA_STRING */, 8, - GDK_PROP_MODE_REPLACE, (const guchar *)CAN_HIBERNATE, - CAN_HIBERNATE_LENGTH); - } - else - { - gdk_property_delete (GTK_WIDGET (self)->window, killable_atom); - } - -} - -/* - * If a common toolbar was set to the program, reparent it to - * us - */ -void -hildon_window_take_common_toolbar (HildonWindow *self) -{ - g_return_if_fail(self && HILDON_IS_WINDOW (self)); - - if (self->priv->program) - { - GtkWidget *common_toolbar = - GTK_WIDGET (hildon_program_get_common_toolbar (self->priv->program)); - - if (common_toolbar && common_toolbar->parent != self->priv->vbox) - { - g_object_ref (common_toolbar); - if (common_toolbar->parent) - { - gtk_container_remove (GTK_CONTAINER (common_toolbar->parent), - common_toolbar); - } - - gtk_box_pack_end (GTK_BOX(self->priv->vbox), common_toolbar, - TRUE, TRUE, 0); - g_object_unref (common_toolbar); - - gtk_widget_set_size_request (common_toolbar, -1, TOOLBAR_HEIGHT); - - gtk_widget_show (self->priv->vbox); - - } - } -} - -/* - * Compare the window that was last topped, and act consequently - */ -void -hildon_window_update_topmost (HildonWindow *self, Window window_id) -{ - Window my_window; - - my_window = GDK_WINDOW_XID (GTK_WIDGET (self)->window); - - if (window_id == my_window) - { - if (!self->priv->is_topmost) - { - self->priv->is_topmost = TRUE; - hildon_window_is_topmost_notify (self); - g_object_notify (G_OBJECT (self), "is-topmost"); - } - } - else if (self->priv->is_topmost) - { - /* Should this go in the signal handler? */ - GtkWidget *focus = gtk_window_get_focus (GTK_WINDOW (self)); - - if (GTK_IS_ENTRY (focus)) - gtk_im_context_focus_out (GTK_ENTRY (focus)->im_context); - if (GTK_IS_TEXT_VIEW (focus)) - gtk_im_context_focus_out (GTK_TEXT_VIEW (focus)->im_context); - - self->priv->is_topmost = FALSE; - hildon_window_is_topmost_notify (self); - g_object_notify (G_OBJECT (self), "is-topmost"); - - } -} - -/* - * If the application - * was given a name (with g_set_application_name(), set - * "ProgramName - WindowTitle" as the displayed - * title - */ -void -hildon_window_update_title (HildonWindow *window) -{ - const gchar * application_name; - g_return_if_fail (window && HILDON_IS_WINDOW (window)); - - if (!GTK_WIDGET_REALIZED (window)) - { - return; - } - - application_name = g_get_application_name (); - - if (application_name && application_name[0]) - { - const gchar *old_title = gtk_window_get_title (GTK_WINDOW (window)); - - if (old_title && old_title[0]) - { - gchar *title = NULL; - - title = g_strjoin (TITLE_SEPARATOR, application_name, - old_title, NULL); - - gdk_window_set_title (GTK_WIDGET (window)->window, title); - - g_free (title); - } - - } -} - -static void -detach_menu_func (GtkWidget *attach_widget, GtkMenu *menu) -{ -} -/* - * Toggles the display of the HildonWindow menu. - * Returns whether or not something was done (whether or not we had a menu - * to toggle) - */ -static gboolean -hildon_window_toggle_menu (HildonWindow * self) -{ - GtkMenu *menu_to_use = NULL; - GList *menu_children = NULL; - - g_return_val_if_fail (self && HILDON_IS_WINDOW (self), FALSE); - - /* Select which menu to use, Window specific has highest priority, - * then program specific */ - if (self->priv->menu) - { - menu_to_use = GTK_MENU (self->priv->menu); - } - else if (self->priv->program) - { - menu_to_use = hildon_program_get_common_menu (self->priv->program); - if (menu_to_use && gtk_menu_get_attach_widget (menu_to_use) != - GTK_WIDGET (self)) - { - g_object_ref (menu_to_use); - if (gtk_menu_get_attach_widget (menu_to_use)) - { - gtk_menu_detach (menu_to_use); - } - - gtk_menu_attach_to_widget (menu_to_use, GTK_WIDGET (self), - &detach_menu_func); - g_object_unref (menu_to_use); - } - } - - if (!menu_to_use) - { - return FALSE; - } - - - if (GTK_WIDGET_MAPPED (GTK_WIDGET (menu_to_use))) - { - gtk_menu_popdown (menu_to_use); - gtk_menu_shell_deactivate (GTK_MENU_SHELL (menu_to_use)); - return TRUE; - } - - /* Check if the menu has items */ - menu_children = gtk_container_get_children (GTK_CONTAINER (menu_to_use)); - - if (menu_children) - { - g_list_free (menu_children); - - /* Apply right theming */ - gtk_widget_set_name (GTK_WIDGET (menu_to_use), - "menu_force_with_corners"); - - if (self->priv->fullscreen) - { - gtk_menu_popup (menu_to_use, NULL, NULL, - (GtkMenuPositionFunc) - hildon_window_menupopupfuncfull, - self, 0, - gtk_get_current_event_time ()); - } - else - { - gtk_menu_popup (menu_to_use, NULL, NULL, - (GtkMenuPositionFunc) - hildon_window_menupopupfunc, - self, 0, - gtk_get_current_event_time ()); - } - gtk_menu_shell_select_first (GTK_MENU_SHELL (menu_to_use), TRUE); - return TRUE; - } - - return FALSE; - -} - -/* - * If the ESC key was not released when the timeout expires, - * close the window - */ -static gboolean -hildon_window_escape_timeout (gpointer data) -{ - HildonWindowPrivate *priv; - GdkEvent *event; - - GDK_THREADS_ENTER (); - - priv = HILDON_WINDOW(data)->priv; - - /* Send fake event, simulation a situation that user - pressed 'x' from the corner */ - event = gdk_event_new(GDK_DELETE); - ((GdkEventAny *)event)->window = GDK_WINDOW (g_object_ref (GTK_WIDGET(data)->window)); - gtk_main_do_event(event); - - /* That unrefs the window, so we're reffing it above */ - gdk_event_free(event); - - priv->escape_timeout = 0; - - GDK_THREADS_LEAVE (); - - return FALSE; -} - - -/******************/ -/* public methods */ -/******************/ - - -/** - * hildon_window_new: - * - * Use this function to create a new HildonWindow. - * - * Return value: A @HildonWindow. - **/ -GtkWidget * -hildon_window_new (void) -{ - HildonWindow *newwindow = g_object_new (HILDON_TYPE_WINDOW, NULL); - - return GTK_WIDGET (newwindow); -} - -/** - * hildon_window_add_with_scrollbar - * @self : A @HildonWindow - * @child : A @GtkWidget - * - * Adds the @child to the HildonWindow and creates a scrollbar - * to it. Similar as adding first a @GtkScrolledWindow and then the - * @child to it. - */ -void -hildon_window_add_with_scrollbar (HildonWindow * self, - GtkWidget * child) -{ - GtkScrolledWindow *scrolledw; - - g_return_if_fail (HILDON_IS_WINDOW (self)); - g_return_if_fail (GTK_IS_WIDGET (child)); - g_return_if_fail (child->parent == NULL); - - scrolledw = GTK_SCROLLED_WINDOW (gtk_scrolled_window_new (NULL, NULL)); - gtk_scrolled_window_set_policy (scrolledw, GTK_POLICY_NEVER, - GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type (scrolledw, GTK_SHADOW_NONE); - - if (GTK_IS_VIEWPORT (child)) - gtk_container_add (GTK_CONTAINER (scrolledw), child); - else - { - if (GTK_IS_CONTAINER (child) ) - gtk_container_set_focus_vadjustment (GTK_CONTAINER(child), - gtk_scrolled_window_get_vadjustment (scrolledw) ); - gtk_scrolled_window_add_with_viewport (scrolledw, child); - } - - gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (scrolledw)); -} - -/** - * hildon_window_add_toolbar: - * @self: A @HildonWindow - * @toolbar: A #GtkToolbar to add to the HildonWindow - * - * Adds a toolbar to the window. - **/ -void -hildon_window_add_toolbar (HildonWindow *self, GtkToolbar *toolbar) -{ - GtkBox *vbox; - - g_return_if_fail (self && HILDON_IS_WINDOW (self)); - g_return_if_fail (toolbar && GTK_IS_TOOLBAR (toolbar)); - - vbox = GTK_BOX (self->priv->vbox); - - gtk_box_pack_start (vbox, GTK_WIDGET(toolbar), TRUE, TRUE, 0); - gtk_box_reorder_child (vbox, GTK_WIDGET(toolbar), 0); - gtk_widget_set_size_request (GTK_WIDGET (toolbar), -1, TOOLBAR_HEIGHT); - - gtk_widget_queue_resize (GTK_WIDGET(self)); -} - -/** - * hildon_window_remove_toolbar: - * @self: A @HildonWindow - * @toolbar: A #GtkToolbar to remove from the HildonWindow - * - * Removes a toolbar from the window. - **/ -void -hildon_window_remove_toolbar (HildonWindow *self, GtkToolbar *toolbar) -{ - GtkContainer *vbox = GTK_CONTAINER (self->priv->vbox); - - g_return_if_fail (self && HILDON_IS_WINDOW (self)); - - gtk_container_remove (vbox, GTK_WIDGET(toolbar)); -} - -/** - * hildon_window_get_menu: - * @self : #HildonWindow - * - * Gets the #GtMenu assigned to the #HildonAppview. - * - * Return value: The #GtkMenu assigned to this application view. - **/ -GtkMenu * -hildon_window_get_menu (HildonWindow * self) -{ - g_return_val_if_fail (self && HILDON_IS_WINDOW (self), NULL); - - return GTK_MENU (self->priv->menu); -} - - -/** - * hildon_window_set_menu: - * @self: A #HildonWindow - * @menu: The #GtkMenu to be used for this #HildonWindow - * - * Sets the menu to be used for this window. This menu overrides - * a program-wide menu that may have been set with - * hildon_program_set_common_menu. Pass NULL to remove the current - * menu. - **/ -void -hildon_window_set_menu (HildonWindow *self, GtkMenu *menu) -{ - g_return_if_fail (HILDON_IS_WINDOW (self)); - - if (self->priv->menu != NULL) { - gtk_menu_detach (GTK_MENU (self->priv->menu)); - g_object_unref (self->priv->menu); - } - - self->priv->menu = (menu != NULL) ? GTK_WIDGET (menu) : NULL; - if (self->priv->menu != NULL) { - gtk_widget_set_name (self->priv->menu, "menu_force_with_corners"); - gtk_menu_attach_to_widget (GTK_MENU (self->priv->menu), GTK_WIDGET (self), &detach_menu_func); - g_object_ref (GTK_MENU (self->priv->menu)); - gtk_widget_show_all (GTK_WIDGET (self->priv->menu)); - } -} - -/** - * hildon_window_get_is_topmost: - * @self: A #HildonWindow - * - * Return value: Whether or not the #HildonWindow is currenltly activated - * by the window manager. - **/ -gboolean -hildon_window_get_is_topmost(HildonWindow *self){ - g_return_val_if_fail (HILDON_IS_WINDOW (self), FALSE); - - return self->priv->is_topmost; -} - diff --git a/hildon-widgets/hildon-window.h b/hildon-widgets/hildon-window.h deleted file mode 100644 index 5a14220..0000000 --- a/hildon-widgets/hildon-window.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - - -#ifndef __HILDON_WINDOW_H__ -#define __HILDON_WINDOW_H__ - -#include -#include -#include -#include -#include -#include - -#include "hildon-defines.h" - -G_BEGIN_DECLS - -#define HILDON_WINDOW_LONG_PRESS_TIME 1500 /* in ms */ - -#define HILDON_TYPE_WINDOW ( hildon_window_get_type() ) -#define HILDON_WINDOW(obj) \ - (GTK_CHECK_CAST (obj, HILDON_TYPE_WINDOW, HildonWindow)) -#define HILDON_WINDOW_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass),\ - HILDON_TYPE_WINDOW, HildonWindowClass)) -#define HILDON_IS_WINDOW(obj) (GTK_CHECK_TYPE (obj, HILDON_TYPE_WINDOW)) -#define HILDON_IS_WINDOW_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_WINDOW)) - -typedef struct _HildonWindow HildonWindow; -typedef struct _HildonWindowClass HildonWindowClass; - -/** - * HildonWindowPrivate: - * - * This structure contains just internal data. - * It should not be accessed directly. - */ -typedef struct _HildonWindowPrivate HildonWindowPrivate; - -struct _HildonWindow -{ - GtkWindow parent; - - /*private*/ - HildonWindowPrivate *priv; -}; - -enum -{ - HILDON_WINDOW_CO_COPY, - HILDON_WINDOW_CO_CUT, - HILDON_WINDOW_CO_PASTE -}; - -struct _HildonWindowClass -{ - GtkWindowClass parent_class; - - /* opera hacks for clip board operation */ - void (*clipboard_operation)(HildonWindow *hwindow, int operation); - /* Padding for future extension */ - void (*_hildon_reserved1)(void); - void (*_hildon_reserved2)(void); - void (*_hildon_reserved3)(void); -}; - - -GType hildon_window_get_type (void); - -GtkWidget * hildon_window_new (void); - -void hildon_window_add_with_scrollbar(HildonWindow *self, - GtkWidget *child); - -GtkMenu * hildon_window_get_menu (HildonWindow *self); -void hildon_window_set_menu (HildonWindow *self, - GtkMenu *menu); - -void hildon_window_add_toolbar (HildonWindow *self, - GtkToolbar *toolbar); - -void hildon_window_remove_toolbar (HildonWindow *self, - GtkToolbar *toolbar); - -gboolean hildon_window_get_is_topmost (HildonWindow *self); - - -G_END_DECLS -#endif /* __HILDON_WINDOW_H__ */ diff --git a/hildon-widgets/hildon-wizard-dialog.c b/hildon-widgets/hildon-wizard-dialog.c deleted file mode 100644 index d775d5a..0000000 --- a/hildon-widgets/hildon-wizard-dialog.c +++ /dev/null @@ -1,487 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * Fixes: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -/** - * SECTION:hildon-wizard-dialog - * @short_description: A widget to create a guided installation - * process wizard - * - * #HildonWizardDialog is a widget to create a guided installation - * process. The dialog has four standard buttons, previous, next, - * finish, cancel, and contains several pages with optional icons. - * Response buttons are dimmed/undimmed automatically and the standard - * icon is shown/hidden in response to page navigation. The notebook - * widget provided by users contains the actual wizard pages. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hildon-wizard-dialog.h" - -#include - -#ifdef HAVE_CONFIG_H -#include -#endif - -#define _(String) dgettext(PACKAGE, String) - -static GtkDialogClass *parent_class; - -static void class_init (HildonWizardDialogClass *wizard_dialog_class); - -static void init (HildonWizardDialog *wizard_dialog); - -static void create_title (HildonWizardDialog *wizard_dialog); - -static void set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec); - -static void get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec); - -static void finalize (GObject *object); - -static void response (HildonWizardDialog *wizard, - gint response_id, - gpointer unused); - -static void make_buttons_sensitive (HildonWizardDialog *wizard_dialog, - gboolean previous, - gboolean finish, - gboolean next); - -enum { - PROP_ZERO, - PROP_WIZARD_NAME, - PROP_WIZARD_NOTEBOOK, - PROP_WIZARD_AUTOTITLE -}; - -struct _HildonWizardDialogPrivate { - gchar *wizard_name; - GtkNotebook *notebook; - GtkBox *box; - GtkWidget *image; - gboolean autotitle; -}; - - -GType -hildon_wizard_dialog_get_type (void) -{ - static GType wizard_dialog_type = 0; - - if (!wizard_dialog_type) { - - static const GTypeInfo wizard_dialog_info = { - sizeof (HildonWizardDialogClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (HildonWizardDialog), - 0, /* n_preallocs */ - (GInstanceInitFunc) init, - }; - - wizard_dialog_type = g_type_register_static (GTK_TYPE_DIALOG, - "HildonWizardDialog", - &wizard_dialog_info, - 0); - } - - return wizard_dialog_type; -} - -static void -class_init (HildonWizardDialogClass *wizard_dialog_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (wizard_dialog_class); - - parent_class = g_type_class_peek_parent (wizard_dialog_class); - - g_type_class_add_private (wizard_dialog_class, - sizeof(HildonWizardDialogPrivate)); - - /* Override virtual methods */ - object_class->set_property = set_property; - object_class->get_property = get_property; - object_class->finalize = finalize; - - /** - * HildonWizardDialog:wizard-name: - * - * The name of the wizard. - */ - g_object_class_install_property (object_class, PROP_WIZARD_NAME, - g_param_spec_string - ("wizard-name", - "Wizard Name", - "The name of the HildonWizardDialog", - NULL, - G_PARAM_READWRITE)); - - /** - * HildonWizardDialog:wizard-notebook: - * - * The notebook object, which is used by the HildonWizardDialog. - */ - g_object_class_install_property(object_class, PROP_WIZARD_NOTEBOOK, - g_param_spec_object - ("wizard-notebook", - "Wizard Notebook", - "GtkNotebook object to be used in the " - "HildonWizardDialog", - GTK_TYPE_NOTEBOOK, G_PARAM_READWRITE)); - - /** - * HildonWizardDialog:autotitle - * - * If the wizard should automatically try to change the window title when changing steps. - * Set to FALSE if you'd like to override the default behaviour. - * - * Since: 0.14.5 - */ - g_object_class_install_property(object_class, PROP_WIZARD_AUTOTITLE, - g_param_spec_boolean - ("autotitle", - "AutoTitle", - "If the wizard should autotitle itself", - TRUE, - G_PARAM_READWRITE)); -} - -static void -finalize (GObject *object) -{ - HildonWizardDialog *dialog = HILDON_WIZARD_DIALOG (object); - g_return_if_fail (dialog != NULL); - - if (dialog->priv->wizard_name != NULL) - g_free (HILDON_WIZARD_DIALOG (object)->priv->wizard_name); - - if (G_OBJECT_CLASS (parent_class)->finalize) - G_OBJECT_CLASS (parent_class)->finalize(object); -} - -/* Disable or enable the Previous, Next and Finish buttons */ -static void -make_buttons_sensitive (HildonWizardDialog *wizard_dialog, - gboolean previous, - gboolean finish, - gboolean next) -{ - gtk_dialog_set_response_sensitive (GTK_DIALOG (wizard_dialog), - HILDON_WIZARD_DIALOG_PREVIOUS, - previous); - - gtk_dialog_set_response_sensitive (GTK_DIALOG (wizard_dialog), - HILDON_WIZARD_DIALOG_FINISH, - finish); - - gtk_dialog_set_response_sensitive (GTK_DIALOG (wizard_dialog), - HILDON_WIZARD_DIALOG_NEXT, - next); -} - -static void -init (HildonWizardDialog *wizard_dialog) -{ - /* Initialize private structure for faster member access */ - HildonWizardDialogPrivate *priv = - G_TYPE_INSTANCE_GET_PRIVATE (wizard_dialog, - HILDON_TYPE_WIZARD_DIALOG, - HildonWizardDialogPrivate); - - GtkDialog *dialog = GTK_DIALOG (wizard_dialog); - - /* Init internal widgets */ - GtkWidget *vbox = gtk_vbox_new (FALSE, 0); - gtk_dialog_set_has_separator (dialog, FALSE); - wizard_dialog->priv = priv; - priv->box = GTK_BOX (gtk_hbox_new (FALSE, 0)); - priv->image = gtk_image_new_from_icon_name ("qgn_widg_wizard", - HILDON_ICON_SIZE_WIDG_WIZARD); - - /* Default values for user provided properties */ - priv->notebook = NULL; - priv->wizard_name = NULL; - priv->autotitle = TRUE; - - /* Build wizard layout */ - gtk_box_pack_start_defaults (GTK_BOX (dialog->vbox), GTK_WIDGET (priv->box)); - gtk_box_pack_start_defaults (GTK_BOX (priv->box), GTK_WIDGET (vbox)); - gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (priv->image), FALSE, FALSE, 0); - - /* Add response buttons: finish, previous, next, cancel */ - gtk_dialog_add_button (dialog, _("ecdg_bd_wizard_finish"), HILDON_WIZARD_DIALOG_FINISH); - gtk_dialog_add_button (dialog, _("ecdg_bd_wizard_previous"), HILDON_WIZARD_DIALOG_PREVIOUS); - gtk_dialog_add_button (dialog, _("ecdg_bd_wizard_next"), HILDON_WIZARD_DIALOG_NEXT); - gtk_dialog_add_button (dialog, _("ecdg_bd_wizard_cancel"), HILDON_WIZARD_DIALOG_CANCEL); - - /* Set initial button states: previous and finish buttons are disabled */ - make_buttons_sensitive (wizard_dialog, FALSE, FALSE, TRUE); - - /* Show all the internal widgets */ - gtk_widget_show_all (GTK_WIDGET (dialog->vbox)); - - /* connect to dialog's response signal */ - g_signal_connect (G_OBJECT (dialog), "response", - G_CALLBACK (response), NULL); -} - -static void -set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - HildonWizardDialogPrivate *priv = HILDON_WIZARD_DIALOG(object)->priv; - - switch (property_id) { - - case PROP_WIZARD_AUTOTITLE: - - priv->autotitle = g_value_get_boolean (value); - - if (priv->autotitle && - priv->wizard_name && - priv->notebook) - create_title (HILDON_WIZARD_DIALOG (object)); - else if (priv->wizard_name) - gtk_window_set_title (GTK_WINDOW (object), priv->wizard_name); - - break; - - case PROP_WIZARD_NAME: - - /* Set new wizard name. This name will appear in titlebar */ - if (priv->wizard_name) - g_free (priv->wizard_name); - - gchar *str = (gchar *) g_value_get_string (value); - g_return_if_fail (str != NULL); - - priv->wizard_name = g_strdup (str); - - /* We need notebook in order to create title, since page information - is used in title generation */ - - if (priv->notebook && priv->autotitle) - create_title (HILDON_WIZARD_DIALOG (object)); - - break; - - case PROP_WIZARD_NOTEBOOK: { - - GtkNotebook *book = GTK_NOTEBOOK (g_value_get_object (value)); - g_return_if_fail (book != NULL); - - priv->notebook = book; - - /* Set the default properties for the notebook (disable tabs, - * and remove borders) to make it look like a nice wizard widget */ - gtk_notebook_set_show_tabs (priv->notebook, FALSE); - gtk_notebook_set_show_border (priv->notebook, FALSE); - gtk_box_pack_start_defaults (GTK_BOX( priv->box), GTK_WIDGET (priv->notebook)); - - /* Show the notebook so that a gtk_widget_show on the dialog is - * all that is required to display the dialog correctly */ - gtk_widget_show (priv->notebook); - - /* Update dialog title to reflect current page stats etc */ - if (priv->wizard_name && priv->autotitle) - create_title (HILDON_WIZARD_DIALOG (object)); - - } break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - HildonWizardDialogPrivate *priv = HILDON_WIZARD_DIALOG (object)->priv; - - switch (property_id) { - - case PROP_WIZARD_NAME: - g_value_set_string (value, priv->wizard_name); - break; - - case PROP_WIZARD_NOTEBOOK: - g_value_set_object (value, priv->notebook); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -/* - * Creates the title of the dialog taking into account the current - * page of the notebook. - */ -static void -create_title (HildonWizardDialog *wizard_dialog) -{ - gint pages, current; - gchar *str = NULL; - HildonWizardDialogPrivate *priv = wizard_dialog->priv; - GtkNotebook *notebook = priv->notebook; - - if (!notebook) - return; - - /* Get page information, we'll need that when creating title */ - pages = gtk_notebook_get_n_pages (notebook); - current = gtk_notebook_get_current_page (priv->notebook); - if (current < 0) - current = 0; - - /* the welcome title on the initial page */ - if (current == 0) { - str = g_strdup_printf (_("ecdg_ti_wizard_welcome"), - priv->wizard_name, pages); - } else { - const gchar *steps = gtk_notebook_get_tab_label_text (notebook, - gtk_notebook_get_nth_page (notebook, current)); - - str = g_strdup_printf (_("ecdg_ti_wizard_step"), - priv->wizard_name, current + 1, pages, steps); - } - - /* Update the dialog to display the generated title */ - gtk_window_set_title (GTK_WINDOW (wizard_dialog), str); - g_free (str); -} - -/* - * Response signal handler. This function is needed because GtkDialog's - * handler for this signal closes the dialog and we don't want that, we - * want to change pages and, dimm certain response buttons. Overriding the - * virtual function would not work because that would be called after the - * signal handler implemented by GtkDialog. - * FIXME: There is a much saner way to do that [MDK] - */ -static void -response (HildonWizardDialog *wizard_dialog, - gint response_id, - gpointer unused) -{ - HildonWizardDialogPrivate *priv = wizard_dialog->priv; - GtkNotebook *notebook = priv->notebook; - gint current = 0; - gint last = gtk_notebook_get_n_pages (notebook) - 1; - gboolean is_first, is_last; - - switch (response_id) { - - case HILDON_WIZARD_DIALOG_PREVIOUS: - gtk_notebook_prev_page (notebook); /* go to previous page */ - break; - - case HILDON_WIZARD_DIALOG_NEXT: - gtk_notebook_next_page (notebook); /* go to next page */ - break; - - case HILDON_WIZARD_DIALOG_CANCEL: - case HILDON_WIZARD_DIALOG_FINISH: - return; - - } - - current = gtk_notebook_get_current_page (notebook); - is_last = current == last; - is_first = current == 0; - - /* If first page, previous and finish are disabled, - if last page, next is disabled */ - make_buttons_sensitive (wizard_dialog, - !is_first, !is_first, !is_last); - - /* Don't let the dialog close */ - g_signal_stop_emission_by_name (wizard_dialog, "response"); - - /* We show the default image on first and last pages */ - if (current == last || current == 0) - gtk_widget_show (GTK_WIDGET(priv->image)); - else - gtk_widget_hide (GTK_WIDGET(priv->image)); - - /* New page number may appear in the title, update it */ - if (priv->autotitle) - create_title (wizard_dialog); -} - -/** - * hildon_wizard_dialog_new: - * @parent: a #GtkWindow - * @wizard_name: the name of dialog - * @notebook: the notebook to be shown on the dialog - * - * Creates a new #HildonWizardDialog. - * - * Returns: a new #HildonWizardDialog - */ -GtkWidget* -hildon_wizard_dialog_new (GtkWindow *parent, - const char *wizard_name, - GtkNotebook *notebook) -{ - GtkWidget *widget; - - g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL); - - widget = GTK_WIDGET (g_object_new - (HILDON_TYPE_WIZARD_DIALOG, - "wizard-name", wizard_name, - "wizard-notebook", notebook, NULL)); - - if (parent) - gtk_window_set_transient_for (GTK_WINDOW (widget), parent); - - return widget; -} diff --git a/hildon-widgets/hildon-wizard-dialog.h b/hildon-widgets/hildon-wizard-dialog.h deleted file mode 100644 index 38de909..0000000 --- a/hildon-widgets/hildon-wizard-dialog.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * This file is part of hildon-libs - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Michael Dominic Kostrzewa - * Fixes: Michael Dominic Kostrzewa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; version 2.1 of - * the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __HILDON_WIZARD_DIALOG_H__ -#define __HILDON_WIZARD_DIALOG_H__ - -#include -#include -#include -#include - -G_BEGIN_DECLS - -#define HILDON_TYPE_WIZARD_DIALOG (hildon_wizard_dialog_get_type()) - -#define HILDON_WIZARD_DIALOG(obj) (GTK_CHECK_CAST ((obj), \ - HILDON_TYPE_WIZARD_DIALOG, HildonWizardDialog)) - -#define HILDON_WIZARD_DIALOG_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), \ - HILDON_TYPE_WIZARD_DIALOG, HildonWizardDialogClass)) - -#define HILDON_IS_WIZARD_DIALOG(obj) (GTK_CHECK_TYPE ((obj), \ - HILDON_TYPE_WIZARD_DIALOG)) - -#define HILDON_IS_WIZARD_DIALOG_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), \ - HILDON_TYPE_WIZARD_DIALOG)) - -typedef struct _HildonWizardDialog HildonWizardDialog; - -typedef struct _HildonWizardDialogClass HildonWizardDialogClass; - -typedef struct _HildonWizardDialogPrivate HildonWizardDialogPrivate; - -/* button response IDs */ -enum { - HILDON_WIZARD_DIALOG_CANCEL = GTK_RESPONSE_CANCEL, - HILDON_WIZARD_DIALOG_PREVIOUS = 0, - HILDON_WIZARD_DIALOG_NEXT, - HILDON_WIZARD_DIALOG_FINISH -}; - -struct _HildonWizardDialog { - GtkDialog parent; - HildonWizardDialogPrivate *priv; -}; - -struct _HildonWizardDialogClass { - GtkDialogClass parent_class; - void (*_gtk_reserved1) (void); - void (*_gtk_reserved2) (void); - void (*_gtk_reserved3) (void); - void (*_gtk_reserved4) (void); -}; - - -GType hildon_wizard_dialog_get_type (void) G_GNUC_CONST; - -GtkWidget* hildon_wizard_dialog_new (GtkWindow *parent, - const char *wizard_name, - GtkNotebook *notebook); - -G_END_DECLS - -#endif /* __HILDON_WIZARD_DIALOG_H__ */ diff --git a/plugins/Makefile.am b/plugins/Makefile.am new file mode 100644 index 0000000..f2b45ee --- /dev/null +++ b/plugins/Makefile.am @@ -0,0 +1,27 @@ +MAINTAINERCLEANFILES = Makefile.in + +INCLUDES = $(GTK_CFLAGS) $(GCONF_CFLAGS) -DLOCALEDIR=\"$(localedir)\" \ + -I$(srcdir)/.. + +LDFLAGS = -module -avoid-version +LIBADD = -L$(srcdir)/../hildon-widgets/.libs -lhildonwidgets $(GTK_LIBS) + +pluginwidgetdir = $(libdir)/hildon-widgets +pluginwidget_LTLIBRARIES = hildoncolorchooser_hsv.la \ + hildoncolorchooserdialog_hsv.la + +hildoncolorchooser_hsv_la_SOURCES = hildon-color-chooser-hsv.c + +hildoncolorchooserdialog_hsv_la_SOURCES = hildon-color-chooser-dialog-hsv.c +hildoncolorchooserdialog_hsv_la_LIBADD = $(GCONF_LIBS) + +install-exec-local: installdirs + @echo "Creating default symlink for color chooser..." + @ln -f -s 'hildoncolorchooser_hsv.so' '$(DESTDIR)/$(libdir)/hildon-widgets/hildoncolorchooser_default.so' + @echo "Creating default symlink for color chooser dialog..." + @ln -f -s 'hildoncolorchooserdialog_hsv.so' '$(DESTDIR)/$(libdir)/hildon-widgets/hildoncolorchooserdialog_default.so' + + + + + diff --git a/plugins/hildon-color-chooser-dialog-hsv.c b/plugins/hildon-color-chooser-dialog-hsv.c new file mode 100644 index 0000000..3f57eb3 --- /dev/null +++ b/plugins/hildon-color-chooser-dialog-hsv.c @@ -0,0 +1,1062 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Author: Kuisma Salonen + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + + +#include +#include + +#include + +#include +#include + +#include + +#include + + +#include +#include + +#include + +#include + +#include + + +#define _(String) dgettext("hildon-libs", String) + + +const char *parent_name = "HildonColorChooserDialog"; +const char *plugin_name = "HSV color chooser dialog"; + +GType export_type(void); + + +static HildonPluginWidgetInfo *chooser_plugin = NULL; + +static HildonColorChooserDialogClass *parent_klass = NULL; + + +/* darkened EGA palette to be used as predefined colors if style doesn't + define anything else (darker colors are darkened 0x8000 -> 0x6666) */ +static GdkColor hardcoded_colors[16] = {{0, 0x0000, 0x0000, 0x0000}, + {0, 0x6666, 0x6666, 0x6666}, + {0, 0x6666, 0x0000, 0x0000}, + {0, 0x0000, 0x6666, 0x0000}, + {0, 0x0000, 0x0000, 0x6666}, + {0, 0x6666, 0x6666, 0x0000}, + {0, 0x6666, 0x0000, 0x6666}, + {0, 0x0000, 0x6666, 0x6666}, + {0, 0xffff, 0xffff, 0xffff}, + {0, 0xc000, 0xc000, 0xc000}, + {0, 0xffff, 0x0000, 0x0000}, + {0, 0x0000, 0xffff, 0x0000}, + {0, 0x0000, 0x0000, 0xffff}, + {0, 0xffff, 0xffff, 0x0000}, + {0, 0xffff, 0x0000, 0xffff}, + {0, 0x0000, 0xffff, 0xffff}}; + + +typedef struct { + GtkBorder radio_sizes; + GtkBorder cont_sizes; + GtkBorder num_buttons; + GtkBorder last_num_buttons; + + GdkColor default_color; +} HildonColorChooserStyleInfo; + + +typedef struct _HildonColorChooserDialogHSV HildonColorChooserDialogHSV; +typedef struct _HildonColorChooserDialogHSVClass HildonColorChooserDialogHSVClass; + + +struct _HildonColorChooserDialogHSV { + HildonColorChooserDialog parent; + + GtkWidget *hbox; + GtkWidget *vbox; + + GtkWidget *align_custom, *align_defined; + GtkWidget *area_custom, *area_defined; + GtkWidget *separator; + + GtkWidget *chooser; + + GdkColor *colors_custom, *colors_defined; + GdkGC **gc_array; + + gint selected; + + HildonColorChooserStyleInfo style_info; + + + gint has_style; + + GdkColor pending_color; + + + struct { + GConfClient *client; + } gconf_data; +}; + +struct _HildonColorChooserDialogHSVClass { + HildonColorChooserDialogClass parent_klass; +}; + + +#define HILDON_COLOR_CHOOSER_DIALOG_HSV(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), export_type(), HildonColorChooserDialogHSV)) +#define HILDON_COLOR_CHOOSER_DIALOG_HSV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), export_type(), HildonColorChooserDialogHSVClass)) + + +GtkType export_type(void); + + +static void hildon_color_chooser_dialog_hsv_init(HildonColorChooserDialogHSV *object); +static void hildon_color_chooser_dialog_hsv_class_init(HildonColorChooserDialogHSVClass *klass); + +static void hildon_color_chooser_dialog_hsv_size_request(GtkWidget *widget, GtkRequisition *req); +static void hildon_color_chooser_dialog_hsv_size_allocate(GtkWidget *widget, GtkAllocation *alloc); + +static void hildon_color_chooser_dialog_hsv_realize(GtkWidget *widget); +static void hildon_color_chooser_dialog_hsv_unrealize(GtkWidget *widget); + +static void hildon_color_chooser_dialog_hsv_style_set(GtkWidget *widget, GtkStyle *previous_style); + +static void hildon_color_chooser_dialog_hsv_show(GtkWidget *widget); +static void hildon_color_chooser_dialog_hsv_show_all(GtkWidget *widget); + +static gboolean hildon_color_chooser_dialog_hsv_key_press_event(GtkWidget *widget, GdkEventKey *event); +static gboolean hildon_color_chooser_dialog_hsv_key_release_event(GtkWidget *widget, GdkEventKey *event); + + +static void hildon_color_chooser_dialog_hsv_destroy(GtkObject *object); + + +static void hildon_color_chooser_dialog_hsv_set_color(HildonColorChooserDialog *dialog, GdkColor *color); + + +static gboolean hildon_color_chooser_dialog_hsv_area_expose(GtkWidget *widget, GdkEventExpose *event, gpointer data); + +static gboolean hildon_color_chooser_dialog_hsv_area_button_press(GtkWidget *widget, GdkEventButton *event, gpointer data); + + +static void hildon_color_chooser_dialog_hsv_chooser_color_changed(HildonColorChooser *chooser, GdkColor *color, gpointer data); + +static void hildon_color_chooser_dialog_hsv_chooser_insensitive_press(GtkWidget *widget, gpointer data); + + +static void hildon_color_chooser_dialog_hsv_refresh_style_info(HildonColorChooserDialogHSV *dialog); + +static void hildon_color_chooser_dialog_hsv_set_color_num(HildonColorChooserDialogHSV *dialog, gint num); + +static void hildon_color_chooser_dialog_hsv_ascii_hex_to_color(gchar *s, GdkColor *color); +static void hildon_color_chooser_dialog_hsv_color_to_ascii_hex(gchar *s, GdkColor *color); + + +GType export_type() +{ + static GType dialog_type = 0; + + if (!dialog_type) { + static const GTypeInfo dialog_info = + { + sizeof (HildonColorChooserDialogHSVClass), + NULL, + NULL, + (GClassInitFunc) hildon_color_chooser_dialog_hsv_class_init, + NULL, + NULL, + sizeof (HildonColorChooserDialogHSV), + 0, + (GInstanceInitFunc) hildon_color_chooser_dialog_hsv_init, + NULL + }; + + dialog_type = g_type_register_static (HILDON_TYPE_COLOR_CHOOSER_DIALOG, "HildonColorChooserDialogHSV", &dialog_info, 0); + } + + return dialog_type; +} + + +static void hildon_color_chooser_dialog_hsv_init(HildonColorChooserDialogHSV *object) +{ + if(!chooser_plugin) { + chooser_plugin = hildon_plugin_info_initialize(HILDON_TYPE_COLOR_CHOOSER, "hsv"); + } + + + gtk_dialog_set_has_separator(GTK_DIALOG(object), FALSE); + + gtk_window_set_title(GTK_WINDOW(object), _("ecdg_ti_colour_selector")); + + + object->chooser = hildon_plugin_info_construct_widget(chooser_plugin); + + object->hbox = gtk_hbox_new(FALSE, 0); + object->vbox = gtk_vbox_new(FALSE, 0); + + gtk_box_pack_start(GTK_BOX(object->hbox), object->chooser, TRUE, TRUE, 0); + gtk_box_pack_end(GTK_BOX(object->hbox), object->vbox, FALSE, FALSE, 0); + + + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(object)->vbox), object->hbox, TRUE, TRUE, 0); + + + object->align_custom = gtk_alignment_new(0.5, 1.0, 0.0, 0.0); + object->align_defined = gtk_alignment_new(0.5, 1.0, 0.0, 0.0); + + object->area_custom = gtk_drawing_area_new(); + object->area_defined = gtk_drawing_area_new(); + + + gtk_container_add(GTK_CONTAINER(object->align_custom), object->area_custom); + gtk_container_add(GTK_CONTAINER(object->align_defined), object->area_defined); + + + object->separator = gtk_hseparator_new(); + + + gtk_box_pack_start(GTK_BOX(object->vbox), object->align_defined, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(object->vbox), object->separator, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(object->vbox), object->align_custom, FALSE, FALSE, 0); + + + gtk_dialog_add_button(GTK_DIALOG(object), _("ecdg_bd_colour_selector_ok"), GTK_RESPONSE_OK); + gtk_dialog_add_button(GTK_DIALOG(object), _("ecdg_bd_colour_selector_cancel"), GTK_RESPONSE_CANCEL); + gtk_dialog_set_default_response (GTK_DIALOG (object), GTK_RESPONSE_OK); + + + g_signal_connect(G_OBJECT(object->chooser), "insensitive-press", G_CALLBACK(hildon_color_chooser_dialog_hsv_chooser_insensitive_press), object); + + + g_signal_connect(G_OBJECT(object->area_custom), "expose-event", G_CALLBACK(hildon_color_chooser_dialog_hsv_area_expose), object); + g_signal_connect(G_OBJECT(object->area_defined), "expose-event", G_CALLBACK(hildon_color_chooser_dialog_hsv_area_expose), object); + + g_signal_connect(G_OBJECT(object->area_custom), "button-press-event", G_CALLBACK(hildon_color_chooser_dialog_hsv_area_button_press), object); + g_signal_connect(G_OBJECT(object->area_defined), "button-press-event", G_CALLBACK(hildon_color_chooser_dialog_hsv_area_button_press), object); + + gtk_widget_add_events(object->area_custom, GDK_BUTTON_PRESS_MASK); + gtk_widget_add_events(object->area_defined, GDK_BUTTON_PRESS_MASK); + + + object->selected = 0; + + + g_signal_connect(G_OBJECT(object->chooser), "color-changed", G_CALLBACK(hildon_color_chooser_dialog_hsv_chooser_color_changed), object); + + + object->gconf_data.client = gconf_client_get_default(); + + + memset(&object->style_info, 0, sizeof(HildonColorChooserStyleInfo)); + + + object->colors_custom = NULL; + object->colors_defined = NULL; + + object->gc_array = NULL; + + + object->has_style = 0; +} + +static void hildon_color_chooser_dialog_hsv_class_init(HildonColorChooserDialogHSVClass *klass) +{ + GtkWidgetClass *widget_klass = GTK_WIDGET_CLASS(klass); + GtkObjectClass *object_klass = GTK_OBJECT_CLASS(klass); + HildonColorChooserDialogClass *dialog_klass = HILDON_COLOR_CHOOSER_DIALOG_CLASS(klass); + gchar tmp[32]; + gint i; + + + widget_klass->size_request = hildon_color_chooser_dialog_hsv_size_request; + widget_klass->size_allocate = hildon_color_chooser_dialog_hsv_size_allocate; + + widget_klass->realize = hildon_color_chooser_dialog_hsv_realize; + widget_klass->unrealize = hildon_color_chooser_dialog_hsv_unrealize; + + widget_klass->style_set = hildon_color_chooser_dialog_hsv_style_set; + + widget_klass->show = hildon_color_chooser_dialog_hsv_show; + widget_klass->show_all = hildon_color_chooser_dialog_hsv_show_all; + + widget_klass->key_press_event = hildon_color_chooser_dialog_hsv_key_press_event; + widget_klass->key_release_event = hildon_color_chooser_dialog_hsv_key_release_event; + + + object_klass->destroy = hildon_color_chooser_dialog_hsv_destroy; + + + dialog_klass->set_color = hildon_color_chooser_dialog_hsv_set_color; + + + parent_klass = g_type_class_peek_parent(klass); + + + gtk_widget_class_install_style_property(widget_klass, + g_param_spec_boxed("container_sizes", + "Container sizes", + "Container specific sizes", + GTK_TYPE_BORDER, + G_PARAM_READABLE)); + + gtk_widget_class_install_style_property(widget_klass, + g_param_spec_boxed("radio_sizes", + "Color radio sizes", + "Color radio specific sizes", + GTK_TYPE_BORDER, + G_PARAM_READABLE)); + + gtk_widget_class_install_style_property(widget_klass, + g_param_spec_boxed("num_buttons", + "Number of buttons", + "Number of color store buttons", + GTK_TYPE_BORDER, + G_PARAM_READABLE)); + + + gtk_widget_class_install_style_property(widget_klass, + g_param_spec_boxed("default_color", "Default color", + "Default color for nonpainted custom colors", + GDK_TYPE_COLOR, + G_PARAM_READABLE)); + + + for(i = 0; i < 32; i++) { + memset(tmp, 0, 32); + g_snprintf(tmp, 32, "defined_color%d", i); + + gtk_widget_class_install_style_property(widget_klass, + g_param_spec_boxed(tmp, "Defined color", + "Pre-defined colors for the dialog", + GDK_TYPE_COLOR, + G_PARAM_READABLE)); + } +} + + +static void hildon_color_chooser_dialog_hsv_size_request(GtkWidget *widget, GtkRequisition *req) +{ + HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(widget); + + + gtk_container_set_border_width(GTK_CONTAINER(dialog->hbox), dialog->style_info.cont_sizes.left); + + gtk_box_set_spacing(GTK_BOX(dialog->hbox), dialog->style_info.cont_sizes.right); + gtk_box_set_spacing(GTK_BOX(dialog->vbox), dialog->style_info.cont_sizes.top); + gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(widget)->vbox), dialog->style_info.cont_sizes.bottom); + + + gtk_widget_set_size_request(dialog->area_custom, + (dialog->style_info.radio_sizes.left + 2*dialog->style_info.radio_sizes.bottom)*(dialog->style_info.num_buttons.top) + + (dialog->style_info.num_buttons.top-1)*dialog->style_info.radio_sizes.top, + (dialog->style_info.radio_sizes.right + 2*dialog->style_info.radio_sizes.bottom)*(dialog->style_info.num_buttons.bottom) + + (dialog->style_info.num_buttons.bottom-1)*dialog->style_info.radio_sizes.top); + gtk_widget_set_size_request(dialog->area_defined, + (dialog->style_info.radio_sizes.left + 2*dialog->style_info.radio_sizes.bottom)*(dialog->style_info.num_buttons.left) + + (dialog->style_info.num_buttons.left-1)*dialog->style_info.radio_sizes.top, + (dialog->style_info.radio_sizes.right + 2*dialog->style_info.radio_sizes.bottom)*(dialog->style_info.num_buttons.right) + + (dialog->style_info.num_buttons.right-1)*dialog->style_info.radio_sizes.top); + + + GTK_WIDGET_CLASS(parent_klass)->size_request(widget, req); +} + +static void hildon_color_chooser_dialog_hsv_size_allocate(GtkWidget *widget, GtkAllocation *alloc) +{ + HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(widget); + GdkRectangle rect; + int i, tmp, tmp2; + + + GTK_WIDGET_CLASS(parent_klass)->size_allocate(widget, alloc); + + + if(GTK_WIDGET_REALIZED(widget)) { + tmp = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right); + tmp2 = (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom); + + for(i = 0; i < tmp; i++) { + rect.x = ((i % dialog->style_info.num_buttons.left) * (dialog->style_info.radio_sizes.left + dialog->style_info.radio_sizes.top + + 2*dialog->style_info.radio_sizes.bottom)) + dialog->style_info.radio_sizes.bottom; + rect.y = ((i / dialog->style_info.num_buttons.left) * (dialog->style_info.radio_sizes.right + dialog->style_info.radio_sizes.top + + 2*dialog->style_info.radio_sizes.bottom)) + dialog->style_info.radio_sizes.bottom; + rect.width = dialog->style_info.radio_sizes.left; + rect.height = dialog->style_info.radio_sizes.right; + + gdk_gc_set_clip_rectangle(dialog->gc_array[i], &rect); + } + + for(i = 0; i < tmp2; i++) { + rect.x = ((i % dialog->style_info.num_buttons.top) * (dialog->style_info.radio_sizes.left + dialog->style_info.radio_sizes.top + + 2*dialog->style_info.radio_sizes.bottom)) + dialog->style_info.radio_sizes.bottom; + rect.y = ((i / dialog->style_info.num_buttons.top) * (dialog->style_info.radio_sizes.right + dialog->style_info.radio_sizes.top + + 2*dialog->style_info.radio_sizes.bottom)) + dialog->style_info.radio_sizes.bottom; + rect.width = dialog->style_info.radio_sizes.left; + rect.height = dialog->style_info.radio_sizes.right; + + gdk_gc_set_clip_rectangle(dialog->gc_array[i + tmp], &rect); + } + } +} + + +static void hildon_color_chooser_dialog_hsv_realize(GtkWidget *widget) +{ + HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(widget); + GdkRectangle rect; + int i, tmp, tmp2; + + + GTK_WIDGET_CLASS(parent_klass)->realize(widget); + + + tmp = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right) + + (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom); + + for(i = 0; i < tmp; i++) { + dialog->gc_array[i] = gdk_gc_new(widget->window); + } + + + + tmp = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right); + tmp2 = (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom); + + for(i = 0; i < tmp; i++) { + gdk_gc_set_rgb_fg_color(dialog->gc_array[i], &dialog->colors_defined[i]); + + rect.x = ((i % dialog->style_info.num_buttons.left) * (dialog->style_info.radio_sizes.left + dialog->style_info.radio_sizes.top + + 2*dialog->style_info.radio_sizes.bottom)) + dialog->style_info.radio_sizes.bottom; + rect.y = ((i / dialog->style_info.num_buttons.left) * (dialog->style_info.radio_sizes.right + dialog->style_info.radio_sizes.top + + 2*dialog->style_info.radio_sizes.bottom)) + dialog->style_info.radio_sizes.bottom; + rect.width = dialog->style_info.radio_sizes.left; + rect.height = dialog->style_info.radio_sizes.right; + + gdk_gc_set_clip_rectangle(dialog->gc_array[i], &rect); + } + + for(i = 0; i < tmp2; i++) { + gdk_gc_set_rgb_fg_color(dialog->gc_array[i + tmp], &dialog->colors_custom[i]); + + rect.x = ((i % dialog->style_info.num_buttons.top) * (dialog->style_info.radio_sizes.left + dialog->style_info.radio_sizes.top + + 2*dialog->style_info.radio_sizes.bottom)) + dialog->style_info.radio_sizes.bottom; + rect.y = ((i / dialog->style_info.num_buttons.top) * (dialog->style_info.radio_sizes.right + dialog->style_info.radio_sizes.top + + 2*dialog->style_info.radio_sizes.bottom)) + dialog->style_info.radio_sizes.bottom; + rect.width = dialog->style_info.radio_sizes.left; + rect.height = dialog->style_info.radio_sizes.right; + + gdk_gc_set_clip_rectangle(dialog->gc_array[i + tmp], &rect); + } +} + +static void hildon_color_chooser_dialog_hsv_unrealize(GtkWidget *widget) +{ + HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(widget); + int i, tmp; + + + tmp = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right) + + (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom); + + for(i = 0; i < tmp; i++) { + g_object_unref(dialog->gc_array[i]); + } + + + GTK_WIDGET_CLASS(parent_klass)->unrealize(widget); +} + + +static void hildon_color_chooser_dialog_hsv_style_set(GtkWidget *widget, GtkStyle *previous_style) +{ + HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(widget); + GdkColor *tmpcolor; + gchar tmp[32], key[128], *val; + int i, tmpn, setcolor = 0; + + + if(!dialog->has_style) + setcolor = 1; + + dialog->has_style = 1; + + + gtk_widget_style_get(widget, "default_color", &tmpcolor, NULL); + if(tmpcolor) { + dialog->style_info.default_color = *tmpcolor; + } else { + dialog->style_info.default_color.red = 0x0000; + dialog->style_info.default_color.green = 0x0000; + dialog->style_info.default_color.blue = 0x0000; + dialog->style_info.default_color.pixel = 0x00000000; + } + + + hildon_color_chooser_dialog_hsv_refresh_style_info(dialog); + + + if(memcmp(&dialog->style_info.num_buttons, &dialog->style_info.last_num_buttons, sizeof(GtkBorder))) { + if(dialog->colors_custom) { + g_free(dialog->colors_custom); + } if(dialog->colors_defined) { + g_free(dialog->colors_defined); + } if(dialog->gc_array) { + if(GTK_WIDGET_REALIZED(widget)) { + tmpn = (dialog->style_info.last_num_buttons.left * dialog->style_info.last_num_buttons.right) + + (dialog->style_info.last_num_buttons.top * dialog->style_info.last_num_buttons.bottom); + + for(i = 0; i < tmpn; i++) { + g_object_unref(dialog->gc_array[i]); + } + } + + g_free(dialog->gc_array); + } + + dialog->colors_custom = (GdkColor *)g_malloc0(sizeof(GdkColor) * (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom)); + dialog->colors_defined = (GdkColor *)g_malloc0(sizeof(GdkColor) * (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right)); + + + tmpn = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right) + + (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom); + dialog->gc_array = (GdkGC **)g_malloc0(sizeof(GdkGC *) * tmpn); + + + if(dialog->gconf_data.client) { + for(i = 0; i < (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom); i++) { + memset(key, 0, 128); + g_snprintf(key, 128, "/system/osso/af/color_chooser/custom_color%d", i); + val = gconf_client_get_string(dialog->gconf_data.client, key, NULL); + if(val) { + hildon_color_chooser_dialog_hsv_ascii_hex_to_color(val, &dialog->colors_custom[i]); + g_free(val); + } else { + dialog->colors_custom[i] = dialog->style_info.default_color; + } + } + } else { + for(i = 0; i < (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom); i++) { + dialog->colors_custom[i] = dialog->style_info.default_color; + } + } + } + + + tmpn = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right); + + hildon_color_chooser_set_color(HILDON_COLOR_CHOOSER(dialog->chooser), + (dialog->selected < tmpn) ? &dialog->colors_defined[dialog->selected] : &dialog->colors_custom[dialog->selected - tmpn]); + + + for(i = 0; i < (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right); i++) { + memset(tmp, 0, 32); + g_snprintf(tmp, 32, "defined_color%d", i); + + gtk_widget_style_get(widget, tmp, &tmpcolor, NULL); + + if(tmpcolor) { + dialog->colors_defined[i] = *tmpcolor; + } else { + if(i < 16) { + dialog->colors_defined[i] = hardcoded_colors[i]; + } else { /* fallback to prevent segfault */ + dialog->colors_defined[i].red = 0x0000; + dialog->colors_defined[i].green = 0x0000; + dialog->colors_defined[i].blue = 0x0000; + dialog->colors_defined[i].pixel = 0x00000000; + } + } + } + + + if(GTK_WIDGET_REALIZED(widget)) { + for(i = 0; i < (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right); i++) { + gdk_gc_set_rgb_fg_color(dialog->gc_array[i], &dialog->colors_defined[i]); + } + } + + + if(setcolor) + hildon_color_chooser_dialog_hsv_set_color(HILDON_COLOR_CHOOSER_DIALOG(dialog), &dialog->pending_color); + + + gtk_widget_queue_resize(widget); + + + GTK_WIDGET_CLASS(parent_klass)->style_set(widget, previous_style); +} + + +static void hildon_color_chooser_dialog_hsv_show(GtkWidget *widget) +{ + HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(widget); + + + gtk_widget_show(dialog->hbox); + gtk_widget_show(dialog->vbox); + + gtk_widget_show(dialog->chooser); + + gtk_widget_show(dialog->align_custom); + gtk_widget_show(dialog->align_defined); + + gtk_widget_show(dialog->separator); + + gtk_widget_show(dialog->area_custom); + gtk_widget_show(dialog->area_defined); + + + GTK_WIDGET_CLASS(parent_klass)->show(widget); +} + +static void hildon_color_chooser_dialog_hsv_show_all(GtkWidget *widget) +{ + hildon_color_chooser_dialog_hsv_show(widget); +} + + +static gboolean hildon_color_chooser_dialog_hsv_key_press_event(GtkWidget *widget, GdkEventKey *event) +{ + HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(widget); + int tmp, tot, sel; + + + if(event->keyval == HILDON_HARDKEY_UP || event->keyval == HILDON_HARDKEY_DOWN || + event->keyval == HILDON_HARDKEY_LEFT || event->keyval == HILDON_HARDKEY_RIGHT) { + tmp = (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom); + tot = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right) + tmp; + + switch(event->keyval) { + case HILDON_HARDKEY_UP: + if(dialog->selected >= dialog->style_info.num_buttons.top) { + if(dialog->selected - dialog->style_info.num_buttons.left >= tmp) { + sel = dialog->selected - dialog->style_info.num_buttons.left; + } else { + sel = dialog->selected - dialog->style_info.num_buttons.top; + } + + hildon_color_chooser_dialog_hsv_set_color_num(dialog, sel); + } + break; + case HILDON_HARDKEY_DOWN: + if(dialog->selected < tot - dialog->style_info.num_buttons.left) { + if(dialog->selected < tmp) { + sel = dialog->selected + dialog->style_info.num_buttons.top; + } else { + sel = dialog->selected + dialog->style_info.num_buttons.left; + } + + hildon_color_chooser_dialog_hsv_set_color_num(dialog, sel); + } + break; + case HILDON_HARDKEY_LEFT: + if((dialog->selected < tmp ? (dialog->selected % dialog->style_info.num_buttons.top) : ((dialog->selected - tmp) % dialog->style_info.num_buttons.left)) > 0) { + sel = dialog->selected - 1; + + hildon_color_chooser_dialog_hsv_set_color_num(dialog, sel); + } + break; + case HILDON_HARDKEY_RIGHT: + if((dialog->selected < tmp) ? (dialog->selected % dialog->style_info.num_buttons.top < dialog->style_info.num_buttons.top - 1) : + ((dialog->selected - tmp) % dialog->style_info.num_buttons.left < dialog->style_info.num_buttons.left - 1)) { + sel = dialog->selected + 1; + + hildon_color_chooser_dialog_hsv_set_color_num(dialog, sel); + } + break; + default: + break; + } + + return FALSE; + } + + return GTK_WIDGET_CLASS(parent_klass)->key_press_event(widget, event); +} + +static gboolean hildon_color_chooser_dialog_hsv_key_release_event(GtkWidget *widget, GdkEventKey *event) +{ + if(event->keyval == HILDON_HARDKEY_UP || event->keyval == HILDON_HARDKEY_DOWN || + event->keyval == HILDON_HARDKEY_LEFT || event->keyval == HILDON_HARDKEY_RIGHT) { + return FALSE; + } + + return GTK_WIDGET_CLASS(parent_klass)->key_press_event(widget, event); +} + + +static void hildon_color_chooser_dialog_hsv_destroy(GtkObject *object) +{ + HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(object); + gchar key[128], color[13]; + int i, tmp; + + + if(dialog->gconf_data.client) { + memset(color, 0, 13); + + tmp = (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom); + + for(i = 0; i < tmp; i++) { + memset(key, 0, 128); + g_snprintf(key, 128, "/system/osso/af/color_chooser/custom_color%d", i); + hildon_color_chooser_dialog_hsv_color_to_ascii_hex(color, &dialog->colors_custom[i]); + gconf_client_set_string(dialog->gconf_data.client, key, color, NULL); + } + + g_object_unref(dialog->gconf_data.client); + dialog->gconf_data.client = NULL; + } + + + if(dialog->gc_array) { + g_free(dialog->gc_array); + dialog->gc_array = NULL; + } if(dialog->colors_defined) { + g_free(dialog->colors_defined); + dialog->colors_defined = NULL; + } if(dialog->colors_custom) { + g_free(dialog->colors_custom); + dialog->colors_custom = NULL; + } + + + GTK_OBJECT_CLASS(parent_klass)->destroy(object); +} + + +static void hildon_color_chooser_dialog_hsv_set_color(HildonColorChooserDialog *dialog, GdkColor *color) +{ + HildonColorChooserDialogHSV *dialog_hsv = HILDON_COLOR_CHOOSER_DIALOG_HSV(dialog); + int i, found = -1, tmp, tmp2; + + + if(!dialog_hsv->has_style) { + dialog_hsv->pending_color = *color; + return; + } + + + tmp = (dialog_hsv->style_info.num_buttons.left * dialog_hsv->style_info.num_buttons.right); + tmp2 = (dialog_hsv->style_info.num_buttons.top * dialog_hsv->style_info.num_buttons.bottom); + + for(i = 0; i < tmp; i++) { + if(dialog_hsv->colors_defined[i].red == color->red && + dialog_hsv->colors_defined[i].green == color->green && + dialog_hsv->colors_defined[i].blue == color->blue) { + found = i; + break; + } + } + + if(found == -1) { + for(i = 0; i < tmp2; i++) { + if(dialog_hsv->colors_custom[i].red == color->red && + dialog_hsv->colors_custom[i].green == color->green && + dialog_hsv->colors_custom[i].blue == color->blue) { + found = i + tmp; + break; + } + } + } + + + if(found == -1) { + dialog_hsv->colors_custom[tmp2-1] = *color; + if(GTK_WIDGET_REALIZED(GTK_WIDGET(dialog))) { + gdk_gc_set_rgb_fg_color(dialog_hsv->gc_array[tmp2-1], color); + } + hildon_color_chooser_dialog_hsv_set_color_num(dialog_hsv, tmp2-1); + } else { + hildon_color_chooser_dialog_hsv_set_color_num(dialog_hsv, found); + } +} + + +static gboolean hildon_color_chooser_dialog_hsv_area_expose(GtkWidget *widget, GdkEventExpose *event, gpointer data) +{ + HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(data); + int i, num_selected, tot_w, tot_h, spacing, brd, x, y; + GdkGC **start_gc; + int tmp, w, h; + + + tmp = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right); + + if(widget == dialog->area_custom) { + num_selected = dialog->selected - tmp; + start_gc = dialog->gc_array + tmp; + tmp = (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom); + w = dialog->style_info.num_buttons.top; h = dialog->style_info.num_buttons.bottom; + } else { /* widget == dialog->area_defined */ + num_selected = dialog->selected; + start_gc = dialog->gc_array; + w = dialog->style_info.num_buttons.left; h = dialog->style_info.num_buttons.right; + } + + spacing = dialog->style_info.radio_sizes.top; + brd = dialog->style_info.radio_sizes.bottom; + tot_w = dialog->style_info.radio_sizes.left + 2*brd; + tot_h = dialog->style_info.radio_sizes.right + 2*brd; + + + for(i = 0; i < tmp; i++) { + x = ((i % w) * (tot_w + spacing)); + y = ((i / w) * (tot_h + spacing)); + + gdk_draw_rectangle(widget->window, + widget->style->black_gc, + TRUE, + (i == num_selected) ? x : x + 2, + (i == num_selected) ? y : y + 2, + (i == num_selected) ? tot_w : tot_w - 4, + (i == num_selected) ? tot_h : tot_h - 4); + + gdk_draw_rectangle(widget->window, + widget->style->white_gc, + TRUE, + x + 3, + y + 3, + tot_w - 6, + tot_h - 6); + + gdk_draw_rectangle(widget->window, + start_gc [i], + TRUE, + x + 3 + 1, + y + 3 + 1, + tot_w - 6 - 2, + tot_h - 6 - 2); + +// gtk_paint_box(gtk_widget_get_style(GTK_WIDGET(dialog)), widget->window, (i == num_selected) ? GTK_STATE_SELECTED : GTK_STATE_NORMAL, +// (i == num_selected) ? GTK_SHADOW_IN : GTK_SHADOW_OUT, &event->area, GTK_WIDGET(dialog), "color-radio", x, y, tot_w, tot_h); + //} + + //gdk_draw_rectangle(widget->window, start_gc[i], TRUE, event->area.x, event->area.y, event->area.width, event->area.height); + } + + + return FALSE; +} + + +static gboolean hildon_color_chooser_dialog_hsv_area_button_press(GtkWidget *widget, GdkEventButton *event, gpointer data) +{ + HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(data); + int i, hskip, vskip, brd, selection = -1; + int x, y, tmp, tmp2, w; + + + x = event->x; + y = event->y; + + + brd = dialog->style_info.radio_sizes.bottom; + hskip = dialog->style_info.radio_sizes.left + dialog->style_info.radio_sizes.top + 2*brd; + vskip = dialog->style_info.radio_sizes.right + dialog->style_info.radio_sizes.top + 2*brd; + + + tmp = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right); + tmp2 = (dialog->style_info.num_buttons.top * dialog->style_info.num_buttons.bottom); + + + if(widget == dialog->area_defined) { + w = dialog->style_info.num_buttons.left; + + for(i = 0; i < tmp; i++) { + if(x >= hskip*(i % w) + brd && x < hskip*(i % w) + brd + dialog->style_info.radio_sizes.left && + y >= vskip*(i / w) + brd && y < hskip*(i / w) + brd + dialog->style_info.radio_sizes.right) { + selection = i; + break; + } + } + } else { + w = dialog->style_info.num_buttons.top; + for(i = 0; i < tmp2; i++) { + if(x >= hskip*(i % w) + brd && x < hskip*(i % w) + brd + dialog->style_info.radio_sizes.left && + y >= vskip*(i / w) + brd && y < hskip*(i / w) + brd + dialog->style_info.radio_sizes.right) { + selection = i + tmp; + break; + } + } + } + + + if(selection != -1) { + hildon_color_chooser_dialog_hsv_set_color_num(dialog, selection); + } + + + return FALSE; +} + + +static void hildon_color_chooser_dialog_hsv_chooser_color_changed(HildonColorChooser *chooser, GdkColor *color, gpointer data) +{ + HildonColorChooserDialogHSV *dialog = HILDON_COLOR_CHOOSER_DIALOG_HSV(data); + HildonColorChooserDialog *dia = HILDON_COLOR_CHOOSER_DIALOG(data); + char key[128], color_str[13]; + int tmp; + + + dia->color = *color; + + + tmp = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right); + + + if(dialog->selected >= tmp) { + dialog->colors_custom[dialog->selected - tmp] = *color; + + gdk_gc_set_rgb_fg_color(dialog->gc_array[dialog->selected], &dialog->colors_custom[dialog->selected - tmp]); + + gtk_widget_queue_draw(dialog->area_custom); + + + if(dialog->gconf_data.client) { + memset(key, 0, 128); + memset(color_str, 0, 13); + g_snprintf(key, 128, "/system/osso/af/color_chooser/custom_color%d", dialog->selected - tmp); + hildon_color_chooser_dialog_hsv_color_to_ascii_hex(color_str, &dialog->colors_custom[dialog->selected - tmp]); + gconf_client_set_string(dialog->gconf_data.client, key, color_str, NULL); + } + } +} + + +static void hildon_color_chooser_dialog_hsv_chooser_insensitive_press(GtkWidget *widget, gpointer data) +{ + hildon_banner_show_information(widget, NULL, _("ecdg_ib_colour_selector_predefined")); +} + + /* function has size defaults */ +static void hildon_color_chooser_dialog_hsv_refresh_style_info(HildonColorChooserDialogHSV *dialog) +{ + GtkBorder *tmp1, *tmp2, *tmp3; + + + gtk_widget_style_get(GTK_WIDGET(dialog), "container_sizes", &tmp1, + "radio_sizes", &tmp2, "num_buttons", &tmp3, NULL); + + + dialog->style_info.last_num_buttons = dialog->style_info.num_buttons; + + + if(tmp1) { + dialog->style_info.cont_sizes = *tmp1; + g_free(tmp1); + } else { + dialog->style_info.cont_sizes.left = 0; + dialog->style_info.cont_sizes.right = 8; + dialog->style_info.cont_sizes.top = 4; + dialog->style_info.cont_sizes.bottom = 0; + } + + if(tmp2) { + dialog->style_info.radio_sizes = *tmp2; + g_free(tmp2); + } else { + dialog->style_info.radio_sizes.left = 16; + dialog->style_info.radio_sizes.right = 16; + dialog->style_info.radio_sizes.top = 4; + dialog->style_info.radio_sizes.bottom = 2; + } + + if(tmp3) { + dialog->style_info.num_buttons = *tmp3; + g_free(tmp3); + } else { + dialog->style_info.num_buttons.left = 8; + dialog->style_info.num_buttons.right = 2; + dialog->style_info.num_buttons.top = 8; + dialog->style_info.num_buttons.bottom = 2; + } +} + + +static void hildon_color_chooser_dialog_hsv_set_color_num(HildonColorChooserDialogHSV *dialog, gint num) +{ + HildonColorChooserDialog *dia = HILDON_COLOR_CHOOSER_DIALOG(dialog); + int tmp; + + + tmp = (dialog->style_info.num_buttons.left * dialog->style_info.num_buttons.right); + + + if(num < tmp) { + gtk_widget_set_sensitive(dialog->chooser, FALSE); + } else { + gtk_widget_set_sensitive(dialog->chooser, TRUE); + } + + + dialog->selected = num; + + gtk_widget_queue_draw(dialog->area_custom); + gtk_widget_queue_draw(dialog->area_defined); + + dia->color = (num < tmp) ? dialog->colors_defined[num] : dialog->colors_custom[num - tmp]; + + hildon_color_chooser_set_color(HILDON_COLOR_CHOOSER(dialog->chooser), (num < tmp) ? &dialog->colors_defined[num] : &dialog->colors_custom[num - tmp]); +} + + +static void hildon_color_chooser_dialog_hsv_ascii_hex_to_color(gchar *s, GdkColor *color) +{ + int vals[12], i; + + + for(i = 0; i < 12; i++) { + if(s[i] >= '0' && s[i] <= '9') { + vals[i] = s[i] - 0x30; + } else if(s[i] >= 'a' && s[i] <= 'f') { + vals[i] = s[i] - 0x57; + } else { + vals[i] = 0; + } + } + + + color->red = (vals[0] << 12) | (vals[1] << 8) | (vals[2 ] << 4) | (vals[3 ] ); + color->green = (vals[4] << 12) | (vals[5] << 8) | (vals[6 ] << 4) | (vals[7 ] ); + color->blue = (vals[8] << 12) | (vals[9] << 8) | (vals[10] << 4) | (vals[11] ); +} + +static void hildon_color_chooser_dialog_hsv_color_to_ascii_hex(gchar *s, GdkColor *color) +{ + g_snprintf(s, 13, "%x%x%x%x%x%x%x%x%x%x%x%x", + (color->red >> 12) & 0xf, (color->red >> 8) & 0xf, + (color->red >> 4) & 0xf, (color->red ) & 0xf, + (color->green >> 12) & 0xf, (color->green >> 8) & 0xf, + (color->green >> 4) & 0xf, (color->green ) & 0xf, + (color->blue >> 12) & 0xf, (color->blue >> 8) & 0xf, + (color->blue >> 4) & 0xf, (color->blue ) & 0xf); +} diff --git a/plugins/hildon-color-chooser-hsv.c b/plugins/hildon-color-chooser-hsv.c new file mode 100644 index 0000000..9804f73 --- /dev/null +++ b/plugins/hildon-color-chooser-hsv.c @@ -0,0 +1,1099 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Author: Kuisma Salonen + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include + +#include + + +const char *parent_name = "HildonColorChooser"; +const char *plugin_name = "HSV color chooser"; + +GType export_type(void); + + +typedef struct { + HildonColorChooser parent; + + GtkAllocation hba; + GtkAllocation spa; + + unsigned short currhue; + unsigned short currsat; + unsigned short currval; + + int mousestate; + gboolean mousein; + + + GdkWindow *event_window; + + GdkPixbuf *dimmed_plane; + GdkPixbuf *dimmed_bar; + + struct { + unsigned short last_expose_hue; + + GTimeVal last_expose_time; + + int expose_queued; + } expose_info; +} HildonColorChooserHSV; + +typedef struct { + HildonColorChooserClass parent; +} HildonColorChooserHSVClass; + + +#define HILDON_COLOR_CHOOSER_HSV(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), export_type(), HildonColorChooserHSV)) +#define HILDON_COLOR_CHOOSER_HSV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), export_type(), HildonColorChooserHSVClass)) + + +static HildonColorChooserClass *parent_class = NULL; + + + /* "crosshair" is hardcoded for now */ +static gchar crosshair[64] = { 0, 0, 0, 2, 2, 0, 0, 0, + 0, 2, 2, 3, 3, 2, 2, 0, + 0, 2, 3, 0, 0, 3, 2, 0, + 2, 3, 0, 0, 0, 0, 3, 2, + 2, 3, 0, 0, 0, 0, 3, 2, + 0, 2, 3, 0, 0, 3, 2, 0, + 0, 2, 2, 3, 3, 2, 2, 0, + 0, 0, 0, 2, 2, 0, 0, 0}; + + +static void hildon_color_chooser_hsv_init(HildonColorChooserHSV *sel); +static void hildon_color_chooser_hsv_class_init(HildonColorChooserHSVClass *klass); + +static void hildon_color_chooser_hsv_dispose(HildonColorChooserHSV *sel); + +static void hildon_color_chooser_hsv_size_request(GtkWidget *widget, GtkRequisition *req); +static void hildon_color_chooser_hsv_size_allocate(GtkWidget *widget, GtkAllocation *alloc); + +static void hildon_color_chooser_hsv_realize(GtkWidget *widget); + +static void hildon_color_chooser_hsv_map(GtkWidget *widget); +static void hildon_color_chooser_hsv_unmap(GtkWidget *widget); + +static gboolean hildon_color_chooser_hsv_expose(GtkWidget *widget, GdkEventExpose *event); + +static gboolean hildon_color_chooser_button_press(GtkWidget *widget, GdkEventButton *event); +static gboolean hildon_color_chooser_button_release(GtkWidget *widget, GdkEventButton *event); +static gboolean hildon_color_chooser_pointer_motion(GtkWidget *widget, GdkEventMotion *event); + +static void hildon_color_chooser_hsv_set_color(HildonColorChooser *sel, GdkColor *color); + + +static void internal_get_border(GtkWidget *w, char *name, GtkBorder *b); +static void _internal_init_borders(GtkWidget *w, GtkBorder *inner, GtkBorder *outer); + +static void internal_invoke_color_changed(HildonColorChooserHSV *sel); + + +inline void inline_clip_to_alloc(void *s, GtkAllocation *a); + +inline void inline_sub_times(GTimeVal *result, GTimeVal *greater, GTimeVal *lesser); + +inline void inline_limited_expose(HildonColorChooserHSV *sel); + +inline void inline_draw_hue_bar(GtkWidget *widget, int x, int y, int w, int h, int sy, int sh); +inline void inline_draw_hue_bar_dimmed(GtkWidget *widget, int x, int y, int w, int h, int sy, int sh); + +inline void inline_draw_sv_plane(HildonColorChooserHSV *sel, int x, int y, int w, int h); +inline void inline_draw_sv_plane_dimmed(HildonColorChooserHSV *sel, int x, int y, int w, int h); + +inline void inline_draw_crosshair(unsigned char *buf, int x, int y, int w, int h); + + +inline void inline_h2rgb(unsigned short hue, unsigned long *rgb); + + +static gboolean hildon_color_chooser_hsv_expose_timer(gpointer data); + + +GType export_type() +{ + static GType chooser_type = 0; + + if (!chooser_type) { + static const GTypeInfo chooser_info = + { + sizeof (HildonColorChooserHSVClass), + NULL, + NULL, + (GClassInitFunc) hildon_color_chooser_hsv_class_init, + NULL, + NULL, + sizeof (HildonColorChooserHSV), + 0, + (GInstanceInitFunc) hildon_color_chooser_hsv_init, + NULL + }; + + chooser_type = g_type_register_static (HILDON_TYPE_COLOR_CHOOSER, + "HildonColorChooserHSV", + &chooser_info, 0); + } + + return chooser_type; +} + +static void hildon_color_chooser_hsv_init(HildonColorChooserHSV *sel) +{ + GTK_WIDGET_SET_FLAGS (sel, GTK_NO_WINDOW); + + + sel->currhue = 0; + sel->currsat = 0; + sel->currval = 0; + + sel->mousestate = 0; + sel->mousein = FALSE; + + + g_get_current_time(&sel->expose_info.last_expose_time); + + sel->expose_info.last_expose_hue = sel->currhue; + sel->expose_info.expose_queued = 0; + + sel->dimmed_plane = NULL; + sel->dimmed_bar = NULL; +} + +static void hildon_color_chooser_hsv_class_init(HildonColorChooserHSVClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + HildonColorChooserClass *selection_class = HILDON_COLOR_CHOOSER_CLASS(klass); + + + parent_class = g_type_class_peek_parent(klass); + + + object_class->dispose = (gpointer) hildon_color_chooser_hsv_dispose; + + widget_class->size_request = hildon_color_chooser_hsv_size_request; + widget_class->size_allocate = hildon_color_chooser_hsv_size_allocate; + + widget_class->realize = hildon_color_chooser_hsv_realize; + + widget_class->map = hildon_color_chooser_hsv_map; + widget_class->unmap = hildon_color_chooser_hsv_unmap; + + widget_class->expose_event = hildon_color_chooser_hsv_expose; + + widget_class->button_press_event = hildon_color_chooser_button_press; + widget_class->button_release_event = hildon_color_chooser_button_release; + widget_class->motion_notify_event = hildon_color_chooser_pointer_motion; + + + selection_class->set_color = hildon_color_chooser_hsv_set_color; + + + gtk_widget_class_install_style_property(widget_class, + g_param_spec_boxed("inner_size", + "Inner sizes", + "Sizes of SV plane, H bar and spacing", + GTK_TYPE_BORDER, + G_PARAM_READABLE)); + gtk_widget_class_install_style_property(widget_class, + g_param_spec_boxed("graphic_border", + "Graphical borders", + "Size of graphical border", + GTK_TYPE_BORDER, + G_PARAM_READABLE)); +} + + +static void hildon_color_chooser_hsv_dispose(HildonColorChooserHSV *sel) +{ + if (sel->dimmed_bar != NULL) { + g_object_unref (sel->dimmed_bar); + sel->dimmed_bar = NULL; + } + + if (sel->dimmed_plane != NULL) { + g_object_unref (sel->dimmed_plane); + sel->dimmed_plane = NULL; + } + + G_OBJECT_CLASS(parent_class)->dispose(sel); +} + +static void hildon_color_chooser_hsv_size_request(GtkWidget *widget, GtkRequisition *req) +{ + GtkBorder inner, outer; + + + _internal_init_borders(widget, &inner, &outer); + + + req->width = inner.left + inner.top + inner.bottom + outer.left + outer.right; + req->height = inner.right + outer.top + outer.bottom; +} + +static void hildon_color_chooser_hsv_size_allocate(GtkWidget *widget, GtkAllocation *alloc) +{ + HildonColorChooserHSV *sel = HILDON_COLOR_CHOOSER_HSV(widget); + GtkBorder outer, inner; + + + widget->allocation = *alloc; + + + _internal_init_borders(widget, &inner, &outer); + + + sel->hba.height = alloc->height - outer.top - outer.bottom; + sel->hba.y = alloc->y + outer.top; + sel->hba.width = inner.top; + sel->hba.x = alloc->x + alloc->width - outer.right - inner.top; + + sel->spa.x = alloc->x + outer.left; + sel->spa.y = alloc->y + outer.top; + sel->spa.height = alloc->height - outer.top - outer.bottom; + sel->spa.width = alloc->width - outer.left - outer.right - inner.top - inner.bottom; + + if(GTK_WIDGET_REALIZED(widget)) { + gdk_window_move_resize(sel->event_window, widget->allocation.x, widget->allocation.y, widget->allocation.width, widget->allocation.height); + } +} + + +static void hildon_color_chooser_hsv_realize(GtkWidget *widget) +{ + HildonColorChooserHSV *sel = HILDON_COLOR_CHOOSER_HSV(widget); + GdkWindowAttr attributes; + gint attributes_mask; + + attributes.x = widget->allocation.x; + attributes.y = widget->allocation.y; + attributes.width = widget->allocation.width; + attributes.height = widget->allocation.height; + attributes.wclass = GDK_INPUT_ONLY; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.event_mask = gtk_widget_get_events(widget) | GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | + GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_MOTION_MASK | + GDK_BUTTON1_MOTION_MASK; + attributes.visual = gtk_widget_get_visual(widget); + attributes.colormap = gtk_widget_get_colormap(widget); + + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_WMCLASS; + sel->event_window = gdk_window_new (widget->parent->window, &attributes, attributes_mask); + + + gdk_window_set_user_data(sel->event_window, widget); + + + widget->window = gtk_widget_get_parent_window(widget); + + + widget->style = gtk_style_attach(widget->style, widget->window); + + + GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED); +} + + +static void hildon_color_chooser_hsv_map(GtkWidget *widget) +{ + HildonColorChooserHSV *sel = HILDON_COLOR_CHOOSER_HSV(widget); + + + GTK_WIDGET_CLASS(parent_class)->map(widget); + + if(sel->event_window) { + gdk_window_show(sel->event_window); + } +} + +static void hildon_color_chooser_hsv_unmap(GtkWidget *widget) +{ + HildonColorChooserHSV *sel = HILDON_COLOR_CHOOSER_HSV(widget); + + + if(sel->event_window) { + gdk_window_hide(sel->event_window); + } + + GTK_WIDGET_CLASS(parent_class)->unmap(widget); +} + + +inline void inline_clip_to_alloc(void *s, GtkAllocation *a) +{ + struct { + int x, y, w, h; + } *area = s; + + + if(area->x < a->x) { + area->w -= a->x - area->x; + area->x = a->x; + } if(area->y < a->y) { + area->h -= a->y - area->y; + area->y = a->y; + } + if(area->x + area->w > a->x + a->width) area->w = a->width - (area->x - a->x); + if(area->y + area->h > a->y + a->height) area->h = a->height - (area->y - a->y); +} + +static gboolean hildon_color_chooser_hsv_expose(GtkWidget *widget, GdkEventExpose *event) +{ + HildonColorChooserHSV *sel = HILDON_COLOR_CHOOSER_HSV(widget); + GtkBorder graphical_border; + struct { + int x, y, w, h; + } area; + + + if(!GTK_WIDGET_REALIZED(widget)) { + return FALSE; + } + + + internal_get_border(widget, "graphic_border", &graphical_border); + + + if(event->area.width || event->area.height) { + gdk_draw_rectangle(widget->window, + widget->style->black_gc, + FALSE, + sel->hba.x - 2, + sel->hba.y - 2, + sel->hba.width + 3, + sel->hba.height + 3); + + gdk_draw_rectangle(widget->window, + widget->style->black_gc, + FALSE, + sel->spa.x - 2, + sel->spa.y - 2, + sel->spa.width + 3, + sel->spa.height + 3); + } + + if(sel->expose_info.expose_queued) { + if(GTK_WIDGET_SENSITIVE(widget)) { + inline_draw_hue_bar(widget, sel->hba.x, sel->hba.y, sel->hba.width, sel->hba.height, sel->hba.y, sel->hba.height); + + inline_draw_sv_plane(sel, sel->spa.x, sel->spa.y, sel->spa.width, sel->spa.height); + } else { + inline_draw_hue_bar_dimmed(widget, sel->hba.x, sel->hba.y, sel->hba.width, sel->hba.height, sel->hba.y, sel->hba.height); + + inline_draw_sv_plane_dimmed(sel, sel->spa.x, sel->spa.y, sel->spa.width, sel->spa.height); + } + + + sel->expose_info.expose_queued = 0; + + g_get_current_time(&sel->expose_info.last_expose_time); + } else { + /* clip hue bar region */ + area.x = event->area.x; + area.y = event->area.y; + area.w = event->area.width; + area.h = event->area.height; + + inline_clip_to_alloc(&area, &sel->hba); + + if(GTK_WIDGET_SENSITIVE(widget)) { + inline_draw_hue_bar(widget, area.x, area.y, area.w, area.h, sel->hba.y, sel->hba.height); + } else { + inline_draw_hue_bar_dimmed(widget, area.x, area.y, area.w, area.h, sel->hba.y, sel->hba.height); + } + + + area.x = event->area.x; + area.y = event->area.y; + area.w = event->area.width; + area.h = event->area.height; + + inline_clip_to_alloc(&area, &sel->spa); + + if(GTK_WIDGET_SENSITIVE(widget)) { + inline_draw_sv_plane(sel, area.x, area.y, area.w, area.h); + } else { + inline_draw_sv_plane_dimmed(sel, area.x, area.y, area.w, area.h); + } + } + + + return FALSE; +} + + +inline void inline_sub_times(GTimeVal *result, GTimeVal *greater, GTimeVal *lesser) +{ + result->tv_sec = greater->tv_sec - lesser->tv_sec; + result->tv_usec = greater->tv_usec - lesser->tv_usec; + + if(result->tv_usec < 0) { + result->tv_sec--; + result->tv_usec += 1000000; + } +} + +#define EXPOSE_INTERVAL 50000 +inline void inline_limited_expose(HildonColorChooserHSV *sel) +{ + GTimeVal curr_time, result; + GdkEventExpose event; + + + if(!GTK_WIDGET_REALIZED(GTK_WIDGET(sel))) { + return; + } + + + if(sel->currhue == sel->expose_info.last_expose_hue) { + return; /* no need to redraw */ + } + + + sel->expose_info.last_expose_hue = sel->currhue; + + + g_get_current_time(&curr_time); + + inline_sub_times(&result, &curr_time, &sel->expose_info.last_expose_time); + + if(result.tv_sec != 0 || result.tv_usec >= EXPOSE_INTERVAL) { + sel->expose_info.expose_queued = 1; + +#if 1 + event.type = GDK_EXPOSE; + event.area.width = 0; + event.area.height = 0; + event.window = GTK_WIDGET(sel)->window; + + gtk_widget_send_expose(GTK_WIDGET(sel), (GdkEvent *)&event); +#else + gtk_widget_queue_draw(GTK_WIDGET(sel)); +#endif + } else if(!sel->expose_info.expose_queued) { + sel->expose_info.expose_queued = 1; + + + g_timeout_add((EXPOSE_INTERVAL - result.tv_usec)/1000, hildon_color_chooser_hsv_expose_timer, sel); + } +} + +static gboolean hildon_color_chooser_button_press(GtkWidget *widget, GdkEventButton *event) +{ + HildonColorChooserHSV *sel = HILDON_COLOR_CHOOSER_HSV(widget); + int x, y, tmp; + + + x = (int)event->x + widget->allocation.x; + y = (int)event->y + widget->allocation.y; + + + if(x >= sel->spa.x && x <= sel->spa.x + sel->spa.width && + y >= sel->spa.y && y <= sel->spa.y + sel->spa.height) { + tmp = y - sel->spa.y; + sel->currsat = tmp * 0xffff / sel->spa.height; + tmp = x - sel->spa.x; + sel->currval = tmp * 0xffff / sel->spa.width; + + internal_invoke_color_changed(sel); + gtk_widget_queue_draw(widget); + + sel->mousestate = 1; + sel->mousein = TRUE; + + gtk_grab_add(widget); + } else if(x >= sel->hba.x && x <= sel->hba.x + sel->hba.width && + y >= sel->hba.y && y <= sel->hba.y + sel->hba.height) { + tmp = y - sel->hba.y; + sel->currhue = tmp * 0xffff / sel->hba.height; + + internal_invoke_color_changed(sel); + inline_limited_expose(sel); + + sel->mousestate = 2; + sel->mousein = TRUE; + + gtk_grab_add(widget); + } + + + return FALSE; +} + +static gboolean hildon_color_chooser_button_release(GtkWidget *widget, GdkEventButton *event) +{ + HildonColorChooserHSV *sel = HILDON_COLOR_CHOOSER_HSV(widget); + + + if(sel->mousestate) { + gtk_grab_remove(widget); + } + + + sel->mousestate = 0; + sel->mousein = FALSE; + + + return FALSE; +} + +static gboolean hildon_color_chooser_pointer_motion(GtkWidget *widget, GdkEventMotion *event) +{ + HildonColorChooserHSV *sel = HILDON_COLOR_CHOOSER_HSV(widget); + GdkModifierType mods; + gint x, y, tmp; + + + if (event->is_hint || (event->window != widget->window)) + gdk_window_get_pointer (widget->window, &x, &y, &mods); + + + if(sel->mousestate == 1) { + if(x >= sel->spa.x && x <= sel->spa.x + sel->spa.width && + y >= sel->spa.y && y <= sel->spa.y + sel->spa.height) { + sel->currsat = (((long)(y - sel->spa.y)) * 0xffff)/sel->spa.height; + sel->currval = (((long)(x - sel->spa.x)) * 0xffff)/sel->spa.width; + + internal_invoke_color_changed(sel); + gtk_widget_queue_draw(widget); + } else if(sel->mousein == TRUE) { + } + } else if(sel->mousestate == 2) { + if(x >= sel->hba.x && x <= sel->hba.x + sel->hba.width && + y >= sel->hba.y && y <= sel->hba.y + sel->hba.height) { + tmp = y - sel->hba.y; + tmp *= 0xffff; + tmp /= sel->hba.height; + + if(tmp != sel->currhue) { + sel->currhue = tmp; + + internal_invoke_color_changed(sel); + inline_limited_expose(sel); + } + } else if(sel->mousein == TRUE) { + } + } + + return FALSE; +} + + +static void internal_get_border(GtkWidget *w, char *name, GtkBorder *b) +{ + GtkBorder *tb; + + gtk_widget_style_get(w, name, &tb, NULL); + + if(tb) { + *b = *tb; + g_free(tb); + } else { + b->left = 0; + b->right = 0; + b->top = 0; + b->bottom = 0; + } +} + + +static void _internal_init_borders(GtkWidget *w, GtkBorder *inner, GtkBorder *outer) +{ + GtkBorder *tb; + + + internal_get_border(w, "outer_border", outer); + + + gtk_widget_style_get(w, "inner_size", &tb, NULL); + + if(tb) { + *inner = *tb; + g_free(tb); + } else { + inner->left = 64; + inner->right = 64; + inner->top = 12; + inner->bottom = 2; + } + + if(inner->left < 2) inner->left = 2; + if(inner->right < 2) inner->right = 2; + if(inner->top < 2) inner->top = 2; +} + + /* calculate RGB color & emit signal */ +static void internal_invoke_color_changed(HildonColorChooserHSV *sel) +{ + HildonColorChooser *parent_sel = HILDON_COLOR_CHOOSER(sel); + GdkVisual *system_visual = gdk_visual_get_system(); + unsigned long rgb[3], rgb2[3]; + + + inline_h2rgb(sel->currhue, rgb); + + rgb2[0] = 0xffffff - rgb[0]; + rgb2[1] = 0xffffff - rgb[1]; + rgb2[2] = 0xffffff - rgb[2]; + + + parent_sel->color.red = ((rgb[0] >> 8) + ((rgb2[0] >> 8) * (0xffff - sel->currsat) / 0xffff)) * sel->currval / 0xffff; + parent_sel->color.green = ((rgb[1] >> 8) + ((rgb2[1] >> 8) * (0xffff - sel->currsat) / 0xffff)) * sel->currval / 0xffff; + parent_sel->color.blue = ((rgb[2] >> 8) + ((rgb2[2] >> 8) * (0xffff - sel->currsat) / 0xffff)) * sel->currval / 0xffff; + + parent_sel->color.pixel = ((parent_sel->color.red >> (16 - system_visual->red_prec)) << system_visual->red_shift) | + ((parent_sel->color.green >> (16 - system_visual->green_prec)) << system_visual->green_shift) | + ((parent_sel->color.blue >> (16 - system_visual->blue_prec)) << system_visual->blue_shift); + + + hildon_color_chooser_emit_color_changed(HILDON_COLOR_CHOOSER(sel)); +} + + /* do the RGB -> HSV conversion here, not so time critical */ +static void hildon_color_chooser_hsv_set_color(HildonColorChooser *sel, GdkColor *color) +{ + HildonColorChooserHSV *sel_hsv = HILDON_COLOR_CHOOSER_HSV(sel); + unsigned short hue, sat, val; + unsigned long min, max; + signed long tmp, diff; + + /* ugly nesting */ + min = MIN(MIN(color->red, color->green), color->blue); + max = MAX(MAX(color->red, color->green), color->blue); + diff = max - min; + + + val = max; + + if(val > 0 && diff != 0) { + sat = (diff * 0x0000ffff) / max; + + if(color->red == max) { + tmp = (signed)color->green - (signed)color->blue; + tmp *= 10922; + tmp /= diff; + if(tmp < 0) { + tmp += 65532; + } + hue = tmp; + } else if(color->green == max) { + hue = (((signed long)color->blue - (signed long)color->red)*10922 / diff) + 21844; + } else { + hue = (((signed long)color->red - (signed long)color->green)*10922 / diff) + 43688; + } + } else { + hue = 0; + sat = 0; + } + + + sel_hsv->currhue = hue; + sel_hsv->currsat = sat; + sel_hsv->currval = val; + + + inline_limited_expose(sel_hsv); +} + + +#define FULL_COLOR 0x00ffffff +inline void inline_h2rgb(unsigned short hue, unsigned long *rgb) +{ + unsigned short hue_rotation, hue_value; + + hue_rotation = hue / 10922; + hue_value = hue % 10922; + + + switch(hue_rotation) { + case 0: + case 6: + rgb[0] = FULL_COLOR; + rgb[1] = hue_value * 6*256; + rgb[2] = 0; + break; + case 1: + rgb[0] = FULL_COLOR - (hue_value * 6*256); + rgb[1] = FULL_COLOR; + rgb[2] = 0; + break; + case 2: + rgb[0] = 0; + rgb[1] = FULL_COLOR; + rgb[2] = hue_value * 6*256; + break; + case 3: + rgb[0] = 0; + rgb[1] = FULL_COLOR - (hue_value * 6*256); + rgb[2] = FULL_COLOR; + break; + case 4: + rgb[0] = hue_value * 6*256; + rgb[1] = 0; + rgb[2] = FULL_COLOR; + break; + case 5: + rgb[0] = FULL_COLOR; + rgb[1] = 0; + rgb[2] = FULL_COLOR - (hue_value * 6*256); + break; + default: + rgb[0] = 0; + rgb[1] = 0; + rgb[2] = 0; + break; + } +} + +#define FULL_COLOR8 0xff +static void intern_h2rgb8(unsigned short hue, unsigned char *rgb) +{ + unsigned short hue_rotation, hue_value; + + hue >>= 8; + hue_rotation = hue / 42; + hue_value = hue % 42; + + + switch(hue_rotation) { + case 0: + case 6: + rgb[0] = FULL_COLOR8; + rgb[1] = hue_value * 6; + rgb[2] = 0; + break; + case 1: + rgb[0] = FULL_COLOR8 - (hue_value * 6); + rgb[1] = FULL_COLOR8; + rgb[2] = 0; + break; + case 2: + rgb[0] = 0; + rgb[1] = FULL_COLOR8; + rgb[2] = hue_value * 6; + break; + case 3: + rgb[0] = 0; + rgb[1] = FULL_COLOR8 - (hue_value * 6); + rgb[2] = FULL_COLOR8; + break; + case 4: + rgb[0] = hue_value * 6; + rgb[1] = 0; + rgb[2] = FULL_COLOR8; + break; + case 5: + rgb[0] = FULL_COLOR8; + rgb[1] = 0; + rgb[2] = FULL_COLOR8 - (hue_value * 6); + break; + default: + rgb[0] = 0; + rgb[1] = 0; + rgb[2] = 0; + break; + } +} + + + /* optimization: do not ask hue for each round but have bilinear vectors */ + /* rethink: benefits from handling data 8 bit? (no shift round) */ +inline void inline_draw_hue_bar(GtkWidget *widget, int x, int y, int w, int h, int sy, int sh) +{ + HildonColorChooserHSV *sel = HILDON_COLOR_CHOOSER_HSV(widget); + unsigned short hvec, hcurr; + unsigned char *buf, *ptr, tmp[3]; + int i, j, tmpy; + + + if(w <= 0 || h <= 0) { + return; + } + + buf = (unsigned char *)g_malloc(w*h*3); + + hvec = 65535/sh; + hcurr = hvec * (y - sy); + + ptr = buf; + + + for(i = 0; i < h; i++) { + intern_h2rgb8(hcurr, tmp); + + for(j = 0; j < w; j++) { + ptr[0] = tmp[0]; + ptr[1] = tmp[1]; + ptr[2] = tmp[2]; + ptr += 3; + } + + hcurr += hvec; + } + + + gdk_draw_rgb_image(widget->parent->window, widget->style->fg_gc[0], x, y, w, h, GDK_RGB_DITHER_NONE, buf, w*3); + + tmpy = sel->hba.y + (sel->currhue * sel->hba.height / 0xffff); + gdk_draw_line(widget->parent->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], sel->hba.x, tmpy, sel->hba.x + sel->hba.width - 1, tmpy); + + if((((sel->currhue * sel->hba.height) & 0xffff) > 0x8000) && (tmpy < (sel->hba.y + sel->hba.height))) { + gdk_draw_line(widget->parent->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], sel->hba.x, tmpy+1, sel->hba.x + sel->hba.width - 1, tmpy+1); + } else if(tmpy > sel->hba.y) { + gdk_draw_line(widget->parent->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], sel->hba.x, tmpy-1, sel->hba.x + sel->hba.width - 1, tmpy-1); + } + + + g_free(buf); +} + +inline void inline_draw_hue_bar_dimmed(GtkWidget *widget, int x, int y, int w, int h, int sy, int sh) +{ + HildonColorChooserHSV *sel = HILDON_COLOR_CHOOSER_HSV(widget); + + + if(w <= 0 || h <= 0) { + return; + } + + /* We need to create (and cache) the pixbuf if we don't + * have it yet */ + if (sel->dimmed_bar == NULL) { + int i, j; + unsigned short hvec, hcurr, avg; + unsigned char *buf, *ptr, tmp[3]; + buf = (unsigned char *)g_malloc(w*h*3); + + hvec = 65535/sh; + hcurr = hvec * (y - sy); + + ptr = buf; + + + for(i = 0; i < h; i++) { + intern_h2rgb8(hcurr, tmp); + + for(j = 0; j < w; j++) { + avg = ((unsigned short)tmp[0]*3 + (unsigned short)tmp[1]*2 + (unsigned short)tmp[2])/6; + ptr[0] = ((((i % 2) + j) % 2) == 0) ? MIN ((avg * 0.7) + 180, 255) : MIN ((avg * 0.7) + 120, 255); + ptr[1] = ((((i % 2) + j) % 2) == 0) ? MIN ((avg * 0.7) + 180, 255) : MIN ((avg * 0.7) + 120, 255); + ptr[2] = ((((i % 2) + j) % 2) == 0) ? MIN ((avg * 0.7) + 180, 255) : MIN ((avg * 0.7) + 120, 255); + ptr += 3; + } + + hcurr += hvec; + } + + sel->dimmed_bar = gdk_pixbuf_new_from_data (buf, GDK_COLORSPACE_RGB, FALSE, 8, w, h, w * 3, g_free, buf); + } + + gdk_draw_pixbuf (widget->parent->window, widget->style->fg_gc [0], sel->dimmed_bar, 0, 0, x, y, w, h, GDK_RGB_DITHER_NONE, 0, 0); +} + + +inline void inline_draw_crosshair(unsigned char *buf, int x, int y, int w, int h) +{ + int i, j, sx, sy; + + /* bad "clipping", clip the loop to save cpu */ + for(i = 0; i < 8; i++) { + for(j = 0; j < 8; j++) { + sx = j + x; sy = i + y; + + if(sx >= 0 && sx < w && sy >= 0 && sy < h) { + if(crosshair[j + 8*i]) { + if(crosshair[j + 8*i] & 0x1) { + buf[(sx)*3+(sy)*w*3+0] = 255; + buf[(sx)*3+(sy)*w*3+1] = 255; + buf[(sx)*3+(sy)*w*3+2] = 255; + } else { + buf[(sx)*3+(sy)*w*3+0] = 0; + buf[(sx)*3+(sy)*w*3+1] = 0; + buf[(sx)*3+(sy)*w*3+2] = 0; + } + } + } + } + } +} + + +inline void inline_draw_sv_plane(HildonColorChooserHSV *sel, int x, int y, int w, int h) +{ + GtkWidget *widget = GTK_WIDGET(sel); + unsigned char *buf, *ptr; + unsigned long rgbx[3] = { 0x00ffffff, 0x00ffffff, 0x00ffffff }, rgbtmp[3]; + signed long rgby[3]; + int tmp = sel->spa.width*sel->spa.height, i, j; + + + if(w <= 0 || h <= 0) { + return; + } + + + buf = (unsigned char *)g_malloc(w*h*3); + + ptr = buf; + + + inline_h2rgb(sel->currhue, rgbtmp); + + rgby[0] = rgbtmp[0] - rgbx[0]; + rgby[1] = rgbtmp[1] - rgbx[1]; + rgby[2] = rgbtmp[2] - rgbx[2]; + + rgbx[0] /= sel->spa.width; + rgbx[1] /= sel->spa.width; + rgbx[2] /= sel->spa.width; + + rgby[0] /= tmp; + rgby[1] /= tmp; + rgby[2] /= tmp; + + + rgbx[0] += (y - sel->spa.y)*rgby[0]; + rgbx[1] += (y - sel->spa.y)*rgby[1]; + rgbx[2] += (y - sel->spa.y)*rgby[2]; + + + for(i = 0; i < h; i++) { + rgbtmp[0] = rgbx[0] * (x - sel->spa.x); + rgbtmp[1] = rgbx[1] * (x - sel->spa.x); + rgbtmp[2] = rgbx[2] * (x - sel->spa.x); + + for(j = 0; j < w; j++) { + ptr[0] = rgbtmp[0] >> 16; + ptr[1] = rgbtmp[1] >> 16; + ptr[2] = rgbtmp[2] >> 16; + rgbtmp[0] += rgbx[0]; + rgbtmp[1] += rgbx[1]; + rgbtmp[2] += rgbx[2]; + ptr += 3; + } + + rgbx[0] += rgby[0]; + rgbx[1] += rgby[1]; + rgbx[2] += rgby[2]; + } + + + inline_draw_crosshair(buf, (sel->spa.width * sel->currval / 0xffff) - x + sel->spa.x - 4, (sel->spa.height * sel->currsat / 0xffff) - y + sel->spa.y - 4, w, h); + + + gdk_draw_rgb_image(widget->parent->window, widget->style->fg_gc[0], x, y, w, h, GDK_RGB_DITHER_NONE, buf, w*3); + + + g_free(buf); +} + +inline void inline_draw_sv_plane_dimmed(HildonColorChooserHSV *sel, int x, int y, int w, int h) +{ + GtkWidget *widget = GTK_WIDGET(sel); + + if(w <= 0 || h <= 0) { + return; + } + + /* We need to create (and cache) the pixbuf if we don't + * have it yet */ + if (sel->dimmed_plane == NULL) { + unsigned char *buf, *ptr; + unsigned long rgbx[3] = { 0x00ffffff, 0x00ffffff, 0x00ffffff }, rgbtmp[3]; + unsigned long avg; + signed long rgby[3]; + int tmp = sel->spa.width*sel->spa.height, i, j; + + buf = (unsigned char *)g_malloc(w*h*3); + + ptr = buf; + + /* possibe optimization: as we are drawing grayscale plane, there might + be some simpler algorithm to do this*/ + rgbtmp[0] = 0x00ffffff; + rgbtmp[1] = 0x00000000; + rgbtmp[2] = 0x00000000; + + rgby[0] = rgbtmp[0] - rgbx[0]; + rgby[1] = rgbtmp[1] - rgbx[1]; + rgby[2] = rgbtmp[2] - rgbx[2]; + + rgbx[0] /= sel->spa.width; + rgbx[1] /= sel->spa.width; + rgbx[2] /= sel->spa.width; + + rgby[0] /= tmp; + rgby[1] /= tmp; + rgby[2] /= tmp; + + rgbx[0] += (y - sel->spa.y)*rgby[0]; + rgbx[1] += (y - sel->spa.y)*rgby[1]; + rgbx[2] += (y - sel->spa.y)*rgby[2]; + + for(i = 0; i < h; i++) { + rgbtmp[0] = rgbx[0] * (x - sel->spa.x); + rgbtmp[1] = rgbx[1] * (x - sel->spa.x); + rgbtmp[2] = rgbx[2] * (x - sel->spa.x); + + for(j = 0; j < w; j++) { + avg = (rgbtmp[0] + rgbtmp[1] + rgbtmp[2])/3; + avg >>= 16; + ptr[0] = ((((i % 2) + j) % 2) == 0) ? MIN ((avg * 0.7) + 180, 255) : MIN ((avg * 0.7) + 120, 255); + ptr[1] = ((((i % 2) + j) % 2) == 0) ? MIN ((avg * 0.7) + 180, 255) : MIN ((avg * 0.7) + 120, 255); + ptr[2] = ((((i % 2) + j) % 2) == 0) ? MIN ((avg * 0.7) + 180, 255) : MIN ((avg * 0.7) + 120, 255); + rgbtmp[0] += rgbx[0]; + rgbtmp[1] += rgbx[1]; + rgbtmp[2] += rgbx[2]; + ptr += 3; + } + + rgbx[0] += rgby[0]; + rgbx[1] += rgby[1]; + rgbx[2] += rgby[2]; + } + + sel->dimmed_plane = gdk_pixbuf_new_from_data (buf, GDK_COLORSPACE_RGB, FALSE, 8, w, h, w * 3, g_free, buf); + } + + gdk_draw_pixbuf (widget->parent->window, widget->style->fg_gc [0], sel->dimmed_plane, 0, 0, x, y, w, h, GDK_RGB_DITHER_NONE, 0, 0); +} + + +static gboolean hildon_color_chooser_hsv_expose_timer(gpointer data) +{ + HildonColorChooserHSV *sel = HILDON_COLOR_CHOOSER_HSV(data); + + + if(sel->expose_info.expose_queued) { + gtk_widget_queue_draw(GTK_WIDGET(data)); + } + + + return FALSE; +} diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..badc28b --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,216 @@ +INCLUDES = $(GTK_CFLAGS) $(GCONF_CFLAGS) \ + $(ESD_CFLAGS) $(LIBMB_CFLAGS) -DLOCALEDIR=\"$(localedir)\" -I$(srcdir)/.. + +lib_LTLIBRARIES = libhildonwidgets.la + +MAINTAINERCLEANFILES = \ + Makefile.in hildon-libs-enum-types.c hildon-libs-enum-types.h + +EXTRA_DIST = hildon-marshalers.list + +libhildonwidgets_la_LDFLAGS = -version-info 5:0:5 + +libhildonwidgets_la_LIBADD = $(GTK_LIBS) $(GCONF_LIBS) \ + $(ESD_LIBS) $(LIBMB_LIBS) + +libhildonwidgets_la_SOURCES = \ + hildon-marshalers.c \ + hildon-marshalers.h \ + hildon-composite-widget.c \ + hildon-composite-widget.h \ + hildon-controlbar.c \ + hildon-controlbar.h \ + hildon-seekbar.c \ + hildon-seekbar.h \ + hildon-color-selector.c \ + hildon-color-selector.h \ + hildon-note.c \ + hildon-note.h \ + hildon-volumebar.c \ + hildon-volumebar.h \ + hildon-volumebar-range.c \ + hildon-volumebar-range.h \ + hildon-volumebar-private.h \ + hildon-hvolumebar.c \ + hildon-hvolumebar.h \ + hildon-vvolumebar.c \ + hildon-vvolumebar.h \ + hildon-dialoghelp.c \ + hildon-dialoghelp.h \ + hildon-calendar-popup.c \ + hildon-calendar-popup.h \ + hildon-date-editor.c \ + hildon-date-editor.h \ + hildon-time-editor.c \ + hildon-time-editor.h \ + hildon-private.h \ + hildon-time-picker.c \ + hildon-time-picker.h \ + hildon-weekday-picker.c \ + hildon-weekday-picker.h \ + hildon-telephone-editor.c \ + hildon-telephone-editor.h \ + hildon-number-editor.c \ + hildon-number-editor.h \ + hildon-range-editor.c \ + hildon-range-editor.h \ + hildon-get-password-dialog.c \ + hildon-get-password-dialog.h \ + hildon-set-password-dialog.c \ + hildon-set-password-dialog.h \ + hildon-sort-dialog.c \ + hildon-sort-dialog.h \ + hildon-add-home-dialog.c \ + hildon-add-home-dialog.h \ + hildon-font-selection-dialog.c \ + hildon-font-selection-dialog.h \ + hildon-grid.c \ + hildon-grid.h \ + hildon-grid-item.c \ + hildon-grid-item.h \ + hildon-grid-item-private.h \ + hildon-file-handling-note.c \ + hildon-file-handling-note.h \ + hildon-name-password-dialog.c \ + hildon-name-password-dialog.h \ + hildon-scroll-area.c \ + hildon-scroll-area.h \ + hildon-wizard-dialog.c \ + hildon-wizard-dialog.h \ + hildon-color-popup.c \ + hildon-color-popup.h \ + hildon-color-button.c \ + hildon-color-button.h \ + hildon-system-sound.c \ + hildon-system-sound.h \ + hildon-app.c \ + hildon-app.h \ + hildon-defines.c \ + hildon-defines.h \ + hildon-appview.c \ + hildon-appview.h \ + hildon-find-toolbar.c \ + hildon-find-toolbar.h \ + gtk-infoprint.c \ + gtk-infoprint.h \ + hildon-banner.c \ + hildon-banner.h \ + hildon-input-mode-hint.h \ + hildon-app-private.h \ + hildon-caption.c \ + hildon-caption.h \ + hildon-window.c \ + hildon-window.h \ + hildon-window-private.h \ + hildon-program.c \ + hildon-program.h \ + hildon-code-dialog.c \ + hildon-code-dialog.h \ + hildon-plugin-widget.c \ + hildon-plugin-widget.h \ + hildon-color-chooser.c \ + hildon-color-chooser.h \ + hildon-color-chooser-dialog.c \ + hildon-color-chooser-dialog.h \ + hildon-color-chooser-button.c \ + hildon-color-chooser-button.h \ + $(hildonlibs_built_headers) \ + $(hildonlibs_built_cfiles) + + +hildon-marshalers.h: hildon-marshalers.list + glib-genmarshal --prefix _hildon_marshal --header \ + hildon-marshalers.list >hildon-marshalers.h + +hildon-marshalers.c: hildon-marshalers.list hildon-marshalers.h + echo '#include ' >hildon-marshalers.c + glib-genmarshal --prefix _hildon_marshal --body \ + hildon-marshalers.list >>hildon-marshalers.c + +hildonwidgetsincludeinstdir=$(includedir)/hildon-widgets +hildonwidgetsincludeinst_DATA = \ + hildon-controlbar.h \ + hildon-note.h \ + hildon-seekbar.h \ + hildon-color-selector.h \ + hildon-volumebar.h \ + hildon-hvolumebar.h \ + hildon-vvolumebar.h \ + hildon-dialoghelp.h \ + hildon-calendar-popup.h \ + hildon-date-editor.h \ + hildon-time-editor.h \ + hildon-time-picker.h \ + hildon-weekday-picker.h \ + hildon-telephone-editor.h \ + hildon-number-editor.h \ + hildon-range-editor.h \ + hildon-get-password-dialog.h \ + hildon-set-password-dialog.h \ + hildon-sort-dialog.h \ + hildon-add-home-dialog.h \ + hildon-font-selection-dialog.h \ + hildon-grid.h \ + hildon-grid-item.h \ + hildon-file-handling-note.h \ + hildon-name-password-dialog.h \ + hildon-scroll-area.h \ + hildon-wizard-dialog.h \ + hildon-color-popup.h \ + hildon-color-button.h \ + hildon-system-sound.h \ + hildon-app.h \ + hildon-defines.h \ + hildon-appview.h \ + hildon-find-toolbar.h \ + gtk-infoprint.h \ + hildon-banner.h \ + hildon-input-mode-hint.h \ + hildon-app-private.h \ + hildon-caption.h \ + hildon-window.h \ + hildon-program.h \ + hildon-window-private.h \ + hildon-code-dialog.h \ + hildon-plugin-widget.h \ + hildon-color-chooser.h \ + hildon-color-chooser-dialog.h \ + hildon-color-chooser-button.h + +headers_to_scan_for_enums = $(hildonwidgetsincludeinst_DATA) + +# Generate the enums source code, with glib-mkenums: +# This is based on the same Makefile.am stuff in pango: +hildonlibs_built_headers = hildon-libs-enum-types.h +hildonlibs_built_cfiles = hildon-libs-enum-types.c + +# Don't build the library until we have built the header that it needs: +$(OBJECTS) $(libhildonwidgets_la_OBJECTS): $(hildonlibs_built_headers) + +hildon-libs-enum-types.h: @REBUILD@ $(headers_to_scan_for_enums) Makefile + (cd $(srcdir) && glib-mkenums \ + --fhead "#ifndef __HILDON_LIBS_ENUM_TYPES_H__\n#define __HILDON_LIBS_ENUM_TYPES_H__\n\n#include \n\nG_BEGIN_DECLS\n" \ + --fprod "/* enumerations from \"@filename@\" */\n" \ + --vhead "GType @enum_name@_get_type (void);\n#define HILDON_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \ + --ftail "G_END_DECLS\n\n#endif /* __HILDON_LIBS_ENUM_TYPES_H__ */" \ + $(headers_to_scan_for_enums)) > $@ + +#FIXME: This would be shorter if there was a hildon-libs.h file: +hildon-libs-enum-types.c: @REBUILD@ $(headers_to_scan_for_enums) Makefile + (cd $(srcdir) && glib-mkenums \ + --fhead "#include \n" \ + --fhead "#include \n" \ + --fhead "#include \n" \ + --fhead "#include \n" \ + --fhead "#include \n" \ + --fhead "#include \n" \ + --fhead "#include \n" \ + --fhead "#include \n" \ + --fhead "#include \n" \ + --fhead '#include "hildon-libs-enum-types.h"\n' \ + --fhead "#include " \ + --fprod "\n/* enumerations from \"@filename@\" */" \ + --vhead "GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {" \ + --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \ + --vtail " { 0, NULL, NULL }\n };\n etype = g_@type@_register_static (\"@EnumName@\", values);\n }\n return etype;\n}\n" \ + $(headers_to_scan_for_enums)) > $@ diff --git a/src/gtk-infoprint.c b/src/gtk-infoprint.c new file mode 100644 index 0000000..0f9be2a --- /dev/null +++ b/src/gtk-infoprint.c @@ -0,0 +1,341 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:gtk-infoprint + * @short_description: deprecated widget. Use #HildonBanner instead + * + * This widget is deprecated. Use #HildonBanner instead + */ + +#include "gtk-infoprint.h" +#include "hildon-banner.h" + +/* This is a helper function that searches the banner for + given window. This is needed to provide backwards + compatibility. */ +static GtkWidget *find_banner_for_parent(GtkWindow *parent) +{ + GList *toplevels, *iter; + GtkWidget *result = NULL; + gboolean is_timed; + + toplevels = gtk_window_list_toplevels(); + for (iter = toplevels; iter; iter = iter->next) + if (HILDON_IS_BANNER(iter->data) && + gtk_window_get_transient_for(GTK_WINDOW(iter->data)) == parent) + { + g_object_get(iter->data, "is-timed", &is_timed, NULL); + + /* We do not want to touch timed infoprints */ + if (!is_timed) { + result = iter->data; + break; + } + } + + g_list_free(toplevels); + return result; +} + +/**************************************************/ +/** Public **/ +/**************************************************/ + +/** + * gtk_infoprint: + * @parent: The transient window for the infoprint. + * @text: The text in infoprint + * + * Opens a new infoprint with @text content. + * + * If parent is %NULL, the infoprint is a system infoprint. + * Normally you should use your application window + * or dialog as a transient parent and avoid passing %NULL. + * + * Deprecated: Use #hildon_banner_show_information instead. + */ +void gtk_infoprint(GtkWindow * parent, const gchar * text) +{ + hildon_banner_show_information((GtkWidget *) parent, NULL, text); +} + +/** + * gtk_infoprint_with_icon_stock: + * @parent: The transient window for the infoprint. + * @text: The text in infoprint + * @stock_id: The stock id of the custom icon + * + * Opens a new infoprint with @text content. + * With this function you can also set a custom icon + * by giving a stock id as last parameter. + * + * If parent is %NULL, the infoprint is a system infoprint. + * Normally you should use your application window + * or dialog as a transient parent and avoid passing %NULL. + * + * Deprecated: Use #hildon_banner_show_information instead. + */ +void +gtk_infoprint_with_icon_stock(GtkWindow * parent, + const gchar * text, const gchar * stock_id) +{ + hildon_banner_show_information((GtkWidget *) parent, NULL, text); +} + +/** + * gtk_infoprint_with_icon_name: + * @parent: The transient window for the infoprint. + * @text: The text in infoprint + * @icon_name: The name of the icon + * + * Opens a new infoprint with @text content. + * With this function you can also set a custom icon + * by giving a icon name as last parameter. + * + * If parent is %NULL, the infoprint is a system infoprint. + * Normally you should use your application window + * or dialog as a transient parent and avoid passing %NULL. + * + * Deprecated: Use #hildon_banner_show_information instead. + */ +void +gtk_infoprint_with_icon_name(GtkWindow * parent, + const gchar * text, const gchar * icon_name) +{ + hildon_banner_show_information((GtkWidget *) parent, icon_name, text); +} + +/** + * gtk_infoprintf: + * @parent: The transient window for the infoprint. + * @format: Format of the text. + * @Varargs: List of parameters. + * + * Opens a new infoprint with @text printf-style formatting + * string and comma-separated list of parameters. + * + * If parent is %NULL, the infoprint is a system infoprint. + * This version of infoprint allow you to make printf-like formatting + * easily. + * + * Deprecated: Use #hildon_banner_show_information instead. + */ +void gtk_infoprintf(GtkWindow * parent, const gchar * format, ...) +{ + gchar *message; + va_list args; + + va_start(args, format); + message = g_strdup_vprintf(format, args); + va_end(args); + + gtk_infoprint(parent, message); + + g_free(message); +} + +/** + * gtk_infoprint_temporarily_disable_wrap: + * + * Will disable wrapping for the next shown infoprint. This only + * affects next infoprint shown in this application. + * + * Currently it does nothing. + * + * Deprecated: + */ +void gtk_infoprint_temporarily_disable_wrap(void) +{ +} + +/** + * gtk_confirmation_banner: + * @parent: The transient window for the confirmation banner. + * @text: The text in confirmation banner + * @stock_id: The stock id of the custom icon + * + * Opens a new confirmation banner with @text content. + * With this function you can also set a custom icon + * by giving a stock id as last parameter. + * + * If parent is %NULL, the banner is a system banner. + * Normally you should use your application window + * or dialog as a transient parent and avoid passing %NULL. + * + * This function is otherwise similar to + * gtk_infoprint_with_icon_stock except in always restricts + * the text to one line and the font is emphasized. + * + * Deprecated: Use #hildon_banner_show_information instead. + */ +void +gtk_confirmation_banner(GtkWindow * parent, const gchar * text, + const gchar * stock_id) +{ + gchar *s; + s = g_strdup_printf("%s", text); + + hildon_banner_show_information_with_markup((GtkWidget *) parent, NULL, s); + + g_free(s); +} + +/** + * gtk_confirmation_banner_with_icon_name: + * @parent: The transient window for the confirmation banner. + * @text: The text in confirmation banner + * @icon_name: The name of the custom icon in icon theme + * + * Opens a new confirmation banner with @text content. + * With this function you can also set a custom icon + * by giving a icon theme's icon name as last parameter. + * + * If parent is %NULL, the banner is a system banner. + * Normally you should use your application window + * or dialog as a transient parent and avoid passing %NULL. + * + * This function is otherwise similar to + * gtk_infoprint_with_icon_name except in always restricts + * the text to one line and the font is emphasized. + * + * Deprecated: Use #hildon_banner_show_information instead. + */ +void +gtk_confirmation_banner_with_icon_name(GtkWindow * parent, const gchar * text, + const gchar * icon_name) +{ + gchar *s; + s = g_strdup_printf("%s", text); + + hildon_banner_show_information_with_markup((GtkWidget *) parent, icon_name, s); + + g_free(s); +} + +/** + * gtk_banner_show_animation: + * @parent: #GtkWindow + * @text: #const gchar * + * + * The @text is the text shown in banner. + * Creates a new banner with the animation. + * + * Deprecated: Use #hildon_banner_show_animation instead. + */ +void gtk_banner_show_animation(GtkWindow * parent, const gchar * text) +{ + (void) hildon_banner_show_animation((GtkWidget *) parent, NULL, text); +} + +/** + * gtk_banner_show_bar + * @parent: #GtkWindow + * @text: #const gchar * + * + * The @text is the text shown in banner. + * Creates a new banner with the progressbar. + * + * Deprecated: Use #hildon_banner_show_progress instead. + */ +void gtk_banner_show_bar(GtkWindow * parent, const gchar * text) +{ + (void) hildon_banner_show_progress((GtkWidget *) parent, NULL, text); +} + +/** + * gtk_banner_set_text + * @parent: #GtkWindow + * @text: #const gchar * + * + * The @text is the text shown in banner. + * Sets the banner text. + * + * Deprecated: Use #hildon_banner_set_text instead. + */ +void gtk_banner_set_text(GtkWindow * parent, const gchar * text) +{ + GtkWidget *banner; + + g_return_if_fail(GTK_IS_WINDOW(parent) || parent == NULL); + + banner = find_banner_for_parent(parent); + if (banner) + hildon_banner_set_text(HILDON_BANNER(banner), text); +} + +/** + * gtk_banner_set_fraction: + * @parent: #GtkWindow + * @fraction: #gdouble + * + * The fraction is the completion of progressbar, + * the scale is from 0.0 to 1.0. + * Sets the amount of fraction the progressbar has. + * + * Deprecated: Use #hildon_banner_set_fraction instead. + */ +void gtk_banner_set_fraction(GtkWindow * parent, gdouble fraction) +{ + GtkWidget *banner; + + g_return_if_fail(GTK_IS_WINDOW(parent) || parent == NULL); + + banner = find_banner_for_parent(parent); + if (banner) + hildon_banner_set_fraction(HILDON_BANNER(banner), fraction); +} + +/** + * gtk_banner_close: + * @parent: #GtkWindow + * + * Destroys the banner + * + * Deprecated: + */ +void gtk_banner_close(GtkWindow * parent) +{ + GtkWidget *banner; + + g_return_if_fail(GTK_IS_WINDOW(parent) || parent == NULL); + + banner = find_banner_for_parent(parent); + if (banner) + gtk_widget_destroy(banner); +} + +/** + * gtk_banner_temporarily_disable_wrap + * + * Will disable wrapping for the next shown banner. This only + * affects next banner shown in this application. + * + * Currently it does nothing. + * + * Deprecated: + **/ +void gtk_banner_temporarily_disable_wrap(void) +{ +} diff --git a/src/gtk-infoprint.h b/src/gtk-infoprint.h new file mode 100644 index 0000000..d97b212 --- /dev/null +++ b/src/gtk-infoprint.h @@ -0,0 +1,52 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __GTK_INFOPRINT_H__ +#define __GTK_INFOPRINT_H__ + +#include + +G_BEGIN_DECLS void gtk_infoprint(GtkWindow * parent, const gchar * text); +void gtk_infoprint_with_icon_stock(GtkWindow * parent, const gchar * text, + const gchar * stock_id); +void gtk_infoprint_with_icon_name(GtkWindow * parent, const gchar * text, + const gchar * icon_name); + +void gtk_infoprintf(GtkWindow * parent, const gchar * format, ...); +void gtk_infoprint_temporarily_disable_wrap(void); + +void gtk_confirmation_banner_with_icon_name(GtkWindow * parent, const gchar * text, + const gchar * icon_name); +void gtk_confirmation_banner(GtkWindow * parent, const gchar * text, + const gchar * stock_id); + +void gtk_banner_show_animation(GtkWindow * parent, const gchar * text); +void gtk_banner_show_bar(GtkWindow * parent, const gchar * text); +void gtk_banner_set_text(GtkWindow * parent, const gchar * text); +void gtk_banner_set_fraction(GtkWindow * parent, gdouble fraction); +void gtk_banner_close(GtkWindow * parent); +void gtk_banner_temporarily_disable_wrap(void); + +G_END_DECLS +#endif /* __GTK_INFOPRINT_H__ */ diff --git a/src/hildon-add-home-dialog.c b/src/hildon-add-home-dialog.c new file mode 100644 index 0000000..9824677 --- /dev/null +++ b/src/hildon-add-home-dialog.c @@ -0,0 +1,525 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "hildon-add-home-dialog.h" +#include + +#define _(String) dgettext(PACKAGE, String) +#define MAX_ERR_MSG 256 +#define HILDON_ADD_HOME_DIALOG_WIDTH 370 +#define HILDON_ADD_HOME_DIALOG_HEIGHT 100 +#define HILDON_MAX_TITLE_LENGTH 256 +#define HILDON_HOME_MAX_SHORTCUT_LEN 255 + +#define HILDON_ADD_HOME_DIALOG_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_ADD_HOME_DIALOG, \ + HildonAddHomeDialogPrivate)); + +typedef struct _HildonAddHomeDialogPrivate HildonAddHomeDialogPrivate; + +static GtkDialogClass *parent_class; + +static const gchar *hildon_add_home_dialog_get_old_name(HildonAddHomeDialog * dialog); +static void hildon_add_home_dialog_set_old_name(HildonAddHomeDialog * dialog, const gchar* name); +static void hildon_add_home_dialog_set_new_name(HildonAddHomeDialog * dialog, const gchar* name); +static void hildon_add_home_dialog_create_widgets(HildonAddHomeDialog * dialog, gboolean new_isrename); + +static void +hildon_add_home_dialog_get_property(GObject * object, + guint prop_id, + GValue * value, + GParamSpec * pspec); +static void +hildon_add_home_dialog_set_property(GObject * object, + guint prop_id, + const GValue * value, + GParamSpec * pspec); +static void +hildon_add_home_dialog_class_init(HildonAddHomeDialogClass * class); +static void hildon_add_home_dialog_init(HildonAddHomeDialog * dialog); + +/* private struct */ + +struct _HildonAddHomeDialogPrivate { + GtkWidget *desc_label; + GtkWidget *name_entry; /* Used when isrename */ + GtkWidget *name_label; /* Used when !isrename */ + GtkWidget *caption_name_entry; /* Used when isrename */ + GtkWidget *new_name_entry; + GtkWidget *caption_new_name_entry; + GtkSizeGroup *size_group; + GtkWidget *okButton; + GtkWidget *cancelButton; + gboolean isrename; +}; + +enum +{ + PROP_0, + + PROP_NAME, + PROP_NEW_NAME, +}; + +/* Private functions */ + +static void +hildon_add_home_dialog_class_init(HildonAddHomeDialogClass * klass) +{ + GObjectClass * gobject_class = G_OBJECT_CLASS(klass); + parent_class = g_type_class_peek_parent(klass); + + gobject_class->set_property = hildon_add_home_dialog_set_property; + gobject_class->get_property = hildon_add_home_dialog_get_property; + + /** + * HildonAddHomeDialog:name + * + * The name + */ + g_object_class_install_property(gobject_class, + PROP_NAME, + g_param_spec_string ("name", + ("Name"), + ("The name."), + NULL, + G_PARAM_READWRITE)); + + /** + * HildonAddHomeDialog:new_name + * + * The new name + */ + g_object_class_install_property(gobject_class, + PROP_NEW_NAME, + g_param_spec_string ("new_name", + ("New Name"), + ("The new name."), + NULL, + G_PARAM_READWRITE)); + + g_type_class_add_private(klass, sizeof(HildonAddHomeDialogPrivate)); +} + +static void hildon_add_home_dialog_init(HildonAddHomeDialog * dialog) +{ + HildonAddHomeDialogPrivate *priv; + + gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); + + priv = HILDON_ADD_HOME_DIALOG_GET_PRIVATE(dialog); + priv->name_entry = NULL; + priv->name_label = NULL; + priv->caption_name_entry = NULL; + priv->new_name_entry = NULL; + priv->isrename = FALSE; + + priv->okButton = gtk_dialog_add_button(GTK_DIALOG(dialog), + "addtoHome_button_ok", + GTK_RESPONSE_OK); + priv->cancelButton = gtk_dialog_add_button(GTK_DIALOG(dialog), + "addtoHome_button_cancel", + GTK_RESPONSE_CANCEL); + + gtk_window_resize(GTK_WINDOW(dialog), + HILDON_ADD_HOME_DIALOG_WIDTH, + HILDON_ADD_HOME_DIALOG_HEIGHT); + + gtk_widget_show_all(GTK_DIALOG(dialog)->vbox); + gtk_widget_show_all(GTK_DIALOG(dialog)->action_area); + + priv->size_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); + + + /* add description text (only shown when isrename==true */ + priv->desc_label = gtk_label_new(_("ckdg_ib_link_exists")); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), + priv->desc_label, FALSE, FALSE, 0); + + /* We don't use the hildon_caption_new() C convenience function, because it demands a non-NULL child widget (via gtk_container_add()). */ + priv->caption_name_entry = GTK_WIDGET( g_object_new( HILDON_TYPE_CAPTION, "size_group", priv->size_group, "label", "addtoHome_editor_caption", "status", HILDON_CAPTION_OPTIONAL, NULL) ); + gtk_widget_show(priv->caption_name_entry); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), priv->caption_name_entry, + FALSE, FALSE, 0); + + + gtk_widget_show_all(GTK_DIALOG(dialog)->action_area); +} + +/* Public functions */ + +GType hildon_add_home_dialog_get_type(void) +{ + static GType dialog_type = 0; + + if (!dialog_type) { + static const GTypeInfo dialog_info = { + sizeof(HildonAddHomeDialogClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_add_home_dialog_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonAddHomeDialog), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_add_home_dialog_init + }; + + dialog_type = g_type_register_static(GTK_TYPE_DIALOG, + "HildonAddHomeDialog", + &dialog_info, 0); + } + return dialog_type; +} + +static void +hildon_add_home_dialog_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + HildonAddHomeDialog * dialog = HILDON_ADD_HOME_DIALOG(object); + HildonAddHomeDialogPrivate *priv = HILDON_ADD_HOME_DIALOG_GET_PRIVATE(dialog); + + switch(prop_id) + { + case PROP_NAME: + { + const gchar* name = NULL; + if(priv->isrename && priv->name_label) + name = gtk_entry_get_text(GTK_ENTRY(priv->name_label)); + else if(!(priv->isrename) && priv->name_entry) + name = gtk_entry_get_text(GTK_ENTRY(priv->name_entry)); + + g_value_set_string (value, name); + break; + } + case PROP_NEW_NAME: + { + const gchar* new_name = NULL; + if(priv->isrename && priv->new_name_entry) + new_name = gtk_entry_get_text(GTK_ENTRY(priv->new_name_entry)); + + g_value_set_string (value, new_name); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +hildon_add_home_dialog_set_window_title (HildonAddHomeDialog * dialog) +{ + HildonAddHomeDialogPrivate *priv; + + g_return_if_fail(HILDON_IS_ADD_HOME_DIALOG(dialog)); + priv = HILDON_ADD_HOME_DIALOG_GET_PRIVATE(dialog); + + /* Set up the window title */ + if (priv->isrename) + gtk_window_set_title(GTK_WINDOW(dialog), _("ckdg_ti_rename_link")); + else + gtk_window_set_title(GTK_WINDOW(dialog), "addtoHome_dialog_title"); +} + + +static void +hildon_add_home_dialog_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + HildonAddHomeDialog * dialog = HILDON_ADD_HOME_DIALOG(object); + HildonAddHomeDialogPrivate *priv; + + g_return_if_fail(HILDON_IS_ADD_HOME_DIALOG(dialog)); + priv = HILDON_ADD_HOME_DIALOG_GET_PRIVATE(dialog); + + switch (prop_id) + { + case PROP_NAME: + hildon_add_home_dialog_set_old_name (dialog, g_value_get_string (value)); + break; + case PROP_NEW_NAME: + hildon_add_home_dialog_set_new_name (dialog, g_value_get_string (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * hildon_add_home_dialog_new: + * @parent: parent window for the dialog + * @name: name to show in the entry (or label, if @new_name is not NULL) + * @new_name: name to show in the new name entry. If this is not NULL + * the widget acts as a RenameShortcutDialog. + * + * Creates a new Add to Home dialog or Rename Shortcut dialog. + * + * Returns: the new dialog. + */ +GtkWidget *hildon_add_home_dialog_new(GtkWindow * parent, + const gchar * name, + const gchar * new_name) +{ + HildonAddHomeDialog *dialog = + HILDON_ADD_HOME_DIALOG(g_object_new + (HILDON_TYPE_ADD_HOME_DIALOG, "name", name, "new_name", new_name, NULL)); + + if (parent) + gtk_window_set_transient_for(GTK_WINDOW(dialog), parent); + + return GTK_WIDGET(dialog); +} + +/** + * hildon_add_home_dialog_get_name: + * @dialog: the dialog + * + * Returns: the string the user has entered in the entry + */ +const gchar *hildon_add_home_dialog_get_name(HildonAddHomeDialog * dialog) +{ + HildonAddHomeDialogPrivate *priv; + + g_return_val_if_fail(HILDON_IS_ADD_HOME_DIALOG(dialog), NULL); + priv = HILDON_ADD_HOME_DIALOG_GET_PRIVATE(dialog); + + if (priv->isrename && priv->new_name_entry) + return gtk_entry_get_text(GTK_ENTRY(priv->new_name_entry)); + else if(priv->name_entry) + return gtk_entry_get_text(GTK_ENTRY(priv->name_entry)); + else + return NULL; +} + +static const gchar *hildon_add_home_dialog_get_old_name(HildonAddHomeDialog * dialog) +{ + HildonAddHomeDialogPrivate *priv; + + g_return_val_if_fail(HILDON_IS_ADD_HOME_DIALOG(dialog), NULL); + priv = HILDON_ADD_HOME_DIALOG_GET_PRIVATE(dialog); + + if (priv->isrename && priv->name_label) + return gtk_label_get_text(GTK_LABEL(priv->name_label)); + else if(!priv->isrename && priv->name_entry) + return gtk_entry_get_text(GTK_ENTRY(priv->name_entry)); + else + return NULL; +} + +static void hildon_add_home_dialog_set_old_name(HildonAddHomeDialog * dialog, const gchar* name) +{ + HildonAddHomeDialogPrivate *priv; + + g_return_if_fail(HILDON_IS_ADD_HOME_DIALOG(dialog)); + priv = HILDON_ADD_HOME_DIALOG_GET_PRIVATE(dialog); + + hildon_add_home_dialog_create_widgets(dialog, priv->isrename); + + /* Set text in the widgets: */ + if (priv->isrename) + gtk_label_set_text(GTK_LABEL(priv->name_label), name); + else + gtk_entry_set_text(GTK_ENTRY(priv->name_entry), name); +} + +static void hildon_add_home_dialog_set_new_name(HildonAddHomeDialog * dialog, const gchar* new_name) +{ + HildonAddHomeDialogPrivate *priv; + gchar* name = NULL; + gboolean new_isrename = FALSE; + + g_return_if_fail(HILDON_IS_ADD_HOME_DIALOG(dialog)); + priv = HILDON_ADD_HOME_DIALOG_GET_PRIVATE(dialog); + + /* We get the old name, in case we need to set it again in a new widget. */ + name = g_strdup( hildon_add_home_dialog_get_old_name(dialog) ); + new_isrename = (new_name != NULL); + + hildon_add_home_dialog_create_widgets(dialog, new_isrename); + + + /* Set text in the widgets: */ + if(priv->isrename) + { + gtk_entry_set_text(GTK_ENTRY(priv->new_name_entry), new_name); + gtk_label_set_text(GTK_LABEL(priv->name_label), (name) ? name : ""); + } + else + { + gtk_entry_set_text(GTK_ENTRY(priv->name_entry), (name) ? name : ""); + } + + if(name) + g_free(name); +} + +static void hildon_add_home_dialog_create_widgets(HildonAddHomeDialog * dialog, gboolean new_isrename) +{ + HildonAddHomeDialogPrivate *priv; + + g_return_if_fail(HILDON_IS_ADD_HOME_DIALOG(dialog)); + priv = HILDON_ADD_HOME_DIALOG_GET_PRIVATE(dialog); + + /* Create and destroy widgets, depending on the mode. + * Note that we are making a small speed sacrifice (recreating the widgets) + * in exchange for memory (creating all widgets and just hiding the ones we don't use.) + */ + + if(priv->isrename && !new_isrename) + { + /* Remove widgets that were used for isrename mode, + because we don't need them anymore. */ + if(priv->new_name_entry) + { + gtk_widget_destroy(priv->new_name_entry); + priv->new_name_entry = NULL; + } + + if(priv->caption_new_name_entry) + { + gtk_widget_destroy(priv->caption_new_name_entry); + priv->caption_new_name_entry = NULL; + } + + if(priv->name_label) /* A label */ + { + gtk_widget_destroy(priv->name_label); + priv->name_label = NULL; + } + + if(priv->name_entry) /* A box with label inside */ + { + gtk_widget_destroy(priv->name_entry); + priv->name_entry = NULL; + } + } + else if(!priv->isrename && new_isrename) + { + /* Remove widgets that were used only for !isrename mode, + because we don't need them anymore. */ + if(priv->name_entry) /* An entry. */ + { + gtk_widget_destroy(priv->name_entry); + priv->name_entry = NULL; + } + } + + priv->isrename = new_isrename; + + if(priv->isrename) + { + /* Create widgets needed for isrename mode: */ + + /* Create Entry (in a Caption) for the new name, and pack it into the dialog: */ + if(!priv->new_name_entry) + { + priv->new_name_entry = gtk_entry_new(); + gtk_widget_show(priv->new_name_entry); + } + + if(!priv->caption_new_name_entry) + { + priv->caption_new_name_entry = hildon_caption_new(priv->size_group, _("ckdg_fi_rename_name"), + priv->new_name_entry, NULL, + HILDON_CAPTION_OPTIONAL); + gtk_widget_show(priv->caption_new_name_entry); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), GTK_WIDGET(priv->caption_new_name_entry), + FALSE, FALSE, 0); + } + + /* add description text */ + if(priv->desc_label) + gtk_widget_show(priv->desc_label); + + /* Create Label (in a Box) for the existing name: */ + if(!priv->name_entry) + { + priv->name_label = gtk_label_new(NULL); + gtk_widget_show(priv->name_label); + + priv->name_entry = gtk_hbox_new(FALSE, 0); + gtk_widget_show(priv->name_entry); + gtk_box_pack_start(GTK_BOX(priv->name_entry), priv->name_label, FALSE, FALSE, + 0); + gtk_container_add(GTK_CONTAINER(priv->caption_name_entry), GTK_WIDGET(priv->name_entry)); + } + } + else + { + if(priv->desc_label) + gtk_widget_hide(priv->desc_label); + + /* Create widgets needed for !isrename mode: */ + if(!priv->name_entry) + { + priv->name_entry = gtk_entry_new(); + gtk_widget_show(priv->name_entry); + gtk_container_add(GTK_CONTAINER(priv->caption_name_entry), GTK_WIDGET(priv->name_entry)); + } + } + + hildon_add_home_dialog_set_window_title(dialog); + + priv->isrename = new_isrename; +} + +void hildon_add_home_dialog_set_name(HildonAddHomeDialog * dialog, const gchar* name) +{ + HildonAddHomeDialogPrivate *priv; + + g_return_if_fail(HILDON_IS_ADD_HOME_DIALOG(dialog)); + priv = HILDON_ADD_HOME_DIALOG_GET_PRIVATE(dialog); + + hildon_add_home_dialog_create_widgets(dialog, priv->isrename); + + /* Set text in the widgets: */ + if (priv->isrename) + gtk_entry_set_text(GTK_ENTRY(priv->new_name_entry), name); + else + gtk_label_set_text(GTK_LABEL(priv->name_entry), name); +} + diff --git a/src/hildon-add-home-dialog.h b/src/hildon-add-home-dialog.h new file mode 100644 index 0000000..bd3e1c2 --- /dev/null +++ b/src/hildon-add-home-dialog.h @@ -0,0 +1,61 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_ADD_HOME_DIALOG_H__ +#define __HILDON_ADD_HOME_DIALOG_H__ + +#include + +G_BEGIN_DECLS +#define HILDON_TYPE_ADD_HOME_DIALOG \ + ( hildon_add_home_dialog_get_type() ) +#define HILDON_ADD_HOME_DIALOG(obj) \ + (GTK_CHECK_CAST (obj, HILDON_TYPE_ADD_HOME_DIALOG, HildonAddHomeDialog)) +#define HILDON_ADD_HOME_DIALOG_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST ((klass), HILDON_TYPE_ADD_HOME_DIALOG, \ + HildonAddHomeDialogClass)) +#define HILDON_IS_ADD_HOME_DIALOG(obj) \ + (GTK_CHECK_TYPE (obj, HILDON_TYPE_ADD_HOME_DIALOG)) +#define HILDON_IS_ADD_HOME_DIALOG_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_ADD_HOME_DIALOG)) +typedef struct _HildonAddHomeDialog HildonAddHomeDialog; +typedef struct _HildonAddHomeDialogClass HildonAddHomeDialogClass; + +struct _HildonAddHomeDialog { + GtkDialog parent; +}; + +struct _HildonAddHomeDialogClass { + GtkDialogClass parent_class; +}; + +GType hildon_add_home_dialog_get_type(void); + +GtkWidget *hildon_add_home_dialog_new(GtkWindow * parent, + const gchar * name, + const gchar * new_name); +const gchar *hildon_add_home_dialog_get_name(HildonAddHomeDialog * dialog); + +G_END_DECLS +#endif /* __HILDON_ADD_HOME_DIALOG_H__ */ diff --git a/src/hildon-app-private.h b/src/hildon-app-private.h new file mode 100644 index 0000000..1441a0b --- /dev/null +++ b/src/hildon-app-private.h @@ -0,0 +1,78 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + + +#ifndef HILDON_APP_PRIVATE_H +#define HILDON_APP_PRIVATE_H + +G_BEGIN_DECLS + +enum { + TOPMOST_STATUS_ACQUIRE, + TOPMOST_STATUS_LOSE, + SWITCH_TO, + IM_CLOSE, + CLIPBOARD_COPY, + CLIPBOARD_CUT, + CLIPBOARD_PASTE, + + HILDON_APP_LAST_SIGNAL +}; + +struct _HildonAppPrivate { + GList *children; + gchar *title; +#ifndef HILDON_DISABLE_DEPRECATED + HildonZoomLevel zoom; +#endif + + /* Used to keep track of menu key press/release */ + gint lastmenuclick; + + gulong curr_view_id; + gulong view_id_counter; + GSList *view_ids; + gboolean scroll_control; + + guint twoparttitle: 1; + guint is_topmost: 1; + gboolean killable; + gboolean autoregistration; + + guint escape_timeout; + guint key_snooper; + + GtkUIManager *uim; + + guint active_menu_id; +}; + +typedef struct { + gpointer view_ptr; + unsigned long view_id; +} view_item; + +G_END_DECLS + +#endif /* HILDON_APP_PRIVATE_H */ diff --git a/src/hildon-app.c b/src/hildon-app.c new file mode 100644 index 0000000..b7a24a7 --- /dev/null +++ b/src/hildon-app.c @@ -0,0 +1,2270 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-app + * @short_description: A base widget to present application. Deprecated, use #HildonProgram instead. + * @see_also: #HildonAppView + * + * #HildonApp is the base for any hildon application. + * It controls basic looks and functionality of an application, like a title. + * + * This widget is deprecated use #HildonProgram instead. + */ + +#include +#include "hildon-app.h" +#include "hildon-app-private.h" +#include "hildon-appview.h" +#include "gtk-infoprint.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#define TITLE_DELIMITER " - " + +/* + * 'Magic' values for the titlebar menu area limits + */ +#define MENUAREA_LEFT_LIMIT 80 +#define MENUAREA_RIGHT_LIMIT MENUAREA_LEFT_LIMIT + 307 +#define MENUAREA_TOP_LIMIT 0 +#define MENUAREA_BOTTOM_LIMIT 39 + +#define KILLABLE "CANKILL" + +#define _(String) dgettext(PACKAGE, String) + +#define HILDON_APP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_APP, HildonAppPrivate)); + +static GtkWindowClass *parent_class; +static guint app_signals[HILDON_APP_LAST_SIGNAL] = { 0 }; + +typedef struct _HildonAppPrivate HildonAppPrivate; + +static gboolean +hildon_app_key_press (GtkWidget *widget, GdkEventKey *keyevent); +static gboolean +hildon_app_key_release (GtkWidget *widget, GdkEventKey *keyevent); +static gboolean +hildon_app_key_snooper (GtkWidget *widget, GdkEventKey *keyevent, HildonApp *app); +static GdkFilterReturn +hildon_app_event_filter (GdkXEvent *xevent, GdkEvent *event, gpointer data); +static void +hildon_app_construct_title (HildonApp *self); +static void +hildon_app_finalize (GObject *obj_self); +static void +hildon_app_destroy (GtkObject *obj); +static void +hildon_app_init (HildonApp *self); +static void +hildon_app_class_init (HildonAppClass *app_class); +static void +hildon_app_real_topmost_status_acquire (HildonApp *self); +static void +hildon_app_real_topmost_status_lose (HildonApp *self); +static void +hildon_app_real_switch_to (HildonApp *self); +static gboolean +hildon_app_button (GtkWidget *widget, GdkEventButton *event); +static GdkWindow * +find_window (GdkWindow *window, gint by, gint co); +static void +hildon_app_clipboard_copy(HildonApp *self, GtkWidget *widget); +static void +hildon_app_clipboard_cut(HildonApp *self, GtkWidget *widget); +static void +hildon_app_clipboard_paste(HildonApp *self, GtkWidget *widget); +static gboolean hildon_app_escape_timeout(gpointer data); + +static void hildon_app_set_property(GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec); +static void hildon_app_get_property(GObject * object, guint property_id, + GValue * value, GParamSpec * pspec); + +static void hildon_app_add (GtkContainer *container, GtkWidget *child); +static void hildon_app_remove (GtkContainer *container, GtkWidget *child); +static void hildon_app_forall (GtkContainer *container, gboolean include_internals, + GtkCallback callback, gpointer callback_data); + +enum { + PROP_0, + PROP_SCROLL_CONTROL, + /* FIXME: Zoom is deprecated, should be removed */ + PROP_ZOOM, + PROP_TWO_PART_TITLE, + PROP_APP_TITLE, + PROP_KILLABLE, + PROP_AUTOREGISTRATION, + PROP_APPVIEW, + PROP_UI_MANAGER +}; + +static gpointer find_view(HildonApp *self, unsigned long view_id); + +/* FIXME: Zoom level is deprecated, should be removed */ +/** + * hildon_zoom_level_get_type: + * + * Initialises, and returns the type of a hildon zoom level + * + * Returns: GType of #HildonZoomLevel + */ + +GType +hildon_zoom_level_get_type (void) +{ + static GType etype = 0; + if (etype == 0) { + static const GEnumValue values[] = { + { HILDON_ZOOM_SMALL, "HILDON_ZOOM_SMALL", "small" }, + { HILDON_ZOOM_MEDIUM, "HILDON_ZOOM_MEDIUM", "medium" }, + { HILDON_ZOOM_LARGE, "HILDON_ZOOM_LARGE", "large" }, + { 0, NULL, NULL } + }; + etype = g_enum_register_static ("HildonZoomLevel", values); + } + return etype; +} + +GType hildon_app_get_type(void) +{ + static GType app_type = 0; + + if (!app_type) + { + static const GTypeInfo app_info = + { + sizeof(HildonAppClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_app_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonApp), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_app_init, + }; + app_type = g_type_register_static(GTK_TYPE_WINDOW, + "HildonApp", &app_info, 0); + } + return app_type; +} + +/* + * Sets or delete a custom property into the XServer, according + * to the boolean value of HildonAppPrivate::killable + */ +static void hildon_app_apply_killable(HildonApp *self) +{ + HildonAppPrivate *priv; + Atom killability_atom = XInternAtom (GDK_DISPLAY(), + "_HILDON_APP_KILLABLE", False); + priv = HILDON_APP_GET_PRIVATE (self); + + g_assert (HILDON_IS_APP (self) ); + g_assert(GTK_WIDGET_REALIZED(self)); + + if (priv->killable) + { + /* Set the atom to specific value, because perhaps in the future, + there may be other possible values? */ + XChangeProperty(GDK_DISPLAY(), + GDK_WINDOW_XID(GTK_WIDGET(self)->window), + killability_atom, XA_STRING, 8, + PropModeReplace, (unsigned char *)KILLABLE, + strlen(KILLABLE)); + } + else + { + XDeleteProperty(GDK_DISPLAY(), + GDK_WINDOW_XID(GTK_WIDGET(self)->window), + killability_atom); + } +} + +/* + * Updates the _NET_CLIENT_LIST property into the XServer. + * It is the list of the views associated to the HildonApp. + * It will be used by the Task Navigator in order to be able to show a list + * of all the views, and let the user switch and navigate them. + */ +static void hildon_app_apply_client_list(HildonApp *self) +{ + HildonAppPrivate *priv; + Window *win_array; + GSList *list_ptr; + int loopctr = 0; + Atom clientlist; + + g_assert (HILDON_IS_APP (self) ); + g_assert(GTK_WIDGET_REALIZED(self)); + + /* Get the client list handle */ + clientlist = XInternAtom (GDK_DISPLAY(), + "_NET_CLIENT_LIST", False); + + /* Allocate a new array for window IDs */ + priv = HILDON_APP_GET_PRIVATE(self); + win_array = g_new(Window, g_slist_length(priv->view_ids)); + + /* Fill the contents of the window array with current view IDs */ + for (list_ptr = priv->view_ids; list_ptr; list_ptr = list_ptr->next) + { + win_array[loopctr] = + (unsigned long)(((view_item *)(list_ptr->data))->view_id); + loopctr++; + } + + /* Update the details of current view IDs to our X property */ + XChangeProperty(GDK_DISPLAY(), GDK_WINDOW_XID(GTK_WIDGET(self)->window), + clientlist, XA_WINDOW, 32, PropModeReplace, + (unsigned char *)win_array, + g_slist_length(priv->view_ids)); + + XFlush(GDK_DISPLAY()); + g_free(win_array); +} + +/* + * Performs the standard gtk realize function. + */ +static void hildon_app_realize(GtkWidget *widget) +{ + HildonApp *self; + HildonAppPrivate *priv; + GdkWindow *window; + Atom *old_atoms, *new_atoms; + gint atom_count; + Display *disp; + + g_assert(widget != NULL); + + self = HILDON_APP(widget); + priv = HILDON_APP_GET_PRIVATE(self); + + /* + * Of course we need to realize the parent. + * parent_class got already initialised in the hildon_app_init function + */ + GTK_WIDGET_CLASS(parent_class)->realize(widget); + + /* some initialisation code */ + hildon_app_apply_killable(self); + hildon_app_construct_title(self); + hildon_app_apply_client_list(self); + hildon_app_notify_view_changed(self, hildon_app_get_appview(self)); + window = widget->window; + disp = GDK_WINDOW_XDISPLAY(window); + + /* Install a key snooper for the Home button - so that it works everywhere */ + priv->key_snooper = gtk_key_snooper_install + ((GtkKeySnoopFunc) hildon_app_key_snooper, widget); + + /* Get the list of Atoms for the WM_PROTOCOLS property... */ + XGetWMProtocols(disp, GDK_WINDOW_XID(window), &old_atoms, &atom_count); + new_atoms = g_new(Atom, atom_count + 1); + + memcpy(new_atoms, old_atoms, sizeof(Atom) * atom_count); + + /* ... creates a new Atom... */ + new_atoms[atom_count++] = + XInternAtom(disp, "_NET_WM_CONTEXT_CUSTOM", False); + + /* ... and finally update the property within the XServer */ + XSetWMProtocols(disp, GDK_WINDOW_XID(window), new_atoms, atom_count); + + XFree(old_atoms); + g_free(new_atoms); + + /* Add the GDK_SUBSTRUCTURE_MASK (receive events about window configuration + * changes of child windows) to the window. + */ + gdk_window_set_events(window, gdk_window_get_events(window) | GDK_SUBSTRUCTURE_MASK); +} + +/* + * Performs the standard gtk unrealize function. + */ +static void hildon_app_unrealize(GtkWidget *widget) +{ + HildonAppPrivate *priv = HILDON_APP_GET_PRIVATE(widget); + + if (priv->key_snooper) + { + /* removing the snooper that handles MENU key presses */ + gtk_key_snooper_remove(priv->key_snooper); + priv->key_snooper = 0; + } + + gdk_window_remove_filter(NULL, hildon_app_event_filter, widget); + GTK_WIDGET_CLASS(parent_class)->unrealize(widget); +} + +/* + * Class initialisation. + */ +static void hildon_app_class_init (HildonAppClass *app_class) +{ + /* get convenience variables */ + GObjectClass *object_class = G_OBJECT_CLASS(app_class); + GtkContainerClass *container_class = GTK_CONTAINER_CLASS (app_class); + GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS(app_class); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(app_class); + + /* set the global parent_class here */ + parent_class = g_type_class_peek_parent(app_class); + + g_type_class_add_private(app_class, sizeof(HildonAppPrivate)); + + /* now the object stuff */ + object_class->finalize = hildon_app_finalize; + object_class->set_property = hildon_app_set_property; + object_class->get_property = hildon_app_get_property; + + gtkobject_class->destroy = hildon_app_destroy; + + widget_class->key_press_event = hildon_app_key_press; + widget_class->key_release_event = hildon_app_key_release; + widget_class->button_press_event = hildon_app_button; + widget_class->button_release_event = hildon_app_button; + widget_class->realize = hildon_app_realize; + widget_class->unrealize = hildon_app_unrealize; + + container_class->add = hildon_app_add; + container_class->remove = hildon_app_remove; + container_class->forall = hildon_app_forall; + + app_class->topmost_status_acquire = + hildon_app_real_topmost_status_acquire; + app_class->topmost_status_lose = hildon_app_real_topmost_status_lose; + app_class->switch_to = hildon_app_real_switch_to; + + /* create the signals */ + app_signals[TOPMOST_STATUS_ACQUIRE] = + g_signal_new("topmost_status_acquire", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(HildonAppClass, + topmost_status_acquire), NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + app_signals[TOPMOST_STATUS_LOSE] = + g_signal_new("topmost_status_lose", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(HildonAppClass, topmost_status_lose), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + app_signals[SWITCH_TO] = + g_signal_new("switch_to", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(HildonAppClass, switch_to), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + app_signals[IM_CLOSE] = + g_signal_new("im_close", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(HildonAppClass, im_close), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + app_signals[CLIPBOARD_COPY] = + g_signal_new("clipboard_copy", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(HildonAppClass, clipboard_copy), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, + GTK_TYPE_WIDGET); + app_signals[CLIPBOARD_CUT] = + g_signal_new("clipboard_cut", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(HildonAppClass, clipboard_cut), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, + GTK_TYPE_WIDGET); + app_signals[CLIPBOARD_PASTE] = + g_signal_new("clipboard_paste", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(HildonAppClass, clipboard_paste), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, + GTK_TYPE_WIDGET); + + /* properties */ + g_object_class_install_property(object_class, PROP_SCROLL_CONTROL, + g_param_spec_boolean("scroll-control", + "Scroll control", + "Set the scroll control ON/OFF", + TRUE, G_PARAM_READWRITE)); + + g_object_class_install_property(object_class, PROP_TWO_PART_TITLE, + g_param_spec_boolean("two-part-title", + "Two part title", + "Use two part title or not", + FALSE, G_PARAM_READWRITE)); +#ifndef HILDON_DISABLE_DEPRECATED + g_object_class_install_property(object_class, PROP_ZOOM, + g_param_spec_enum ("zoom", + "Zoom level", + "Set the zoom level", + HILDON_TYPE_ZOOM_LEVEL, + HILDON_ZOOM_MEDIUM, + G_PARAM_READWRITE)); +#endif + g_object_class_install_property(object_class, PROP_APP_TITLE, + g_param_spec_string ("app-title", + "Application title", + "Set the application title", + "", + G_PARAM_READWRITE)); + + g_object_class_install_property(object_class, PROP_KILLABLE, + g_param_spec_boolean("killable", + "Killable", + "Whether the application is killable or not", + FALSE, + G_PARAM_READWRITE)); + g_object_class_install_property(object_class, PROP_AUTOREGISTRATION, + g_param_spec_boolean("autoregistration", + "Autoregistration", + "Whether the application views should be registered automatically", + TRUE, + G_PARAM_READWRITE)); + g_object_class_install_property(object_class, PROP_APPVIEW, + g_param_spec_object("appview", + "Appplication View", + "The currently active application view", + HILDON_TYPE_APPVIEW, + G_PARAM_READWRITE)); + g_object_class_install_property(object_class, PROP_UI_MANAGER, + g_param_spec_object("ui-manager", + "UIManager", + "The associated GtkUIManager for this app", + GTK_TYPE_UI_MANAGER, + G_PARAM_READWRITE)); +} + +/* + * Performs the standard gtk finalize function, freeing allocated + * memory and propagating the finalization to the parent. + */ +static void +hildon_app_finalize (GObject *obj) +{ + HildonAppPrivate *priv = NULL; + + g_assert (obj != NULL); + + priv = HILDON_APP_GET_PRIVATE (obj); + + g_free (priv->title); + + if (G_OBJECT_CLASS(parent_class)->finalize) + G_OBJECT_CLASS(parent_class)->finalize(obj); + + /* FIXME: This is legacy code, but cannot be removed + without changing functionality */ + gtk_main_quit (); +} + +/* + * Removes the long escape ("cancel" hw key) press timeout. + */ +static void +hildon_app_remove_timeout(HildonAppPrivate *priv) +{ + g_assert(priv != NULL); + + if (priv->escape_timeout > 0) + { + g_source_remove (priv->escape_timeout); + priv->escape_timeout = 0; + } +} + +/* + * Frees all the resources and propagates the destroy call to the parent. + */ +static void +hildon_app_destroy (GtkObject *obj) +{ + HildonAppPrivate *priv = NULL; + + g_assert (obj != NULL); + + priv = HILDON_APP_GET_PRIVATE (obj); + + /* Just in case a GDK_Escape key was pressed shortly before the propagation + * of this event, it is safer to remove the timeout that will generate a + * GDK_DELETE key press. We are destroying the app, so we're not interested + * anymore in processing key presses. + */ + hildon_app_remove_timeout(priv); + + if (priv->uim != NULL) + { + g_object_unref (G_OBJECT (priv->uim)); + priv->uim = NULL; + } + + /* Free all the views */ + if (priv->view_ids) + { + g_slist_foreach (priv->view_ids, (GFunc)g_free, NULL); + g_slist_free (priv->view_ids); + priv->view_ids = NULL; + } + + if (GTK_OBJECT_CLASS (parent_class)->destroy) + GTK_OBJECT_CLASS (parent_class)->destroy(obj); +} + +/* + * Overrides gtk_container_forall, calling the callback function for each of + * the children of HildonAppPrivate. + */ +static void hildon_app_forall (GtkContainer *container, gboolean include_internals, + GtkCallback callback, gpointer callback_data) +{ + HildonAppPrivate *priv = NULL; + + g_return_if_fail (container != NULL); + g_return_if_fail (callback != NULL); + + priv = HILDON_APP_GET_PRIVATE (container); + + /* Note! we only have user added children, no internals */ + g_list_foreach (priv->children, (GFunc)callback, callback_data); +} + +/* + * An accessor to set private properties of HildonAppPrivate. + */ +static void hildon_app_set_property(GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + HildonAppPrivate *priv = HILDON_APP_GET_PRIVATE(object); + + switch (property_id) { + case PROP_SCROLL_CONTROL: + priv->scroll_control = g_value_get_boolean(value); + break; +#ifndef HILDON_DISABLE_DEPRECATED + case PROP_ZOOM: + hildon_app_set_zoom( HILDON_APP (object), g_value_get_enum (value) ); + break; +#endif + case PROP_TWO_PART_TITLE: + hildon_app_set_two_part_title( HILDON_APP (object), + g_value_get_boolean (value) ); + break; + case PROP_APP_TITLE: + hildon_app_set_title( HILDON_APP (object), g_value_get_string (value)); + break; + case PROP_KILLABLE: + hildon_app_set_killable( HILDON_APP (object), + g_value_get_boolean (value)); + break; + case PROP_AUTOREGISTRATION: + hildon_app_set_autoregistration( HILDON_APP (object), + g_value_get_boolean (value)); + break; + case PROP_APPVIEW: + hildon_app_set_appview( HILDON_APP (object), + HILDON_APPVIEW (g_value_get_object (value))); + break; + case PROP_UI_MANAGER: + hildon_app_set_ui_manager( HILDON_APP (object), + GTK_UI_MANAGER (g_value_get_object (value))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +/* + * An accessor to get private properties of HildonAppPrivate. + */ +static void hildon_app_get_property(GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + HildonAppPrivate *priv = HILDON_APP_GET_PRIVATE(object); + + switch (property_id) { + case PROP_SCROLL_CONTROL: + g_value_set_boolean( value, priv->scroll_control ); + break; +#ifndef HILDON_DISABLE_DEPRECATED + case PROP_ZOOM: + g_value_set_enum( value, priv->zoom); + break; +#endif + case PROP_TWO_PART_TITLE: + g_value_set_boolean( value, priv->twoparttitle); + break; + case PROP_APP_TITLE: + g_value_set_string (value, priv->title); + break; + case PROP_KILLABLE: + g_value_set_boolean (value, priv->killable); + break; + case PROP_AUTOREGISTRATION: + g_value_set_boolean (value, priv->autoregistration); + break; + case PROP_APPVIEW: + g_value_set_object (value, hildon_app_get_appview (HILDON_APP (object))); + break; + case PROP_UI_MANAGER: + g_value_set_object (value, hildon_app_get_ui_manager (HILDON_APP (object))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +/* + * Adds a child widget to HildonApp. + */ +static void hildon_app_add (GtkContainer *container, GtkWidget *child) +{ + HildonApp *app = NULL; + HildonAppPrivate *priv = NULL; + + g_return_if_fail (container != NULL); + g_return_if_fail (GTK_IS_WIDGET (child)); + + app = HILDON_APP (container); + priv = HILDON_APP_GET_PRIVATE (app); + + /* Check if child is already added here */ + if (g_list_find (priv->children, child) != NULL) + return; + + priv->children = g_list_append (priv->children, child); + GTK_BIN (container)->child = child; + gtk_widget_set_parent (child, GTK_WIDGET (app)); + + /* If the default direction (RTL/LTR) is different from the real + default, change it This happens if the locale has been changed + but this appview was orphaned and thus never got to know about + it. "default_direction" could be RTL, but the widget direction + of the view might still be LTR. Thats what we're fixing here. */ + + /* FIXME: This is legacy stuff */ + if (gtk_widget_get_default_direction () != + gtk_widget_get_direction (GTK_WIDGET (child))) + { + gtk_widget_set_direction (GTK_WIDGET (child), + gtk_widget_get_default_direction ()); + } + + if (HILDON_IS_APPVIEW (child)) + { + g_signal_connect_swapped (G_OBJECT (child), "title_change", + G_CALLBACK (hildon_app_construct_title), app); + if (priv->autoregistration) + hildon_app_register_view (app, child); + } +} + +/* + * Removes a child widget from HildonApp. + */ +static void hildon_app_remove (GtkContainer *container, GtkWidget *child) +{ + HildonAppPrivate *priv; + GtkBin *bin; + HildonApp *app; + + g_return_if_fail (container != NULL); + g_return_if_fail (GTK_IS_WIDGET (child)); + + priv = HILDON_APP_GET_PRIVATE (container); + bin = GTK_BIN (container); + app = HILDON_APP (bin); + + /* Make sure that child is found in the list */ + if (g_list_find (priv->children, child) == NULL) + return; + + priv->children = g_list_remove (priv->children, child); + + if (HILDON_IS_APPVIEW (child)) + { + /* FIXME: This is a compilation workaround for gcc > 3.3, since glib-2 API is buggy. + * see http://bugzilla.gnome.org/show_bug.cgi?id=310175 */ + +G_GNUC_EXTENSION + + g_signal_handlers_disconnect_by_func (G_OBJECT (child), + (gpointer)hildon_app_construct_title, app); + + if (priv->autoregistration) + hildon_app_unregister_view (app, HILDON_APPVIEW (child)); + } + + /* If that was our visible child, we need to recalculate size. + We could chain up to parent as well... */ + gtk_widget_unparent (child); + + if (bin->child == child) + { + bin->child = NULL; + gtk_widget_queue_resize (GTK_WIDGET (bin)); + } +} + + +/* + * Long escape keypress handler. + * Long press of the escape key means "close this window", so we fake a delete-event + * for our GdkWindow to make it act the same as if the user had closed the window the + * usual way. This allows any application code to gracefully exit. + * + * It returns FALSE in order to get called only once. + */ +static gboolean +hildon_app_escape_timeout(gpointer app) +{ + HildonAppPrivate *priv; + GdkEvent *event; + + GDK_THREADS_ENTER (); + + g_assert(GTK_WIDGET_REALIZED(app)); + + priv = HILDON_APP_GET_PRIVATE(app); + + /* Send fake event, simulation a situation that user + pressed 'x' from the corner */ + event = gdk_event_new(GDK_DELETE); + ((GdkEventAny *)event)->window = GTK_WIDGET(app)->window; + gtk_main_do_event(event); + gdk_event_free(event); + + priv->escape_timeout = 0; + + GDK_THREADS_LEAVE (); + + return FALSE; +} + +/* + * Looks for the visible window to whom the point of coordinates (co,by) + * belongs. Search recursively all the children of the window. + * + * This functionality is only needed for scrollbar remote control. + */ +static GdkWindow *find_window (GdkWindow *window, gint by, gint co) +{ + GdkWindow *child; + GList *children = gdk_window_peek_children (window); + + /* If the window has no children, then the coordinates must match it */ + if (!children) + return window; + + if (!(child = (GdkWindow *)children->data)) + return window; + + do + { + /* It makes sense to process a child window only if it's visible and it's + * capable to get the GDK_BUTTON_PRESS_MASK event. */ + if (gdk_window_is_visible (child) && + gdk_window_get_events (child) & GDK_BUTTON_PRESS_MASK) + { + gint x, width, y, height; + + gdk_window_get_geometry (child, &x, &y, &width, &height, NULL); + /* This checks that the the point of coordinates (co,by) is in the rectangle + * made by (x,y,x+width,y+height). If so, then we spotted which child of the + * original window is in the point (co,by). We can now recursively search + * its own children. + */ + if (x < co && x + width > co && y < by && y + height > by) + return find_window (child, by, co); + } + + /* If the window has no more children, then it's the one we're looking for */ + if (!(children = g_list_next (children))) + return window; + + } while ( (child = children->data)); + + return NULL; +} + +/* + * This is the callback function that gets called on a mouse button press + * event. If the press is happens in a "sensitive border" area in the right side of + * the window, the event is translated to the left edge of that border (which + * usually will contain a scrollbar). + * + * This functionality is used for right-hand side scroll control feature (dragging on the + * right edge of the window controls the rightmost scrollbar if present). + */ +static gboolean +hildon_app_button (GtkWidget *widget, GdkEventButton *event) +{ + HildonAppPrivate *priv = NULL; + + /* FIXME: This is an estimate, but the AppView does not expose the + width of it's borders so we default to something */ + gint sensitive_border = 31; + + if (!GTK_WIDGET_REALIZED(widget)) + { + return FALSE; + } + + priv = HILDON_APP_GET_PRIVATE (widget); + + if (!priv->scroll_control) + { + return FALSE; + } + + /* We can easily get the location of the vertical scrollbar and get the exact + * area for the scroll_control *if* the setup is such that the HildonAppview + * contains a GtkScrolledWindow, so we check for it before defaulting to + * the previous guess. More complex situations are not feasible to autodetect. + * Applications should provide the GtkAdjustment to be changed for this to work + * flawlessly. + */ + if (HILDON_IS_APPVIEW(GTK_BIN(widget)->child)) + { + GtkBin *avbin = GTK_BIN(GTK_BIN(widget)->child); + if (GTK_IS_SCROLLED_WINDOW(avbin->child)) + { + GtkScrolledWindow *win; + win = GTK_SCROLLED_WINDOW(avbin->child); + + if (GTK_WIDGET_VISIBLE(win->vscrollbar)) + { + /* Calculate the distance between the AppView's right border and + * the scrollbars center + */ + sensitive_border = (GTK_WIDGET(avbin)->allocation.x + + GTK_WIDGET(avbin)->allocation.width) - + (win->vscrollbar->allocation.x + + win->vscrollbar->allocation.width / 2); + } + } + } + + /* If the press event comes to the sensitive area, we send a fake event to the + * area we think the scrollbar is in to make it think the button press happened on it + */ + if (event->x > widget->allocation.width - sensitive_border) + { + GdkWindow *window = NULL; + gint co = widget->allocation.width - sensitive_border; + + /* We now need to know in which window the _modified_ coordinates are */ + if ((window = find_window (widget->window, event->y, co))) + { + GdkEventButton nevent; + + if (window == widget->window) + return FALSE; + + /* Build a new event and associate the proper window to it */ + nevent = *event; + nevent.x = 8; + nevent.window = window; + g_object_ref (nevent.window); + gtk_main_do_event ((GdkEvent*)&nevent); + } + } + return FALSE; +} + +/* + * Performs the initialisation of the widget. + */ +static void +hildon_app_init (HildonApp *self) +{ + HildonAppPrivate *priv; + + priv = HILDON_APP_GET_PRIVATE(self); + + /* init private */ + priv->title = g_strdup(""); +#ifndef HILDON_DISABLE_DEPRECATED + priv->zoom = HILDON_ZOOM_MEDIUM; +#endif + priv->twoparttitle = FALSE; + priv->lastmenuclick = 0; + priv->is_topmost = FALSE; + priv->curr_view_id = 0; + priv->view_id_counter = 1; + priv->view_ids = NULL; + priv->killable = FALSE; + priv->autoregistration = TRUE; + priv->scroll_control = TRUE; + priv->uim = NULL; + priv->active_menu_id = 0; + + /* grab the events here since HildonApp isn't necessarily ever shown */ + gdk_window_set_events(gdk_get_default_root_window(), + gdk_window_get_events(gdk_get_default_root_window()) | + GDK_PROPERTY_CHANGE_MASK); + + /* For some reason, the titlebar menu has problems with the grab + (bugzilla bug 1527). This is part of somewhat ugly fix for it to + get it to work until a more satisfactory solution is found */ + gdk_window_add_filter(NULL, hildon_app_event_filter, self); + + gtk_widget_set_events (GTK_WIDGET(self), GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | + GDK_POINTER_MOTION_MASK); +} + +/*public functions */ + +/** + * hildon_app_new: + * + * Creates a new #HildonApp + * + * Returns: pointer to a new #HildonApp structure + */ +GtkWidget * +hildon_app_new (void) +{ + return GTK_WIDGET(g_object_new(HILDON_TYPE_APP, NULL)); +} + +/** + * hildon_app_new_with_appview: + * @appview : a #HildonAppView + * + * Creates an app, and sets it's initial appview. + * + * Returns: pointer to a new #HildonApp structure + */ +GtkWidget * +hildon_app_new_with_appview (HildonAppView *appview) +{ + GtkWidget *app; + + g_return_val_if_fail (HILDON_IS_APPVIEW (appview), NULL); + + app = hildon_app_new (); + + hildon_app_set_appview(HILDON_APP(app), appview); + + return app; +} + +/** + * hildon_app_get_appview: + * @self : a #HildonApp + * + * Gets the currently shown appview. + * + * Returns: the currently shown appview in this HildonApp. + * If no appview is currently set for this HildonApp, + * returns NULL. + */ +HildonAppView * +hildon_app_get_appview (HildonApp *self) +{ + GtkBin *bin; + + g_return_val_if_fail (HILDON_IS_APP (self), NULL); + bin = GTK_BIN (self); + if (HILDON_IS_APPVIEW (bin->child)) + { + return HILDON_APPVIEW (bin->child); + } + + return NULL; +} + +/** + * hildon_app_set_appview: + * @self : a #HildonApp + * @appview : a #HildonAppView + * + * Sets (switches to) appview. + */ +void +hildon_app_set_appview (HildonApp *app, HildonAppView *view) +{ + HildonAppPrivate *priv; + GtkBin *bin; + GtkWidget *widget; /*(view to be set)*/ + gchar *menu_ui; + + g_return_if_fail (HILDON_IS_APP (app)); + g_return_if_fail (HILDON_IS_APPVIEW (view)); + + bin = GTK_BIN (app); + priv = HILDON_APP_GET_PRIVATE (app); + widget = GTK_WIDGET (view); + + if (widget == bin->child) + return; + + /* Make old appview dissapear */ + if (bin->child) + { + gtk_widget_hide (bin->child); + g_signal_emit_by_name (bin->child, "switched_from", NULL); + + if (priv->active_menu_id > 0) + { + if (priv->uim != NULL) + { + gtk_ui_manager_remove_ui (priv->uim, + priv->active_menu_id); + } + priv->active_menu_id = 0; + } + + bin->child = NULL; + } + + /* Ensure that new view is in our child list */ + if (!g_list_find (priv->children, widget)) + gtk_container_add (GTK_CONTAINER (app), widget); + + bin->child = widget; + + gtk_widget_show (widget); + + /* UI manager support, merge menu for activated view */ + g_object_get (G_OBJECT (view), + "menu-ui", &menu_ui, + NULL); + + if (menu_ui && priv->uim) + { + + priv->active_menu_id = + gtk_ui_manager_add_ui_from_string (priv->uim, menu_ui, -1, NULL); + + gtk_ui_manager_ensure_update (priv->uim); + + } + + g_free (menu_ui); + + g_signal_emit_by_name (widget, "switched_to", NULL); + + /* Inform task navigator about changed view */ + hildon_app_notify_view_changed (app, view); + + /* Update title to show currently activated view */ + hildon_app_construct_title (app); + gtk_widget_child_focus (widget, GTK_DIR_TAB_FORWARD); +} + +/** + * hildon_app_set_title: + * @self : a #HildonApp + * @newtitle : the new title assigned to the application + * + * Sets title of the application. + */ +void +hildon_app_set_title (HildonApp *self, const gchar *newtitle) +{ + HildonAppPrivate *priv; + gchar *oldstr; + + g_return_if_fail(HILDON_IS_APP(self)); + + priv = HILDON_APP_GET_PRIVATE(self); + oldstr = priv->title; + + if (newtitle) + { + priv->title = g_strdup(newtitle); + g_strstrip(priv->title); + } + else + priv->title = g_strdup(""); + + if (oldstr) + g_free(oldstr); + + hildon_app_construct_title(self); +} + +/** + * hildon_app_get_title: + * @self : a #HildonApp + * + * Gets the title of the application. + * + * Returns: the title currently assigned to the application. This + * value is not to be freed or modified by the calling application + */ +const gchar * +hildon_app_get_title (HildonApp *self) +{ + HildonAppPrivate *priv; + + g_return_val_if_fail (HILDON_IS_APP(self), NULL); + priv = HILDON_APP_GET_PRIVATE(self); + return priv->title; +} + +/* FIXME: Zoom is deprecated, remove */ +/** + * hildon_app_set_zoom: + * @self : a #HildonApp + * @newzoom: the zoom level of type #HildonZoomLevel to be assigned to an + * application + * + * Sets the zoom level. Warning! This function is deprecated and + * should not be used. It's lecacy stuff from ancient specs. + */ +void +hildon_app_set_zoom (HildonApp *self, HildonZoomLevel newzoom) +{ + HildonAppPrivate *priv; + + g_return_if_fail(HILDON_IS_APP(self)); + + priv = HILDON_APP_GET_PRIVATE(self); + + if (newzoom != priv->zoom) + { + if (newzoom < HILDON_ZOOM_SMALL) + { + newzoom = HILDON_ZOOM_SMALL; + gtk_infoprint(GTK_WINDOW(self), _("ckct_ib_min_zoom_level_reached")); + } + else if (newzoom > HILDON_ZOOM_LARGE) { + newzoom = HILDON_ZOOM_LARGE; + gtk_infoprint(GTK_WINDOW(self), _("ckct_ib_max_zoom_level_reached")); + } + priv->zoom = newzoom; + } +} + +/** + * hildon_app_get_zoom: + * @self : a #HildonApp + * + * Gets the zoom level. Warning! This function is deprecated and + * should not be used. It's lecacy stuff from ancient specifications. + * + * Returns: the zoom level of the Hildon application. The + * returned zoom level is of type #HildonZoomLevel. + */ +HildonZoomLevel +hildon_app_get_zoom (HildonApp *self) +{ + HildonAppPrivate *priv; + + g_return_val_if_fail(HILDON_IS_APP(self), HILDON_ZOOM_MEDIUM); + priv = HILDON_APP_GET_PRIVATE(self); + return priv->zoom; +} + +/** + * hildon_app_get_default_font: + * @self : a #HildonApp + * + * Gets default font. Warning! This function is deprecated and should + * not be used. It's legacy stuff from ancient version of specification. + * + * Returns: pointer to PangoFontDescription for the default, + * normal size font + */ +PangoFontDescription * +hildon_app_get_default_font (HildonApp *self) +{ + PangoFontDescription *font_desc = NULL; + GtkStyle *fontstyle = NULL; + + g_return_val_if_fail(HILDON_IS_APP(self), NULL); + + fontstyle = + gtk_rc_get_style_by_paths (gtk_widget_get_settings + (GTK_WIDGET(self)), NULL, NULL, + gtk_widget_get_type()); + + if (!fontstyle) + { + g_print("WARNING : default font not found. " + "Defaulting to swissa 19\n"); + font_desc = pango_font_description_from_string("swissa 19"); + + } + else + font_desc = pango_font_description_copy(fontstyle->font_desc); + + return font_desc; +} + +/** + * hildon_app_get_zoom_font: + * @self : a #HildonApp + * + * Gets the description of the default font. Warning! This function + * is deprecated and should not be used. It's legacy stuff from + * ancient specs. + * + * Returns: pointer to PangoFontDescription for the default, + * normal size font + */ +PangoFontDescription * +hildon_app_get_zoom_font (HildonApp *self) +{ + HildonAppPrivate *priv; + PangoFontDescription *font_desc = NULL; + gchar *style_name = 0; + GtkStyle *fontstyle = NULL; + + g_return_val_if_fail(HILDON_IS_APP(self), NULL); + + priv = HILDON_APP_GET_PRIVATE(self); + if (priv->zoom == HILDON_ZOOM_SMALL) + style_name = g_strdup("hildon-zoom-small"); + else if (priv->zoom == HILDON_ZOOM_MEDIUM) + style_name = g_strdup("hildon-zoom-medium"); + else if (priv->zoom == HILDON_ZOOM_LARGE) + style_name = g_strdup("hildon-zoom-large"); + else + { + g_warning("Invalid Zoom Value\n"); + style_name = g_strdup(""); + } + + fontstyle = + gtk_rc_get_style_by_paths (gtk_widget_get_settings + (GTK_WIDGET(self)), style_name, NULL, + G_TYPE_NONE); + g_free (style_name); + + if (!fontstyle) + { + g_print("WARNING : theme specific zoomed font not found. " + "Defaulting to preset zoom-specific fonts\n"); + if (priv->zoom == HILDON_ZOOM_SMALL) + font_desc = pango_font_description_from_string("swissa 16"); + else if (priv->zoom == HILDON_ZOOM_MEDIUM) + font_desc = pango_font_description_from_string("swissa 19"); + else if (priv->zoom == HILDON_ZOOM_LARGE) + font_desc = pango_font_description_from_string("swissa 23"); + } + else + font_desc = pango_font_description_copy(fontstyle->font_desc); + + return font_desc; +} + + /* FIXME: Zoom is deprecated, remove the code above */ + +/** + * hildon_app_set_two_part_title: + * @self : a #HildonApp + * @istwoparttitle : a gboolean indicating wheter to activate + * a title that has both the application title and application + * view title separated by a triangle + * + * Sets the two part title. + */ +void +hildon_app_set_two_part_title (HildonApp *self, gboolean istwoparttitle) +{ + HildonAppPrivate *priv; + g_return_if_fail(HILDON_IS_APP(self)); + priv = HILDON_APP_GET_PRIVATE(self); + + if (istwoparttitle != priv->twoparttitle) + { + priv->twoparttitle = istwoparttitle; + hildon_app_construct_title(self); + } +} + +/** + * hildon_app_get_two_part_title: + * @self : a #HildonApp + * + * Gets the 'twopart' represention of the title inside #HildonApp. + * + * Returns: a boolean indicating wheter title shown has both + * application, and application view title separated by a triangle. + */ +gboolean +hildon_app_get_two_part_title (HildonApp *self) +{ + HildonAppPrivate *priv; + + g_return_val_if_fail(HILDON_IS_APP(self), FALSE); + priv = HILDON_APP_GET_PRIVATE(self); + return priv->twoparttitle; +} + + +/* private functions */ + + +/* + * Handles the key press of the Escape, Increase and Decrease keys. Other keys + * are handled by the parent GtkWidgetClass. + */ +static gboolean +hildon_app_key_press (GtkWidget *widget, GdkEventKey *keyevent) +{ + HildonApp *app = HILDON_APP (widget); + HildonAppView *appview; + HildonAppPrivate *priv = HILDON_APP_GET_PRIVATE(app); + + if (HILDON_IS_APPVIEW(GTK_BIN (app)->child)) + { + appview = HILDON_APPVIEW (GTK_BIN (app)->child); + } + else + { + return FALSE; + } + + if (keyevent->keyval == GDK_Escape && priv->escape_timeout == 0) + { + /* Call hildon_app_escape_timeout every 1500ms until it returns FALSE + * and store the relative GSource id. Since hildon_app_escape_timeout + * can only return FALSE, the call will occurr only once. + */ + priv->escape_timeout = g_timeout_add(1500, hildon_app_escape_timeout, app); + } + + /* FIXME: Handling +/- keys here is not usefull. Applications + can equally easily handle the keypress themselves. */ + else if (HILDON_KEYEVENT_IS_INCREASE_KEY (keyevent)) + { + _hildon_appview_increase_button_state_changed (appview, + keyevent->type); + } + else if (HILDON_KEYEVENT_IS_DECREASE_KEY (keyevent)) + { + _hildon_appview_decrease_button_state_changed (appview, + keyevent->type); + } + + /* Activate default bindings and let the widget with focus to handle key */ + return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, keyevent); +} + +/* + * Handles the key release event for the Escape, Toolbar and Fullscreen keys. + */ +static gboolean +hildon_app_key_release (GtkWidget *widget, GdkEventKey *keyevent) +{ + HildonApp *app = HILDON_APP (widget); + HildonAppView *appview; + HildonAppPrivate *priv = HILDON_APP_GET_PRIVATE(app); + + if (HILDON_IS_APPVIEW(GTK_BIN (app)->child)) + { + appview = HILDON_APPVIEW (GTK_BIN (app)->child); + } + else + { + return FALSE; + } + + if (keyevent->keyval == GDK_Escape) + { + /* + * This will prevent the hildon_app_escape_timeout from being called. + * See hildon_app_escape_timeout and hildon_app_remove_timeout for more. + */ + hildon_app_remove_timeout(priv); + } + else if (HILDON_KEYEVENT_IS_TOOLBAR_KEY (keyevent)) + { + g_signal_emit_by_name(G_OBJECT(appview), + "toolbar-toggle-request"); + } + else if (HILDON_KEYEVENT_IS_FULLSCREEN_KEY (keyevent)) + { + /* Emit the fullscreen_state_change directly, it'll save one step */ + if (hildon_appview_get_fullscreen_key_allowed (appview)) + { + gboolean fullscreen; + + fullscreen = hildon_appview_get_fullscreen(appview); + g_signal_emit_by_name(G_OBJECT(appview), + "fullscreen_state_change", + !fullscreen); + } + } + + /* FIXME: Should the event be marked as handled if any of the three + above cases took an action */ + + /* Activate default bindings and let the widget with focus to handle key */ + return GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, keyevent); +} + +/* + * Handles the MENU key presses. + */ +static gboolean +hildon_app_key_snooper (GtkWidget *widget, GdkEventKey *keyevent, HildonApp *app) +{ + /* FIXME: Using normal keypress handler would be better choise. All + keyevents come to window anyway, so we would get the same + keys in that way as well, but we wouldn't need to struggle + with grabs (modal dialogs etc). */ + + /* Menu key handling is done here */ + if ( HILDON_KEYEVENT_IS_MENU_KEY (keyevent) ) { + HildonAppView *appview; + HildonAppPrivate *priv; + GtkWidget *toplevel; + GtkWidget *focus = NULL; + + /* Don't act on modal dialogs */ + toplevel = gtk_widget_get_toplevel (widget); + focus = gtk_window_get_focus(GTK_WINDOW(app)); + + /* Don't act when comboboxes are active, if a togglebutton + (combobox) has the focus and it is active, we deactivate the + combobox and do nothing */ + if (GTK_IS_TOGGLE_BUTTON (focus)) + { + GtkWidget *parent = gtk_widget_get_parent (focus); + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (focus)) && + GTK_IS_COMBO_BOX (parent)) + { + gtk_combo_box_popdown (GTK_COMBO_BOX (parent)); + return TRUE; + } + } + + /* Don't act when a GtkWindow of a combobox is selected, this + can happen in some applications that change the properties of + the widget focus attribute, WARNING: we are using the name of + the hildon combobox widget to identify the window + (gtkcombobox.c, HILDON_COMBO_BOX_POPUP), if it changes we + must change this name */ + if (GTK_IS_WINDOW (widget) && + !g_ascii_strcasecmp("hildon-combobox-window", gtk_widget_get_name (widget))) + { + return TRUE; + } + + if (GTK_IS_DIALOG (toplevel) + && gtk_window_get_modal (GTK_WINDOW (toplevel))) + { + return TRUE; + } + + appview = HILDON_APPVIEW (GTK_BIN(app)->child); + priv = HILDON_APP_GET_PRIVATE(app); + + if ( keyevent->type == GDK_KEY_PRESS ) { + /* Toggle menu on press, avoid key repeat */ + if ( priv->lastmenuclick == 0 ){ + priv->lastmenuclick = 1; + if (_hildon_appview_toggle_menu(appview, + gtk_get_current_event_time())) + { + return TRUE; + } + } + } else if ( keyevent->type == GDK_KEY_RELEASE ) { + /* We got release, so next press is really a new press, + not a repeat */ + if ( priv->lastmenuclick == 1 ) { + priv->lastmenuclick = 0; + } + + } else { + /* Unknown key event */ + return FALSE; + } + + /* don't stop the key event so that it reaches GTK where it + closes all existing menus that might be open */ + return FALSE; + } + + return FALSE; +} + +/* + * Returns the message_type of the Atom registered with a certain name. + */ +static int +xclient_message_type_check(XClientMessageEvent *cm, const gchar *name) +{ + return cm->message_type == XInternAtom(GDK_DISPLAY(), name, FALSE); +} + +/* + * Returns the GtkWidget associated to a certain Window. + */ +static GtkWidget * +hildon_app_xwindow_lookup_widget(Window xwindow) +{ + GdkWindow *window; + gpointer widget; + + window = gdk_xid_table_lookup(xwindow); + if (window == NULL) + return NULL; + + gdk_window_get_user_data(window, &widget); + return widget; +} + +/* + * Let's search a actual main window using tranciency hints. + * Note that there can be several levels of menus/dialogs above + * the actual main window. + */ +static Window get_active_main_window(Window window) +{ + Window parent_window; + gint limit = 0; + + gdk_error_trap_push (); + + while (XGetTransientForHint(GDK_DISPLAY(), window, &parent_window)) + { + /* The limit > TRANSIENCY_MAXITER ensures that we can't be stuck + here forever if we have circular transiencies for some reason. + Use of _MB_CURRENT_APP_WINDOW might be more elegant... */ + + if (!parent_window || parent_window == GDK_ROOT_WINDOW() || + parent_window == window || limit > TRANSIENCY_MAXITER) + { + break; + } + + limit++; + window = parent_window; + } + + gdk_flush (); + + if (gdk_error_trap_pop ()) + return 0; + + return window; +} + +/* + * Filters every GDK event first. + */ +static GdkFilterReturn +hildon_app_event_filter (GdkXEvent *xevent, GdkEvent *event, gpointer data) +{ + gint x,y; + HildonApp *app = data; + HildonAppPrivate *priv; + HildonAppView *appview = NULL; + + XAnyEvent *eventti = xevent; + + if (HILDON_IS_APPVIEW (GTK_BIN (app)->child)) + { + appview = HILDON_APPVIEW (GTK_BIN (app)->child); + } + + g_return_val_if_fail (app, GDK_FILTER_CONTINUE); + g_return_val_if_fail (HILDON_IS_APP(app), GDK_FILTER_CONTINUE); + + priv = HILDON_APP_GET_PRIVATE(app); + if (eventti->type == ClientMessage) + { + XClientMessageEvent *cm = xevent; + + /* Check if a message indicating a click on titlebar has been + received. Don't open it if mouse is grabbed (eg. modal dialog + was just opened). + _MB_GRAB_TRANSFER is emitted by MatchBox, and signals that a button + has just been released. */ + if (xclient_message_type_check(cm, "_MB_GRAB_TRANSFER") && + HILDON_IS_APPVIEW(appview) && + gtk_grab_get_current() == NULL && + !_hildon_appview_menu_visible(appview)) + { + _hildon_appview_toggle_menu(appview, cm->data.l[0]); + return GDK_FILTER_REMOVE; + } + /* IM_CLOSE is input method specific hack that is really questionable */ + else if (xclient_message_type_check(cm, "_HILDON_IM_CLOSE")) + { + g_signal_emit_by_name(app, "im_close", NULL); + return GDK_FILTER_REMOVE; + } + /* Task user changed the view through task navigator? */ + else if (xclient_message_type_check(cm, "_NET_ACTIVE_WINDOW")) + { + unsigned long view_id = cm->window; + gpointer view_ptr = find_view(app, view_id); + + /* When getting a _NET_ACTIVE_WINDOW signal from the WM we need + * to bring the application to the front */ + if (!priv->is_topmost) + g_signal_emit_by_name (G_OBJECT(app), "topmost_status_acquire"); + + if (HILDON_IS_APPVIEW(view_ptr)) + /* Sets the current view to the "window" that the _NET_ACTIVE_WINDOW + * specified */ + hildon_app_set_appview(app, (HILDON_APPVIEW(view_ptr))); + else + /* there was no view, so we have to switch to an actual application */ + g_signal_emit_by_name (G_OBJECT(app), "switch_to", view_ptr); + + /* FIXME: This is a hack. This was once just gtk_window_present, but + was changed into this at some day!! */ + if (GTK_WIDGET(app)->window) + { + mb_util_window_activate(GDK_DISPLAY(), + GDK_WINDOW_XID(GTK_WIDGET(app)->window)); + } + } + /* FIXME: IM hack */ + else if (xclient_message_type_check(cm, "_HILDON_IM_CLIPBOARD_COPY")) + { + Window xwindow = cm->data.l[0]; + GtkWidget *widget = hildon_app_xwindow_lookup_widget(xwindow); + + g_signal_emit_by_name (G_OBJECT(app), "clipboard_copy", widget); + } + /* FIXME: IM hack */ + else if (xclient_message_type_check(cm, "_HILDON_IM_CLIPBOARD_CUT")) + { + Window xwindow = cm->data.l[0]; + GtkWidget *widget = hildon_app_xwindow_lookup_widget(xwindow); + + g_signal_emit_by_name (G_OBJECT(app), "clipboard_cut", widget); + } + /* FIXME: IM hack */ + else if (xclient_message_type_check(cm, "_HILDON_IM_CLIPBOARD_PASTE")) + { + Window xwindow = cm->data.l[0]; + GtkWidget *widget = hildon_app_xwindow_lookup_widget(xwindow); + + g_signal_emit_by_name (G_OBJECT(app), "clipboard_paste", widget); + } + } + + if (eventti->type == ButtonPress) + { + + /* FIXME: This is mysterious bugfix related to problems to open the + application menu (bugzilla N#3204) */ + XButtonEvent *bev = (XButtonEvent *)xevent; + + if (HILDON_IS_APPVIEW(appview) && + _hildon_appview_menu_visible(appview) && + !hildon_appview_get_fullscreen(appview)) + { + x = bev->x_root; + y = bev->y_root; + if ( (x >= MENUAREA_LEFT_LIMIT) && (x <= MENUAREA_RIGHT_LIMIT) && + (y >= MENUAREA_TOP_LIMIT) && (y <= MENUAREA_BOTTOM_LIMIT)) + { + _hildon_appview_toggle_menu(appview, bev->time); + return GDK_FILTER_CONTINUE; + } + } + } + + /* FIXME: as above */ + if (eventti->type == ButtonRelease) + { + if (HILDON_IS_APPVIEW(appview) && + _hildon_appview_menu_visible(appview) && + !hildon_appview_get_fullscreen(appview)) + { + XButtonEvent *bev = (XButtonEvent *)xevent; + x = bev->x_root; + y = bev->y_root; + if ( (x >= MENUAREA_LEFT_LIMIT) && (x < MENUAREA_RIGHT_LIMIT) && + (y >= MENUAREA_TOP_LIMIT) && (y <= MENUAREA_BOTTOM_LIMIT)) + { + return GDK_FILTER_REMOVE; + } + } + return GDK_FILTER_CONTINUE; + } + + /* Application stacking order changed */ + if (eventti->type == PropertyNotify) + { + Atom active_app_atom = + XInternAtom (GDK_DISPLAY(), "_MB_CURRENT_APP_WINDOW", False); + XPropertyEvent *prop = xevent; + + if ((prop->atom == active_app_atom) + && (prop->window == GDK_ROOT_WINDOW())) + { + Atom realtype; + int format; + int status; + unsigned long n; + unsigned long extra; + Window my_window; + union + { + Window *win; + unsigned char *char_pointer; + } win; + + win.win = NULL; + + status = XGetWindowProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(), + active_app_atom, 0L, 16L, + 0, XA_WINDOW, &realtype, &format, + &n, &extra, &win.char_pointer); + if (!(status == Success && realtype == XA_WINDOW && format == 32 + && n == 1 && win.win != NULL)) + { + if (win.win != NULL) + XFree(win.char_pointer); + return GDK_FILTER_CONTINUE; + } + + my_window = GDK_WINDOW_XID(GTK_WIDGET(app)->window); + + /* Are we the topmost one? */ + if (win.win[0] == my_window || + get_active_main_window(win.win[0]) == my_window) + { + if (!priv->is_topmost) + g_signal_emit_by_name (G_OBJECT(app), + "topmost_status_acquire"); + } + else if (priv->is_topmost) + { + GtkWidget *focus = gtk_window_get_focus(GTK_WINDOW(app)); + + /* FIXME: IM hack, IM-module should do this in response to + topmost_status_lose (emission hook?) */ + if (GTK_IS_ENTRY(focus)) + gtk_im_context_focus_out(GTK_ENTRY(focus)->im_context); + if (GTK_IS_TEXT_VIEW(focus)) + gtk_im_context_focus_out(GTK_TEXT_VIEW(focus)->im_context); + + g_signal_emit_by_name (app, "topmost_status_lose"); + } + + if (win.win != NULL) + XFree(win.char_pointer); + } + } + + return GDK_FILTER_CONTINUE; + } + +/* + * Sets the GTK Window title to the application's title, or + * combined appview/app title, if two part title is asked. + */ +static void +hildon_app_construct_title (HildonApp *self) +{ + g_return_if_fail (HILDON_IS_APP (self)); + + if (GTK_WIDGET_REALIZED(self)) + { + HildonAppPrivate *priv; + GdkAtom subname; + gchar *concatenated_title = NULL; + HildonAppView *appview; + + priv = HILDON_APP_GET_PRIVATE (self); + appview = hildon_app_get_appview(self); + + /* FIXME: The subname property is legacy stuff no longer supported by + Matchbox. However, it is still set for the convenience of + the Task Navigator. */ + subname = gdk_atom_intern("_MB_WIN_SUB_NAME", FALSE); + + if (!appview || !hildon_app_get_two_part_title(self) || + g_utf8_strlen(hildon_appview_get_title(appview), -1) < 1 ) + { + /* Set an invisible dummy value if there is no appview title */ + gdk_property_change (GTK_WIDGET(self)->window, subname, + gdk_atom_intern ("UTF8_STRING", FALSE), + 8, GDK_PROP_MODE_REPLACE, (guchar *) " \0", 1); + gtk_window_set_title (GTK_WINDOW(self), priv->title); + } + else + { + gdk_property_change (GTK_WIDGET(self)->window, subname, + gdk_atom_intern ("UTF8_STRING", FALSE), + 8, GDK_PROP_MODE_REPLACE, + (guchar *)hildon_appview_get_title(appview), + strlen(hildon_appview_get_title (appview))); + concatenated_title = g_strjoin(TITLE_DELIMITER, priv->title, + hildon_appview_get_title(appview), NULL); + /* priv->title should always be non-null, but check anyway */ + if (concatenated_title != NULL) + { + gtk_window_set_title (GTK_WINDOW(self), concatenated_title); + g_free(concatenated_title); + } + } + } +} + +/* + * Callback function to the topmost_status_acquire signal emitted by + * hildon_app_event_filter function. See it for more details. + */ +void +hildon_app_real_topmost_status_acquire (HildonApp *self) +{ + HildonAppPrivate *priv; + g_return_if_fail (HILDON_IS_APP (self)); + priv = HILDON_APP_GET_PRIVATE (self); + + /* FIXME: What is the logic not to update topmost status now? */ + if (!GTK_BIN (self)->child) + return; + + priv->is_topmost = TRUE; +} + +/* + * Callback function to the topmost_status_lose signal emitted by + * hildon_app_event_filter function. See it for more details. + */ +void +hildon_app_real_topmost_status_lose (HildonApp *self) +{ + HildonAppPrivate *priv; + g_return_if_fail (HILDON_IS_APP (self)); + priv = HILDON_APP_GET_PRIVATE (self); + + /* FIXME: What is the logic not to update topmost status now? */ + if (!GTK_BIN (self)->child) + return; + + priv->is_topmost = FALSE; +} + +void +hildon_app_real_switch_to (HildonApp *self) +{ + g_return_if_fail (HILDON_IS_APP (self)); + /* Do we have to do anything here? */ +} + + +/** + * hildon_app_set_autoregistration + * @self : a #HildonApp + * @auto_reg : whether the (app)view autoregistration should be active + * + * Controls the autoregistration/unregistration of (app)views. + */ + +void hildon_app_set_autoregistration(HildonApp *self, gboolean auto_reg) +{ + HildonAppPrivate *priv; + g_return_if_fail (HILDON_IS_APP (self)); + + priv = HILDON_APP_GET_PRIVATE (self); + priv->autoregistration = auto_reg; +} + + +/** + * hildon_app_register_view: + * @self : a #HildonApp + * @view_ptr : pointer to the view instance to be registered + * + * Registers a new view. For appviews, this can be done automatically + * if autoregistration is set. + */ + +void hildon_app_register_view(HildonApp *self, gpointer view_ptr) +{ + HildonAppPrivate *priv; + view_item *view_item_inst; + + g_return_if_fail (HILDON_IS_APP (self) || view_ptr != NULL); + + priv = HILDON_APP_GET_PRIVATE (self); + + if (hildon_app_find_view_id(self, view_ptr) == 0) + { + /* The pointer to the view was unique, so add it to the list */ + view_item_inst = g_malloc(sizeof(view_item)); + view_item_inst->view_id = priv->view_id_counter; + view_item_inst->view_ptr = view_ptr; + + priv->view_id_counter++; + + priv->view_ids = + g_slist_append(priv->view_ids, view_item_inst); + + /* Update the list of views */ + if (GTK_WIDGET_REALIZED(self)) + hildon_app_apply_client_list(self); + } +} + + +/** + * hildon_app_register_view_with_id: + * @self : a #HildonApp + * @view_ptr : pointer to the view instance to be registered + * @view_id : the ID of the view + * + * Registers a new view. Allows the application to specify any ID. + * + * Returns: TRUE if the view registration succeeded, FALSE otherwise. + * The probable cause of failure is that view with that ID + * already existed. + */ + +gboolean hildon_app_register_view_with_id(HildonApp *self, + gpointer view_ptr, + unsigned long view_id) +{ + view_item *view_item_inst; + HildonAppPrivate *priv; + GSList *list_ptr = NULL; + + g_return_val_if_fail (HILDON_IS_APP (self), FALSE); + g_return_val_if_fail (view_ptr, FALSE); + + priv = HILDON_APP_GET_PRIVATE (self); + + list_ptr = priv->view_ids; + + /* Check that the view is not already registered */ + while (list_ptr) + { + if ( (gpointer)((view_item *)list_ptr->data)->view_ptr == view_ptr + && (unsigned long)((view_item *)list_ptr->data)->view_id == view_id) + { + return FALSE; + } + list_ptr = list_ptr->next; + } + + /* The pointer to the view was unique, so add it to the list */ + view_item_inst = g_malloc(sizeof(view_item)); + view_item_inst->view_id = view_id; + view_item_inst->view_ptr = view_ptr; + + priv->view_ids = + g_slist_append(priv->view_ids, view_item_inst); + + priv->view_id_counter++; + + /* Finally, update the _NET_CLIENT_LIST property */ + if (GTK_WIDGET_REALIZED(self)) + hildon_app_apply_client_list(self); + + return TRUE; +} + +/** + * hildon_app_unregister_view: + * @self : a #HildonApp + * @view_ptr : pointer to the view instance to be unregistered + * + * Unregisters a view from HildonApp. Done usually when a view is + * destroyed. For appviews, this is can be automatically + * if autoregistration is set. + */ +void hildon_app_unregister_view(HildonApp *self, gpointer view_ptr) +{ + HildonAppPrivate *priv = NULL; + GSList *list_ptr = NULL; + + g_return_if_fail (HILDON_IS_APP (self)); + g_return_if_fail (view_ptr != NULL); + + priv = HILDON_APP_GET_PRIVATE (self); + + /* Search the view from the list */ + list_ptr = priv->view_ids; + + while (list_ptr) + { + if ( (gpointer)((view_item *)list_ptr->data)->view_ptr == view_ptr) + { + /* Found the view, kick it off */ + g_free (list_ptr->data); + priv->view_ids = g_slist_delete_link(priv->view_ids, list_ptr); + break; + } + list_ptr = list_ptr->next; + } + + if (GTK_WIDGET_REALIZED(self)) + hildon_app_apply_client_list(self); +} + + +/** + * hildon_app_unregister_view_with_id: + * @self: a #HildonApp + * @view_id: the ID of the view that should be unregistered + * + * Unregisters a view with specified ID, if it exists. + */ +void hildon_app_unregister_view_with_id(HildonApp *self, + unsigned long view_id) +{ + HildonAppPrivate *priv; + GSList *list_ptr = NULL; + + g_return_if_fail (HILDON_IS_APP (self)); + + priv = HILDON_APP_GET_PRIVATE (self); + + /* Search the view from the list */ + list_ptr = priv->view_ids; + + while (list_ptr) + { + if ( (unsigned long)((view_item *)list_ptr->data)->view_id == view_id) + { + /* Found view with given id, kick it off */ + g_free (list_ptr->data); + priv->view_ids = g_slist_delete_link(priv->view_ids, list_ptr); + break; + } + list_ptr = list_ptr->next; + } + + /* Update client list to reflect new situation. If we are not + realized, then nobody knows about us anyway... */ + if (GTK_WIDGET_REALIZED(self)) + hildon_app_apply_client_list(self); +} + + +/** + * hildon_app_notify_view_changed: + * @self : a #HildonApp + * @view_ptr : pointer to the view that is switched to + * + * Updates the X property that contains the currently active view + */ +void hildon_app_notify_view_changed(HildonApp *self, gpointer view_ptr) +{ + g_return_if_fail (HILDON_IS_APP (self)); + g_return_if_fail (view_ptr != NULL); + + /* We need GdkWindow before we can send X messages */ + if (GTK_WIDGET_REALIZED(self)) + { + gulong id = hildon_app_find_view_id(self, view_ptr); + Atom active_view = XInternAtom (GDK_DISPLAY(), + "_NET_ACTIVE_WINDOW", False); + + if (id) { + /* Set _NET_ACTIVE_WINDOW for our own toplevel to contain view id */ + XChangeProperty(GDK_DISPLAY(), GDK_WINDOW_XID(GTK_WIDGET(self)->window), + active_view, XA_WINDOW, 32, PropModeReplace, + (unsigned char *)&id, 1); + XFlush(GDK_DISPLAY()); + } + } +} + + +/** + * hildon_app_find_view_id: + * @self : a #HildonApp + * @view_ptr : pointer to the view whose ID we want to acquire + * + * Returns: the ID of the view, or 0 if not found + * + * Allows mapping of view pointer to its view ID. If NULL is passed + * as the view pointer, returns the ID of the current view. + */ +unsigned long hildon_app_find_view_id(HildonApp *self, gpointer view_ptr) +{ + HildonAppPrivate *priv; + GSList *iter; + + priv = HILDON_APP_GET_PRIVATE (self); + + /* If no view is given, find the ID for the currently visible view */ + if (!view_ptr) + view_ptr = GTK_BIN (self)->child; + if (!view_ptr) + return 0; + + /* Iterate through list and search for given view pointer */ + for (iter = priv->view_ids; iter; iter = iter->next) + { + if ( (gpointer)((view_item *)iter->data)->view_ptr == view_ptr) + return (unsigned long)((view_item *)iter->data)->view_id; + } + + return 0; +} + +/** + * hildon_app_set_killable: + * @self : a #HildonApp + * @killability : truth value indicating whether the app can be killed + * + * Updates information about whether the application can be killed or not by + * Task Navigator (i.e. whether its statesave is up to date) + */ +void hildon_app_set_killable(HildonApp *self, gboolean killability) +{ + HildonAppPrivate *priv = HILDON_APP_GET_PRIVATE (self); + g_return_if_fail (HILDON_IS_APP (self) ); + + if (killability != priv->killable) + { + priv->killable = killability; + + /* If we have a window, then we can actually set this + property. Otherwise we wait until we are realized */ + if (GTK_WIDGET_REALIZED(self)) + hildon_app_apply_killable(self); + } +} + + +/** + * hildon_app_set_ui_manager: + * @self : #HildonApp + * @uim : #GtkUIManager to be set + * + * Sets the #GtkUIManager assigned to the #HildonApp. + * If @uim is NULL, unsets the current ui manager. + * The @HildonApp holds a reference to the ui manager until + * the @HildonApp is destroyed or unset. + */ +void hildon_app_set_ui_manager(HildonApp *self, GtkUIManager *uim) +{ + HildonAppPrivate *priv; + + g_return_if_fail(self && HILDON_IS_APP(self)); + + priv = HILDON_APP_GET_PRIVATE (self); + + /* Release old ui-manager object if such exists */ + if (priv->uim != NULL) + { + g_object_unref (G_OBJECT (priv->uim)); + } + + priv->uim = uim; + + /* If we got new ui-manager (it's perfectly valid not + to give one), acquire reference to it */ + if (priv->uim != NULL) + { + g_object_ref (G_OBJECT (uim)); + } + + g_object_notify (G_OBJECT(self), "ui-manager"); +} + +/** + * hildon_app_get_ui_manager: + * @self : #HildonApp + * + * Gets the #GtkUIManager assigned to the #HildonApp. + * + * Returns: the #GtkUIManager assigned to this application + * or null if no manager is assigned + */ +GtkUIManager *hildon_app_get_ui_manager(HildonApp *self) +{ + HildonAppPrivate *priv; + + g_return_val_if_fail(self && HILDON_IS_APP(self), NULL); + + priv = HILDON_APP_GET_PRIVATE (self); + + return (priv->uim); +} + +/* + * Search for a view with the given id within HildonApp. + * Returns a pointer to the found view, or NULL if not found. + */ +static gpointer find_view(HildonApp *self, unsigned long view_id) +{ + HildonAppPrivate *priv; + GSList *iter; + + priv = HILDON_APP_GET_PRIVATE (self); + + /* Iterate through the list of view ids and search given id */ + for (iter = priv->view_ids; iter; iter = iter->next) + { + if ( (unsigned long)((view_item *)iter->data)->view_id == view_id) + return (gpointer)((view_item *)iter->data)->view_ptr; + } + + return NULL; +} diff --git a/src/hildon-app.h b/src/hildon-app.h new file mode 100644 index 0000000..bf41d04 --- /dev/null +++ b/src/hildon-app.h @@ -0,0 +1,158 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_APP_H__ +#define __HILDON_APP_H__ + +#include +#include +#include "hildon-appview.h" + +G_BEGIN_DECLS +/** + * HildonApp: + * + * Contains only private data not to be touched by outsiders. + */ +typedef struct _HildonApp HildonApp; +typedef struct _HildonAppClass HildonAppClass; + +#define HILDON_TYPE_APP ( hildon_app_get_type() ) + +#define HILDON_APP(obj) (GTK_CHECK_CAST (obj, HILDON_TYPE_APP, \ + HildonApp)) + +#define HILDON_APP_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), \ + HILDON_TYPE_APP, HildonAppClass)) + +#define HILDON_IS_APP(obj) (GTK_CHECK_TYPE (obj, HILDON_TYPE_APP)) + +#define HILDON_IS_APP_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), \ + HILDON_TYPE_APP)) + + +struct _HildonApp { + GtkWindow parent; +}; + +struct _HildonAppClass { + GtkWindowClass parent_class; + void (*topmost_status_acquire) (HildonApp *self); + void (*topmost_status_lose) (HildonApp *self); + void (*switch_to) (HildonApp *self); /* FIXME: Possible browser hack?? */ + void (*im_close) (HildonApp *self); + void (*clipboard_copy) (HildonApp *self, GtkWidget *widget); + void (*clipboard_cut) (HildonApp *self, GtkWidget *widget); + void (*clipboard_paste) (HildonApp *self, GtkWidget *widget); +}; + +#ifndef HILDON_DISABLE_DEPRECATED +/* Make these values >0 so that we can detect when someone sets SMALL-1 + * zoom level (enum seems to be unsigned int) + */ + +/** + * HildonZoomLevel: + * @HILDON_ZOOM_SMALL: Smallest font. + * @HILDON_ZOOM_MEDIUM: Middle size font. + * @HILDON_ZOOM_LARGE: Largest font. + * + * The Hildon zoom levels. Small meaning small font. Large meaning + * large font. These font are specified in the gtkrc files. + * This enum is deprecated and should not be used. It's just + * lecagy stuff from ancient specs. + */ +typedef enum /*< skip >*/ +{ + HILDON_ZOOM_SMALL = 1, + HILDON_ZOOM_MEDIUM = 2, + HILDON_ZOOM_LARGE = 3 +} HildonZoomLevel; + +#define HILDON_TYPE_ZOOM_LEVEL (hildon_zoom_level_get_type ()) + +GType hildon_zoom_level_get_type (void); +#endif /* deprecated */ + + +/* You should use the correct ones from hildon-defines.h + * + * FIXME: These should be removed when API changes are allowed, + * they are not used in hildon code anymore (but might be in external). + */ +#define HILDON_MENU_KEY GDK_F4 +#define HILDON_HOME_KEY GDK_F5 +#define HILDON_TOOLBAR_KEY GDK_T +#define HILDON_FULLSCREEN_KEY GDK_F6 +#define HILDON_INCREASE_KEY GDK_F7 +#define HILDON_DECREASE_KEY GDK_F8 +#define HILDON_TOOLBAR_MODIFIERS (GDK_SHIFT_MASK | GDK_CONTROL_MASK) + +#define HILDON_KEYEVENT_IS_MENU_KEY(keyevent) (keyevent->keyval == HILDON_MENU_KEY) +#define HILDON_KEYEVENT_IS_HOME_KEY(keyevent) (keyevent->keyval == HILDON_HOME_KEY) +#define HILDON_KEYEVENT_IS_TOOLBAR_KEY(keyevent) ((keyevent->keyval == HILDON_TOOLBAR_KEY) && \ + (keyevent->state == HILDON_TOOLBAR_MODIFIERS)) +#define HILDON_KEYEVENT_IS_FULLSCREEN_KEY(keyevent) (keyevent->keyval == HILDON_FULLSCREEN_KEY) +#define HILDON_KEYEVENT_IS_INCREASE_KEY(keyevent) (keyevent->keyval == HILDON_INCREASE_KEY) +#define HILDON_KEYEVENT_IS_DECREASE_KEY(keyevent) (keyevent->keyval == HILDON_DECREASE_KEY) + +#define TRANSIENCY_MAXITER 50 + +GType hildon_app_get_type(void) G_GNUC_CONST; +GtkWidget *hildon_app_new(void); +GtkWidget *hildon_app_new_with_appview(HildonAppView * appview); +void hildon_app_set_appview(HildonApp * self, HildonAppView * appview); +HildonAppView *hildon_app_get_appview(HildonApp * self); +void hildon_app_set_title(HildonApp * self, const gchar * newtitle); +const gchar *hildon_app_get_title(HildonApp * self); + +#ifndef HILDON_DISABLE_DEPRECATED +void hildon_app_set_zoom(HildonApp * self, HildonZoomLevel newzoom); +HildonZoomLevel hildon_app_get_zoom(HildonApp * self); +PangoFontDescription *hildon_app_get_default_font(HildonApp * self); +PangoFontDescription *hildon_app_get_zoom_font(HildonApp * self); +#endif + +void hildon_app_set_two_part_title(HildonApp * self, + gboolean istwoparttitle); +gboolean hildon_app_get_two_part_title(HildonApp * self); + +void hildon_app_set_autoregistration(HildonApp *self, gboolean auto_reg); +void hildon_app_register_view(HildonApp *self, gpointer view_ptr); +gboolean hildon_app_register_view_with_id(HildonApp *self, + gpointer view_ptr, + unsigned long view_id); +void hildon_app_unregister_view(HildonApp *self, gpointer view_ptr); +void hildon_app_unregister_view_with_id(HildonApp *self, + unsigned long view_id); +unsigned long hildon_app_find_view_id(HildonApp *self, gpointer view_ptr); +void hildon_app_notify_view_changed(HildonApp *self, gpointer view_ptr); + +void hildon_app_set_killable(HildonApp *self, gboolean killability); + +void hildon_app_set_ui_manager(HildonApp *self, GtkUIManager *uim); +GtkUIManager *hildon_app_get_ui_manager(HildonApp *self); + +G_END_DECLS +#endif /* __HILDON_APP_H__ */ diff --git a/src/hildon-appview.c b/src/hildon-appview.c new file mode 100644 index 0000000..631eb1e --- /dev/null +++ b/src/hildon-appview.c @@ -0,0 +1,1495 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-appview + * @short_description: A widget which present one view of an application + * @see_also: #HildonApp + * + * #HildonAppView is a widget which presents one view of an application. + * Application can have many different views and the appview helps to organize. + * It has automatic fullscreen and menu handling. It also helps to handle + * components like a toolbar. + */ + +#include +#include +#include +#include +#include "hildon-app.h" +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +#include +#define _(String) gettext(String) + +enum { + PROP_0, + PROP_CONNECTED_ADJUSTMENT, + PROP_FULLSCREEN_KEY_ALLOWED, + PROP_FULLSCREEN, + PROP_TITLE, + PROP_MENU_UI +}; + +/*The size of screen*/ +#define WINDOW_HEIGHT 480 +#define WINDOW_WIDTH 800 + +#define NAVIGATOR_HEIGHT WINDOW_HEIGHT + +#define APPVIEW_HEIGHT 396 +#define APPVIEW_WIDTH 672 + +#define TOOLBAR_HEIGHT 40 +#define TOOLBAR_UP 9 +#define TOOLBAR_DOWN 9 +#define TOOLBAR_MIDDLE 10 +#define TOOLBAR_RIGHT 24 +#define TOOLBAR_LEFT 24 +#define TOOLBAR_WIDTH APPVIEW_WIDTH + +#define WORKAREA_ATOM "_NET_WORKAREA" + +/* Non atom defines */ +#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */ +#define _NET_WM_STATE_ADD 1 /* add/set property */ + +/*Margins + * These margins are set to be 5pixels smaller than in the specs + * Inner things are allocation that extra space + * */ +/* +#define MARGIN_TOOLBAR_TOP 2 +#define MARGIN_TOOLBAR_BOTTOM 6 +#define MARGIN_TOOLBAR_LEFT 22 +#define MARGIN_TOOLBAR_RIGHT 23 +*/ +#define MARGIN_APPVIEW_TOP 0 +#define MARGIN_APPVIEW_BOTTOM 24 +#define MARGIN_APPVIEW_LEFT 24 +#define MARGIN_APPVIEW_RIGHT 24 + + +#define HILDON_APPVIEW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ + HILDON_TYPE_APPVIEW, HildonAppViewPrivate)) + +/*Progressbar*/ +#define DEFAULT_WIDTH 20 +#define DEFAULT_HEIGHT 28 +#define BANNER_WIDTH DEFAULT_WIDTH +#define BANNER_HEIGHT DEFAULT_HEIGHT + +static GtkBinClass *parent_class; + +static void hildon_appview_init(HildonAppView * self); +static void hildon_appview_class_init(HildonAppViewClass * appview_class); + +static void hildon_appview_menupopupfunc(GtkMenu *menu, gint *x, gint *y, + gboolean *push_in, + GtkWidget *widget); +static void hildon_appview_menupopupfuncfull(GtkMenu *menu, gint *x, gint *y, + gboolean *push_in, + GtkWidget *widget); +static gboolean hildon_appview_expose(GtkWidget * widget, + GdkEventExpose * event); +static void hildon_appview_forall(GtkContainer * container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data); +static void hildon_appview_show_all(GtkWidget *widget); + +static void hildon_appview_size_allocate(GtkWidget * widget, + GtkAllocation * allocation); +static void hildon_appview_size_request(GtkWidget * widget, + GtkRequisition * requisition); +static void hildon_appview_finalize(GObject * obj_self); +static void hildon_appview_set_property(GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec); +static void hildon_appview_get_property(GObject * object, guint property_id, + GValue * value, GParamSpec * pspec); +static void hildon_appview_destroy(GtkObject *obj); +static void hildon_appview_real_fullscreen_state_change(HildonAppView * + self, + gboolean + fullscreen); +static void hildon_appview_switched_to(HildonAppView * self); +static void get_client_area(GtkWidget * widget, + GtkAllocation * allocation); + +typedef void (*HildonAppViewSignal) (HildonAppView *, gint, gpointer); + +/* signals */ +enum { + TOOLBAR_CHANGED, + TOOLBAR_TOGGLE_REQUEST, + FULLSCREEN_STATE_CHANGE, + TITLE_CHANGE, + SWITCHED_TO, + SWITCHED_FROM, + INCREASE_BUTTON_EVENT, + DECREASE_BUTTON_EVENT, + HILDON_APPVIEW_LAST_SIGNAL +}; + +static guint appview_signals[HILDON_APPVIEW_LAST_SIGNAL] = { 0 }; + +enum { + WIN_TYPE = 0, + WIN_TYPE_MESSAGE, + MAX_WIN_MESSAGES +}; + +struct _HildonAppViewPrivate { + GtkWidget *menu; + gchar *title; + + GtkAllocation allocation; + + guint fullscreen : 1; + guint fullscreenshortcutallowed : 1; + + /* For future expansion. + * We might use the below variables for disabling keyrepeat if we need it someday. */ + guint increase_button_pressed_down : 1; + guint decrease_button_pressed_down : 1; + gint visible_toolbars; + GtkAdjustment * connected_adjustment; + + gchar *menu_ui; +}; + +/* FIXME: Extremely old Legacy code. I wonder why we need + a custom marshaller in the first place. */ +static void hildon_appview_signal_marshal(GClosure * closure, + GValue * return_value, + guint n_param_values, + const GValue * param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + register HildonAppViewSignal callback; + register GCClosure *cc = (GCClosure *) closure; + register gpointer data1, data2; + + g_assert(n_param_values == 2); + + if (G_CCLOSURE_SWAP_DATA(closure)) { + data1 = closure->data; + data2 = g_value_peek_pointer(param_values + 0); + } else { + data1 = g_value_peek_pointer(param_values + 0); + data2 = closure->data; + } + + callback = + /* FIXME: This is a compilation workaround for gcc > 3.3 since glib is buggy */ + /* see http://bugzilla.gnome.org/show_bug.cgi?id=310175 */ + +#ifdef __GNUC__ + __extension__ +#endif + (HildonAppViewSignal) (marshal_data != + NULL ? marshal_data : cc->callback); + + callback((HildonAppView *) data1, + (gint) g_value_get_int(param_values + 1), data2); +} + +GType hildon_appview_get_type(void) +{ + static GType appview_type = 0; + + if (!appview_type) { + static const GTypeInfo appview_info = { + sizeof(HildonAppViewClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_appview_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonAppView), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_appview_init, + }; + appview_type = g_type_register_static(GTK_TYPE_BIN, + "HildonAppView", + &appview_info, 0); + } + return appview_type; +} + +/* + * Class initialisation. + */ +static void hildon_appview_class_init(HildonAppViewClass * appview_class) +{ + /* Get convenience variables */ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(appview_class); + GObjectClass *object_class = G_OBJECT_CLASS(appview_class); + GtkContainerClass *container_class = + GTK_CONTAINER_CLASS(appview_class); + + /* Set the global parent_class here */ + parent_class = g_type_class_peek_parent(appview_class); + + object_class->set_property = hildon_appview_set_property; + object_class->get_property = hildon_appview_get_property; + + /* Set the widgets virtual functions */ + widget_class->size_allocate = hildon_appview_size_allocate; + widget_class->size_request = hildon_appview_size_request; + widget_class->expose_event = hildon_appview_expose; + widget_class->show_all = hildon_appview_show_all; + /* widget_class->realize = hildon_appview_realize; */ + + /* now the object stuff */ + object_class->finalize = hildon_appview_finalize; + + /* To the container */ + container_class->forall = hildon_appview_forall; + + /* gtkobject stuff*/ + GTK_OBJECT_CLASS(appview_class)->destroy = hildon_appview_destroy; + + /* And own virtual functions */ + appview_class->fullscreen_state_change = + hildon_appview_real_fullscreen_state_change; + appview_class->switched_to = hildon_appview_switched_to; + + g_type_class_add_private(appview_class, + sizeof(struct _HildonAppViewPrivate)); + + /* New signals */ + appview_signals[TOOLBAR_CHANGED] = + g_signal_new("toolbar-changed", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(HildonAppViewClass, toolbar_changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + appview_signals[TOOLBAR_TOGGLE_REQUEST] = + g_signal_new("toolbar-toggle-request", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(HildonAppViewClass, + toolbar_toggle_request), NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + appview_signals[FULLSCREEN_STATE_CHANGE] = + g_signal_new("fullscreen_state_change", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(HildonAppViewClass, + fullscreen_state_change), NULL, NULL, + hildon_appview_signal_marshal, G_TYPE_NONE, 1, + G_TYPE_INT); + + appview_signals[TITLE_CHANGE] = + g_signal_new("title_change", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(HildonAppViewClass, title_change), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + appview_signals[SWITCHED_TO] = + g_signal_new("switched_to", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(HildonAppViewClass, switched_to), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + appview_signals[SWITCHED_FROM] = + g_signal_new("switched_from", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(HildonAppViewClass, switched_from), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + appview_signals[INCREASE_BUTTON_EVENT] = + g_signal_new("increase_button_event", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(HildonAppViewClass, increase_button_event), + NULL, NULL, + g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, + G_TYPE_UINT); + + appview_signals[DECREASE_BUTTON_EVENT] = + g_signal_new("decrease_button_event", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(HildonAppViewClass, decrease_button_event), + NULL, NULL, + g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, + G_TYPE_UINT); + + /* New properties */ + g_object_class_install_property(object_class, PROP_CONNECTED_ADJUSTMENT, + g_param_spec_object("connected-adjustment", + "Connected GtkAdjustment", + "The GtkAdjustment. The increase and decrease hardware buttons are mapped to this.", + GTK_TYPE_ADJUSTMENT, + G_PARAM_READWRITE)); + + g_object_class_install_property(object_class, PROP_FULLSCREEN_KEY_ALLOWED, + g_param_spec_boolean("fullscreen-key-allowed", + "Fullscreen key allowed", + "Whether the fullscreen key is allowed or not", + FALSE, + G_PARAM_READWRITE)); + + g_object_class_install_property(object_class, PROP_FULLSCREEN, + g_param_spec_boolean("fullscreen", + "Fullscreen", + "Whether the appview should be fullscreen or not", + FALSE, + G_PARAM_READWRITE)); + g_object_class_install_property(object_class, PROP_TITLE, + g_param_spec_string("title", + "Title", + "Appview title", + NULL, + G_PARAM_READWRITE)); + g_object_class_install_property(object_class, PROP_MENU_UI, + g_param_spec_string("menu-ui", + "Menu UI string", + "UI string for application view menu", + NULL, + G_PARAM_READWRITE)); + widget_class = (GtkWidgetClass*) appview_class; +} + +/* + * Performs the initialisation of the widget. + */ +static void hildon_appview_init(HildonAppView * self) +{ + HildonAppViewPrivate *priv = self->priv = + HILDON_APPVIEW_GET_PRIVATE(self); + + /* the vbox is used to handle both the view's main body and how many + * toolbars as the user wants */ + + self->vbox = gtk_vbox_new(TRUE, TOOLBAR_MIDDLE); + /* TOOLBAR_MIDDLE is here properly used, as originally meant. In order to + * be free to use whatever distance between toolbars, it's crucial to mind + * that the relevant gtkrc file must contain the following border property + * for the "toolbar-frame-middle" property: border = {24, 24, 5, 4} + */ + + gtk_widget_set_parent(self->vbox, GTK_WIDGET(self)); + priv->menu = NULL; + priv->visible_toolbars = 0; + + priv->title = g_strdup(""); + + priv->fullscreen = FALSE; + priv->fullscreenshortcutallowed = FALSE; + priv->increase_button_pressed_down = FALSE; + priv->decrease_button_pressed_down = FALSE; + + priv->connected_adjustment = NULL; +} + +/* + * Performs the standard gtk finalize function, freeing allocated + * memory and propagating the finalization to the parent. + */ +static void hildon_appview_finalize(GObject * obj_self) +{ + HildonAppView *self; + g_assert(HILDON_APPVIEW(obj_self)); + self = HILDON_APPVIEW(obj_self); + + if (self->priv->menu_ui) + g_free (self->priv->menu_ui); + + if (self->priv->connected_adjustment != NULL) + g_object_remove_weak_pointer (G_OBJECT (self->priv->connected_adjustment), + (gpointer) &self->priv->connected_adjustment); + + if (G_OBJECT_CLASS(parent_class)->finalize) + G_OBJECT_CLASS(parent_class)->finalize(obj_self); + + g_free(self->priv->title); +} + +/* + * An accessor to set private properties of HildonAppView. + */ +static void hildon_appview_set_property(GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + HildonAppView *appview = HILDON_APPVIEW (object); + + switch (property_id) { + case PROP_CONNECTED_ADJUSTMENT: + hildon_appview_set_connected_adjustment (appview, g_value_get_object (value)); + break; + + case PROP_FULLSCREEN_KEY_ALLOWED: + hildon_appview_set_fullscreen_key_allowed (appview, g_value_get_boolean (value)); + break; + + case PROP_FULLSCREEN: + hildon_appview_set_fullscreen (appview, g_value_get_boolean (value)); + break; + + case PROP_TITLE: + hildon_appview_set_title (appview, g_value_get_string (value)); + break; + + case PROP_MENU_UI: + hildon_appview_set_menu_ui (appview, g_value_get_string (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +/* + * An accessor to get private properties of HildonAppView. + */ +static void hildon_appview_get_property(GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + HildonAppViewPrivate *priv = HILDON_APPVIEW_GET_PRIVATE(object); + + switch (property_id) { + case PROP_CONNECTED_ADJUSTMENT: + g_value_set_object (value, priv->connected_adjustment); + break; + + case PROP_FULLSCREEN_KEY_ALLOWED: + g_value_set_boolean (value, priv->fullscreenshortcutallowed); + break; + + case PROP_FULLSCREEN: + g_value_set_boolean (value, priv->fullscreen); + break; + + case PROP_TITLE: + g_value_set_string (value, priv->title); + break; + + case PROP_MENU_UI: + g_value_set_string (value, priv->menu_ui); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +/* + * Used when the HildonAppView is exposed, this function gets a GtkBoxChild + * as first argument, and a pointer to a gint as second argument. If such + * GtkBoxChild is visible, the function increments the gint. It is used + * in a loop, to compute the number of visible toolbars. + */ +static void visible_toolbar(gpointer child, gpointer number_of_visible_toolbars) +{ + if(GTK_WIDGET_VISIBLE(((GtkBoxChild *)child)->widget)) + (*((gint *)number_of_visible_toolbars))++; +} + +/* + * Used in the paint_toolbar function to discover how many toolbars are + * above the find toolbar. It's called in a loop that iterates through + * all the children of the GtkVBox of the HildonAppView. + */ +static void find_findtoolbar_index(gpointer child, gpointer number_of_visible_toolbars) +{ + gint *pass_bundle = (gint *)number_of_visible_toolbars; + + if(((GtkBoxChild *)child)->widget->allocation.y < pass_bundle[0] + && GTK_WIDGET_VISIBLE(((GtkBoxChild *)child)->widget)) + pass_bundle[1]++; +} + +/* + * Used in the paint_toolbar function, it's get a GtkBoxChild as first argument + * and a pointer to a GtkWidget as the second one, which will be addressed to + * the find toolbar widget, if it is contained in the given GtkBoxChild. + */ +static void find_findtoolbar(gpointer child, gpointer widget) +{ + if(HILDON_IS_FIND_TOOLBAR(((GtkBoxChild *)child)->widget) + && GTK_WIDGET_VISIBLE(((GtkBoxChild *)child)->widget)) + (*((GtkWidget **)widget)) = ((GtkBoxChild *)child)->widget; +} + +/* + * Paints all the toolbar children of the GtkVBox of the HildonAppView. + */ +static void paint_toolbar(GtkWidget *widget, GtkBox *box, + GdkEventExpose * event, + gboolean fullscreen) +{ + gint toolbar_num = 0; + gint ftb_index = 0; + gint count; + GtkWidget *findtoolbar = NULL; + gchar toolbar_mode[40]; + + /* Iterate through all the children of the vbox of the HildonAppView. + * The visible_toolbar function increments toolbar_num if the toolbar + * is visible. After this loop, toobar_num will contain the number + * of the visible toolbars. */ + g_list_foreach(box->children, visible_toolbar, + (gpointer) &toolbar_num); + if(toolbar_num <= 0) + return; + + /* Loop through all the children of the GtkVBox of the HildonAppView. + * The find_findtoolbar function will assign a pointer to the find toolbar + * to "findtoolbar" argument. If the findtoolbar is not found, i.e. it + * isn't in the GtkVBox, then the "findtoolbar" argument will stay NULL */ + g_list_foreach(box->children, find_findtoolbar, + (gpointer) &findtoolbar); + if(findtoolbar != NULL){ + gint pass_bundle[2]; + + /* an array for convient data passing + * the first member contains the y allocation + * of the find toolbar, and the second allocation + * contains the index(how many toolbars are above + * find toolbar) */ + pass_bundle[0] = findtoolbar->allocation.y; + pass_bundle[1] = ftb_index; + + /* computes how many toolbars are above the find toolbar, and the + * value is stored in pass_bundle[1] */ + g_list_foreach(box->children, find_findtoolbar_index, + (gpointer) pass_bundle); + ftb_index = pass_bundle[1]; + } + /*upper border*/ + sprintf(toolbar_mode, "toolbar%sframe-top", + fullscreen ? "-fullscreen-" : "-"); + gtk_paint_box(widget->style, widget->window, + GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, + &event->area, widget, toolbar_mode, + widget->allocation.x, + GTK_WIDGET(box)->allocation.y -TOOLBAR_UP, + widget->allocation.width, TOOLBAR_UP); + + /*top most toolbar painting*/ + if(findtoolbar != NULL && ftb_index == 0 ) + { + sprintf(toolbar_mode, "findtoolbar%s", + fullscreen ? "-fullscreen" : ""); + + gtk_paint_box(widget->style, widget->window, + GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, + &event->area, widget, toolbar_mode, + widget->allocation.x, + GTK_WIDGET(box)->allocation.y, + widget->allocation.width, + TOOLBAR_HEIGHT); + }else{ + sprintf(toolbar_mode, "toolbar%s", + fullscreen ? "-fullscreen" : ""); + gtk_paint_box(widget->style, widget->window, + GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, + &event->area, widget, toolbar_mode, + widget->allocation.x, + GTK_WIDGET(box)->allocation.y, + widget->allocation.width, + TOOLBAR_HEIGHT); + } + /*multi toolbar painting*/ + for(count = 0; count < toolbar_num - 1; count++) + { + sprintf(toolbar_mode, "toolbar%sframe-middle", + fullscreen ? "-fullscreen-" : "-"); + + gtk_paint_box(widget->style, widget->window, + GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, + &event->area, widget, toolbar_mode, + widget->allocation.x, + GTK_WIDGET(box)->allocation.y + + (1 + count) * TOOLBAR_HEIGHT + + count * TOOLBAR_MIDDLE, + widget->allocation.width, + TOOLBAR_MIDDLE); + + if(findtoolbar != NULL && count + 1 == ftb_index){ + sprintf(toolbar_mode, "findtoolbar%s", + fullscreen ? "-fullscreen" : ""); + + gtk_paint_box(widget->style, widget->window, + GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, + &event->area, widget, toolbar_mode, + widget->allocation.x, + GTK_WIDGET(box)->allocation.y + + (1 + count) * (TOOLBAR_HEIGHT + TOOLBAR_MIDDLE), + widget->allocation.width, + TOOLBAR_HEIGHT); + }else{ + sprintf(toolbar_mode, "toolbar%s", + fullscreen ? "-fullscreen" : ""); + + gtk_paint_box(widget->style, widget->window, + GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, + &event->area, widget, toolbar_mode, + widget->allocation.x, + GTK_WIDGET(box)->allocation.y + + (1 + count) * (TOOLBAR_HEIGHT + TOOLBAR_MIDDLE), + widget->allocation.width, + TOOLBAR_HEIGHT); + } + } + sprintf(toolbar_mode, "toolbar%sframe-bottom", + fullscreen ? "-fullscreen-" : "-"); + + gtk_paint_box(widget->style, widget->window, + GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, + &event->area, widget, toolbar_mode, + widget->allocation.x, + GTK_WIDGET(box)->allocation.y + + GTK_WIDGET(box)->allocation.height, + widget->allocation.width, TOOLBAR_DOWN); +} + +/* + * Callback function to an expose event. + */ +static gboolean hildon_appview_expose(GtkWidget * widget, + GdkEventExpose * event) +{ + gint toolbar_num = 0; + GtkBox *box = GTK_BOX(HILDON_APPVIEW(widget)->vbox); + + if(GTK_WIDGET_VISIBLE(box) && box->children != NULL) + { + HildonAppViewPrivate *priv = HILDON_APPVIEW_GET_PRIVATE(widget); + + /* Iterate through all the children of the vbox of the HildonAppView. + * The visible_toolbar function increments toolbar_num if the toolbar + * is visible. After this loop, toobar_num will contain the number + * of the visible toolbars. */ + g_list_foreach(box->children, visible_toolbar, + (gpointer) &toolbar_num); + + if( priv->visible_toolbars != toolbar_num) + { + /* If the code reaches this block, it means that a toolbar as + * been added or removed since last time the view was drawn. + * Let's then compute the new height of the toolbars areas */ + gint y_pos = 0; + /* the height difference */ + gint change = (priv->visible_toolbars - toolbar_num) * + (TOOLBAR_HEIGHT+TOOLBAR_MIDDLE+TOOLBAR_UP); + if( change < 0 ) + change = TOOLBAR_MIDDLE + TOOLBAR_UP; + /* the new y-coordinate for the toolbars area */ + y_pos = HILDON_APPVIEW(widget)->vbox->allocation.y - change; + + gtk_widget_queue_draw_area(widget, 0, y_pos, widget->allocation.width, + change + HILDON_APPVIEW(widget)->vbox->allocation.height + + TOOLBAR_DOWN); + priv->visible_toolbars = toolbar_num; + } + } + + + if (HILDON_APPVIEW(widget)->priv->fullscreen) + { + if (toolbar_num > 0) + paint_toolbar(widget, box, event, TRUE); + } + else + { + gint appview_height_decrement = 0; + if (toolbar_num > 0) + { + appview_height_decrement = toolbar_num * TOOLBAR_HEIGHT + + (toolbar_num - 1) * TOOLBAR_MIDDLE + + TOOLBAR_UP + TOOLBAR_DOWN; + + paint_toolbar(widget, box, event, FALSE); + } + else + { + appview_height_decrement = MARGIN_APPVIEW_BOTTOM; + + gtk_paint_box(widget->style, widget->window, + GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, + &event->area, widget, "bottom-border", + widget->allocation.x, + widget->allocation.y + + (widget->allocation.height - MARGIN_APPVIEW_BOTTOM), + widget->allocation.width, MARGIN_APPVIEW_BOTTOM); + } + gtk_paint_box( widget->style, widget->window, + GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, + &event->area, + widget, "left-border", widget->allocation.x, + widget->allocation.y, MARGIN_APPVIEW_LEFT, + widget->allocation.height - appview_height_decrement ); + gtk_paint_box( widget->style, widget->window, + GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, + &event->area, + widget, "right-border", + (widget->allocation.x + + widget->allocation.width) - + MARGIN_APPVIEW_RIGHT, widget->allocation.y, + MARGIN_APPVIEW_RIGHT, + widget->allocation.height - appview_height_decrement ); + } + + GTK_WIDGET_CLASS(parent_class)->expose_event(widget, event); + + return FALSE; +} + +/* + * Responds to the usual size_request signal. + */ +static void hildon_appview_size_request(GtkWidget * widget, + GtkRequisition * requisition) +{ + HildonAppViewPrivate *priv = HILDON_APPVIEW(widget)->priv; + GtkWidget *child = GTK_BIN(widget)->child; + + /* forward the size_request to the eventual child of the main container */ + if (child) + gtk_widget_size_request(child, requisition); + + /* forward the size_request to the eventual vbox (which may contain + * toolbars) */ + if (HILDON_APPVIEW(widget)->vbox != NULL) + gtk_widget_size_request(HILDON_APPVIEW(widget)->vbox, requisition); + + /* express the size_request for the view */ + if (priv->fullscreen) { + requisition->height = WINDOW_HEIGHT; + requisition->width = WINDOW_WIDTH; + } else { + requisition->height = APPVIEW_HEIGHT; + requisition->width = APPVIEW_WIDTH; + } +} + +/* + * Computes size and position for the children of the view. + */ +static void hildon_appview_size_allocate(GtkWidget * widget, + GtkAllocation * allocation) +{ + GtkAllocation box_allocation; + GtkAllocation alloc = *allocation; + gint border_width = GTK_CONTAINER(widget)->border_width; + GtkBin *bin = GTK_BIN(widget); + GtkBox *box = GTK_BOX(HILDON_APPVIEW(widget)->vbox); + gboolean at_least_one_visible_toolbar = FALSE; + + if(!GTK_IS_WIDGET(bin->child)) return; + + widget->allocation = *allocation; + + if (bin->child != NULL && GTK_IS_WIDGET(bin->child)) { + if (HILDON_APPVIEW(widget)->priv->fullscreen) { + alloc.x += border_width; + alloc.y += border_width; + alloc.width -= (border_width * 2); + alloc.height -= (border_width * 2); + } else { + alloc.x += border_width + MARGIN_APPVIEW_LEFT; + alloc.y += border_width + MARGIN_APPVIEW_TOP; + alloc.width -= (border_width * 2) + (MARGIN_APPVIEW_LEFT + + MARGIN_APPVIEW_RIGHT); + alloc.height -= (border_width * 2) + MARGIN_APPVIEW_TOP; + } + } + + if (box->children != NULL) { + gint length = 0; + gint box_height = 0; + /* Iterate through all the children of the vbox of the HildonAppView. + * The visible_toolbar function increments toolbar_num if the toolbar + * is visible. After this loop, toobar_num will contain the number + * of the visible toolbars. */ + g_list_foreach(box->children, visible_toolbar, + (gpointer) &length); + if(length > 0){ + box_height = length * TOOLBAR_HEIGHT + + (length - 1) * TOOLBAR_MIDDLE; + + if(bin->child != NULL) { + alloc.height = alloc.height - box_height - TOOLBAR_UP + - TOOLBAR_DOWN; + at_least_one_visible_toolbar = TRUE; + } + + box_allocation.y = allocation->height - box_height - TOOLBAR_DOWN; + box_allocation.height = box_height; + box_allocation.x = allocation->x + TOOLBAR_LEFT; + box_allocation.width = allocation->width - TOOLBAR_LEFT - + TOOLBAR_RIGHT; + gtk_widget_size_allocate(GTK_WIDGET(box), &box_allocation); + } + } + + /* The bottom skin graphics is visible only when there are no toolbars */ + if ((HILDON_APPVIEW(widget)->priv->fullscreen == FALSE) && + (at_least_one_visible_toolbar == FALSE)) + alloc.height -= MARGIN_APPVIEW_BOTTOM; + + gtk_widget_size_allocate(GTK_WIDGET(bin->child), &alloc); +} + +/* + * Overrides gtk_container_forall, calling the callback function for each of + * the children of HildonAppPrivate. + */ +static void hildon_appview_forall(GtkContainer * container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) +{ + HildonAppView *self = HILDON_APPVIEW(container); + + g_assert(callback != NULL); + + GTK_CONTAINER_CLASS(parent_class)->forall(container, include_internals, + callback, callback_data); + if(include_internals && self->vbox != NULL) + (* callback)(GTK_WIDGET(self->vbox), callback_data); +} + +/** + * Shows all the widgets in the container. + */ +static void hildon_appview_show_all(GtkWidget *widget) +{ + HildonAppView *self = HILDON_APPVIEW(widget); + + /* Toolbar items */ + gtk_widget_show_all(self->vbox); + + /* Parent handless stuff inside appview */ + GTK_WIDGET_CLASS(parent_class)->show_all(widget); +} + +/* + * Frees all the resources and propagates the destroy call to the parent. + */ +static void hildon_appview_destroy(GtkObject *obj) +{ + HildonAppView *self = HILDON_APPVIEW(obj); + + if(self->vbox != NULL){ + gtk_widget_unparent(self->vbox); + self->vbox = NULL; + } + + GTK_OBJECT_CLASS(parent_class)->destroy(obj); +} + +/*******************/ +/* Signals */ +/*******************/ + +/*Signal - When is changed to this appview, this is called*/ +static void hildon_appview_switched_to(HildonAppView * self) +{ + GtkWidget *parent; + + g_assert(self && HILDON_IS_APPVIEW(self)); + + parent = gtk_widget_get_parent(GTK_WIDGET(self)); + hildon_appview_set_fullscreen( self, self->priv->fullscreen ); +} + +/*Signal - When the fullscreen state is changed, this is called*/ +static void hildon_appview_real_fullscreen_state_change(HildonAppView * + self, + gboolean + fullscreen) +{ + HildonAppViewPrivate *priv; + g_assert(self && HILDON_IS_APPVIEW(self)); + priv = self->priv; + + /* Ensure that state is really changed */ + if( priv->fullscreen == fullscreen ) + return; + + if( fullscreen ) + gtk_window_fullscreen( GTK_WINDOW( + gtk_widget_get_parent(GTK_WIDGET(self))) ); + else + gtk_window_unfullscreen( GTK_WINDOW( + gtk_widget_get_parent(GTK_WIDGET(self))) ); + + priv->fullscreen = fullscreen; +} + +/*******************/ +/* General */ +/*******************/ + + +/* + * queries a window for the root window coordinates and size of its + * client area (i.e. minus the title borders etc.) + */ +static void get_client_area(GtkWidget * widget, GtkAllocation * allocation) +{ + GdkWindow *window = widget->window; + + if (window) + gdk_window_get_origin(window, &allocation->x, &allocation->y); + else + memset( allocation, 0, sizeof(GtkAllocation) ); +} + +/*The menu popuping needs a menu popup-function*/ +static void hildon_appview_menupopupfunc( GtkMenu *menu, gint *x, gint *y, + gboolean *push_in, GtkWidget *widget ) +{ + GtkAllocation client_area = { 0, 0, 0, 0 }; + + get_client_area( GTK_WIDGET(widget), &client_area ); + + gtk_widget_style_get (GTK_WIDGET (menu), "horizontal-offset", x, + "vertical-offset", y, NULL); + + *x += client_area.x; + *y += client_area.y; + +} + +/* Similar to above, but used in fullscreen mode */ +static void hildon_appview_menupopupfuncfull( GtkMenu *menu, gint *x, gint *y, + gboolean *push_in, + GtkWidget *widget ) +{ + gtk_widget_style_get (GTK_WIDGET (menu), "horizontal-offset", x, + "vertical-offset", y, NULL); + + *x = MAX (0, *x); + *y = MAX (0, *y); +} + +/*******************/ +/*public functions*/ +/*******************/ + + +/** + * hildon_appview_new: + * @title:the application view title of the new @HildonAppView + * + * Use this function to create a new application view. The title will + * be set only if two-part-title is enabled on the @HildonApp. + * + * Returns: A #HildonAppView. + **/ +GtkWidget *hildon_appview_new(const gchar * title) +{ + HildonAppView *newappview = g_object_new(HILDON_TYPE_APPVIEW, NULL); + + hildon_appview_set_title(newappview, title); + return GTK_WIDGET(newappview); +} + +/** + * hildon_appview_add_with_scrollbar + * @self : a @HildonAppView + * @child : a @GtkWidget + * + * Adds the @child to the @self(HildonAppView) and creates a vertical + * scrollbar to it. Similar as adding first a #GtkScrolledWindow + * and then the @child to it. + */ +void hildon_appview_add_with_scrollbar(HildonAppView * self, + GtkWidget * child) +{ + GtkScrolledWindow *scrolledw; + + g_return_if_fail(HILDON_IS_APPVIEW(self)); + g_return_if_fail(GTK_IS_WIDGET(child)); + g_return_if_fail(child->parent == NULL); + + scrolledw = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL)); + gtk_scrolled_window_set_policy(scrolledw, GTK_POLICY_NEVER, + GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type(scrolledw, GTK_SHADOW_NONE); + + /* Check whether child widget supports adjustments */ + if (GTK_WIDGET_GET_CLASS (child)->set_scroll_adjustments_signal) + gtk_container_add(GTK_CONTAINER(scrolledw), child); + else + { + if( GTK_IS_CONTAINER(child) ) + gtk_container_set_focus_vadjustment( GTK_CONTAINER(child), + gtk_scrolled_window_get_vadjustment(scrolledw) ); + gtk_scrolled_window_add_with_viewport(scrolledw, child); + } + + gtk_container_add(GTK_CONTAINER(self), GTK_WIDGET(scrolledw)); +} + +/** + * hildon_appview_get_title: + * @self : a #HildonAppView + * + * Gets the title of given #HildonAppView. + * + * Returns: the title of the application view + */ +const gchar *hildon_appview_get_title(HildonAppView * self) +{ + g_return_val_if_fail(self && HILDON_IS_APPVIEW(self), ""); + return self->priv->title; +} + +/** + * hildon_appview_set_title: + * @self : a #HildonAppView + * @newname : the new title of the application view. + * + * Sets an title of an application view. The title is visible only if + * two-part-title is enabled on the #HildonApp. + * + */ +void hildon_appview_set_title(HildonAppView * self, const gchar * newname) +{ + gchar *oldtitle; + + g_return_if_fail(self && HILDON_IS_APPVIEW(self)); + oldtitle = self->priv->title; + + if (newname != NULL) + self->priv->title = g_strdup(newname); + else + self->priv->title = g_strdup(""); + + g_free(oldtitle); + g_signal_emit_by_name(G_OBJECT(self), "title_change"); +} + +/** + * hildon_appview_set_toolbar: + * @self: a #HildonAppView + * @toolbar: a #GtkToolbar + * + * Sets the #GtkToolbar to given #HildonAppView. This is, however, not a + * recommended way to set your toolbars. When you have multi toolbars, calling + * this function more than once will just replace the bottom most toolbar. + * There is a #GtkVBox in #HildonAppView's public structure, the programmer + * is responsible to pack his toolbars in the #GtkVBox, and #HildonAppView will + * take care of putting them at the right place. + * + */ +#ifndef HILDON_DISABLE_DEPRECATED +void hildon_appview_set_toolbar(HildonAppView * self, GtkToolbar * toolbar) +{ + GtkBox *box = GTK_BOX(HILDON_APPVIEW(self)->vbox); + g_return_if_fail(self && HILDON_IS_APPVIEW(self)); + if(toolbar != NULL)/*for failure checking*/ + g_return_if_fail(GTK_IS_TOOLBAR(toolbar)); + + /*if it is NULL, it unsets the last one, + * if it is not null, it unsets the last one anyway*/ + if(box->children != NULL){ + GtkWidget *last_widget; + + last_widget = ((GtkBoxChild *)g_list_last + (box->children)->data)->widget; + gtk_container_remove(GTK_CONTAINER(box), + last_widget); + } + + gtk_box_pack_end(box, GTK_WIDGET(toolbar), TRUE, TRUE, 0); + gtk_widget_queue_resize(GTK_WIDGET(self)); + /*deprecated signal*/ + g_signal_emit_by_name(G_OBJECT(self), "toolbar-changed"); +} +#endif +/** + * hildon_appview_get_toolbar: + * @self: a #HildonAppView + * + * This function will only + * return the last widget that has been packed into the #GtkVBox in the public + * structure. Note this does not, however, mean that it is the bottom most + * toolbar. + * + * Return value: the #GtkToolbar assigned to this application view. + **/ +#ifndef HILDON_DISABLE_DEPRECATED +GtkToolbar *hildon_appview_get_toolbar(HildonAppView * self) +{ + GtkBox *box = GTK_BOX(HILDON_APPVIEW(self)->vbox); + g_return_val_if_fail(self != NULL && HILDON_IS_APPVIEW(self), FALSE); + if(box != NULL && box->children != NULL) + return GTK_TOOLBAR(((GtkBoxChild*) + g_list_last(box->children)->data)->widget); + else + return NULL; +} +#endif +/** + * hildon_appview_set_fullscreen: + * @self: a #HildonAppView + * @fullscreen: the new state of fullscreen mode. TRUE means fullscreen + * will be set. FALSE the opposite. + * + * Set the fullscreen state of given #HildonAppView class. + */ +void hildon_appview_set_fullscreen(HildonAppView * self, + gboolean fullscreen) +{ + g_return_if_fail(self && HILDON_IS_APPVIEW(self)); + g_signal_emit_by_name(G_OBJECT(self), "fullscreen_state_change", + fullscreen); +} + +/** + * hildon_appview_get_fullscreen: + * @self: a #HildonAppView + * + * Gets the current state of fullscreen mode. + * + * Returns: the current state of fullscreen mode + */ +gboolean hildon_appview_get_fullscreen(HildonAppView * self) +{ + g_return_val_if_fail(self && HILDON_IS_APPVIEW(self), FALSE); + return self->priv->fullscreen; +} + +/** + * hildon_appview_get_fullscreen_key_allowed: + * @self: a #HildonAppView + * + * Check if fullscreening with a shortcut is allowed for given + * #HildonAppView. + * + * Returns: wheter it's possible to swith fullscreen on/off with + * a shortcut key + */ +gboolean hildon_appview_get_fullscreen_key_allowed(HildonAppView * self) +{ + g_return_val_if_fail(self && HILDON_IS_APPVIEW(self), FALSE); + return self->priv->fullscreenshortcutallowed; +} + +/** + * hildon_appview_set_fullscreen_key_allowed: + * @self: a #HildonAppView + * @allow: wheter it's possible to swith fullscreen on/off with + * a shortcut key + * + * Sets given #HildonAppView whether to allow toggling fullscreen mode + * with a shortcut key. + */ +void hildon_appview_set_fullscreen_key_allowed(HildonAppView * self, + gboolean allow) +{ + g_return_if_fail(self && HILDON_IS_APPVIEW(self)); + self->priv->fullscreenshortcutallowed = allow; +} + +/** + * hildon_appview_get_menu: + * @self : #HildonAppView + * + * Gets the #GtMenu assigned to the #HildonAppview. + * + * Returns: the #GtkMenu assigned to this application view + */ +GtkMenu *hildon_appview_get_menu(HildonAppView * self) +{ + g_return_val_if_fail(self && HILDON_IS_APPVIEW(self), NULL); + + if (self->priv->menu == NULL) { + /* Create hildonlike menu */ + + GtkUIManager *uim; + GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (self)); + + /* Try to get appview menu from ui manager */ + if (parent && HILDON_IS_APP (parent)) + { + uim = hildon_app_get_ui_manager (HILDON_APP (parent)); + if (uim) + { + self->priv->menu = + gtk_ui_manager_get_widget (uim, "/HildonApp"); + } + } + + + if (self->priv->menu == NULL) + { + /* Fall back to oldskool menus */ + self->priv->menu = GTK_WIDGET (g_object_new (GTK_TYPE_MENU, NULL)); + } + + gtk_widget_set_name(GTK_WIDGET(self->priv->menu), + "menu_force_with_corners"); + gtk_widget_show_all (self->priv->menu); + } + + return GTK_MENU(self->priv->menu); +} + +/** + * _hildon_appview_toggle_menu: + * @self : a #HildonAppView + * @button_event_time : + * + * This function should be only called from @HildonApp. + * Should be renamed to popup menu. Just the first parameter is used. + * + * Returns: Whether or not something was done (whether or not we had + * a menu) + */ +gboolean _hildon_appview_toggle_menu(HildonAppView * self, + Time button_event_time) +{ + GList *children; + + g_return_val_if_fail(self && HILDON_IS_APPVIEW(self), FALSE); + + if (!self->priv->menu) + return FALSE; + + if (GTK_WIDGET_VISIBLE(self->priv->menu)) { + gtk_menu_popdown(GTK_MENU(self->priv->menu)); + gtk_menu_shell_deactivate(GTK_MENU_SHELL(self->priv->menu)); + return TRUE; + } + + /* Avoid opening an empty menu */ + children = gtk_container_get_children( + GTK_CONTAINER(hildon_appview_get_menu(self))); + if (children != NULL) { + GtkWidget *menu; + + g_list_free(children); + menu = GTK_WIDGET(hildon_appview_get_menu(self)); + if (self->priv->fullscreen) { + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, + (GtkMenuPositionFunc) + hildon_appview_menupopupfuncfull, + self, 0, button_event_time); + } else { + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, + (GtkMenuPositionFunc) + hildon_appview_menupopupfunc, + self, 0, button_event_time); + } + gtk_menu_shell_select_first(GTK_MENU_SHELL(menu), TRUE); + return TRUE; + } + return FALSE; + +} + +/** + * _hildon_appview_menu_visible + * @self: a #HildonAppView + * + * Checks whether the titlebar menu is currently visible + * Returns: TRUE if the menu is visible, FALSE if not + */ + +gboolean _hildon_appview_menu_visible(HildonAppView * self) +{ + g_return_val_if_fail (HILDON_IS_APPVIEW (self), FALSE); + + return GTK_WIDGET_VISIBLE(GTK_WIDGET(hildon_appview_get_menu(self))); +} + +/** + * hildon_appview_set_connected_adjustment + * @self : #HildonAppView + * @adjustment : a new #GtkAdjustment set to reach to increase + * / decrease hardware keys or NULL to unset + * + * Sets a #GtkAdjustment which will change when increase/decrease buttons + * are pressed. + */ +void hildon_appview_set_connected_adjustment (HildonAppView * self, + GtkAdjustment * adjustment) +{ + g_return_if_fail (HILDON_IS_APPVIEW (self)); + + /* Disconnect old adjustment */ + if (self->priv->connected_adjustment != NULL) + g_object_remove_weak_pointer (G_OBJECT (self->priv->connected_adjustment), + (gpointer) &self->priv->connected_adjustment); + + /* Start using the new one */ + self->priv->connected_adjustment = adjustment; + if (self->priv->connected_adjustment != NULL) + g_object_add_weak_pointer (G_OBJECT (self->priv->connected_adjustment), + (gpointer) &self->priv->connected_adjustment); +} + +/** + * hildon_appview_get_connected_adjustment + * @self : a #HildonAppView + * + * Retrieves the #GtkAdjustment which is connected to this application view + * and is changed with increase / decrease hardware buttons. + * + * Returns: currently connectd #GtkAdjustment assigned to this + * application view or NULL if it's not set + */ +GtkAdjustment * hildon_appview_get_connected_adjustment (HildonAppView * self) +{ + g_return_val_if_fail (HILDON_IS_APPVIEW (self), NULL); + + return self->priv->connected_adjustment; +} + + +/** + * hildon_appview_set_menu_ui + * @self : a #HildonAppView + * @ui_string : a #GtkUIManager ui description string + * + * Sets the ui description (xml) from which the UIManager creates menus + * (see @GtkUIManager for details on how to use it) + */ +void hildon_appview_set_menu_ui(HildonAppView *self, const gchar *ui_string) +{ + g_return_if_fail (HILDON_IS_APPVIEW (self)); + + if (ui_string) + { + if (self->priv->menu_ui) + g_free (self->priv->menu_ui); + + self->priv->menu_ui = g_strdup (ui_string); + + /* FIXME: We should update the menu here, preferrably by a + * hildon_app_ensure_menu_update() which re-installs the menu ui + * and calls gtk_ui_manager_ensure_update() + */ + } + else + { + /* Reset the UI */ + if (self->priv->menu_ui) + { + g_free (self->priv->menu_ui); + self->priv->menu_ui = NULL; + } + } + + g_object_notify (G_OBJECT(self), "menu-ui"); +} + +/** + * hildon_appview_get_menu_ui + * @self : a #HildonAppView + * + * Sets the ui description (xml) from which the UIManager creates menus + * (see #GtkUIManager for details on how to use it) + * + * Returns: currently set ui description + */ +const gchar *hildon_appview_get_menu_ui(HildonAppView *self) +{ + g_return_val_if_fail (HILDON_IS_APPVIEW (self), NULL); + + return (self->priv->menu_ui); + +} + +/* Called when '+' hardkey is pressed/released */ +void _hildon_appview_increase_button_state_changed (HildonAppView * self, + guint newkeytype) +{ + self->priv->increase_button_pressed_down = newkeytype; + + /* Transform '+' press into adjustment update (usually scrollbar move) */ + if ((self->priv->connected_adjustment != NULL) && (newkeytype == GDK_KEY_PRESS)) + { + gfloat clampedvalue = CLAMP (gtk_adjustment_get_value (self->priv->connected_adjustment) + self->priv->connected_adjustment->step_increment, + self->priv->connected_adjustment->lower, + self->priv->connected_adjustment->upper - self->priv->connected_adjustment->page_size); + gtk_adjustment_set_value (self->priv->connected_adjustment, clampedvalue); + } + + g_signal_emit (G_OBJECT (self), appview_signals[INCREASE_BUTTON_EVENT], 0, newkeytype); +} + +/* Called when '-' hardkey is pressed/released */ +void _hildon_appview_decrease_button_state_changed (HildonAppView * self, + guint newkeytype) +{ + self->priv->decrease_button_pressed_down = newkeytype; + + /* Transform '-' press into adjustment update (usually scrollbar move) */ + if ((self->priv->connected_adjustment != NULL) && (newkeytype == GDK_KEY_PRESS)) + { + gfloat clampedvalue = CLAMP (gtk_adjustment_get_value (self->priv->connected_adjustment) - self->priv->connected_adjustment->step_increment, + self->priv->connected_adjustment->lower, + self->priv->connected_adjustment->upper - self->priv->connected_adjustment->page_size); + gtk_adjustment_set_value (self->priv->connected_adjustment, clampedvalue); + } + + g_signal_emit (G_OBJECT (self), appview_signals[DECREASE_BUTTON_EVENT], 0, newkeytype); +} diff --git a/src/hildon-appview.h b/src/hildon-appview.h new file mode 100644 index 0000000..bc802ab --- /dev/null +++ b/src/hildon-appview.h @@ -0,0 +1,121 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + + +#ifndef __HILDON_APPVIEW_H__ +#define __HILDON_APPVIEW_H__ + +#include +#include +#include +#include +#include +#include + + +G_BEGIN_DECLS +#define HILDON_TYPE_APPVIEW ( hildon_appview_get_type() ) +#define HILDON_APPVIEW(obj) \ + (GTK_CHECK_CAST (obj, HILDON_TYPE_APPVIEW, HildonAppView)) +#define HILDON_APPVIEW_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST ((klass),\ + HILDON_TYPE_APPVIEW, HildonAppViewClass)) +#define HILDON_IS_APPVIEW(obj) (GTK_CHECK_TYPE (obj, HILDON_TYPE_APPVIEW)) +#define HILDON_IS_APPVIEW_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_APPVIEW)) +typedef struct _HildonAppView HildonAppView; +typedef struct _HildonAppViewClass HildonAppViewClass; + +/** + * HildonAppViewPrivate: + * + * This structure contains just internal data. It should not + * be accessed directly. + */ +typedef struct _HildonAppViewPrivate HildonAppViewPrivate; + +struct _HildonAppView { + GtkBin parent; + + /*public*/ + GtkWidget *vbox; + + /*private*/ + HildonAppViewPrivate *priv; +}; + +struct _HildonAppViewClass { + GtkBinClass parent_class; + void (*toolbar_changed) (HildonAppView * self); + void (*toolbar_toggle_request) (HildonAppView * self); + void (*fullscreen_state_change) (HildonAppView * self, + gboolean is_fullscreen); + void (*title_change) (HildonAppView * self); + void (*switched_to) (HildonAppView * self); + void (*switched_from) (HildonAppView * self); + void (*increase_button_event) (HildonAppView * self, + guint newkeytype); + void (*decrease_button_event) (HildonAppView * self, + guint newkeytype); +}; + + +GType hildon_appview_get_type(void) G_GNUC_CONST; +GtkWidget *hildon_appview_new(const gchar * title); +void hildon_appview_add_with_scrollbar(HildonAppView * self, + GtkWidget * child); +void hildon_appview_set_fullscreen_key_allowed(HildonAppView * self, + gboolean allow); +gboolean hildon_appview_get_fullscreen_key_allowed(HildonAppView * self); + +gboolean hildon_appview_get_fullscreen(HildonAppView * self); +void hildon_appview_set_fullscreen(HildonAppView * self, + gboolean fullscreen); +GtkMenu *hildon_appview_get_menu(HildonAppView * self); +#ifndef HILDON_DISABLE_DEPRECATED +void hildon_appview_set_toolbar(HildonAppView * self, + GtkToolbar * toolbar); +GtkToolbar *hildon_appview_get_toolbar(HildonAppView * self); +#endif +void hildon_appview_set_title(HildonAppView * self, const gchar * newname); +const gchar *hildon_appview_get_title(HildonAppView * self); + +gboolean _hildon_appview_toggle_menu(HildonAppView * self, + Time button_event_time); +gboolean _hildon_appview_menu_visible(HildonAppView * self); + +void hildon_appview_set_connected_adjustment (HildonAppView * self, + GtkAdjustment * adjustment); +GtkAdjustment * hildon_appview_get_connected_adjustment (HildonAppView * self); + +void _hildon_appview_increase_button_state_changed (HildonAppView * self, + guint newkeytype); +void _hildon_appview_decrease_button_state_changed (HildonAppView * self, + guint newkeytype); + +void hildon_appview_set_menu_ui(HildonAppView *self, const gchar *ui_string); +const gchar *hildon_appview_get_menu_ui(HildonAppView *self); + +G_END_DECLS +#endif /* HILDON_APPVIEW_H */ diff --git a/src/hildon-banner.c b/src/hildon-banner.c new file mode 100644 index 0000000..1b267d8 --- /dev/null +++ b/src/hildon-banner.c @@ -0,0 +1,913 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include +#include +#include +#include +#include + +#include "hildon-defines.h" +#include "hildon-banner.h" + +/* position relative to the screen */ +#define HILDON_BANNER_WINDOW_X 30 +#define HILDON_BANNER_WINDOW_Y 73 +#define HILDON_BANNER_WINDOW_FULLSCREEN_Y 20 + +/* max widths */ +#define HILDON_BANNER_PROGRESS_WIDTH 104 +#define HILDON_BANNER_LABEL_MAX_TIMED 375 +#define HILDON_BANNER_LABEL_MAX_PROGRESS 375 /*265*/ + +/* default timeout */ +#define HILDON_BANNER_TIMEOUT 3000 + +/* default icons */ +#define HILDON_BANNER_DEFAULT_ICON "qgn_note_infoprint" +#define HILDON_BANNER_DEFAULT_PROGRESS_ANIMATION "qgn_indi_pball_a" + +enum { + PROP_PARENT_WINDOW = 1, + PROP_IS_TIMED +}; + +struct _HildonBannerPrivate +{ + GtkWidget *main_item; + GtkWidget *label; + GtkWidget *layout; + guint timeout_id; + gboolean is_timed; +}; + +static GtkWidget *global_timed_banner = NULL; + +G_DEFINE_TYPE(HildonBanner, hildon_banner, GTK_TYPE_WINDOW) + +/* copy/paste from old infoprint implementation: Use matchbox + properties to find the topmost application window */ +static Window get_current_app_window(void) +{ + unsigned long n; + unsigned long extra; + int format; + int status; + + Atom atom_current_app_window = gdk_x11_get_xatom_by_name ("_MB_CURRENT_APP_WINDOW"); + Atom realType; + Window win_result = None; + guchar *data_return = NULL; + + status = XGetWindowProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(), + atom_current_app_window, 0L, 16L, + 0, XA_WINDOW, &realType, &format, + &n, &extra, + &data_return); + + if ( status == Success && realType == XA_WINDOW + && format == 32 && n == 1 && data_return != NULL ) + { + win_result = ((Window*) data_return)[0]; + } + + if ( data_return ) + XFree(data_return); + + return win_result; +} + +/* Checks if a window is in fullscreen state or not. This + information is needed when banners are positioned on screen. + copy/paste from old infoprint implementation. */ +static gboolean check_fullscreen_state( Window window ) +{ + unsigned long n; + unsigned long extra; + int format, status, i; + guchar *data_return = NULL; + + Atom realType; + Atom atom_window_state = gdk_x11_get_xatom_by_name ("_NET_WM_STATE"); + Atom atom_fullscreen = gdk_x11_get_xatom_by_name ("_NET_WM_STATE_FULLSCREEN"); + + if ( window == None ) + return FALSE; + + /* in some cases XGetWindowProperty seems to generate BadWindow, + so at the moment this function does not always work perfectly */ + gdk_error_trap_push(); + status = XGetWindowProperty(GDK_DISPLAY(), window, + atom_window_state, 0L, 1000000L, + 0, XA_ATOM, &realType, &format, + &n, &extra, &data_return); + gdk_flush(); + if (gdk_error_trap_pop()) + return FALSE; + + if (status == Success && realType == XA_ATOM && format == 32 && n > 0) + { + for(i=0; i < n; i++) + if ( ((Atom*)data_return)[i] && + ((Atom*)data_return)[i] == atom_fullscreen) + { + if (data_return) XFree(data_return); + return TRUE; + } + } + + if (data_return) + XFree(data_return); + + return FALSE; +} + +static GQuark hildon_banner_timed_quark(void) +{ + static GQuark quark = 0; + + if (G_UNLIKELY(quark == 0)) + quark = g_quark_from_static_string("hildon-banner-timed"); + + return quark; +} + +/* Set the label name to make the correct rc-style attached into it */ +static void hildon_banner_bind_label_style(HildonBanner *self, + const gchar *name) +{ + GtkWidget *label = self->priv->label; + + /* Too bad that we cannot really reset the widget name */ + gtk_widget_set_name(label, name ? name : g_type_name(GTK_WIDGET_TYPE(label))); +} + +/* In timeout function we automatically destroy timed banners */ +static gboolean hildon_banner_timeout(gpointer data) +{ + GtkWidget *widget; + GdkEvent *event; + gboolean continue_timeout = FALSE; + + GDK_THREADS_ENTER (); + + g_assert(HILDON_IS_BANNER(data)); + + widget = GTK_WIDGET(data); + g_object_ref(widget); + + /* If the banner is currently visible (it normally should), + we simulate clicking the close button of the window. + This allows applications to reuse the banner by prevent + closing it etc */ + if (GTK_WIDGET_DRAWABLE(widget)) + { + event = gdk_event_new (GDK_DELETE); + event->any.window = g_object_ref(widget->window); + event->any.send_event = FALSE; + continue_timeout = gtk_widget_event (widget, event); + gdk_event_free(event); + } + + if (!continue_timeout) + gtk_widget_destroy (widget); + + g_object_unref(widget); + + GDK_THREADS_LEAVE (); + + return continue_timeout; +} + +static gboolean hildon_banner_clear_timeout(HildonBanner *self) +{ + g_assert(HILDON_IS_BANNER(self)); + + if (self->priv->timeout_id != 0) { + g_source_remove(self->priv->timeout_id); + self->priv->timeout_id = 0; + return TRUE; + } + + return FALSE; +} + +static void hildon_banner_ensure_timeout(HildonBanner *self) +{ + g_assert(HILDON_IS_BANNER(self)); + + if (self->priv->timeout_id == 0 && self->priv->is_timed) + self->priv->timeout_id = g_timeout_add(HILDON_BANNER_TIMEOUT, + hildon_banner_timeout, self); +} + +static void hildon_banner_set_property(GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GtkWidget *window; + GdkGeometry geom; + HildonBannerPrivate *priv = HILDON_BANNER(object)->priv; + + switch (prop_id) { + case PROP_IS_TIMED: + priv->is_timed = g_value_get_boolean(value); + + /* Timed and progress notifications have different + pixel size values for text. + We force to use requisition size for timed banners + in order to avoid resize problems when reusing the + window (see bug #24339) */ + geom.max_width = priv->is_timed ? -1 + : HILDON_BANNER_LABEL_MAX_PROGRESS; + geom.max_height = -1; + gtk_window_set_geometry_hints(GTK_WINDOW(object), + priv->label, &geom, GDK_HINT_MAX_SIZE); + break; + + case PROP_PARENT_WINDOW: + window = g_value_get_object(value); + + gtk_window_set_transient_for(GTK_WINDOW(object), (GtkWindow *) window); + + if (window) + gtk_window_set_destroy_with_parent(GTK_WINDOW(object), TRUE); + + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void hildon_banner_get_property(GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + HildonBanner *self = HILDON_BANNER(object); + + switch (prop_id) + { + case PROP_IS_TIMED: + g_value_set_boolean(value, self->priv->is_timed); + break; + + case PROP_PARENT_WINDOW: + g_value_set_object(value, gtk_window_get_transient_for(GTK_WINDOW(object))); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void hildon_banner_destroy(GtkObject *object) +{ + HildonBanner *self; + GObject *parent_window; + + g_assert(HILDON_IS_BANNER(object)); + self = HILDON_BANNER(object); + + /* Drop possible global pointer. That can hold reference to us */ + if ((gpointer) object == (gpointer) global_timed_banner) { + global_timed_banner = NULL; + g_object_unref(object); + } + + /* Remove the data from parent window for timed banners. Those hold reference */ + if (self->priv->is_timed && + (parent_window = (GObject *) gtk_window_get_transient_for( + GTK_WINDOW(object))) != NULL) + g_object_set_qdata(parent_window, hildon_banner_timed_quark(), NULL); + + (void) hildon_banner_clear_timeout(self); + + if (GTK_OBJECT_CLASS(hildon_banner_parent_class)->destroy) + GTK_OBJECT_CLASS(hildon_banner_parent_class)->destroy(object); +} + +/* Search a previous banner instance */ +static GObject *hildon_banner_real_get_instance(GObject *window, gboolean timed) +{ + g_assert(window == NULL || GTK_IS_WINDOW(window)); + + if (timed) { + /* If we have a parent window, the previous instance is stored there */ + if (window) + return g_object_get_qdata(window, hildon_banner_timed_quark()); + + /* System notification instance is stored into global pointer */ + return (GObject *) global_timed_banner; + } + + /* Non-timed banners are normal (non-singleton) objects */ + return NULL; +} + +/* By overriding constructor we force timed banners to be + singletons for each window */ +static GObject* hildon_banner_constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + GObject *banner, *window = NULL; + gboolean timed = FALSE; + guint i; + + /* Search banner type information from parameters in order + to locate the possible previous banner instance. */ + for (i = 0; i < n_construct_params; i++) + { + if (strcmp(construct_params[i].pspec->name, "parent-window") == 0) + window = g_value_get_object(construct_params[i].value); + else if (strcmp(construct_params[i].pspec->name, "is-timed") == 0) + timed = g_value_get_boolean(construct_params[i].value); + } + + /* Try to get a previous instance if such exists */ + banner = hildon_banner_real_get_instance(window, timed); + if (!banner) + { + /* We have to create a new banner */ + banner = G_OBJECT_CLASS(hildon_banner_parent_class)->constructor( + type, n_construct_params, construct_params); + + /* Store the newly created singleton instance either into parent + window data or into global variables. */ + if (timed) { + if (window) { + g_object_set_qdata_full(G_OBJECT(window), hildon_banner_timed_quark(), + g_object_ref(banner), g_object_unref); + } else { + g_assert(global_timed_banner == NULL); + global_timed_banner = g_object_ref(banner); + } + } + } + else { + /* FIXME: This is a hack! We have to manually freeze + notifications. This is normally done by g_object_init, but we + are not going to call that. g_object_newv will otherwise give + a critical like this: + + GLIB CRITICAL ** GLib-GObject - g_object_notify_queue_thaw: + assertion `nqueue->freeze_count > 0' failed */ + + g_object_freeze_notify(banner); + } + + /* We restart possible timeouts for each new timed banner request */ + if (timed && hildon_banner_clear_timeout(HILDON_BANNER(banner))) + hildon_banner_ensure_timeout(HILDON_BANNER(banner)); + + return banner; +} + +/* We start the timer for timed notifications after the window appears on screen */ +static gboolean hildon_banner_map_event(GtkWidget *widget, GdkEventAny *event) +{ + gboolean result = FALSE; + + if (GTK_WIDGET_CLASS(hildon_banner_parent_class)->map_event) + result = GTK_WIDGET_CLASS(hildon_banner_parent_class)->map_event(widget, event); + + hildon_banner_ensure_timeout(HILDON_BANNER(widget)); + + return result; +} + + +/* force to wrap truncated label by setting explicit size request + * see N#27000 and G#329646 */ +static void force_to_wrap_truncated(HildonBanner *banner){ + GtkLabel *label; + PangoLayout *layout; + int width_text, width_max; + int width = -1; + + label = GTK_LABEL(banner->priv->label); + + layout = gtk_label_get_layout(label); + width_text = PANGO_PIXELS(pango_layout_get_width(layout)); + /* = width to which the lines of the PangoLayout should be wrapped */ + + width_max = banner->priv->is_timed ? HILDON_BANNER_LABEL_MAX_TIMED + : HILDON_BANNER_LABEL_MAX_PROGRESS; + + if(width_text >= width_max){ + /* explicitly request maximum size to force wrapping */ + PangoRectangle logical; + + pango_layout_set_width (layout, width_max * PANGO_SCALE); + pango_layout_get_extents (layout, NULL, &logical); + + width = PANGO_PIXELS (logical.width); + } + + /* use fixed width when wrapping or natural one otherwise */ + gtk_widget_set_size_request (GTK_WIDGET (label), + width, -1); +} + + +static void hildon_banner_check_position(GtkWidget *widget) +{ + gint x, y; + GtkRequisition req; + + force_to_wrap_truncated(HILDON_BANNER(widget)); /* see N#27000 and G#329646 */ + + gtk_widget_size_request(widget, &req); + + if (req.width == 0) + { + return; + } + + x = gdk_screen_width() - HILDON_BANNER_WINDOW_X - req.width; + y = check_fullscreen_state(get_current_app_window()) ? + HILDON_BANNER_WINDOW_FULLSCREEN_Y : HILDON_BANNER_WINDOW_Y; + + gtk_window_move(GTK_WINDOW(widget), x, y); +} + +static void hildon_banner_realize(GtkWidget *widget) +{ + /* We let the parent to init widget->window before we need it */ + if (GTK_WIDGET_CLASS(hildon_banner_parent_class)->realize) + GTK_WIDGET_CLASS(hildon_banner_parent_class)->realize(widget); + + /* We use special hint to turn the banner into information notification. */ + gdk_window_set_type_hint(widget->window, GDK_WINDOW_TYPE_HINT_MESSAGE); + + hildon_banner_check_position(widget); +} + +static void hildon_banner_class_init(HildonBannerClass *klass) +{ + GObjectClass *object_class; + GtkWidgetClass *widget_class; + + object_class = G_OBJECT_CLASS(klass); + widget_class = GTK_WIDGET_CLASS(klass); + + /* Append private structure to class. This is more elegant than + on g_new based approach */ + g_type_class_add_private(klass, sizeof(HildonBannerPrivate)); + + /* Override virtual methods */ + object_class->constructor = hildon_banner_constructor; + object_class->set_property = hildon_banner_set_property; + object_class->get_property = hildon_banner_get_property; + GTK_OBJECT_CLASS(klass)->destroy = hildon_banner_destroy; + widget_class->map_event = hildon_banner_map_event; + widget_class->realize = hildon_banner_realize; + + /* Install properties. + We need construct properties for singleton purposes */ + g_object_class_install_property(object_class, PROP_PARENT_WINDOW, + g_param_spec_object("parent-window", + "Parent window", + "The window for which the banner will be singleton", + GTK_TYPE_WINDOW, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property(object_class, PROP_IS_TIMED, + g_param_spec_boolean("is-timed", + "Is timed", + "Whether or not the notification goes away automatically " + "after the specified time has passed", + FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +} + +static void hildon_banner_init(HildonBanner *self) +{ + HildonBannerPrivate *priv; + + /* Make private data available through cached pointer */ + self->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE(self, + HILDON_TYPE_BANNER, + HildonBannerPrivate); + + /* Initialize the common layout inside banner */ + self->priv->layout = gtk_hbox_new(FALSE, HILDON_MARGIN_DEFAULT); + + priv->label = g_object_new(GTK_TYPE_LABEL, NULL); + gtk_label_set_line_wrap(GTK_LABEL(priv->label), TRUE); + + gtk_container_set_border_width(GTK_CONTAINER(self->priv->layout), HILDON_MARGIN_DEFAULT); + gtk_container_add(GTK_CONTAINER(self), self->priv->layout); + gtk_box_pack_start(GTK_BOX(self->priv->layout), priv->label, TRUE, TRUE, 0); + + gtk_window_set_accept_focus(GTK_WINDOW(self), FALSE); +} + +/* Makes sure that icon/progress item contains the desired type + of item. If possible, tries to avoid creating a new widget but + reuses the existing one */ +static void hildon_banner_ensure_child(HildonBanner *self, + GtkWidget *user_widget, + guint pos, + GType type, + const gchar *first_property, ...) +{ + GtkWidget *widget; + va_list args; + + g_assert(HILDON_IS_BANNER(self)); + g_assert(user_widget == NULL || GTK_IS_WIDGET(user_widget)); + + widget = self->priv->main_item; + va_start(args, first_property); + + /* Reuse existing widget if possible */ + if (!user_widget && G_TYPE_CHECK_INSTANCE_TYPE(widget, type)) + { + g_object_set_valist(G_OBJECT(widget), first_property, args); + } + else + { + /* We have to abandon old content widget */ + if (widget) + gtk_container_remove(GTK_CONTAINER(self->priv->layout), widget); + + /* Use user provided widget or create a new one */ + self->priv->main_item = widget = user_widget ? + user_widget : GTK_WIDGET(g_object_new_valist(type, first_property, args)); + gtk_box_pack_start(GTK_BOX(self->priv->layout), widget, TRUE, TRUE, 0); + } + + /* We make sure that the widget exists in desired position. Different + banners place this child widget to different places */ + gtk_box_reorder_child(GTK_BOX(self->priv->layout), widget, pos); + va_end(args); +} + +/* Creates a new banner instance or uses an existing one */ +static HildonBanner *hildon_banner_get_instance_for_widget(GtkWidget *widget, gboolean timed) +{ + GtkWidget *window; + + g_return_val_if_fail(widget == NULL || GTK_IS_WIDGET(widget), NULL); + window = widget ? gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW) : NULL; + return g_object_new(HILDON_TYPE_BANNER, "parent-window", window, "is-timed", timed, NULL); +} + + + + + +/* Public functions **************************************************************/ + +/** + * hildon_banner_show_information: + * @widget: the #GtkWidget that wants to display banner + * @icon_name: the name of icon to use. Can be %NULL for default icon. + * @text: Text to display + * + * This function creates and displays an information banner that + * automatically goes away after certain time period. For each window + * in your application there can only be one timed banner, so if you + * spawn a new banner before the earlier one has timed out, the + * previous one will be replaced. + * + * Since: 0.12.2 + */ +void hildon_banner_show_information(GtkWidget *widget, + const gchar *icon_name, + const gchar *text) +{ + HildonBanner *banner; + + g_return_if_fail(widget == NULL || GTK_IS_WIDGET(widget)); + g_return_if_fail(icon_name == NULL || icon_name[0] != 0); + g_return_if_fail(text != NULL); + + /* Prepare banner */ + banner = hildon_banner_get_instance_for_widget(widget, TRUE); + hildon_banner_ensure_child(banner, NULL, 0, GTK_TYPE_IMAGE, + "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE, + "icon-name", icon_name ? icon_name : HILDON_BANNER_DEFAULT_ICON, + "yalign", 0.0, + NULL); + hildon_banner_set_text(banner, text); + hildon_banner_bind_label_style(banner, NULL); + + /* Show the banner, since caller cannot do that */ + gtk_widget_show_all(GTK_WIDGET(banner)); +} + +/** + * hildon_banner_show_information_with_markup: + * @widget: the #GtkWidget that wants to display banner + * @icon_name: the name of icon to use. Can be %NULL for default icon. + * @markup: a markup string to display (see Pango markup format) + * + * This function creates and displays an information banner that + * automatically goes away after certain time period. For each window + * in your application there can only be one timed banner, so if you + * spawn a new banner before the earlier one has timed out, the + * previous one will be replaced. + * + * Since: 0.12.8 + */ +void hildon_banner_show_information_with_markup(GtkWidget *widget, + const gchar *icon_name, const gchar *markup) +{ + HildonBanner *banner; + + g_return_if_fail(widget == NULL || GTK_IS_WIDGET(widget)); + g_return_if_fail(icon_name == NULL || icon_name[0] != 0); + g_return_if_fail(markup != NULL); + + /* Prepare banner */ + banner = hildon_banner_get_instance_for_widget(widget, TRUE); + + hildon_banner_ensure_child(banner, NULL, 0, GTK_TYPE_IMAGE, + "pixel-size", HILDON_ICON_PIXEL_SIZE_NOTE, + "icon-name", icon_name ? icon_name : HILDON_BANNER_DEFAULT_ICON, + "yalign", 0.0, + NULL); + hildon_banner_set_markup(banner, markup); + hildon_banner_bind_label_style(banner, NULL); + + /* Show the banner, since caller cannot do that */ + gtk_widget_show_all(GTK_WIDGET(banner)); +} + +/** + * hildon_banner_show_animation: + * @widget: the #GtkWidget that wants to display banner + * @animation_name: The progress animation to use. You usually can just + * pass %NULL for the default animation. + * @text: the text to display. + * + * Shows an animated progress notification. It's recommended not to try + * to show more than one progress notification at a time, since + * they will appear on top of each other. You can use progress + * notifications with timed banners. In this case the banners are + * located so that you can somehow see both. + * + * Please note that banners are destroyed automatically once the + * window they are attached to is closed. The pointer that you + * receive with this function do not contain additional references, + * so it can become invalid without warning (this is true for + * all toplevel windows in gtk). To make sure that the banner do not disapear + * automatically, you can separately ref the return value (this + * doesn't prevent the banner from disappearing, but the object it just + * not finalized). In this case you have to call both #gtk_widget_destroy + * followed by #g_object_unref (in this order). + * + * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy + * once you are ready with the banner. + * + * Since: 0.12.2 + */ +GtkWidget *hildon_banner_show_animation(GtkWidget *widget, + const gchar *animation_name, const gchar *text) +{ + HildonBanner *banner; + GtkIconTheme *theme; + GtkIconInfo *info; + GtkWidget *image_widget; + const gchar *filename; + + g_return_val_if_fail(widget == NULL || GTK_IS_WIDGET(widget), NULL); + g_return_val_if_fail(animation_name == NULL || animation_name[0] != 0, NULL); + g_return_val_if_fail(text != NULL, NULL); + + /* Find out which animation to use */ + theme = gtk_icon_theme_get_default(); + info = gtk_icon_theme_lookup_icon(theme, animation_name ? /* TODO: consider using: gtk_icon_theme_load_icon() */ + animation_name : HILDON_BANNER_DEFAULT_PROGRESS_ANIMATION, + HILDON_ICON_SIZE_NOTE, 0); + + /* Try to load animation. One could try to optimize this + to avoid loading the default animation during each call */ + if (info) { + filename = gtk_icon_info_get_filename(info); + image_widget = gtk_image_new_from_file(filename); + gtk_icon_info_free(info); + } else { + g_warning("icon theme lookup for icon failed!"); + image_widget = NULL; + } + + /* Prepare banner */ + banner = hildon_banner_get_instance_for_widget(widget, FALSE); + hildon_banner_ensure_child(banner, image_widget, 0, + GTK_TYPE_IMAGE, "yalign", 0.0, NULL); + hildon_banner_set_text(banner, text); + hildon_banner_bind_label_style(banner, NULL); + + /* And show it */ + gtk_widget_show_all(GTK_WIDGET(banner)); + + return GTK_WIDGET(banner); +} + +/** + * hildon_banner_show_progress: + * @widget: the #GtkWidget that wants to display banner + * @bar: Progressbar to use. You usually can just pass %NULL, unless + * you want somehow customized progress bar. + * @text: text to display. + * + * Shows progress notification. See #hildon_banner_show_animation + * for more information. + * + * Returns: a #HildonBanner widget. You must call #gtk_widget_destroy + * once you are ready with the banner. + * + * Since: 0.12.2 + */ +GtkWidget *hildon_banner_show_progress(GtkWidget *widget, + GtkProgressBar *bar, const gchar *text) +{ + HildonBanner *banner; + + g_return_val_if_fail(widget == NULL || GTK_IS_WIDGET(widget), NULL); + g_return_val_if_fail(bar == NULL || GTK_IS_PROGRESS_BAR(bar), NULL); + g_return_val_if_fail(text != NULL, NULL); + + /* Prepare banner */ + banner = hildon_banner_get_instance_for_widget(widget, FALSE); + hildon_banner_ensure_child(banner, (GtkWidget *) bar, -1, GTK_TYPE_PROGRESS_BAR, NULL); + gtk_widget_set_size_request(banner->priv->main_item, + HILDON_BANNER_PROGRESS_WIDTH, -1); + hildon_banner_set_text(banner, text); + hildon_banner_bind_label_style(banner, NULL); + + /* Show the banner */ + gtk_widget_show_all(GTK_WIDGET(banner)); + + return GTK_WIDGET(banner); +} + +/** + * hildon_banner_set_text: + * @self: a #HildonBanner widget + * @text: a new text to display in banner + * + * Sets the text that is displayed in the banner. + * + * Since: 0.12.2 + */ +void hildon_banner_set_text(HildonBanner *self, const gchar *text) +{ + GtkLabel *label; + + g_return_if_fail(HILDON_IS_BANNER(self)); + + label = GTK_LABEL(self->priv->label); + gtk_label_set_text(label, text); + + hildon_banner_check_position(GTK_WIDGET(self)); +} + +/** + * hildon_banner_set_markup: + * @self: a #HildonBanner widget + * @markup: a new text with Pango markup to display in the banner + * + * Sets the text with markup that is displayed in the banner. + * + * Since: 0.12.8 + */ +void hildon_banner_set_markup(HildonBanner *self, const gchar *markup) +{ + GtkLabel *label; + + g_return_if_fail(HILDON_IS_BANNER(self)); + + label = GTK_LABEL(self->priv->label); + gtk_label_set_markup(label, markup); + + hildon_banner_check_position(GTK_WIDGET(self)); +} + +/** + * hildon_banner_set_fraction: + * @self: a #HildonBanner widget + * @fraction: #gdouble + * + * The fraction is the completion of progressbar, + * the scale is from 0.0 to 1.0. + * Sets the amount of fraction the progressbar has. + * + * Since: 0.12.2 + */ +void hildon_banner_set_fraction(HildonBanner *self, gdouble fraction) +{ + g_return_if_fail(HILDON_IS_BANNER(self)); + g_return_if_fail(GTK_IS_PROGRESS_BAR(self->priv->main_item)); + gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(self->priv->main_item), fraction); +} + + + + + +/** + * Deprecated: really, do NOT use. + */ +void _hildon_gtk_label_set_text_n_lines(GtkLabel *label, const gchar *text, gint max_lines) +{ +/* Forces the wrapping of text into several lines and ellipsizes the rest. + Similar to combination of gtk_label_set_wrap and pango ellipzation. + We cannot just use those directly, since ellipzation always wins wrapping. + + This means that we have to: + * First wrap the text + * Insert forced linebreaks into text + * Truncate the result + + NOTE! This will not work with pango markup! + + FIXME: luc: DO NOT TRUNCATE the text. Use as many lines as needed. + Lenth of the text is under applications' responsibility. + Widget does not have to enforce this. +*/ + PangoLayout *layout; + PangoLayoutLine *line; + GtkRequisition req; + GString *wrapped_text; + gchar *line_data; + gint lines, i; + + g_return_if_fail(GTK_IS_LABEL(label)); + g_return_if_fail(max_lines >= 1); + + /* Setup the label to contain the new data */ + gtk_label_set_text(label, text); + gtk_label_set_line_wrap(label, TRUE); + gtk_label_set_ellipsize(label, PANGO_ELLIPSIZE_NONE); + + /* We really want to recalculate the size, not use some old values */ + gtk_widget_size_request(GTK_WIDGET(label), &req); + layout = gtk_label_get_layout(label); + lines = pango_layout_get_line_count(layout); + + /* Now collect the wrapped text. */ + wrapped_text = g_string_new(NULL); + + for (i = 0; i < lines; i++) + { + /* Append the next line into wrapping buffer, but + avoid adding extra whitespaces at the end, since those + can cause other lines to be ellipsized as well. */ + line = pango_layout_get_line(layout, i); + line_data = g_strndup(pango_layout_get_text(layout) + line->start_index, + line->length); + g_strchomp(line_data); + g_string_append(wrapped_text, line_data); + + /* Append forced linebreaks, until we have the desired + amount of lines. After that we put the rest to the + last line to make ellipzation to happen */ + if (i < lines - 1) + { + if (i < max_lines - 1) + g_string_append_c(wrapped_text, '\n'); + else + g_string_append_c(wrapped_text, ' '); + } + + g_free(line_data); + } + + /* Now update the label to use wrapped text. Use builtin + ellipzation as well. */ + gtk_widget_set_size_request(GTK_WIDGET(label), req.width, -1); + gtk_label_set_text(label, wrapped_text->str); + gtk_label_set_ellipsize(label, PANGO_ELLIPSIZE_END); + gtk_label_set_line_wrap(label, FALSE); + + g_string_free(wrapped_text, TRUE); +} diff --git a/src/hildon-banner.h b/src/hildon-banner.h new file mode 100644 index 0000000..fe8c5d2 --- /dev/null +++ b/src/hildon-banner.h @@ -0,0 +1,88 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_BANNER_H__ +#define __HILDON_BANNER_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#define HILDON_TYPE_BANNER (hildon_banner_get_type()) + +#define HILDON_BANNER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), HILDON_TYPE_BANNER, HildonBanner)) +#define HILDON_IS_BANNER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), HILDON_TYPE_BANNER)) + +typedef struct _HildonBanner HildonBanner; +typedef struct _HildonBannerClass HildonBannerClass; +typedef struct _HildonBannerPrivate HildonBannerPrivate; + +struct _HildonBanner +{ + GtkWindow parent; + HildonBannerPrivate *priv; +}; + +struct _HildonBannerClass +{ + GtkWindowClass parent_class; +}; + +GType hildon_banner_get_type (void) G_GNUC_CONST; + +void hildon_banner_show_information (GtkWidget *widget, + const gchar *icon_name, + const gchar *text); + +void hildon_banner_show_information_with_markup (GtkWidget *widget, + const gchar *icon_name, + const gchar *markup); + +GtkWidget *hildon_banner_show_animation (GtkWidget *widget, + const gchar *animation_name, + const gchar *text); + +GtkWidget *hildon_banner_show_progress (GtkWidget *widget, + GtkProgressBar *bar, + const gchar *text); + +void hildon_banner_set_text (HildonBanner *self, + const gchar *text); + +void hildon_banner_set_markup (HildonBanner *self, + const gchar *markup); + +void hildon_banner_set_fraction (HildonBanner *self, + gdouble fraction); + + + +/* For internal use of hildon libraries only */ +void _hildon_gtk_label_set_text_n_lines(GtkLabel *label, const gchar *text, gint max_lines); + +G_END_DECLS + +#endif /* __HILDON_BANNER_H__ */ diff --git a/src/hildon-calendar-popup.c b/src/hildon-calendar-popup.c new file mode 100644 index 0000000..3139374 --- /dev/null +++ b/src/hildon-calendar-popup.c @@ -0,0 +1,439 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-calendar-popup + * @shortdesc: CalendarPopup allows choosing a date from a popup calendar. + * @longdesc: The Calendar popup is a dialog that contains a GtkCalendar + * widget. The pop-up is cancelled by pressing the ESC key. + * + * + * @seealso: #HildonDateEditor, #HildonTimeEditor + * + * HildonCalendarPopup is a dialog which contains a GtkCalendar. It + * also contains arrow buttons for changing the month/year. If an + * entered date is invalid, an information message will be shown. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#define _(String) dgettext(PACKAGE, String) + +#define HILDON_CALENDAR_POPUP_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE\ + ((obj), HILDON_TYPE_CALENDAR_POPUP, HildonCalendarPopupPrivate)); + +static GtkDialog *parent_class; + +typedef struct _HildonCalendarPopupPrivate HildonCalendarPopupPrivate; + +static void init_dmy(guint year, guint month, guint day, guint * d, + guint * m, guint * y); + +static void +hildon_calendar_popup_class_init(HildonCalendarPopupClass * cal_class); + +static void hildon_calendar_popup_init(HildonCalendarPopup * cal); + +static void hildon_calendar_selected_date(GtkWidget * self, gpointer cal_popup); + +static gboolean hildon_key_pressed(GtkWidget * widget, GdkEventKey * event, + gpointer cal_popup); + +static void hildon_calendar_popup_set_property(GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec); +static void hildon_calendar_popup_get_property(GObject * object, guint property_id, + GValue * value, GParamSpec * pspec); + +enum { + PROP_0, + PROP_DAY, + PROP_MONTH, + PROP_YEAR, + PROP_MIN_YEAR, + PROP_MAX_YEAR +}; + +struct _HildonCalendarPopupPrivate { + GtkWidget *cal; +}; + +GType hildon_calendar_popup_get_type(void) +{ + static GType popup_type = 0; + + if (!popup_type) { + static const GTypeInfo popup_info = { + sizeof(HildonCalendarPopupClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_calendar_popup_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonCalendarPopup), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_calendar_popup_init, + }; + popup_type = g_type_register_static(GTK_TYPE_DIALOG, + "HildonCalendarPopup", + &popup_info, 0); + } + + return popup_type; +} + +/** + * hildon_calendar_popup_new: + * @parent: parent window for dialog + * @year: initial year + * @month: initial month + * @day: initial day + * + * This function returns a new HildonCalendarPopup. The initially + * selected date is specified by the parameters (year, month, day). + * If the specified date is invalid, the current date is used. + * + * Returns: new @HildonCalendarPopup widget + */ +GtkWidget *hildon_calendar_popup_new(GtkWindow * parent, guint year, + guint month, guint day) +{ + HildonCalendarPopup *cal = NULL; + + /* Create new HildonCalendarPopup */ + cal = HILDON_CALENDAR_POPUP(g_object_new(HILDON_TYPE_CALENDAR_POPUP, + "year", year, "month", month, "day", day, + NULL)); + + if (parent) { + gtk_window_set_transient_for(GTK_WINDOW(cal), parent); + } + + return GTK_WIDGET(cal); +} + +/** + * hildon_calendar_popup_set_date: + * @cal: the @HildonCalendarPopup widget + * @year: year + * @month: month + * @day: day + * + * activates a new date on the calendar popup. + **/ +void +hildon_calendar_popup_set_date(HildonCalendarPopup * cal, + guint year, guint month, guint day) +{ + guint dtmp, mtmp, ytmp = 0; + HildonCalendarPopupPrivate *priv; + + g_return_if_fail(HILDON_IS_CALENDAR_POPUP(cal)); + + priv = HILDON_CALENDAR_POPUP_GET_PRIVATE(cal); + + /* Choose current date if the date is invalid: + */ + init_dmy(year, month, day, &dtmp, &mtmp, &ytmp); + + /* Remove all visual markers */ + gtk_calendar_clear_marks(GTK_CALENDAR(priv->cal)); + + /* Set a new date */ + gtk_calendar_select_month(GTK_CALENDAR(priv->cal), mtmp - 1, ytmp); + gtk_calendar_select_day(GTK_CALENDAR(priv->cal), dtmp); +} + +/** + * hildon_calendar_popup_get_date: + * @cal: the @HildonCalendarPopup widget + * @year: year + * @month: month + * @day: day + * + * Gets the currently selected year, month, and day. + */ +void +hildon_calendar_popup_get_date(HildonCalendarPopup * cal, + guint * year, guint * month, guint * day) +{ + HildonCalendarPopupPrivate *priv; + + g_return_if_fail(HILDON_IS_CALENDAR_POPUP(cal)); + + priv = HILDON_CALENDAR_POPUP_GET_PRIVATE(cal); + gtk_calendar_get_date(GTK_CALENDAR(priv->cal), year, month, day); + *month = *month + 1; + + if (!g_date_valid_dmy(*day, *month, *year)) { + *day = g_date_get_days_in_month(*month, *year); + } +} + +static void +hildon_calendar_popup_class_init(HildonCalendarPopupClass * cal_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(cal_class); + parent_class = g_type_class_peek_parent(cal_class); + + object_class->set_property = hildon_calendar_popup_set_property; + object_class->get_property = hildon_calendar_popup_get_property; + + g_type_class_add_private(cal_class, + sizeof(HildonCalendarPopupPrivate)); + + /* Install new properties for the GObject_class */ + g_object_class_install_property(object_class, PROP_MIN_YEAR, + g_param_spec_uint("min-year", + "Minimum valid year", + "Minimum valid year", + 1, 2100, + 1970, + G_PARAM_WRITABLE)); + + g_object_class_install_property(object_class, PROP_MAX_YEAR, + g_param_spec_uint("max-year", + "Maximum valid year", + "Maximum valid year", + 1, 2100, + 2037, + G_PARAM_WRITABLE)); + + g_object_class_install_property(object_class, PROP_DAY, + g_param_spec_int ("day", + "Day", + "currently selected day", + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + g_object_class_install_property(object_class, PROP_MONTH, + g_param_spec_int ("month", + "Month", + "currently selected month", + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + g_object_class_install_property(object_class, PROP_YEAR, + g_param_spec_int ("year", + "Year", + "the currently selected year", + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + +} + +static void hildon_calendar_popup_init(HildonCalendarPopup * cal) +{ + HildonCalendarPopupPrivate *priv; + static int set_domain = 1; + + priv = HILDON_CALENDAR_POPUP_GET_PRIVATE(cal); + + /* set the domain directory for different language */ + if (set_domain) { + (void) bindtextdomain(PACKAGE, LOCALEDIR); + set_domain = 0; + } + + priv->cal = gtk_calendar_new(); + + /* dialog options and packing */ + gtk_calendar_set_display_options(GTK_CALENDAR(priv->cal), + GTK_CALENDAR_SHOW_HEADING | + GTK_CALENDAR_SHOW_DAY_NAMES | + GTK_CALENDAR_SHOW_WEEK_NUMBERS); + + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(cal)->vbox), priv->cal, + TRUE, TRUE, 0); + gtk_dialog_set_has_separator(GTK_DIALOG(cal), FALSE); + gtk_dialog_add_button(GTK_DIALOG(cal), _("ecdg_bd_calendar_popout_done"), + GTK_RESPONSE_OK); + gtk_widget_show(priv->cal); + + /* Connect signals */ + g_signal_connect(G_OBJECT(priv->cal), "key-press-event", + G_CALLBACK(hildon_key_pressed), cal); + + g_signal_connect(G_OBJECT(priv->cal), "selected_date", + G_CALLBACK(hildon_calendar_selected_date), cal); + + /* set decorations, needs realizing first*/ + gtk_widget_realize(GTK_WIDGET(cal)); + gdk_window_set_decorations(GTK_WIDGET(cal)->window, GDK_DECOR_BORDER); + +} + + +/* + * Signal handler for key-press-event. Closes the dialog for some + * special keys. + */ +static gboolean +hildon_key_pressed(GtkWidget * widget, GdkEventKey * event, gpointer cal_popup) +{ + g_assert(HILDON_IS_CALENDAR_POPUP(cal_popup)); + + /* Handle Return key press as OK response */ + if (event->keyval == GDK_Return) + { + gtk_dialog_response(GTK_DIALOG(cal_popup), GTK_RESPONSE_OK); + return TRUE; + } + + /* Handle Esc key press as CANCEL response */ + if ((event->keyval == GDK_Escape)) + { + gtk_dialog_response(GTK_DIALOG(cal_popup), GTK_RESPONSE_CANCEL); + return TRUE; + } + + return FALSE; +} + + +/* + * Validates the given date or initializes it with the current date + */ +static void +init_dmy(guint year, guint month, guint day, guint *d, guint *m, guint *y) +{ + GDate date; + + /* Initialize the date with a valid selected date */ + if (g_date_valid_dmy(day, month, year)) { + *d = day; + *m = month; + *y = year; + } else { + + /* If selected date is invalid initialize the date with current date */ + g_date_clear(&date, 1); + g_date_set_time(&date, time(NULL)); + + *d = g_date_get_day(&date); + *m = g_date_get_month(&date); + *y = g_date_get_year(&date); + } +} + +/* + * Exits the dialog when "selected_date" signal is emmited. The + * "selected_date" signal is a Hildon addition to GtkCalendar and is + * emitted on button-release. + */ +static void +hildon_calendar_selected_date(GtkWidget * self, gpointer cal_popup) +{ + g_assert(GTK_IS_WIDGET (self)); + g_assert(HILDON_IS_CALENDAR_POPUP (cal_popup)); + + gtk_dialog_response(GTK_DIALOG(cal_popup), GTK_RESPONSE_OK); +} + + +static void hildon_calendar_popup_set_property(GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + HildonCalendarPopup *popup = HILDON_CALENDAR_POPUP (object); + HildonCalendarPopupPrivate *priv = + HILDON_CALENDAR_POPUP_GET_PRIVATE(HILDON_CALENDAR_POPUP (object)); + + switch (property_id) { + case PROP_DAY: + { + guint year, month, day = 0; + hildon_calendar_popup_get_date(popup, &year, &month, &day); + + /*Verifies that the date is valid: */ + hildon_calendar_popup_set_date(popup, year, month, g_value_get_int(value)); + break; + } + case PROP_MONTH: + { + guint year, month, day = 0; + hildon_calendar_popup_get_date(popup, &year, &month, &day); + + /*Verifies that the date is valid: */ + hildon_calendar_popup_set_date(popup, year, g_value_get_int(value), day); + break; + } + case PROP_YEAR: + { + guint year, month, day = 0; + hildon_calendar_popup_get_date(popup, &year, &month, &day); + + /*Verifies that the date is valid: */ + hildon_calendar_popup_set_date(popup, g_value_get_int(value), month, day); + break; + } + case PROP_MIN_YEAR: + g_object_set_property(G_OBJECT(priv->cal), "min-year", value); + break; + case PROP_MAX_YEAR: + g_object_set_property(G_OBJECT(priv->cal), "max-year", value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void hildon_calendar_popup_get_property(GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + HildonCalendarPopupPrivate *priv = + HILDON_CALENDAR_POPUP_GET_PRIVATE(HILDON_CALENDAR_POPUP (object)); + + switch (property_id) { + case PROP_DAY: + g_object_get_property(G_OBJECT(priv->cal), pspec->name, value); + break; + case PROP_MONTH: + g_object_get_property(G_OBJECT(priv->cal), pspec->name, value); + break; + case PROP_YEAR: + g_object_get_property(G_OBJECT(priv->cal), pspec->name, value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} diff --git a/src/hildon-calendar-popup.h b/src/hildon-calendar-popup.h new file mode 100644 index 0000000..e2e1d15 --- /dev/null +++ b/src/hildon-calendar-popup.h @@ -0,0 +1,87 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_CALENDAR_POPUP_H__ +#define __HILDON_CALENDAR_POPUP_H__ + +#include + +G_BEGIN_DECLS +/** + * HILDON_TYPE_CALENDAR_POPUP: + * + * Macro for getting type of calendar popup. + * Since: 0.12.10 + */ +#define HILDON_TYPE_CALENDAR_POPUP ( hildon_calendar_popup_get_type() ) + +/** + * HILDON_CALENDAR_POPUP_TYPE: + * + * Deprecated: use #HILDON_TYPE_CALENDAR_POPUP instead + */ +#define HILDON_CALENDAR_POPUP_TYPE HILDON_TYPE_CALENDAR_POPUP + +#define HILDON_CALENDAR_POPUP(obj) (GTK_CHECK_CAST (obj,\ + HILDON_TYPE_CALENDAR_POPUP, HildonCalendarPopup)) +#define HILDON_CALENDAR_POPUP_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass),\ + HILDON_TYPE_CALENDAR_POPUP, HildonCalendarPopupClass)) +#define HILDON_IS_CALENDAR_POPUP(obj) (GTK_CHECK_TYPE (obj,\ + HILDON_TYPE_CALENDAR_POPUP)) +#define HILDON_IS_CALENDAR_POPUP_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_CALENDAR_POPUP)) + +/** + * HildonCalendarPopup: + * + * Internal struct for calendar popup. + */ +typedef struct _HildonCalendarPopup HildonCalendarPopup; +typedef struct _HildonCalendarPopupClass HildonCalendarPopupClass; + +/* Note: CalendarPopup is no longer derived from GtkWindow + but from GtkDialog */ + +struct _HildonCalendarPopup { + GtkDialog par; +}; + +struct _HildonCalendarPopupClass { + GtkDialogClass parent_class; +}; + +GType hildon_calendar_popup_get_type(void) G_GNUC_CONST; + +GtkWidget *hildon_calendar_popup_new(GtkWindow * parent, guint year, + guint month, guint day); + +void hildon_calendar_popup_set_date(HildonCalendarPopup * cal, + guint year, guint month, guint day); + +void hildon_calendar_popup_get_date(HildonCalendarPopup * cal, + guint * year, guint * month, + guint * day); + +G_END_DECLS +#endif /* __HILDON_CALENDAR_POPUP_H__ */ diff --git a/src/hildon-caption.c b/src/hildon-caption.c new file mode 100644 index 0000000..5accf57 --- /dev/null +++ b/src/hildon-caption.c @@ -0,0 +1,1254 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-caption + * @short_description: A single-child container widget that precedes the + * contained widget with a field label and an optional icon + * + * #HildonCaption is a single-child container widget that precedes the + * contained widget with a field label and an optional icon. It allows + * grouping of several controls together. When a captioned widget has focus, + * both widget and caption label are displayed with active focus. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hildon-caption.h" +#include "hildon-defines.h" + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#define _(String) dgettext(PACKAGE, String) + +#define HILDON_CAPTION_SPACING 6 + +#define HILDON_CAPTION_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_CAPTION, HildonCaptionPrivate)); + +/*our parent class*/ +static GtkEventBox *parent_class = NULL; + +typedef struct _HildonCaptionPrivate HildonCaptionPrivate; + +enum +{ + PROP_NONE, + PROP_LABEL, + PROP_ICON, + PROP_STATUS, + PROP_SEPARATOR, + PROP_SIZE_GROUP, + PROP_ICON_POSITION, +}; + +enum +{ + CHILD_PROP_NONE, + CHILD_PROP_EXPAND +}; + +static void hildon_caption_class_init ( HildonCaptionClass *caption_class ); +static void hildon_caption_init ( HildonCaption *caption ); +static void hildon_caption_size_request ( GtkWidget *widget, GtkRequisition *requisition ); +static void hildon_caption_size_allocate( GtkWidget *widget, GtkAllocation *allocation ); + +static void hildon_caption_forall( GtkContainer *container, + gboolean include_internals, + GtkCallback callback, gpointer data ); +static void hildon_caption_hierarchy_changed( GtkWidget *widget, + GtkWidget *previous_toplevel); +static void hildon_caption_set_focus( GtkWindow *window, GtkWidget *widget, + GtkWidget *caption ); +static void hildon_caption_activate( GtkWidget *widget ); + +static void hildon_caption_set_property( GObject *object, guint param_id, + const GValue *value, GParamSpec *pspec ); +static void hildon_caption_get_property( GObject *object, guint param_id, + GValue *value, GParamSpec *pspec ); +static gboolean hildon_caption_expose( GtkWidget *widget, + GdkEventExpose *event ); +static void hildon_caption_destroy( GtkObject *self ); +static gboolean hildon_caption_button_press( GtkWidget *widget, GdkEventButton *event ); + +static void +hildon_caption_set_label_text( HildonCaptionPrivate *priv ); + +static void hildon_caption_set_child_property (GtkContainer *container, + GtkWidget *child, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void hildon_caption_get_child_property (GtkContainer *container, + GtkWidget *child, + guint property_id, + GValue *value, + GParamSpec *pspec); + +struct _HildonCaptionPrivate +{ + GtkWidget *caption_area; + GtkWidget *label; + GtkWidget *icon; + GtkWidget *icon_align; /* Arbitrary icon widgets do not support alignment */ + GtkSizeGroup *group; + gchar *text; + gchar *separator; + guint is_focused : 1; + guint expand : 1; + HildonCaptionStatus status; + HildonCaptionIconPosition icon_position; +}; + +/* Register optional/mandatory type enumeration */ +/* FIXME: mandatory icon was removed. The mandatory/optional logic + remains, it should most probably be removed as well. This imply APi + change, especially hildon_caption_new() */ +GType +hildon_caption_status_get_type (void) +{ + static GType etype = 0; + if (etype == 0) { + static const GEnumValue values[] = { + { HILDON_CAPTION_OPTIONAL, "HILDON_CAPTION_OPTIONAL", "optional" }, + { HILDON_CAPTION_MANDATORY, "HILDON_CAPTION_MANDATORY", "mandatory" }, + { 0, NULL, NULL } + }; + etype = g_enum_register_static ("HildonCaptionStatus", values); + } + return etype; +} + +GType +hildon_caption_icon_position_get_type (void) +{ + static GType etype = 0; + if (etype == 0) { + static const GEnumValue values[] = { + { HILDON_CAPTION_POSITION_LEFT, "HILDON_CAPTION_POSITION_LEFT", "left" }, + { HILDON_CAPTION_POSITION_RIGHT, "HILDON_CAPTION_POSITION_RIGHT", "right" }, + { 0, NULL, NULL } + }; + etype = g_enum_register_static ("HildonCaptionIconPosition", values); + } + return etype; +} + +/** + * hildon_caption_get_type: + * + * Initialises, and returns the type of a hildon caption. + * + * @Returns: GType of #HildonCaption + */ +GType hildon_caption_get_type (void) +{ + static GType caption_type = 0; + + if (!caption_type) + { + static const GTypeInfo caption_info = { + sizeof(HildonCaptionClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_caption_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonCaption), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_caption_init, + }; + caption_type = g_type_register_static( GTK_TYPE_EVENT_BOX, + "HildonCaption", &caption_info, 0 ); + } + return caption_type; +} + +/* + * Initialises the caption class. + */ +static void hildon_caption_class_init( HildonCaptionClass *caption_class ) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(caption_class); + GObjectClass *gobject_class = G_OBJECT_CLASS(caption_class); + GtkContainerClass *container_class = GTK_CONTAINER_CLASS(caption_class); + + parent_class = g_type_class_peek_parent( caption_class ); + + g_type_class_add_private( caption_class, sizeof(HildonCaptionPrivate) ); + + /* Override virtual functions */ + gobject_class->get_property = hildon_caption_get_property; + gobject_class->set_property = hildon_caption_set_property; + + caption_class->activate = hildon_caption_activate; + + GTK_OBJECT_CLASS(caption_class)->destroy = hildon_caption_destroy; + + container_class->forall = hildon_caption_forall; + container_class->set_child_property = hildon_caption_set_child_property; + container_class->get_child_property = hildon_caption_get_child_property; + + widget_class->expose_event = hildon_caption_expose; + widget_class->hierarchy_changed = hildon_caption_hierarchy_changed; + widget_class->size_request = hildon_caption_size_request; + widget_class->size_allocate = hildon_caption_size_allocate; + widget_class->button_press_event = hildon_caption_button_press; + + /* Create new signals and properties */ + widget_class->activate_signal = g_signal_new( "activate", + G_OBJECT_CLASS_TYPE( + gobject_class), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_ACTION, + G_STRUCT_OFFSET( HildonCaptionClass, + activate), NULL, NULL, + gtk_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * HildonCaption:label: + * + * Caption label. + */ + g_object_class_install_property( gobject_class, PROP_LABEL, + g_param_spec_string("label", + "Current label", "Caption label", + NULL, G_PARAM_READABLE | G_PARAM_WRITABLE) ); + + /** + * HildonCaption:icon: + * + * The icon shown on the caption area. + */ + g_object_class_install_property( gobject_class, PROP_ICON, + g_param_spec_object("icon", + "Current icon", + "The icon shown on the caption area", + GTK_TYPE_WIDGET, G_PARAM_READABLE | + G_PARAM_WRITABLE) ); + /** + * HildonCaption:status: + * + * Mandatory or optional status. + */ + g_object_class_install_property( gobject_class, PROP_STATUS, + g_param_spec_enum("status", + "Current status", + "Mandatory or optional status", + HILDON_TYPE_CAPTION_STATUS, + HILDON_CAPTION_OPTIONAL, + G_PARAM_READABLE | G_PARAM_WRITABLE) ); + /** + * HildonCaption:icon-position: + * + * If the icon is positioned on the left or right side. + * + * Since: 0.14.5 + */ + g_object_class_install_property( gobject_class, PROP_ICON_POSITION, + g_param_spec_enum("icon-position", + "Icon position", + "If the icon is on the left or right side", + HILDON_TYPE_CAPTION_ICON_POSITION, + HILDON_CAPTION_POSITION_RIGHT, + G_PARAM_READABLE | G_PARAM_WRITABLE) ); + + /** + * HildonCaption:size_group: + * + * Current size group the caption is in. + */ + g_object_class_install_property( gobject_class, PROP_SIZE_GROUP, + g_param_spec_object("size_group", + "Current size group", + "Current size group the caption is in", + GTK_TYPE_SIZE_GROUP, G_PARAM_READABLE | + G_PARAM_WRITABLE) ); + + /** + * HildonCaption:separator: + * + * The current separator. + */ + g_object_class_install_property( gobject_class, PROP_SEPARATOR, + g_param_spec_string("separator", + "Current separator", "Current separator", + _("ecdg_ti_caption_separator"), + G_PARAM_READABLE | G_PARAM_WRITABLE) ); + + /* Create child properties. These are related to + child <-> parent relationship, not to either of objects itself */ + gtk_container_class_install_child_property (container_class, + CHILD_PROP_EXPAND, + g_param_spec_boolean ("expand", + "Same as GtkBox expand.", + "Same as GtkBox expand. Wheter the child should be expanded or not.", + FALSE, + G_PARAM_READWRITE)); +} + +/* Destroy can be called multiple times, remember to set pointers to NULL */ +static void hildon_caption_destroy( GtkObject *self ) +{ + HildonCaptionPrivate *priv = HILDON_CAPTION_GET_PRIVATE(self); + + /* Free our internal child */ + if( priv->caption_area ) + { + gtk_widget_unparent( priv->caption_area ); + priv->caption_area = NULL; + } + + /* Free user provided strings */ + if( priv->text ) + { + g_free( priv->text ); + priv->text = NULL; + } + if( priv->separator ) + { + g_free( priv->separator ); + priv->separator = NULL; + } + + /* Parent classes destroy takes care of user packed contents */ + if( GTK_OBJECT_CLASS(parent_class)->destroy ) + GTK_OBJECT_CLASS(parent_class)->destroy( self ); +} + +/* Parent, eventbox will run allocate also for the child which may be + * owning a window too. This window is then moved and resized + * and we do not want to do that (it causes flickering). + */ +static gboolean hildon_caption_expose( GtkWidget *widget, + GdkEventExpose *event ) +{ + HildonCaptionPrivate *priv = NULL; + GtkRequisition req; + GtkAllocation alloc; + gfloat align; + + g_assert( HILDON_IS_CAPTION(widget) ); + priv = HILDON_CAPTION_GET_PRIVATE(widget); + + if( !GTK_WIDGET_DRAWABLE(widget) ) + return FALSE; + + GTK_WIDGET_CLASS(parent_class)->expose_event( widget, event ); + + /* If our child control is focused, we draw nice looking focus + graphics for the caption */ + if ( priv->is_focused && priv->text ) + { + /* Determine focus box dimensions */ + gtk_widget_get_child_requisition( priv->caption_area, &req ); + align = hildon_caption_get_label_alignment(HILDON_CAPTION(widget)); + + alloc.width = priv->caption_area->allocation.width + HILDON_CAPTION_SPACING; + alloc.height = MIN (req.height + (2 * widget->style->ythickness), priv->caption_area->allocation.height); + + alloc.x = priv->caption_area->allocation.x - HILDON_CAPTION_SPACING; /* - left margin */ + alloc.y = priv->caption_area->allocation.y + + MAX(((priv->caption_area->allocation.height - alloc.height) * align), 0); + + /* Paint the focus box */ + gtk_paint_box( widget->style, widget->window, GTK_STATE_ACTIVE, + GTK_SHADOW_OUT, NULL, widget, "selection", + alloc.x, alloc.y, alloc.width, alloc.height ); + + /* Paint caption contents on top of the focus box */ + GTK_WIDGET_GET_CLASS(priv->caption_area)->expose_event( + priv->caption_area, event); + } + + return FALSE; +} + +static void hildon_caption_set_property( GObject *object, guint param_id, + const GValue *value, + GParamSpec *pspec ) +{ + HildonCaptionPrivate *priv = HILDON_CAPTION_GET_PRIVATE(object); + + switch( param_id ) + { + case PROP_ICON_POSITION: + + hildon_caption_set_icon_position (HILDON_CAPTION (object), + g_value_get_enum (value)); + + break; + + case PROP_LABEL: + /* Free old label string */ + if( priv->text ) + { + g_free( priv->text ); + priv->text = NULL; + } + + /* Update label */ + priv->text = g_value_dup_string(value); + hildon_caption_set_label_text( priv ); + break; + + case PROP_ICON: + /* Remove old icon */ + if( priv->icon ) + gtk_container_remove( GTK_CONTAINER(priv->icon_align), priv->icon ); + + /* Pack and display new icon */ + priv->icon = g_value_get_object( value ); + if( priv->icon ) + { + gtk_container_add(GTK_CONTAINER(priv->icon_align), priv->icon); + gtk_widget_show_all( priv->caption_area ); + } + break; + + case PROP_STATUS: + priv->status = g_value_get_enum( value ); + break; + + case PROP_SIZE_GROUP: + /* Detach from previous size group */ + if( priv->group ) + gtk_size_group_remove_widget( priv->group, priv->caption_area ); + + priv->group = g_value_get_object( value ); + + /* Attach to new size group */ + if( priv->group ) + gtk_size_group_add_widget( priv->group, priv->caption_area ); + gtk_widget_queue_draw( GTK_WIDGET(object) ); + break; + + case PROP_SEPARATOR: + + /* Free old separator */ + if( priv->separator ) + { + g_free( priv->separator ); + priv->separator = NULL; + } + + priv->separator = g_value_dup_string(value); + hildon_caption_set_label_text( priv ); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); + break; + } +} + +static void hildon_caption_get_property( GObject *object, guint param_id, + GValue *value, GParamSpec *pspec ) +{ + HildonCaptionPrivate *priv = HILDON_CAPTION_GET_PRIVATE(object); + + switch (param_id) + { + case PROP_LABEL: + g_value_set_string( value, priv->text ); + break; + case PROP_ICON: + g_value_set_object( value, priv->icon ); + break; + case PROP_STATUS: + g_value_set_enum( value, priv->status ); + break; + case PROP_ICON_POSITION: + g_value_set_enum( value, priv->icon_position); + break; + case PROP_SIZE_GROUP: + g_value_set_object( value, priv->group ); + break; + case PROP_SEPARATOR: + g_value_set_string( value, priv->separator ); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); + break; + } +} + +static void hildon_caption_set_child_property( GtkContainer *container, + GtkWidget *child, + guint property_id, + const GValue *value, + GParamSpec *pspec ) +{ + switch (property_id) + { + case CHILD_PROP_EXPAND: + hildon_caption_set_child_expand( HILDON_CAPTION(container), + g_value_get_boolean(value) ); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(container, property_id, pspec); + break; + } +} + +static void hildon_caption_get_child_property( GtkContainer *container, + GtkWidget *child, + guint property_id, + GValue *value, + GParamSpec *pspec ) +{ + switch (property_id) + { + case CHILD_PROP_EXPAND: + g_value_set_boolean( value, hildon_caption_get_child_expand( + HILDON_CAPTION(container)) ); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(container, property_id, pspec); + break; + } +} + +/* We want to activate out child control on button press */ +static gboolean hildon_caption_button_press( GtkWidget *widget, + GdkEventButton *event ) +{ + HildonCaptionPrivate *priv = HILDON_CAPTION_GET_PRIVATE(widget); + GtkWidget *child = GTK_BIN(widget)->child; + + /* nothing to do */ + if (priv->is_focused == TRUE) + return; + + /* If child can take focus, we simply grab focus to it */ + if ((GTK_WIDGET_CAN_FOCUS(child) || GTK_IS_CONTAINER(child)) && + GTK_WIDGET_IS_SENSITIVE(child)) + { + /* Only if container can be focusable we must set is_focused to TRUE */ + if (GTK_IS_CONTAINER(child)) + { + if (gtk_widget_child_focus (child, + GTK_DIR_TAB_FORWARD)) + priv->is_focused = TRUE; + } + else + { + priv->is_focused = TRUE; + gtk_widget_grab_focus (GTK_BIN (widget)->child); + } + } + + return FALSE; +} + +static void hildon_caption_init( HildonCaption *caption ) +{ + HildonCaptionPrivate *priv = NULL; + + /* Initialize startup state */ + priv = HILDON_CAPTION_GET_PRIVATE(caption); + priv->status = HILDON_CAPTION_OPTIONAL; + priv->icon = NULL; + priv->group = NULL; + priv->is_focused = FALSE; + priv->text = NULL; + + priv->separator = g_strdup(_("ecdg_ti_caption_separator")); + + gtk_widget_push_composite_child(); + + /* Create caption text */ + priv->caption_area = gtk_hbox_new( FALSE, HILDON_CAPTION_SPACING ); + priv->label = gtk_label_new( NULL ); + priv->icon_align = gtk_alignment_new(0.5f, 0.5f, 0.0f, 0.0f); + priv->icon_position = HILDON_CAPTION_POSITION_RIGHT; + + /* We want to receive button presses for child widget activation */ + gtk_event_box_set_above_child( GTK_EVENT_BOX(caption), FALSE ); + gtk_widget_add_events( GTK_WIDGET(caption), GDK_BUTTON_PRESS_MASK ); + + /* Pack text label caption layout */ + gtk_box_pack_end( GTK_BOX(priv->caption_area), priv->icon_align, FALSE, FALSE, 0); + gtk_box_pack_end( GTK_BOX(priv->caption_area), priv->label, FALSE, FALSE, 0 ); + gtk_widget_set_parent( priv->caption_area, GTK_WIDGET(caption) ); + + + gtk_widget_pop_composite_child(); + + hildon_caption_set_child_expand( caption, TRUE ); + + gtk_widget_show_all( priv->caption_area ); +} + +static void hildon_caption_set_focus( GtkWindow *window, GtkWidget *widget, + GtkWidget *caption ) +{ + HildonCaptionPrivate *priv = HILDON_CAPTION_GET_PRIVATE(caption); + + /* check if ancestor gone */ + if (!widget) + { + return; + } + + /* Try to find caption among the ancestors of widget */ + if (gtk_widget_is_ancestor(widget, caption)) + { + priv->is_focused = TRUE; + gtk_widget_queue_draw( caption ); + return; + } + + if( priv->is_focused == TRUE ) + { + /* Caption wasn't found, so cannot focus */ + priv->is_focused = FALSE; + gtk_widget_queue_draw( caption ); + } +} + +/* We need to connect/disconnect signal handlers to toplevel window + in which we reside. Ww want to update connected signals if our + parent changes */ +static void hildon_caption_hierarchy_changed( GtkWidget *widget, + GtkWidget *previous_toplevel) +{ + GtkWidget *current_ancestor; + HildonCaptionPrivate *priv; + + priv = HILDON_CAPTION_GET_PRIVATE(widget); + + if( GTK_WIDGET_CLASS(parent_class)->hierarchy_changed ) + GTK_WIDGET_CLASS(parent_class)->hierarchy_changed( widget, + previous_toplevel ); + + /* If we already were inside a window, remove old handler */ + if (previous_toplevel) { + /* This is a compilation workaround for gcc > 3.3 since glib is buggy */ + /* see http://bugzilla.gnome.org/show_bug.cgi?id=310175 */ +#ifdef __GNUC__ + __extension__ +#endif + g_signal_handlers_disconnect_by_func + (previous_toplevel, (gpointer) hildon_caption_set_focus, widget); + } + current_ancestor = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW); + + /* Install new handler for focus movement */ + if (current_ancestor) + g_signal_connect( current_ancestor, "set-focus", + G_CALLBACK(hildon_caption_set_focus), widget ); +} + +static void hildon_caption_size_request( GtkWidget *widget, + GtkRequisition *requisition ) +{ + GtkRequisition req; + HildonCaptionPrivate *priv = NULL; + g_return_if_fail( HILDON_IS_CAPTION(widget) ); + priv = HILDON_CAPTION_GET_PRIVATE(widget); + + /* Use the same size requisition for the main box of the caption */ + gtk_widget_size_request( priv->caption_area, &req ); + + if( GTK_WIDGET_CLASS(parent_class)->size_request ) + GTK_WIDGET_CLASS(parent_class)->size_request( widget, requisition ); + + requisition->width += req.width + HILDON_CAPTION_SPACING * 3; + + if( (req.height + (2 * widget->style->ythickness)) > requisition->height ) + requisition->height = req.height + (2 * widget->style->ythickness); +} + +/* We use HILDON_CAPTION_SPACING to make it look a bit nicer */ +static void hildon_caption_size_allocate( GtkWidget *widget, + GtkAllocation *allocation ) +{ + GtkAllocation allocA; + GtkAllocation allocB; + GtkRequisition req; + GtkWidget *child = NULL; + HildonCaptionPrivate *priv = NULL; + + g_assert( HILDON_IS_CAPTION(widget) ); + priv = HILDON_CAPTION_GET_PRIVATE(widget); + + /* Position the caption to its allocated location */ + if( GTK_WIDGET_REALIZED(widget) ) + gdk_window_move_resize (widget->window, + allocation->x + GTK_CONTAINER (widget)->border_width, + allocation->y + GTK_CONTAINER (widget)->border_width, + MAX (allocation->width - GTK_CONTAINER (widget)->border_width * 2, 0), + MAX (allocation->height - GTK_CONTAINER (widget)->border_width * 2, 0)); + + child = GTK_BIN(widget)->child; + + widget->allocation = *allocation; + gtk_widget_get_child_requisition( priv->caption_area, &req ); + + allocA.height = allocB.height = allocation->height; + allocA.width = allocB.width = allocation->width; + allocA.x = allocB.x = allocB.y = allocA.y = 0; + + /* Center the captioned widget */ + if( allocA.width > req.width + HILDON_CAPTION_SPACING ) + { + allocA.x += req.width + HILDON_CAPTION_SPACING * 2; + allocB.width = req.width; + } + + /* Leave at least the space of the HILDON_CAPTION_SPACING in the left */ + allocB.x = HILDON_CAPTION_SPACING; + + /* Leave room for the other drawable parts of the caption control */ + allocA.width -= req.width + HILDON_CAPTION_SPACING * 2; + + /* Give the child at least its minimum requisition, unless it is expandable */ + if( !priv->expand && child && GTK_WIDGET_VISIBLE(child) ) + { + GtkRequisition child_req; + gtk_widget_get_child_requisition( child, &child_req ); + allocA.width = MIN( allocA.width, child_req.width ); + allocA.height = MIN( allocA.height, child_req.height ); + } + + /* Ensure there are no negative dimensions */ + if( allocA.width < 0 ) + { + allocB.width = req.width + allocA.width; + allocA.width = 0; + allocB.width = MAX (allocB.width, 0); + } + + allocA.height = MAX (allocA.height, 0); + allocB.height = MAX (allocB.height, 0); + + if (child && GTK_WIDGET_VISIBLE(child) ) + gtk_widget_size_allocate( child, &allocA ); + + gtk_widget_size_allocate( priv->caption_area, &allocB ); +} + +static void hildon_caption_forall( GtkContainer *container, + gboolean include_internals, + GtkCallback callback, gpointer data ) +{ + HildonCaptionPrivate *priv = NULL; + + g_assert( HILDON_IS_CAPTION(container) ); + g_assert( callback != NULL ); + + priv = HILDON_CAPTION_GET_PRIVATE(container); + + /* Execute callback for the child widgets */ + if( GTK_CONTAINER_CLASS(parent_class)->forall ) + GTK_CONTAINER_CLASS(parent_class)->forall( container, include_internals, + callback, data ); + + if( include_internals ) + /* Execute callback for the parent box as well */ + (*callback)( priv->caption_area, data ); +} + + +/** + * hildon_caption_set_sizegroup: + * @caption : a #HildonCaption + * @new_group : a #GtkSizeGroup + * + * Sets a #GtkSizeGroup of a given captioned control. + * + * Deprecated: use g_object_set, property :size-group + */ +void hildon_caption_set_sizegroup( const HildonCaption *self, + GtkSizeGroup *group ) +{ + g_object_set( G_OBJECT(self), "size_group", group, NULL ); +} + +/** + * hildon_caption_get_sizegroup: + * @caption : a #HildonCaption + * + * Query given captioned control for the #GtkSizeGroup assigned to it. + * + * @Returns : a #GtkSizeGroup + * + * Deprecated: Use g_object_get, property :size-group + */ +GtkSizeGroup *hildon_caption_get_sizegroup( const HildonCaption *self ) +{ + HildonCaptionPrivate *priv; + g_return_val_if_fail( HILDON_IS_CAPTION (self), NULL ); + priv = HILDON_CAPTION_GET_PRIVATE(self); + return priv->group; +} + +/** + * hildon_caption_new: + * @group : a #GtkSizeGroup for controlling the size of related captions, + * Can be NULL + * @value : the caption text to accompany the text entry. The widget makes + * a copy of this text. + * @control : the control that is to be captioned + * @icon : an icon to accompany the label - can be NULL in which case no + * icon is displayed + * @flag : indicates whether this captioned control is mandatory or + * optional + * + * Creates a new instance of hildon_caption widget, with a specific + * control and image. + * Note: Clicking on a focused caption will trigger the activate signal. + * The default behaviour for the caption's activate signal is to call + * gtk_widget_activate on it's control. + * + * @Returns : a #GtkWidget pointer of Caption + */ +GtkWidget *hildon_caption_new( GtkSizeGroup *group, const gchar *value, + GtkWidget *child, GtkWidget *icon, + HildonCaptionStatus flag) +{ + GtkWidget *widget; + g_return_val_if_fail( GTK_IS_WIDGET(child), NULL ); + + widget = g_object_new( HILDON_TYPE_CAPTION, "label", value, + "child" /* From GtkContainer */, child, "size_group", group, "icon", icon, "status", flag, + NULL ); + + return widget; +} + +/** + * hildon_caption_is_mandatory: + * @caption : a #HildonCaption + * + * Query #HildonCaption whether this captioned control is a mandatory one. + * + * @Returns : is this captioned control a mandatory one? + */ + +gboolean hildon_caption_is_mandatory( const HildonCaption *caption ) +{ + HildonCaptionPrivate *priv; + g_return_val_if_fail( HILDON_IS_CAPTION(caption), FALSE ); + priv = HILDON_CAPTION_GET_PRIVATE(caption); + + return priv->status == HILDON_CAPTION_MANDATORY; +} + +/** + * hildon_caption_set_icon_position: + * @caption : a #HildonCaption + * @pos : one of the values from #HildonCaptionIconPosition + * + * Sets #HildonCaption icon position. + * + * Since: 0.14.5 + */ + +void hildon_caption_set_icon_position( HildonCaption *caption, + HildonCaptionIconPosition pos ) +{ + g_return_if_fail (HILDON_IS_CAPTION (caption)); + HildonCaptionPrivate *priv = HILDON_CAPTION_GET_PRIVATE(caption); + + g_return_if_fail (priv->caption_area != NULL); + int order = (pos == HILDON_CAPTION_POSITION_LEFT) ? -1 : 0; + gtk_box_reorder_child (GTK_BOX (priv->caption_area), priv->icon_align, order); + + priv->icon_position = pos; +} + +/** + * hildon_caption_get_icon_position: + * @caption : a #HildonCaption + * + * Gets #HildonCaption icon position. + * + * @Returns : one of the values from #HildonCaptionIconPosition. + * + * Since: 0.14.5 + */ + +HildonCaptionIconPosition hildon_caption_get_icon_position( const HildonCaption *caption ) +{ + g_return_if_fail (HILDON_IS_CAPTION (caption)); + HildonCaptionPrivate *priv = HILDON_CAPTION_GET_PRIVATE(caption); + + return priv->icon_position; +} + +/** + * hildon_caption_set_status: + * @caption : a #HildonCaption + * @flag : one of the values from #HildonCaptionStatus + * + * Sets #HildonCaption status. + */ + +void hildon_caption_set_status( HildonCaption *caption, + HildonCaptionStatus flag ) +{ + g_return_if_fail( HILDON_IS_CAPTION(caption) ); + + g_object_set( G_OBJECT(caption), "status", flag, NULL ); +} + +/** + * hildon_caption_get_status: + * @caption : a #HildonCaption + * + * Gets #HildonCaption status. + * + * @Returns : one of the values from #HildonCaptionStatus + */ + +HildonCaptionStatus hildon_caption_get_status( const HildonCaption *caption ) +{ + HildonCaptionPrivate *priv; + g_return_val_if_fail( HILDON_IS_CAPTION(caption), HILDON_CAPTION_OPTIONAL ); + priv = HILDON_CAPTION_GET_PRIVATE(caption); + + return priv->status; +} + +/** + * hildon_caption_set_icon_image: + * @caption : a #HildonCaption + * @icon : the #GtkImage to use as the icon. + * calls gtk_widget_show on the icon if !GTK_WIDGET_VISIBLE(icon) + * + * Sets the icon to be used by this hildon_caption widget. + */ + +void hildon_caption_set_icon_image( HildonCaption *caption, GtkWidget *icon ) +{ + g_return_if_fail( HILDON_IS_CAPTION(caption) ); + + g_object_set( G_OBJECT(caption), "icon", icon, NULL ); +} + +/** + * hildon_caption_get_icon_image: + * @caption : a #HildonCaption + * + * Gets icon of #HildonCaption + * + * @Returns : the #GtkImage that is being used as the icon by the + * hildon_caption, or NULL if no icon is in use + */ + +GtkWidget *hildon_caption_get_icon_image( const HildonCaption *caption ) +{ + HildonCaptionPrivate *priv; + g_return_val_if_fail( HILDON_IS_CAPTION(caption), NULL ); + priv = HILDON_CAPTION_GET_PRIVATE(caption); + + return priv->icon; +} + +/** + * hildon_caption_set_label: + * @caption : a #HildonCaption + * @label : the text to use + * + * Sets the label text that appears before the control. + * Separator character is added to the end of the label string. By default + * the separator is ":". + */ + +void hildon_caption_set_label( HildonCaption *caption, const gchar *label ) +{ + g_return_if_fail( HILDON_IS_CAPTION(caption) ); + + g_object_set( G_OBJECT(caption), "label", label, NULL ); +} + +/** + * hildon_caption_get_label: + * @caption : a #HildonCaption + * + * Gets label of #HildonCaption + * + * @Returns : the text currently being used as the label of the caption + * control. The string is owned by the label and the caller should never + * free or modify this value. + */ + +gchar *hildon_caption_get_label( const HildonCaption *caption ) +{ + HildonCaptionPrivate *priv; + g_return_val_if_fail(HILDON_IS_CAPTION(caption), ""); + priv = HILDON_CAPTION_GET_PRIVATE(caption); + + return (gchar*)gtk_label_get_text(GTK_LABEL(GTK_LABEL(priv->label))); +} + +/** + * hildon_caption_set_separator: + * @caption : a #HildonCaption + * @separator : the separator to use + * + * Sets the separator character that appears after the label. + * The default seaparator character is ":" + * separately. + */ + +void hildon_caption_set_separator( HildonCaption *caption, + const gchar *separator ) +{ + g_return_if_fail( HILDON_IS_CAPTION(caption) ); + + g_object_set( G_OBJECT(caption), "separator", separator, NULL ); +} + +/** + * hildon_caption_get_separator: + * @caption : a #HildonCaption + * + * Gets separator string of #HildonCaption + * + * @Returns : the text currently being used as the separator of the caption + * control. The string is owned by the caption control and the caller should + * never free or modify this value. + */ + +gchar *hildon_caption_get_separator( const HildonCaption *caption ) +{ + HildonCaptionPrivate *priv; + g_return_val_if_fail(HILDON_IS_CAPTION(caption), ""); + priv = HILDON_CAPTION_GET_PRIVATE(caption); + + return priv->separator; +} + + +/** + * hildon_caption_get_control: + * @caption : a #HildonCaption + * + * Gets caption's control. + * + * @Returns : a #GtkWidget + * + * Deprecated: use gtk_bin_get_child instead + */ +GtkWidget *hildon_caption_get_control( const HildonCaption *caption ) +{ + g_return_val_if_fail( HILDON_IS_CAPTION(caption), NULL ); + return GTK_BIN(caption)->child; +} + +/*activates the child control + *We have this signal so that if needed an application can + *know when we've been activated (useful for captions with + *multiple children + */ +/* FIXME: There never are multiple children. Possibly activate + signal could be removed entirely? (does anyone use it?) */ +static void hildon_caption_activate( GtkWidget *widget ) +{ + HildonCaptionPrivate *priv; + GtkWidget *child = GTK_BIN(widget)->child; + priv = HILDON_CAPTION_GET_PRIVATE(widget); + + gtk_widget_grab_focus( child ); +} + +/** + * hildon_caption_set_child_expand: + * @caption : a #HildonCaption + * @expand : gboolean to determine is the child expandable + * + * Sets child expandability. + */ +void hildon_caption_set_child_expand( HildonCaption *caption, gboolean expand ) +{ + HildonCaptionPrivate *priv = NULL; + GtkWidget *child = NULL; + g_return_if_fail( HILDON_IS_CAPTION(caption) ); + + priv = HILDON_CAPTION_GET_PRIVATE(caption); + + /* Did the setting really change? */ + if( priv->expand == expand ) + return; + + priv->expand = expand; + child = GTK_BIN(caption)->child; + + /* We do not have a child, nothing to do */ + if( !GTK_IS_WIDGET(child) ) + return; + + if( GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (caption) ) + gtk_widget_queue_resize( child ); + + gtk_widget_child_notify( child, "expand" ); +} + +/** + * hildon_caption_get_child_expand: + * @caption : a #HildonCaption + * + * Gets childs expandability. + * + * @Returns : wheter the child is expandable or not. + */ +gboolean hildon_caption_get_child_expand( const HildonCaption *caption ) +{ + HildonCaptionPrivate *priv = NULL; + g_return_val_if_fail( HILDON_IS_CAPTION(caption), FALSE ); + priv = HILDON_CAPTION_GET_PRIVATE(caption); + return priv->expand; +} + +/** + * hildon_caption_set_control: + * @caption : a #HildonCaption + * @control : the control to use. Control should not be NULL. + * + * Sets the control of the caption. + * The old control will be destroyed, unless the caller has added a + * reference to it. + * Function unparents the old control (if there is one) and adds the new + * control. + * + * Deprecated: use gtk_container_add + */ +void hildon_caption_set_control( HildonCaption *caption, GtkWidget *control ) +{ + GtkWidget *child = NULL; + g_return_if_fail( HILDON_IS_CAPTION(caption) ); + child = GTK_BIN(caption)->child; + + if( child ) + gtk_container_remove( GTK_CONTAINER(caption), child ); + + if( control ) + { + gtk_container_add( GTK_CONTAINER(caption), control ); + child = control; + } + else + child = NULL; +} + +static void +hildon_caption_set_label_text( HildonCaptionPrivate *priv ) +{ + gchar *tmp = NULL; + g_assert ( priv != NULL ); + + if ( priv->text ) + { + if( priv->separator ) + { + /* Don't duplicate the separator, if the string already contains one */ + if (g_str_has_suffix(priv->text, priv->separator)) + { + gtk_label_set_text( GTK_LABEL( priv->label ), priv->text ); + } + else + { + /* Append separator and set text */ + tmp = g_strconcat( priv->text, priv->separator, NULL ); + gtk_label_set_text( GTK_LABEL( priv->label ), tmp ); + g_free( tmp ); + } + } + else + { + gtk_label_set_text( GTK_LABEL( priv->label ), priv->text ); + } + } + else + { + /* Clear the label */ + gtk_label_set_text( GTK_LABEL( priv->label ), "" ); + } + +} + +/** + * hildon_caption_set_label_alignment: + * @caption: a #HildonCaption widget + * @alignment: new vertical alignment + * + * Sets the vertical alignment to be used for the + * text part of the caption. Applications need to + * align the child control themselves. + * + * Since: 0.12.0 + */ +void hildon_caption_set_label_alignment(HildonCaption *caption, + gfloat alignment) +{ + HildonCaptionPrivate *priv; + + g_return_if_fail(HILDON_IS_CAPTION(caption)); + + priv = HILDON_CAPTION_GET_PRIVATE(caption); + g_object_set(priv->label, "yalign", alignment, NULL); + g_object_set(priv->icon_align, "yalign", alignment, NULL); + +} + +/** + * hildon_caption_get_label_alignment: + * @caption: a #HildonCaption widget + * + * Gets current vertical alignment for the text part. + * + * Returns: vertical alignment + * + * Since: 0.12.0 + */ +gfloat hildon_caption_get_label_alignment(HildonCaption *caption) +{ + HildonCaptionPrivate *priv; + gfloat result; + + g_return_val_if_fail( HILDON_IS_CAPTION(caption), 0); + priv = HILDON_CAPTION_GET_PRIVATE(caption); + g_object_get(priv->label, "yalign", &result, NULL); + + return result; +} diff --git a/src/hildon-caption.h b/src/hildon-caption.h new file mode 100644 index 0000000..49d4244 --- /dev/null +++ b/src/hildon-caption.h @@ -0,0 +1,156 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_CAPTION_H__ +#define __HILDON_CAPTION_H__ + +#include +#include +#include +#include + +G_BEGIN_DECLS + + +#define HILDON_TYPE_CAPTION ( hildon_caption_get_type() ) +#define HILDON_CAPTION(obj) \ + (GTK_CHECK_CAST (obj, HILDON_TYPE_CAPTION, HildonCaption)) +#define HILDON_CAPTION_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST ((klass),\ + HILDON_TYPE_CAPTION, HildonCaptionClass)) +#define HILDON_IS_CAPTION(obj) (GTK_CHECK_TYPE (obj, HILDON_TYPE_CAPTION)) +#define HILDON_IS_CAPTION_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_CAPTION)) + + +/** + * HildonCaptionStatus: + * @HILDON_CAPTION_OPTIONAL: Optional. + * @HILDON_CAPTION_MANDATORY: Mandatory. + * + * Keys to set the #HildonCaption to be optional or mandatory. + */ +typedef enum /*< skip >*/ +{ + HILDON_CAPTION_OPTIONAL = 0, + HILDON_CAPTION_MANDATORY +} HildonCaptionStatus; + +/** + * HildonCaptionIconPosition: + * @HILDON_CAPTION_POSITION_LEFT: Show the icon on the left side. + * @HILDON_CAPTION_POSITION_RIGHT: Show the icon on the right side. + * + * Keys to set the icon placement in #HildonCaption. + * + * Since: 0.14.5 + */ +typedef enum /*< skip >*/ +{ + HILDON_CAPTION_POSITION_LEFT = 0, + HILDON_CAPTION_POSITION_RIGHT +} HildonCaptionIconPosition; + +#define HILDON_TYPE_CAPTION_STATUS (hildon_caption_status_get_type ()) + +#define HILDON_TYPE_CAPTION_ICON_POSITION (hildon_caption_icon_position_get_type ()) + +GType hildon_caption_status_get_type (void) G_GNUC_CONST; + +GType hildon_caption_icon_position_get_type (void) G_GNUC_CONST; + +/** + * HildonCaption: + * + * Contains only private data. + */ +typedef struct _HildonCaption HildonCaption; +typedef struct _HildonCaptionClass HildonCaptionClass; + + +struct _HildonCaption +{ + GtkEventBox event_box; +}; + + +struct _HildonCaptionClass +{ + GtkEventBoxClass parent_class; + void (*activate) (HildonCaption *widget); +}; + + +GType hildon_caption_get_type (void) G_GNUC_CONST; + +GtkWidget *hildon_caption_new( GtkSizeGroup *group, const gchar *value, + GtkWidget *control, GtkWidget *icon, + HildonCaptionStatus flag ); +#ifndef HILDON_DISABLE_DEPRECATED +GtkSizeGroup *hildon_caption_get_sizegroup( const HildonCaption *caption ); + +void hildon_caption_set_sizegroup( const HildonCaption *caption, + GtkSizeGroup *new_group ); +#endif + +gboolean hildon_caption_is_mandatory( const HildonCaption *caption ); + +void hildon_caption_set_status( HildonCaption *caption, + HildonCaptionStatus flag ); + +HildonCaptionStatus hildon_caption_get_status( const HildonCaption *caption ); + +void hildon_caption_set_icon_position( HildonCaption *caption, + HildonCaptionIconPosition pos ); + +HildonCaptionIconPosition hildon_caption_get_icon_position( const HildonCaption *caption ); + +void hildon_caption_set_icon_image( HildonCaption *caption, GtkWidget *icon ); + +GtkWidget *hildon_caption_get_icon_image(const HildonCaption *caption); + +void hildon_caption_set_label( HildonCaption *caption, const gchar *label ); + +gchar *hildon_caption_get_label( const HildonCaption *caption ); + +void hildon_caption_set_separator( HildonCaption *caption, + const gchar *separator ); + +gchar *hildon_caption_get_separator( const HildonCaption *caption ); + +void hildon_caption_set_label_alignment(HildonCaption *caption, + gfloat alignment); +gfloat hildon_caption_get_label_alignment(HildonCaption *caption); + +#ifndef HILDON_DISABLE_DEPRECATED +GtkWidget *hildon_caption_get_control( const HildonCaption *caption ); + +void hildon_caption_set_control( HildonCaption *caption, GtkWidget *control ); +#endif + +void hildon_caption_set_child_expand( HildonCaption *caption, gboolean expand ); +gboolean hildon_caption_get_child_expand( const HildonCaption *caption ); + +G_END_DECLS +#endif /* __HILDON_CAPTION_H__ */ diff --git a/src/hildon-code-dialog.c b/src/hildon-code-dialog.c new file mode 100644 index 0000000..9a53ff1 --- /dev/null +++ b/src/hildon-code-dialog.c @@ -0,0 +1,480 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + + +#include "hildon-code-dialog.h" +#include "hildon-defines.h" +#include "hildon-banner.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#define HEIGHT (38-HILDON_MARGIN_DEFAULT) +#define WIDTH (60-HILDON_MARGIN_DEFAULT) +#define BACKSPACE_ICON "qgn_calculator_backspace" + +#define _(String) dgettext(PACKAGE, String) +#define c_(String) dgettext("hildon-common-strings", String) +#define DEVICELOCK_OK _("secu_enter_lock_code_dialog_ok") +#define DEVICELOCK_CANCEL _("secu_enter_lock_code_dialog_cancel") +#define DEVICELOCK_TITLE _("secu_application_title") +#define DEVICELOCK_MAX_CHAR_REACHED c_("ckdg_ib_maximum_characters_reached") + + + +#define MAX_PINCODE_LEN (10) + + + +static void hildon_code_dialog_class_init (HildonCodeDialogClass *cd_class); +static void hildon_code_dialog_init (HildonCodeDialog *self); +static void hildon_code_dialog_finalize (GObject *self); +static void hildon_code_dialog_button_clicked (GtkButton *buttonm, + gpointer user_data); +static void hildon_code_dialog_insert_text (GtkEditable *editable, + gchar *new_text, + gint new_text_length, + gint *position, + gpointer user_data); + +static gboolean hildon_code_dialog_key_press_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data); + + +GtkDialogClass *parent_class; + +struct _HildonCodeDialogPrivate +{ + GtkWidget *entry; + GtkWidget *buttons[5][3]; + GtkWidget *help_text; +}; + +GType hildon_code_dialog_get_type (void) +{ + static GType type = 0; + + if (!type) + { + static const GTypeInfo info = + { + sizeof(HildonCodeDialogClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_code_dialog_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonCodeDialog), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_code_dialog_init + }; + type = g_type_register_static (GTK_TYPE_DIALOG, + "HildonCodeDialog", &info, 0); + } + return type; +} + +static void hildon_code_dialog_class_init (HildonCodeDialogClass *cd_class) +{ + /* Get convenience variables */ + GObjectClass *object_class = G_OBJECT_CLASS (cd_class); + + parent_class = GTK_DIALOG_CLASS (g_type_class_peek_parent (cd_class)); + + object_class->finalize = hildon_code_dialog_finalize; + +} + +static void hildon_code_dialog_init (HildonCodeDialog *dialog) +{ + HildonCodeDialogPrivate *priv; + gint i, x, y; + GtkWidget *dialog_vbox1 = NULL; + GtkWidget *table = NULL; + GtkWidget *alignment = NULL; + GtkWidget *vbox1 = NULL; + GtkWidget *image1 = NULL; + GtkWidget *dialog_action_area1 = NULL; + GdkGeometry hints; + GtkWidget *okButton; + GtkWidget *cancelButton; + + priv = dialog->priv = (HildonCodeDialogPrivate*) g_malloc0 + (sizeof (HildonCodeDialogPrivate)); + + const gchar* numstrs[10] = { + "0","1","2","3","4","5","6","7","8","9" + }; + + GdkPixbuf* pixbuf = NULL; + GtkIconTheme* icon_theme = NULL; + GtkIconInfo *icon_info = NULL; + gint base_size=0; + + /* Set default title */ + gtk_window_set_title (GTK_WINDOW (dialog), DEVICELOCK_TITLE); + + gtk_window_set_type_hint(GTK_WINDOW (dialog), GDK_WINDOW_TYPE_HINT_DIALOG); + + hints.min_width = -1; + hints.min_height = -1; + hints.max_width = -1; + hints.max_height = -1; + + gtk_window_set_geometry_hints(GTK_WINDOW(dialog), GTK_WIDGET(dialog), + &hints, + GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE); + + table = gtk_table_new (4, 3, FALSE); + gtk_table_set_row_spacings (GTK_TABLE (table), HILDON_MARGIN_DEFAULT ); + gtk_table_set_col_spacings (GTK_TABLE (table), HILDON_MARGIN_DEFAULT ); + + dialog_vbox1 = GTK_DIALOG (dialog)->vbox; + vbox1 = gtk_vbox_new (FALSE, 0); + gtk_box_set_spacing (GTK_BOX(vbox1),HILDON_MARGIN_DOUBLE); + + priv->help_text= gtk_label_new (""); + alignment=gtk_alignment_new(0.5,0,1,1); + gtk_container_add(GTK_CONTAINER(alignment),priv->help_text); + + priv->entry = gtk_entry_new (); + + GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(priv->entry),GTK_CAN_FOCUS); + gtk_entry_set_invisible_char (GTK_ENTRY(priv->entry), g_utf8_get_char ("*")); + gtk_entry_set_alignment (GTK_ENTRY(priv->entry),1.0); + + gtk_editable_set_editable (GTK_EDITABLE(priv->entry),FALSE); + gtk_entry_set_visibility (GTK_ENTRY(priv->entry), FALSE); + + gtk_box_pack_start (GTK_BOX (vbox1),alignment,TRUE,FALSE,0); + gtk_box_pack_start (GTK_BOX (vbox1),priv->entry,TRUE,FALSE,0); + gtk_box_pack_start (GTK_BOX (vbox1),table,FALSE,TRUE,0); + + gtk_box_pack_start (GTK_BOX (dialog_vbox1), vbox1,FALSE,TRUE,0); + + + for(i=1;i<=3;i++) { + priv->buttons[0][i-1] = gtk_button_new_with_mnemonic(numstrs[i]); + gtk_widget_set_size_request(priv->buttons[0][i-1],WIDTH,HEIGHT); + gtk_table_attach_defaults(GTK_TABLE(table), priv->buttons[0][i-1], + i-1,i,0,1); + } + + for(i=4;i<=6;i++) { + priv->buttons[1][i-4] = gtk_button_new_with_mnemonic (numstrs[i]); + gtk_widget_set_size_request(priv->buttons[1][i-4],WIDTH,HEIGHT); + gtk_table_attach_defaults(GTK_TABLE(table),priv->buttons[1][i-4], + i-4,i-3,1,2); + } + + for(i=7;i<=9;i++) { + priv->buttons[2][i-7] = gtk_button_new_with_mnemonic (numstrs[i]); + gtk_widget_set_size_request(priv->buttons[2][i-7], WIDTH,HEIGHT); + gtk_table_attach_defaults(GTK_TABLE(table), priv->buttons[2][i-7], + i-7,i-6,2,3); + } + + priv->buttons[3][0] = priv->buttons[3][1] = + gtk_button_new_with_mnemonic (numstrs[0]); + gtk_widget_set_size_request (priv->buttons[3][0], WIDTH,HEIGHT); + gtk_table_attach (GTK_TABLE(table), priv->buttons[3][0], + 0,2,3,4, (GtkAttachOptions) (GTK_FILL), + (GtkAttachOptions) (0), 0, 0); + + priv->buttons[3][2] = gtk_button_new (); + gtk_widget_set_size_request(priv->buttons[3][2], WIDTH,HEIGHT); + gtk_table_attach_defaults(GTK_TABLE(table), priv->buttons[3][2], + 2,3,3,4); + + icon_theme = gtk_icon_theme_get_default (); + + icon_info = gtk_icon_theme_lookup_icon(icon_theme, BACKSPACE_ICON, 1, + GTK_ICON_LOOKUP_NO_SVG); + base_size = gtk_icon_info_get_base_size(icon_info); + gtk_icon_info_free(icon_info); + icon_info = NULL; + pixbuf = gtk_icon_theme_load_icon (icon_theme, + BACKSPACE_ICON, base_size, + GTK_ICON_LOOKUP_NO_SVG, + NULL); + image1 = gtk_image_new_from_pixbuf (pixbuf); + g_object_unref (G_OBJECT(pixbuf)); + gtk_container_add (GTK_CONTAINER (priv->buttons[3][2]), image1); + dialog_action_area1 = GTK_DIALOG (dialog)->action_area; + gtk_button_box_set_layout (GTK_BUTTON_BOX(dialog_action_area1), + GTK_BUTTONBOX_END); + + okButton = gtk_dialog_add_button (GTK_DIALOG(dialog),DEVICELOCK_OK, + GTK_RESPONSE_OK); + cancelButton = + gtk_dialog_add_button (GTK_DIALOG(dialog),DEVICELOCK_CANCEL, + GTK_RESPONSE_CANCEL); + + gtk_widget_set_sensitive (okButton, FALSE); + + priv->buttons[4][0] = priv->buttons[4][1] = okButton; + priv->buttons[4][2] = cancelButton; + + /* + Connect signals. + */ + g_signal_connect (G_OBJECT(priv->entry), "insert_text", + G_CALLBACK (hildon_code_dialog_insert_text), dialog); + + gtk_entry_set_max_length(GTK_ENTRY(priv->entry),MAX_PINCODE_LEN); + + for (x=0; x<3; x++) + { + for (y=0; y<3 ;y++) + { + g_signal_connect (G_OBJECT (priv->buttons[x][y]), "clicked", + G_CALLBACK (hildon_code_dialog_button_clicked), dialog); + g_signal_connect (G_OBJECT (priv->buttons[x][y]), "key-press-event", + G_CALLBACK (hildon_code_dialog_key_press_event), dialog); + } + } + + g_signal_connect (G_OBJECT (priv->buttons[3][0]), "clicked", + G_CALLBACK (hildon_code_dialog_button_clicked), dialog); + g_signal_connect (G_OBJECT (priv->buttons[3][0]), "key-press-event", + G_CALLBACK (hildon_code_dialog_key_press_event), dialog); + + g_signal_connect (G_OBJECT (priv->buttons[3][2]), "clicked", + G_CALLBACK (hildon_code_dialog_button_clicked), dialog); + g_signal_connect (G_OBJECT (priv->buttons[3][2]), "key-press-event", + G_CALLBACK (hildon_code_dialog_key_press_event), dialog); + + g_signal_connect (G_OBJECT (okButton), "key-press-event", + G_CALLBACK(hildon_code_dialog_key_press_event), dialog); + + g_signal_connect (G_OBJECT (cancelButton), "key-press-event", + G_CALLBACK (hildon_code_dialog_key_press_event), dialog); + +} + +static void hildon_code_dialog_finalize (GObject *self) +{ + HildonCodeDialog *dialog = HILDON_CODE_DIALOG (self); + + fprintf( stderr, "called destroy\n" ); + + g_free (dialog->priv); + + G_OBJECT_CLASS (parent_class)->finalize (self); +} + +/* Signal handlers */ +void hildon_code_dialog_button_clicked (GtkButton *button, gpointer user_data) +{ + HildonCodeDialog *dialog = HILDON_CODE_DIALOG (user_data); + HildonCodeDialogPrivate *priv = dialog->priv; + const char *number = gtk_button_get_label (button); + + if (number && *number ) + { + gtk_entry_append_text (GTK_ENTRY (priv->entry), number); + } + else + { + /* Backspace */ + gchar *text = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->entry))); + gchar *pos; + + pos = text; + + while (*pos != '\0') + { + pos ++; + } + + pos = g_utf8_find_prev_char (text, pos); + + if (pos) + { + *pos=0; + } + + gtk_entry_set_text (GTK_ENTRY (priv->entry), text); + + if (*text == 0) + { + gtk_widget_set_sensitive (priv->buttons[4][0], FALSE); + } + + g_free (text); + } + +} + +static void hildon_code_dialog_insert_text (GtkEditable *editable, + gchar *new_text, + gint new_text_length, + gint *position, + gpointer user_data) +{ + HildonCodeDialog *dialog = HILDON_CODE_DIALOG (user_data); + HildonCodeDialogPrivate *priv = dialog->priv; + gchar * text = g_strdup(gtk_entry_get_text (GTK_ENTRY (priv->entry))); + glong length = g_utf8_strlen (text, -1); + g_free (text); + + if (length == MAX_PINCODE_LEN) + { + hildon_banner_show_information (dialog, + NULL, + DEVICELOCK_MAX_CHAR_REACHED); + } + + else if (!length) + { + /* make the Ok button sensitive */ + gtk_widget_set_sensitive(priv->buttons[4][0], TRUE); + } +} + +static gboolean hildon_code_dialog_key_press_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data) +{ + HildonCodeDialog *dialog = HILDON_CODE_DIALOG (user_data); + HildonCodeDialogPrivate *priv = dialog->priv; + GtkWidget *new_widget = widget; + gint x, y; + + for (x = 0; x < 5; x++) + { + for (y = 0; y < 3; y++) + { + if (priv->buttons[x][y] == widget) + goto found; + } + } + return FALSE; + +found: + + while (new_widget == widget) + { + switch (event->keyval) + { + case GDK_Up: + x = (x+4)%5; + break; + + case GDK_Down: + x = (x+1)%5; + break; + + case GDK_Left: + y = (y+2)%3; + break; + + case GDK_Right: + y = (y+1)%3; + break; + + default: + return FALSE; + } + + new_widget = priv->buttons[x][y]; + } + + gtk_widget_grab_focus (new_widget); + + return TRUE; +} + +/* Public methods */ + +/** + * hildon_code_dialog_new: + * + * Use this function to create a new HildonCodeDialog. + * + * Return value: A @HildonCodeDialog. + **/ +GtkWidget *hildon_code_dialog_new() +{ + HildonCodeDialog *dialog = g_object_new (HILDON_TYPE_CODE_DIALOG, NULL); + + return GTK_WIDGET (dialog); +} + +/** + * hildon_code_dialog_get_code: + * @dialog: The #HildonCodeDialog from which to get the entered code + * + * Use this function to access the code entered by the user. + * + * Return value: The entered code. + **/ +const gchar *hildon_code_dialog_get_code (HildonCodeDialog *dialog) +{ + g_return_val_if_fail (HILDON_IS_CODE_DIALOG (dialog), NULL); + return gtk_entry_get_text (GTK_ENTRY (dialog->priv->entry)); +} + +/** + * hildon_code_dialog_clear_clode: + * @dialog: The #HildonCodeDialog whose entry should be cleared: + * + * Use this function to clear the user entered code. + **/ +void hildon_code_dialog_clear_code (HildonCodeDialog *dialog) +{ + g_return_if_fail (HILDON_IS_CODE_DIALOG (dialog)); + gtk_entry_set_text (GTK_ENTRY (dialog->priv->entry), ""); + gtk_widget_set_sensitive (dialog->priv->buttons[4][0], FALSE); +} + +/** + * hildon_code_dialog_set_help_text: + * @dialog: The #HildonCodeDialog whose entry should be cleared: + * @text: The text to use in the help label. + * + * Use this function to set the text that will be displayd in the + * help label + **/ +void hildon_code_dialog_set_help_text (HildonCodeDialog *dialog, + const gchar *text) +{ + g_return_if_fail (HILDON_IS_CODE_DIALOG (dialog)); + gtk_label_set_text (GTK_LABEL (dialog->priv->help_text), text); +} diff --git a/src/hildon-code-dialog.h b/src/hildon-code-dialog.h new file mode 100644 index 0000000..8ecc5dd --- /dev/null +++ b/src/hildon-code-dialog.h @@ -0,0 +1,71 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_CODE_DIALOG_H__ +#define __HILDON_CODE_DIALOG_H__ + +#include + +G_BEGIN_DECLS + + +#define HILDON_TYPE_CODE_DIALOG ( hildon_code_dialog_get_type() ) +#define HILDON_CODE_DIALOG(obj) \ + (GTK_CHECK_CAST (obj, HILDON_TYPE_CODE_DIALOG, HildonCodeDialog)) +#define HILDON_CODE_DIALOG_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST ((klass),\ + HILDON_TYPE_CODE_DIALOG, HildonCodeDialogClass)) +#define HILDON_IS_CODE_DIALOG(obj) (GTK_CHECK_TYPE (obj, HILDON_TYPE_CODE_DIALOG)) +#define HILDON_IS_CODE_DIALOG_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_CODE_DIALOG)) + + +typedef struct _HildonCodeDialogPrivate HildonCodeDialogPrivate; +typedef struct _HildonCodeDialog HildonCodeDialog; +typedef struct _HildonCodeDialogClass HildonCodeDialogClass; + + +struct _HildonCodeDialog +{ + GtkDialog parent; + + HildonCodeDialogPrivate *priv; +}; + +struct _HildonCodeDialogClass +{ + GtkDialogClass parent_class; +}; + + +GType hildon_code_dialog_get_type (void); +GtkWidget *hildon_code_dialog_new(void); +const gchar *hildon_code_dialog_get_code (HildonCodeDialog *dialog); +void hildon_code_dialog_clear_code (HildonCodeDialog *dialog); +void hildon_code_dialog_set_help_text (HildonCodeDialog *dialog, + const gchar *text); + + +G_END_DECLS +#endif /* __HILDON_CODE_DIALOG_H__ */ diff --git a/src/hildon-color-button.c b/src/hildon-color-button.c new file mode 100644 index 0000000..430bc94 --- /dev/null +++ b/src/hildon-color-button.c @@ -0,0 +1,491 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-color-button + * @short_description: A widget to open HildonColorChooserDialog + * @see_also: #HildonColorChooserDialog, #HildonColorPopup + * + * HildonColorButton is a widget to open a HildonColorChooserDialog. + * The selected color is shown in the button. + * The selected color is a property of the button. + * The property name is "color" and its type is GtkColor. + */ +#include + +#include +#include +#include +#include +#include +#include + +#include "hildon-color-button.h" +#include "hildon-color-chooser-dialog.h" + +#define HILDON_COLOR_BUTTON_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE\ + ((obj), HILDON_TYPE_COLOR_BUTTON, HildonColorButtonPrivate)) + +#define COLOR_FILLED_HEIGHT 22 +#define COLOR_FILLED_WIDTH 22 + +#define COLOR_BUTTON_WIDTH 52 +#define COLOR_BUTTON_HEIGHT 48 + +/* the outer border color */ +#define OUTER_BORDER_RED 0 +#define OUTER_BORDER_BLUE 0 +#define OUTER_BORDER_GREEN 0 +#define OUTER_BORDER_THICKNESS 1 + +/* the inner border color */ +#define INNER_BORDER_RED 65535 +#define INNER_BORDER_BLUE 65535 +#define INNER_BORDER_GREEN 65535 +#define INNER_BORDER_THICKNESS 2 + +struct _HildonColorButtonPrivate +{ + GtkWidget *dialog; + + GdkColor color; + GdkGC *gc; +}; + +enum +{ + PROP_NONE, + PROP_COLOR +}; + +static void +hildon_color_button_class_init(HildonColorButtonClass *klass); +static void +hildon_color_button_init(HildonColorButton *color_button); + +static void +hildon_color_button_finalize(GObject *object); +static void +hildon_color_button_set_property(GObject *object, guint param_id, + const GValue *value, GParamSpec *pspec); +static void +hildon_color_button_get_property(GObject *object, guint param_id, + GValue *value, GParamSpec *pspec); +static void +hildon_color_button_realize(GtkWidget *widget); +static void +hildon_color_button_unrealize(GtkWidget *widget); +static void +hildon_color_button_clicked(GtkButton *button); +static gboolean +hildon_color_button_key_pressed(GtkWidget * button, + GdkEventKey * event, + gpointer data); +static gint +hildon_color_field_expose_event(GtkWidget *widget, GdkEventExpose *event, + HildonColorButton *cb); + +static gboolean +hildon_color_button_mnemonic_activate( GtkWidget *widget, + gboolean group_cycling ); + +static void +draw_grid (GdkDrawable *drawable, GdkGC *gc, + int x, int y, + gint w, gint h); + +static gpointer parent_class = NULL; + +GType +hildon_color_button_get_type(void) +{ + static GType color_button_type = 0; + + if (!color_button_type) + { + static const GTypeInfo color_button_info = + { + sizeof (HildonColorButtonClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_color_button_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (HildonColorButton), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_color_button_init, + }; + + color_button_type = + g_type_register_static (GTK_TYPE_BUTTON, "HildonColorButton", + &color_button_info, 0); + } + + return color_button_type; +} + +static void +hildon_color_button_class_init(HildonColorButtonClass *klass) +{ + GObjectClass *gobject_class; + GtkButtonClass *button_class; + GtkWidgetClass *widget_class; + + gobject_class = G_OBJECT_CLASS (klass); + button_class = GTK_BUTTON_CLASS (klass); + widget_class = GTK_WIDGET_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->get_property = hildon_color_button_get_property; + gobject_class->set_property = hildon_color_button_set_property; + gobject_class->finalize = hildon_color_button_finalize; + widget_class->realize = hildon_color_button_realize; + widget_class->unrealize = hildon_color_button_unrealize; + button_class->clicked = hildon_color_button_clicked; + widget_class->mnemonic_activate = hildon_color_button_mnemonic_activate; + + /** + * HildonColorButton:color: + * + * The selected color. + */ + g_object_class_install_property (gobject_class, PROP_COLOR, + g_param_spec_boxed ("color", + "Current Color", + "The selected color", + GDK_TYPE_COLOR, + G_PARAM_READWRITE)); + + g_type_class_add_private (gobject_class, sizeof (HildonColorButtonPrivate)); +} + +/* Draw a dotted grid over the specified area to make it look + * insensitive. Actually, we should generate that pixbuf once and + * just render it over later... */ +static void +draw_grid (GdkDrawable *drawable, GdkGC *gc, + int x, int y, + gint w, gint h) +{ + int currentx; + int currenty; + for (currenty = y; currenty <= h; currenty++) + for (currentx = ((currenty % 2 == 0) ? x : x + 1); currentx <= w; currentx += 2) + gdk_draw_point (drawable, gc, currentx, currenty); +} + +/* Handle exposure events for the color picker's drawing area */ +static gint +hildon_color_field_expose_event(GtkWidget *widget, GdkEventExpose *event, + HildonColorButton *cb) +{ + GdkColor outer_border, inner_border; + + /* Create the outer border color */ + outer_border.pixel = 0; + outer_border.red = OUTER_BORDER_RED; + outer_border.blue = OUTER_BORDER_BLUE; + outer_border.green = OUTER_BORDER_GREEN; + + /* Create the inner border color */ + inner_border.pixel = 0; + inner_border.red = INNER_BORDER_RED; + inner_border.blue = INNER_BORDER_BLUE; + inner_border.green = INNER_BORDER_GREEN; + + /* serve the outer border color to the Graphic Context */ + gdk_gc_set_rgb_fg_color(cb->priv->gc, &outer_border); + /* draw the outer border as a filled rectangle */ + gdk_draw_rectangle(widget->window, + (GTK_WIDGET_IS_SENSITIVE (widget)) ? cb->priv->gc : widget->style->bg_gc [GTK_STATE_INSENSITIVE], + TRUE, + 0, + 0, + widget->allocation.width, + widget->allocation.height); + + /* serve the inner border color to the Graphic Context */ + gdk_gc_set_rgb_fg_color(cb->priv->gc, &inner_border); + /* draw the inner border as a filled rectangle */ + gdk_draw_rectangle(widget->window, + cb->priv->gc, + TRUE, + OUTER_BORDER_THICKNESS, + OUTER_BORDER_THICKNESS, + widget->allocation.width - (OUTER_BORDER_THICKNESS * 2), + widget->allocation.height - (OUTER_BORDER_THICKNESS * 2)); + + /* serve the actual color to the Graphic Context */ + gdk_gc_set_rgb_fg_color(cb->priv->gc, &cb->priv->color); + /* draw the actual rectangle */ + gdk_draw_rectangle(widget->window, + cb->priv->gc, + TRUE, + INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS, + INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS, + widget->allocation.width - ((INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS)*2), + widget->allocation.height - ((INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS)*2)); + + if (! GTK_WIDGET_IS_SENSITIVE (widget)) { + draw_grid (GDK_DRAWABLE (widget->window), widget->style->bg_gc [GTK_STATE_INSENSITIVE], + INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS, + INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS, + widget->allocation.width - ((INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS)*2) + 2, + widget->allocation.height - ((INNER_BORDER_THICKNESS + OUTER_BORDER_THICKNESS)*2) + 2); + } + + return FALSE; +} + +static void +hildon_color_button_init(HildonColorButton *cb) +{ + GtkWidget *align; + GtkWidget *drawing_area; + + cb->priv = HILDON_COLOR_BUTTON_GET_PRIVATE(cb); + + cb->priv->dialog = NULL; + cb->priv->gc = NULL; + + gtk_widget_push_composite_child(); + + /* create widgets and pixbuf */ + align = gtk_alignment_new(0.5, 0.5, 0, 0); /*composite widget*/ + + drawing_area = gtk_drawing_area_new(); /*composite widget*/ + + /* setting minimum sizes */ + gtk_widget_set_size_request(GTK_WIDGET(cb), COLOR_BUTTON_WIDTH, + COLOR_BUTTON_HEIGHT); + gtk_widget_set_size_request(GTK_WIDGET(drawing_area), + COLOR_FILLED_WIDTH, COLOR_FILLED_HEIGHT); + + /* Connect the callback function for exposure event */ + g_signal_connect(drawing_area, "expose-event", + G_CALLBACK(hildon_color_field_expose_event), cb); + + /* Connect to callback function for key press event */ + g_signal_connect(G_OBJECT(cb), "key-press-event", + G_CALLBACK(hildon_color_button_key_pressed), cb); + + /* packing */ + gtk_container_add(GTK_CONTAINER(align), drawing_area); + gtk_container_add(GTK_CONTAINER(cb), align); + + gtk_widget_show_all(align); + + gtk_widget_pop_composite_child(); +} + +/* Free memory used by HildonColorButton */ +static void +hildon_color_button_finalize(GObject *object) +{ + HildonColorButton *cb = HILDON_COLOR_BUTTON(object); + + if (cb->priv->dialog) + { + gtk_widget_destroy(cb->priv->dialog); + cb->priv->dialog = NULL; + } + + if( G_OBJECT_CLASS(parent_class)->finalize ) + G_OBJECT_CLASS(parent_class)->finalize(object); +} + +static void +hildon_color_button_realize(GtkWidget *widget) +{ + HildonColorButton *cb = HILDON_COLOR_BUTTON(widget); + + GTK_WIDGET_CLASS(parent_class)->realize(widget); + + cb->priv->gc = gdk_gc_new(widget->window); +} + +static void +hildon_color_button_unrealize(GtkWidget *widget) +{ + HildonColorButton *cb = HILDON_COLOR_BUTTON(widget); + + g_object_unref(cb->priv->gc); + cb->priv->gc = NULL; + + GTK_WIDGET_CLASS(parent_class)->unrealize(widget); +} + +/* Make the widget sensitive with the keyboard event */ +static gboolean +hildon_color_button_mnemonic_activate( GtkWidget *widget, + gboolean group_cycling ) +{ + gtk_widget_grab_focus( widget ); + return TRUE; +} + +/* Popup a color selector dialog on button click */ +static void +hildon_color_button_clicked(GtkButton *button) +{ + HildonColorButton *cb = HILDON_COLOR_BUTTON(button); + HildonColorChooserDialog *cs_dialog = HILDON_COLOR_CHOOSER_DIALOG(cb->priv->dialog); + + /* Popup the color selector dialog */ + if (!cs_dialog) + { + /* The dialog hasn't been created yet, do it. */ + GtkWidget *parent = gtk_widget_get_toplevel(GTK_WIDGET(cb)); + cb->priv->dialog = hildon_color_chooser_dialog_new(GTK_WINDOW(parent)); + cs_dialog = HILDON_COLOR_CHOOSER_DIALOG(cb->priv->dialog); + if (parent) + gtk_window_set_transient_for(GTK_WINDOW(cs_dialog), GTK_WINDOW(parent)); + } + + /* Set the initial color for the color selector dialog */ + hildon_color_chooser_dialog_set_color(cs_dialog, &cb->priv->color); + + /* Update the color for color button if selection was made */ + if (gtk_dialog_run(GTK_DIALOG(cs_dialog)) == GTK_RESPONSE_OK) + { + hildon_color_chooser_dialog_get_color(cs_dialog, &cb->priv->color); + hildon_color_button_set_color( HILDON_COLOR_BUTTON( button ), + &(cb->priv->color) ); + } + + gtk_widget_hide(GTK_WIDGET(cs_dialog)); +} + +/* Popup a color selector dialog on hardkey Select press */ +static gboolean +hildon_color_button_key_pressed(GtkWidget * button, + GdkEventKey * event, + gpointer data) +{ + g_return_val_if_fail (HILDON_IS_COLOR_BUTTON(button), FALSE); + + if (event->keyval == HILDON_HARDKEY_SELECT) + { + hildon_color_button_clicked(GTK_BUTTON(button)); + return TRUE; + } + + return FALSE; +} + +/* Set_property function for HildonColorButtonClass initialization */ +static void +hildon_color_button_set_property(GObject *object, guint param_id, + const GValue *value, GParamSpec *pspec) +{ + HildonColorButton *cb = HILDON_COLOR_BUTTON(object); + + switch (param_id) + { + case PROP_COLOR: + cb->priv->color = *(GdkColor*)g_value_get_boxed(value); + gtk_widget_queue_draw(GTK_WIDGET(cb)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); + break; + } +} + +/* Get_property function for HildonColorButtonClass initialization */ +static void +hildon_color_button_get_property(GObject *object, guint param_id, + GValue *value, GParamSpec *pspec) +{ + HildonColorButton *cb = HILDON_COLOR_BUTTON(object); + + switch (param_id) + { + case PROP_COLOR: + g_value_set_boxed(value, &cb->priv->color); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); + break; + } +} + +/** + * hildon_color_button_new: + * + * Creates a new color button. This returns a widget in the form of a + * small button containing a swatch representing the selected color. + * When the button is clicked, a color-selection dialog will open, + * allowing the user to select a color. The swatch will be updated to + * reflect the new color when the user finishes. + * + * Returns: a new color button + */ +GtkWidget * +hildon_color_button_new(void) +{ + return g_object_new( HILDON_TYPE_COLOR_BUTTON, NULL ); +} + +/** + * hildon_color_button_new_with_color: + * @color: a #GdkColor for the initial color + * + * Creates a new color button with @color as the initial color. + * + * Returns: a new color button + */ +GtkWidget * +hildon_color_button_new_with_color(const GdkColor *color) +{ + return g_object_new( HILDON_TYPE_COLOR_BUTTON, "color", color, NULL ); +} + +/** + * hildon_color_button_set_color: + * @button: a #HildonColorButton + * @color: a color to be set + * + * Sets the color selected by the button. + */ +void +hildon_color_button_set_color( HildonColorButton *button, GdkColor *color ) +{ + g_object_set( G_OBJECT(button), "color", color, NULL ); +} + +/** + * hildon_color_button_get_color: + * @button: a #HildonColorButton + * + * Returns: the color selected by the button + */ +GdkColor * +hildon_color_button_get_color( HildonColorButton *button ) +{ + GdkColor *color = NULL; + g_object_get( G_OBJECT(button), "color", &color, NULL ); + return color; +} diff --git a/src/hildon-color-button.h b/src/hildon-color-button.h new file mode 100644 index 0000000..490788a --- /dev/null +++ b/src/hildon-color-button.h @@ -0,0 +1,82 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_COLOR_BUTTON_H__ +#define __HILDON_COLOR_BUTTON_H__ + +#include + +G_BEGIN_DECLS + +#define HILDON_TYPE_COLOR_BUTTON (hildon_color_button_get_type ()) +#define HILDON_COLOR_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HILDON_TYPE_COLOR_BUTTON, HildonColorButton)) +#define HILDON_COLOR_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_COLOR_BUTTON, HildonColorButtonClass)) +#define HILDON_IS_COLOR_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_COLOR_BUTTON)) +#define HILDON_IS_COLOR_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_COLOR_BUTTON)) +#define HILDON_COLOR_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), HILDON_TYPE_COLOR_BUTTON, HildonColorButtonClass)) + +typedef struct _HildonColorButton HildonColorButton; +typedef struct _HildonColorButtonClass HildonColorButtonClass; +typedef struct _HildonColorButtonPrivate HildonColorButtonPrivate; + +struct _HildonColorButton +{ + GtkButton button; + HildonColorButtonPrivate *priv; +}; + +struct _HildonColorButtonClass +{ + GtkButtonClass parent_class; + + /* Padding for future expansion */ + void (*_gtk_reserved1) (void); + void (*_gtk_reserved2) (void); + void (*_gtk_reserved3) (void); + void (*_gtk_reserved4) (void); +}; + + +GType +hildon_color_button_get_type( void ) G_GNUC_CONST; + +GtkWidget * +hildon_color_button_new( void ); + +GtkWidget * +hildon_color_button_new_with_color( const GdkColor *color ); + +GdkColor * +hildon_color_button_get_color( HildonColorButton *button ); + +void +hildon_color_button_set_color( HildonColorButton *button, GdkColor *color ); + +G_END_DECLS + +#endif /* __HILDON_COLOR_BUTTON_H__ */ + + + + diff --git a/src/hildon-color-chooser-button.c b/src/hildon-color-chooser-button.c new file mode 100644 index 0000000..ec5ca29 --- /dev/null +++ b/src/hildon-color-chooser-button.c @@ -0,0 +1,409 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Author: Kuisma Salonen + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + + +#include + + +#include "hildon-color-chooser-button.h" + +#include "hildon-color-chooser-dialog.h" + + +enum { + COLOR_CHANGED, + LAST_SIGNAL +}; + + +static guint color_chooser_button_signals[LAST_SIGNAL] = { 0 }; + + +static GtkButtonClass *parent_klass = NULL; + + +static void hildon_color_chooser_button_init(HildonColorChooserButton *object); +static void hildon_color_chooser_button_class_init(HildonColorChooserButtonClass *klass); + + +static void hildon_color_chooser_button_size_request(GtkWidget *widget, GtkRequisition *req); +static void hildon_color_chooser_button_size_allocate(GtkWidget *widget, GtkAllocation *alloc); + +static void hildon_color_chooser_button_realize(GtkWidget *widget); +static void hildon_color_chooser_button_unrealize(GtkWidget *widget); + +static void hildon_color_chooser_button_style_set(GtkWidget *widget, GtkStyle *previous_style); + +static void hildon_color_chooser_button_show(GtkWidget *widget); +static void hildon_color_chooser_button_show_all(GtkWidget *widget); + +static void hildon_color_chooser_button_virtual_set_color(HildonColorChooserButton *button, GdkColor *color); +static void hildon_color_chooser_button_virtual_color_changed(HildonColorChooserButton *button, GdkColor *color); + +static void hildon_color_chooser_button_clicked(GtkButton *button); + + +static gboolean hildon_color_chooser_button_area_expose(GtkWidget *widget, GdkEventExpose *event, gpointer data); + + +static void hildon_color_chooser_button_helper_get_style_info(HildonColorChooserButton *button); + + +GtkType hildon_color_chooser_button_get_type () +{ + static GtkType button_type = 0; + + if (!button_type) + { + static const GtkTypeInfo button_info = + { + "HildonColorChooserButton", + sizeof (HildonColorChooserButton), + sizeof (HildonColorChooserButtonClass), + (GtkClassInitFunc) hildon_color_chooser_button_class_init, + (GtkObjectInitFunc) hildon_color_chooser_button_init, + /* reserved_1 */ NULL, + /* reserved_1 */ NULL, + (GtkClassInitFunc) NULL + }; + + button_type = gtk_type_unique (GTK_TYPE_BUTTON, &button_info); + } + + return button_type; +} + + + /* initializer functions */ +static void hildon_color_chooser_button_init(HildonColorChooserButton *object) +{ + object->color.red = 0x0000; + object->color.green = 0x0000; + object->color.blue = 0x0000; + object->color.pixel = 0x00000000; + + + object->area = gtk_drawing_area_new(); + + gtk_container_add(GTK_CONTAINER(object), object->area); + + + g_signal_connect(G_OBJECT(object->area), "expose-event", + G_CALLBACK(hildon_color_chooser_button_area_expose), object); +} + +static void hildon_color_chooser_button_class_init(HildonColorChooserButtonClass *klass) +{ + GtkWidgetClass *widget_klass = GTK_WIDGET_CLASS(klass); + GtkButtonClass *button_klass = GTK_BUTTON_CLASS(klass); + GtkObjectClass *object_klass = GTK_OBJECT_CLASS(klass); + + + parent_klass = g_type_class_peek_parent(klass); + + + klass->set_color = hildon_color_chooser_button_virtual_set_color; + klass->color_changed = hildon_color_chooser_button_virtual_color_changed; + + + button_klass->clicked = hildon_color_chooser_button_clicked; + + + widget_klass->size_request = hildon_color_chooser_button_size_request; + widget_klass->size_allocate = hildon_color_chooser_button_size_allocate; + + widget_klass->realize = hildon_color_chooser_button_realize; + widget_klass->unrealize = hildon_color_chooser_button_unrealize; + + widget_klass->style_set = hildon_color_chooser_button_style_set; + + widget_klass->show = hildon_color_chooser_button_show; + widget_klass->show_all = hildon_color_chooser_button_show_all; + + + gtk_widget_class_install_style_property(widget_klass, + g_param_spec_boxed("outer_border", + "Outer border", + "Size of the outer border", + GTK_TYPE_BORDER, + G_PARAM_READABLE)); + gtk_widget_class_install_style_property(widget_klass, + g_param_spec_boxed("inner_border", + "Inner border", + "Size of the inner border", + GTK_TYPE_BORDER, + G_PARAM_READABLE)); + gtk_widget_class_install_style_property(widget_klass, + g_param_spec_boxed("minimum_size", + "minimum_size", + "Minimum size of the color area", + GTK_TYPE_BORDER, + G_PARAM_READABLE)); + + + color_chooser_button_signals[COLOR_CHANGED] = g_signal_new("color-changed", G_OBJECT_CLASS_TYPE (object_klass), + G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (HildonColorChooserButtonClass, color_changed), + NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, GDK_TYPE_COLOR); +} + + + /* virtual widget functions */ +static void hildon_color_chooser_button_size_request(GtkWidget *widget, GtkRequisition *req) +{ + HildonColorChooserButton *button = HILDON_COLOR_CHOOSER_BUTTON(widget); + + + req->width = button->style_info.outer.left + button->style_info.min.left + button->style_info.outer.right; + req->height = button->style_info.outer.top + button->style_info.min.right + button->style_info.outer.bottom; +} + +static void hildon_color_chooser_button_size_allocate(GtkWidget *widget, GtkAllocation *alloc) +{ + HildonColorChooserButton *button = HILDON_COLOR_CHOOSER_BUTTON(widget); + GtkAllocation child_alloc; + GdkRectangle clip_rect; + + + GTK_WIDGET_CLASS(parent_klass)->size_allocate(widget, alloc); + child_alloc = *alloc; + + + child_alloc.x += button->style_info.outer.left; + child_alloc.y += button->style_info.outer.top; + + child_alloc.width -= (button->style_info.outer.left + button->style_info.outer.right); + child_alloc.height -= (button->style_info.outer.top + button->style_info.outer.bottom); + + + gtk_widget_size_allocate(button->area, &child_alloc); + + + if(GTK_WIDGET_REALIZED(widget)) { + clip_rect.x = button->style_info.inner.left; + clip_rect.y = button->style_info.inner.top; + clip_rect.width = button->area->allocation.width - button->style_info.inner.left - button->style_info.inner.right; + clip_rect.height = button->area->allocation.height - button->style_info.inner.top - button->style_info.inner.bottom; + + gdk_gc_set_clip_rectangle(button->color_gc, &clip_rect); + } +} + + +static void hildon_color_chooser_button_realize(GtkWidget *widget) +{ + HildonColorChooserButton *button = HILDON_COLOR_CHOOSER_BUTTON(widget); + GdkRectangle clip_rect; + + + GTK_WIDGET_CLASS(parent_klass)->realize(widget); + + + button->color_gc = gdk_gc_new(widget->window); + gdk_gc_set_rgb_fg_color(button->color_gc, &button->color); + + + clip_rect.x = button->style_info.inner.left; + clip_rect.y = button->style_info.inner.top; + clip_rect.width = button->area->allocation.width - button->style_info.inner.left - button->style_info.inner.right; + clip_rect.height = button->area->allocation.height - button->style_info.inner.top - button->style_info.inner.bottom; + + gdk_gc_set_clip_rectangle(button->color_gc, &clip_rect); +} + +static void hildon_color_chooser_button_unrealize(GtkWidget *widget) +{ + HildonColorChooserButton *button = HILDON_COLOR_CHOOSER_BUTTON(widget); + + + g_object_unref(button->color_gc); + button->color_gc = NULL; + + + GTK_WIDGET_CLASS(parent_klass)->unrealize(widget); +} + + +static void hildon_color_chooser_button_style_set(GtkWidget *widget, GtkStyle *previous_style) +{ + HildonColorChooserButton *button = HILDON_COLOR_CHOOSER_BUTTON(widget); + GdkRectangle clip_rect; + + + hildon_color_chooser_button_helper_get_style_info(button); + + + if(GTK_WIDGET_REALIZED(widget)) { + clip_rect.x = button->style_info.inner.left; + clip_rect.y = button->style_info.inner.top; + clip_rect.width = button->area->allocation.width - button->style_info.inner.left - button->style_info.inner.right; + clip_rect.height = button->area->allocation.height - button->style_info.inner.top - button->style_info.inner.bottom; + + gdk_gc_set_clip_rectangle(button->color_gc, &clip_rect); + } +} + + +static void hildon_color_chooser_button_show(GtkWidget *widget) +{ + HildonColorChooserButton *button = HILDON_COLOR_CHOOSER_BUTTON(widget); + + + gtk_widget_show(button->area); + + GTK_WIDGET_CLASS(parent_klass)->show(widget); +} + +static void hildon_color_chooser_button_show_all(GtkWidget *widget) +{ + hildon_color_chooser_button_show(widget); +} + + +static void hildon_color_chooser_button_virtual_set_color(HildonColorChooserButton *button, GdkColor *color) +{ + button->color = *color; + + if(GTK_WIDGET_REALIZED(button)) { + gdk_gc_set_rgb_fg_color(button->color_gc, &button->color); + + gtk_widget_queue_draw(button->area); + } + + + g_signal_emit(button, color_chooser_button_signals[COLOR_CHANGED], 0, &button->color); +} + +static void hildon_color_chooser_button_virtual_color_changed(HildonColorChooserButton *button, GdkColor *color) +{ +} + + +static void hildon_color_chooser_button_clicked(GtkButton *button) +{ + HildonColorChooserButton *color_button = HILDON_COLOR_CHOOSER_BUTTON(button); + GtkWidget *dialog; + GdkColor color; + gint result = 0; + + + dialog = hildon_color_chooser_dialog_new(); + gtk_widget_realize(dialog); + hildon_color_chooser_dialog_set_color(HILDON_COLOR_CHOOSER_DIALOG(dialog), &color_button->color); + gtk_widget_show(dialog); + + + result = gtk_dialog_run(GTK_DIALOG(dialog)); + + + if(result == GTK_RESPONSE_OK) { + hildon_color_chooser_dialog_get_color(HILDON_COLOR_CHOOSER_DIALOG(dialog), &color); + hildon_color_chooser_button_virtual_set_color(color_button, &color); + } + + +/*g_object_unref(G_OBJECT(dialog));*/ + gtk_widget_destroy(dialog); +} + + + /* signal handlers */ +static gboolean hildon_color_chooser_button_area_expose(GtkWidget *widget, GdkEventExpose *event, gpointer data) +{ + HildonColorChooserButton *button = HILDON_COLOR_CHOOSER_BUTTON(data); + GtkWidget *button_widget = GTK_WIDGET(data); + + + if(button->style_info.inner.left > 0 || button->style_info.inner.right > 0 || + button->style_info.inner.top > 0 || button->style_info.inner.bottom > 0) { + gtk_paint_box(gtk_widget_get_style(button_widget), widget->window, GTK_WIDGET_STATE(button_widget), GTK_SHADOW_NONE, + &event->area, button_widget, "color-button", 0, 0, widget->allocation.width, widget->allocation.height); + } + + + gdk_draw_rectangle(widget->window, button->color_gc, TRUE, event->area.x, event->area.y, event->area.width, event->area.height); + + + return FALSE; +} + + + /* additional use-only-here functions */ +static void hildon_color_chooser_button_helper_get_style_info(HildonColorChooserButton *button) +{ + GtkBorder *in, *out, *min; + + gtk_widget_style_get(GTK_WIDGET(button), "inner_border", &in, + "outer_border", &out, + "minimum_size", &min, NULL); + + + if(in) { + button->style_info.inner = *in; + g_free(in); + } else { + button->style_info.inner.left = 0; + button->style_info.inner.right = 0; + button->style_info.inner.top = 0; + button->style_info.inner.bottom = 0; + } + + if(out) { + button->style_info.outer = *out; + g_free(out); + } else { + button->style_info.outer.left = 4; + button->style_info.outer.right = 4; + button->style_info.outer.top = 4; + button->style_info.outer.bottom = 4; + } + + if(min) { + button->style_info.min = *min; + g_free(min); + } else { + button->style_info.min.left = 8; + button->style_info.min.right = 8; + button->style_info.min.top = 0; + button->style_info.min.bottom = 0; + } +} + + + /* public API */ +GtkWidget *hildon_color_chooser_button_new() +{ + return gtk_type_new(HILDON_TYPE_COLOR_CHOOSER_BUTTON); +} + + +void hildon_color_chooser_button_set_color(HildonColorChooserButton *button, GdkColor *color) +{ + HILDON_COLOR_CHOOSER_BUTTON_CLASS(G_OBJECT_GET_CLASS(button))->set_color(button, color); +} + +void hildon_color_chooser_button_get_color(HildonColorChooserButton *button, GdkColor *color) +{ + *color = button->color; +} diff --git a/src/hildon-color-chooser-button.h b/src/hildon-color-chooser-button.h new file mode 100644 index 0000000..9dcb446 --- /dev/null +++ b/src/hildon-color-chooser-button.h @@ -0,0 +1,82 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Author: Kuisma Salonen + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + + +#ifndef __HILDON_COLOR_CHOOSER_BUTTON_H__ +#define __HILDON_COLOR_CHOOSER_BUTTON_H__ + + +#include + +#include + + +#define HILDON_TYPE_COLOR_CHOOSER_BUTTON (hildon_color_chooser_button_get_type()) + +#define HILDON_COLOR_CHOOSER_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HILDON_TYPE_COLOR_CHOOSER_BUTTON, HildonColorChooserButton)) +#define HILDON_COLOR_CHOOSER_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), HILDON_TYPE_COLOR_CHOOSER_BUTTON, HildonColorChooserButtonClass)) +#define HILDON_IS_COLOR_CHOOSER_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_COLOR_CHOOSER_BUTTON)) + + +typedef struct HildonColorChooserButton_ HildonColorChooserButton; +typedef struct HildonColorChooserButtonClass_ HildonColorChooserButtonClass; + + +struct HildonColorChooserButton_ +{ + GtkButton parent; + + GdkColor color; + + GtkWidget *area; + + GdkGC *color_gc; + + + struct { + GtkBorder outer; + GtkBorder inner; + GtkBorder min; + } style_info; +}; + +struct HildonColorChooserButtonClass_ +{ + GtkButtonClass parent; + + void (*color_changed) (HildonColorChooserButton *button, GdkColor *color); + + void (*set_color) (HildonColorChooserButton *, GdkColor *); +}; + + +GtkType hildon_color_chooser_button_get_type(); +GtkWidget *hildon_color_chooser_button_new(); + +void hildon_color_chooser_button_set_color(HildonColorChooserButton *button, GdkColor *color); +void hildon_color_chooser_button_get_color(HildonColorChooserButton *button, GdkColor *color); + + +#endif /* __HILDON_COLOR_CHOOSER_BUTTON_H__ */ diff --git a/src/hildon-color-chooser-dialog.c b/src/hildon-color-chooser-dialog.c new file mode 100644 index 0000000..bb367a4 --- /dev/null +++ b/src/hildon-color-chooser-dialog.c @@ -0,0 +1,172 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Author: Kuisma Salonen + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + + +/** + * SECTION:hildon-color-chooser-dialog + * @short_description: A dialog to choose a color. + * @see_also: #HildonColorButton, #HildonColorChooser + * + * HildonColorChooserDialog is a widget widget to choose a color. + */ +#include + + +#include "hildon-color-chooser-dialog.h" + +#include "hildon-plugin-widget.h" + + +enum { + COLOR_CHANGED, + LAST_SIGNAL +}; + + +static HildonPluginWidgetInfo *global_plugin = NULL; + + +static guint color_chooser_dialog_signals[LAST_SIGNAL] = { 0 }; + + +static void hildon_color_chooser_dialog_init(HildonColorChooserDialog *object); +static void hildon_color_chooser_dialog_class_init(HildonColorChooserDialogClass *klass); + + +GtkType hildon_color_chooser_dialog_get_type () +{ + static GtkType chooser_type = 0; + + if (!chooser_type) + { + static const GtkTypeInfo chooser_info = + { + "HildonColorChooserDialog", + sizeof (HildonColorChooserDialog), + sizeof (HildonColorChooserDialogClass), + (GtkClassInitFunc) hildon_color_chooser_dialog_class_init, + (GtkObjectInitFunc) hildon_color_chooser_dialog_init, + /* reserved_1 */ NULL, + /* reserved_1 */ NULL, + (GtkClassInitFunc) NULL + }; + + chooser_type = gtk_type_unique (GTK_TYPE_DIALOG, &chooser_info); + } + + return chooser_type; +} + + +static void hildon_color_chooser_dialog_init(HildonColorChooserDialog *object) +{ + int i; + + + object->color.red = 0x0000; + object->color.green = 0x0000; + object->color.blue = 0x0000; + object->color.pixel = 0x00000000; + + + for(i = 0; i < 32; i++) { + object->reserved[i] = 0; + } +} + +static void hildon_color_chooser_dialog_class_init(HildonColorChooserDialogClass *klass) +{ + GtkObjectClass *object_klass = GTK_OBJECT_CLASS(klass); + int i; + + + for(i = 0; i < 32; i++) { + klass->reserved[i] = 0; + } + + klass->set_color = 0; + + + color_chooser_dialog_signals[COLOR_CHANGED] = g_signal_new("color-changed", G_OBJECT_CLASS_TYPE (object_klass), + G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (HildonColorChooserDialogClass, color_changed), + NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, GDK_TYPE_COLOR); +} + +/** + * hildon_color_chooser_dialog_new: + * + * Creates a new color chooser dialog. The dialog is created through + * HildonPluginWidget API and is loaded from plugin. The initially selected + * color can be anything, so it's recommended to call + * hildon_color_chooser_dialog_set_color () after creating the widget. + * + * Returns: a new color chooser dialog + */ +GtkWidget *hildon_color_chooser_dialog_new() +{ + if(!global_plugin) { + global_plugin = hildon_plugin_info_initialize(HILDON_TYPE_COLOR_CHOOSER_DIALOG, NULL); + g_return_val_if_fail (global_plugin != NULL, NULL); + } + + return hildon_plugin_info_construct_widget(global_plugin); +} + +/** + * hildon_color_chooser_dialog_set_color: + * @chooser: a #HildonColorChooserDialog + * @color: a color to be set + * + * Sets the color selected in the dialog. + */ +void hildon_color_chooser_dialog_set_color(HildonColorChooserDialog *chooser, GdkColor *color) +{ + HildonColorChooserDialogClass *klass = HILDON_COLOR_CHOOSER_DIALOG_CLASS(G_OBJECT_GET_CLASS(chooser)); + + + chooser->color = *color; + + if(klass->set_color) { + klass->set_color(chooser, color); + } +} + +/** + * hildon_color_chooser_dialog_get_color: + * @chooser: a #HildonColorChooserDialog + * @color: a pointer to #GdkColor to be filled by the function + * + * Gets the color selected in the dialog. + */ +void hildon_color_chooser_dialog_get_color(HildonColorChooserDialog *chooser, GdkColor *color) +{ + *color = chooser->color; +} + + +void hildon_color_chooser_dialog_emit_color_changed(HildonColorChooserDialog *chooser) +{ + g_signal_emit(chooser, color_chooser_dialog_signals[COLOR_CHANGED], 0, &chooser->color); +} diff --git a/src/hildon-color-chooser-dialog.h b/src/hildon-color-chooser-dialog.h new file mode 100644 index 0000000..e03492a --- /dev/null +++ b/src/hildon-color-chooser-dialog.h @@ -0,0 +1,76 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Author: Kuisma Salonen + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + + +#ifndef __HILDON_COLOR_CHOOSER_DIALOG_H__ +#define __HILDON_COLOR_CHOOSER_DIALOG_H__ + + +#include + +#include + + +#define HILDON_TYPE_COLOR_CHOOSER_DIALOG (hildon_color_chooser_dialog_get_type()) + +#define HILDON_COLOR_CHOOSER_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HILDON_TYPE_COLOR_CHOOSER_DIALOG, HildonColorChooserDialog)) +#define HILDON_COLOR_CHOOSER_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), HILDON_TYPE_COLOR_CHOOSER_DIALOG, HildonColorChooserDialogClass)) +#define HILDON_IS_COLOR_CHOOSER_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_COLOR_CHOOSER_DIALOG)) + + +typedef struct HildonColorChooserDialog_ HildonColorChooserDialog; +typedef struct HildonColorChooserDialogClass_ HildonColorChooserDialogClass; + + +struct HildonColorChooserDialog_ { + GtkDialog parent; + + GdkColor color; + + guint32 reserved[32]; +}; + +struct HildonColorChooserDialogClass_ { + GtkDialogClass parent_class; + + gboolean (*color_changed) (HildonColorChooserDialog *chooser, GdkColor *color); + + void (*set_color) (HildonColorChooserDialog *, GdkColor *); + + void (*reserved[32]) (void *); +}; + + +GtkType hildon_color_chooser_dialog_get_type(); + +GtkWidget *hildon_color_chooser_dialog_new(); + +void hildon_color_chooser_dialog_set_color(HildonColorChooserDialog *chooser, GdkColor *color); +void hildon_color_chooser_dialog_get_color(HildonColorChooserDialog *chooser, GdkColor *color); + +void hildon_color_chooser_dialog_emit_color_changed(HildonColorChooserDialog *chooser); + + +#endif /* __HILDON_COLOR_CHOOSER_DIALOG_H__ */ diff --git a/src/hildon-color-chooser.c b/src/hildon-color-chooser.c new file mode 100644 index 0000000..f781eee --- /dev/null +++ b/src/hildon-color-chooser.c @@ -0,0 +1,166 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Author: Kuisma Salonen + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + + +/** + * SECTION:hildon-color-chooser + * @short_description: A widget to choose a color. + * @see_also: #HildonColorChooserDialog, #HildonColorButton + * + * HildonColorChooser is a widget to choose a color. + */ +#include + + +#include "hildon-color-chooser.h" + +#include "hildon-plugin-widget.h" + + +enum { + COLOR_CHANGED, + LAST_SIGNAL +}; + + +static HildonPluginWidgetInfo *global_plugin = NULL; + + +static guint color_chooser_signals[LAST_SIGNAL] = { 0 }; + + +static void hildon_color_chooser_init(HildonColorChooser *sel); +static void hildon_color_chooser_class_init(HildonColorChooserClass *klass); + + +GtkType hildon_color_chooser_get_type () +{ + static GtkType chooser_type = 0; + + if (!chooser_type) + { + static const GtkTypeInfo chooser_info = + { + "HildonColorChooser", + sizeof (HildonColorChooser), + sizeof (HildonColorChooserClass), + (GtkClassInitFunc) hildon_color_chooser_class_init, + (GtkObjectInitFunc) hildon_color_chooser_init, + /* reserved_1 */ NULL, + /* reserved_1 */ NULL, + (GtkClassInitFunc) NULL + }; + + chooser_type = gtk_type_unique (GTK_TYPE_WIDGET, &chooser_info); + } + + return chooser_type; +} + + +static void hildon_color_chooser_init(HildonColorChooser *sel) +{ + sel->color.red = 0x0000; + sel->color.green = 0x0000; + sel->color.blue = 0x0000; + sel->color.pixel = 0x00000000; +} + +static void hildon_color_chooser_class_init(HildonColorChooserClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); + GtkObjectClass *object_class = GTK_OBJECT_CLASS(klass); + + klass->set_color = NULL; + + + gtk_widget_class_install_style_property(widget_class, + g_param_spec_boxed("outer_border", + "Outer border", + "Size of outer border", + GTK_TYPE_BORDER, + G_PARAM_READABLE)); + + color_chooser_signals[COLOR_CHANGED] = g_signal_new("color-changed", G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (HildonColorChooserClass, color_changed), + NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, GDK_TYPE_COLOR); +} + +/** + * hildon_color_chooser_new: + * + * Creates a new color chooser widget. The dialog is created through + * HildonPluginWidget API and is loaded from plugin. The initially selected + * color can be anything, so it's recommended to call + * hildon_color_chooser_dialog_set_color () after creating the widget. + * + * Returns: a new color chooser widget + */ +GtkWidget *hildon_color_chooser_new() +{ + if(!global_plugin) { + global_plugin = hildon_plugin_info_initialize(HILDON_TYPE_COLOR_CHOOSER, NULL); + } + + + return hildon_plugin_info_construct_widget(global_plugin); +} + +/** + * hildon_color_chooser_set_color: + * @chooser: a #HildonColorChooser + * @color: a color to be set + * + * Sets the color selected in the widget. + */ +void hildon_color_chooser_set_color(HildonColorChooser *chooser, GdkColor *color) +{ + HildonColorChooserClass *klass = HILDON_COLOR_CHOOSER_CLASS(G_OBJECT_GET_CLASS(chooser)); + + + chooser->color = *color; + + if(klass->set_color) { + klass->set_color(chooser, color); + } +} + +/** + * hildon_color_chooser_get_color: + * @chooser: a #HildonColorChooser + * @color: a pointer to #GdkColor to be filled by the function + * + * Gets the color selected in the widget. + */ +void hildon_color_chooser_get_color(HildonColorChooser *chooser, GdkColor *color) +{ + *color = chooser->color; +} + + +void hildon_color_chooser_emit_color_changed(HildonColorChooser *chooser) +{ + g_signal_emit(chooser, color_chooser_signals[COLOR_CHANGED], 0, &chooser->color); +} diff --git a/src/hildon-color-chooser.h b/src/hildon-color-chooser.h new file mode 100644 index 0000000..0135085 --- /dev/null +++ b/src/hildon-color-chooser.h @@ -0,0 +1,73 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Author: Kuisma Salonen + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + + +#ifndef __HILDON_COLOR_CHOOSER_H__ +#define __HILDON_COLOR_CHOOSER_H__ + + +#include + +#include + + +#define HILDON_TYPE_COLOR_CHOOSER (hildon_color_chooser_get_type()) + +#define HILDON_COLOR_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HILDON_TYPE_COLOR_CHOOSER, HildonColorChooser)) +#define HILDON_COLOR_CHOOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), HILDON_TYPE_COLOR_CHOOSER, HildonColorChooserClass)) +#define HILDON_IS_COLOR_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_COLOR_CHOOSER)) + + +typedef struct HildonColorChooser_ HildonColorChooser; +typedef struct HildonColorChooserClass_ HildonColorChooserClass; + + +struct HildonColorChooser_ +{ + GtkWidget parent; + + GdkColor color; +}; + +struct HildonColorChooserClass_ +{ + GtkWidgetClass parent; + + void (*color_changed) (HildonColorChooser *selection, GdkColor *color); + + void (*set_color) (HildonColorChooser *, GdkColor *); +}; + + +GtkType hildon_color_chooser_get_type(void); +GtkWidget *hildon_color_chooser_new(void); + +void hildon_color_chooser_set_color(HildonColorChooser *chooser, GdkColor *color); +void hildon_color_chooser_get_color(HildonColorChooser *chooser, GdkColor *color); + +void hildon_color_chooser_emit_color_changed(HildonColorChooser *chooser); + + +#endif /* __HILDON_COLOR_CHOOSER_H__ */ diff --git a/src/hildon-color-popup.c b/src/hildon-color-popup.c new file mode 100644 index 0000000..1279490 --- /dev/null +++ b/src/hildon-color-popup.c @@ -0,0 +1,242 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-color-popup + * @short_description: A popup dialog for editing a color and showing the + * edited result + * @see_also: #HildonColorButton, #HildonColorSelector + * + * #HildonColorPopup is only used inside #HildonColorButton. It is a + * popup dialog for editing a color. The color can be changed using + * three control bars that are used to adjust the red, green and blue + * color channels. The display is updated in real time when the bars are + * moved. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "hildon-color-selector.h" +#include "hildon-color-popup.h" +#include "hildon-controlbar.h" + +#include +#define _(String) dgettext(PACKAGE, String) + +/* Pixel sizes */ +#define HILDON_COLOR_PALETTE_SIZE 120 +#define HILDON_COLOR_CONTROLBAR_MAX 31 +#define HILDON_COLOR_CONTROLBAR_MIN 0 +#define HILDON_COLOR_LABELS_LEFT_PAD 35 +#define HILDON_COLOR_PALETTE_POS_PAD 45 +#define HILDON_COLOR_BAR_WIDTH 449 +#define HILDON_COLOR_COL_SPACING 18 + +/* + * Private function prototype definitions + */ + +static gboolean +hildon_popup_palette_expose (GtkWidget * widget, + GdkEventExpose * event, + gpointer data); +/** + * hildon_color_popup_new: + * @parent: the parent window of the dialog + * @initial_color: a #GdkColor with the initial values to be used + * @popup_data: a #HildonColorPopup + * + * This function creates a new popup dialog with three controlbars + * (red, green, blue) and a drawing area with the current color. + * + * Used as normal GtkDialog (run with gtk_dialog_run() and read + * stardard responses (GTK_RESPONSE_OK, GTK_RESPONSE_CANCEL). + * + * Returns: the newly created popup dialog + */ + +GtkWidget * +hildon_color_popup_new(GtkWindow *parent, const GdkColor *initial_color, + HildonColorPopup *popup_data) +{ + GtkWidget *popup; + GtkTable *layout; + GtkWidget *area; + GtkWidget *l_red, *l_green, *l_blue; + + /* Create control bars for HildonColorPopup */ + popup_data->ctrlbar_red = hildon_controlbar_new (); + popup_data->ctrlbar_green = hildon_controlbar_new (); + popup_data->ctrlbar_blue = hildon_controlbar_new (); + area = gtk_drawing_area_new(); + layout = GTK_TABLE(gtk_table_new(12, 2, FALSE)); + + /* Set widgets' size */ + gtk_widget_set_size_request (area, + HILDON_COLOR_PALETTE_SIZE, + HILDON_COLOR_PALETTE_SIZE); + gtk_widget_set_size_request(popup_data->ctrlbar_red, + HILDON_COLOR_BAR_WIDTH, -1); + gtk_widget_set_size_request(popup_data->ctrlbar_green, + HILDON_COLOR_BAR_WIDTH, -1); + gtk_widget_set_size_request(popup_data->ctrlbar_blue, + HILDON_COLOR_BAR_WIDTH, -1); + + /* Create labels for three kinds of color */ + l_red = gtk_label_new(_("ecdg_fi_5bit_colour_selector_red")); + l_green = gtk_label_new(_("ecdg_fi_5bit_colour_selector_green")); + l_blue = gtk_label_new(_("ecdg_fi_5bit_colour_selector_blue")); + + /* Position the labels to start about the same label as the controlbars */ + gtk_misc_set_alignment(GTK_MISC(l_red), 0.08f, 0.5f); + gtk_misc_set_alignment(GTK_MISC(l_green), 0.08f, 0.5f); + gtk_misc_set_alignment(GTK_MISC(l_blue), 0.08f, 0.5f); + + /* Add labels and control bars to the layout table */ + gtk_table_set_col_spacing(layout, 0, HILDON_COLOR_COL_SPACING); + gtk_table_attach_defaults(layout, l_red, 0, 1, 0, 2); + gtk_table_attach_defaults(layout, popup_data->ctrlbar_red, 0, 1, 2, 4); + gtk_table_attach_defaults(layout, l_green, 0, 1, 4, 6); + gtk_table_attach_defaults(layout, popup_data->ctrlbar_green, 0, 1, 6, 8); + gtk_table_attach_defaults(layout, l_blue, 0, 1, 8, 10); + gtk_table_attach_defaults(layout, popup_data->ctrlbar_blue, 0, 1, 10, 12); + gtk_table_attach(layout, area, 1, 2, 3, 11, GTK_SHRINK, GTK_SHRINK, 0, 0); + + /* Give the maximum and minimum limits for each control bar */ + hildon_controlbar_set_range (HILDON_CONTROLBAR(popup_data->ctrlbar_red), + HILDON_COLOR_CONTROLBAR_MIN, + HILDON_COLOR_CONTROLBAR_MAX); + hildon_controlbar_set_range (HILDON_CONTROLBAR(popup_data->ctrlbar_green), + HILDON_COLOR_CONTROLBAR_MIN, + HILDON_COLOR_CONTROLBAR_MAX); + hildon_controlbar_set_range (HILDON_CONTROLBAR(popup_data->ctrlbar_blue), + HILDON_COLOR_CONTROLBAR_MIN, + HILDON_COLOR_CONTROLBAR_MAX); + + /* Give the initial values for each control bar */ + hildon_controlbar_set_value (HILDON_CONTROLBAR(popup_data->ctrlbar_red), + (initial_color->red >> 11)&0x1F); + hildon_controlbar_set_value (HILDON_CONTROLBAR(popup_data->ctrlbar_green), + (initial_color->green >> 11)&0x1F); + hildon_controlbar_set_value (HILDON_CONTROLBAR(popup_data->ctrlbar_blue), + (initial_color->blue >> 11)&0x1F); + + /* Register controlbar callbacks */ + g_signal_connect_swapped(popup_data->ctrlbar_red, "value-changed", + G_CALLBACK(gtk_widget_queue_draw), area); + g_signal_connect_swapped(popup_data->ctrlbar_green, "value-changed", + G_CALLBACK(gtk_widget_queue_draw), area); + g_signal_connect_swapped(popup_data->ctrlbar_blue, "value-changed", + G_CALLBACK(gtk_widget_queue_draw), area); + + /* Attach expose_event callback function to drawing area */ + g_signal_connect (area, "expose_event", + G_CALLBACK(hildon_popup_palette_expose), + popup_data); + + /* Create popup dialog */ + popup = gtk_dialog_new_with_buttons (_("ecdg_ti_5bit_colour_selector"), + GTK_WINDOW(parent), + GTK_DIALOG_DESTROY_WITH_PARENT | + GTK_DIALOG_NO_SEPARATOR, + _("ecdg_bd_5bit_colour_selector_ok"), GTK_RESPONSE_OK, + _("ecdg_bd_5bit_colour_selector_cancel"), + GTK_RESPONSE_CANCEL, + NULL); + + /* Select-key shouldn't do anything unless dialog's button is focused */ + gtk_dialog_set_default_response(GTK_DIALOG(popup), GTK_RESPONSE_NONE); + + /* Add layout table to the Vbox of the popup dialog */ + gtk_box_pack_start (GTK_BOX(GTK_DIALOG(popup)->vbox), + GTK_WIDGET(layout), TRUE, TRUE, 0); + + /* Show thw Vbox of the popup dialog */ + gtk_widget_show_all(GTK_DIALOG(popup)->vbox); + + return popup; +} + +/** + * hildon_color_popup_set_color_from_sliders: + * @color: a pointer to #GdkColor to which the new values will be put + * @popup_data: a #HildonColorPopup + * + * Sets the values in the given #GdkColor to the values of the + * controlbars. + */ + +void +hildon_color_popup_set_color_from_sliders(GdkColor *color, + HildonColorPopup *popup_data) +{ + color->pixel = 0; + color->red = hildon_controlbar_get_value ( + HILDON_CONTROLBAR(popup_data->ctrlbar_red)) << 11; + color->green = hildon_controlbar_get_value ( + HILDON_CONTROLBAR(popup_data->ctrlbar_green)) << 11; + color->blue = hildon_controlbar_get_value ( + HILDON_CONTROLBAR(popup_data->ctrlbar_blue)) << 11; +} + +/* expose_event callback function */ +static gboolean +hildon_popup_palette_expose (GtkWidget * widget, + GdkEventExpose *event, gpointer data) +{ + if (GTK_WIDGET_DRAWABLE(widget)) + { + GdkColor color; + GdkGC * gc = gdk_gc_new (widget->window); + + /* Get the current color value */ + hildon_color_popup_set_color_from_sliders(&color, data); + gdk_gc_set_rgb_fg_color(gc, &color); + + /* draw the color area */ + gdk_draw_rectangle( widget->window, gc, TRUE /* filled */, + 1, 1, widget->allocation.width - 2, + widget->allocation.height - 2); + + color.pixel = color.red = color.green = color.blue = 0; + gdk_gc_set_rgb_fg_color(gc, &color); + + /* Draw frames on color box */ + gdk_draw_rectangle( widget->window, gc, FALSE, + 0, 0, widget->allocation.width - 1, + widget->allocation.height - 1); + + /* Free memory used by the graphics contexts */ + g_object_unref(gc); + } + + return TRUE; +} diff --git a/src/hildon-color-popup.h b/src/hildon-color-popup.h new file mode 100644 index 0000000..d4277a2 --- /dev/null +++ b/src/hildon-color-popup.h @@ -0,0 +1,52 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_COLOR_POPUP_H__ +#define __HILDON_COLOR_POPUP_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +typedef struct +{ + GtkWidget *ctrlbar_red; + GtkWidget *ctrlbar_green; + GtkWidget *ctrlbar_blue; + +} HildonColorPopup; + +GtkWidget *hildon_color_popup_new(GtkWindow *parent, + const GdkColor *initial_color, + HildonColorPopup *popupdata); + +void hildon_color_popup_set_color_from_sliders(GdkColor *color, + HildonColorPopup *popupdata); + + +G_END_DECLS + +#endif /* __HILDON_COLOR_POPUP_H__ */ diff --git a/src/hildon-color-selector.c b/src/hildon-color-selector.c new file mode 100644 index 0000000..d155d1d --- /dev/null +++ b/src/hildon-color-selector.c @@ -0,0 +1,845 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-color-selector + * @short_description: A widget for selecting a color + * @see_also: #HildonColorButton, #HildonColorPopup + * + * #HildonColorSelector allows selection of a color from a standard + * 16-color palette or a palette of 8 user-customizable colors. + * The user-customizable colors can be modified through HildonColorPopup. + */ + + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "hildon-color-selector.h" +#include "hildon-color-popup.h" + +#include +#define _(String) dgettext(PACKAGE, String) + +/* Color amounts */ +#define HILDON_BASE_COLOR_NUM 16 +#define HILDON_CUSTOM_COLOR_NUM 8 +#define HILDON_TOTAL_COLOR_NUM (HILDON_BASE_COLOR_NUM + HILDON_CUSTOM_COLOR_NUM) +#define BLACKIND 0 +#define GREYIND 6 +#define WHITEIND 9 + +#define SELECTION_BORDER_COLOR_NAME "ImageBorderColor" +#define FOCUS_BORDER_COLOR "#8080FF" +#define FOCUS_BORDER_WIDTH 2 + +/* Pixel sizes */ +#define HILDON_COLOR_SELECTOR_BOX_W 26 +#define HILDON_COLOR_SELECTOR_BOX_H 26 +#define HILDON_COLOR_SELECTOR_BORDER_WIDTH 1 +#define HILDON_COLOR_SELECTOR_PADDING_WIDTH 1 + +#define HILDON_COLOR_SELECTOR_BOX_FULL_WIDTH \ + ( HILDON_COLOR_SELECTOR_BOX_W \ + + HILDON_COLOR_SELECTOR_BORDER_WIDTH * 2 \ + + HILDON_COLOR_SELECTOR_PADDING_WIDTH * 2 ) + +#define HILDON_COLOR_SELECTOR_BOX_FULL_HEIGHT \ + ( HILDON_COLOR_SELECTOR_BOX_H \ + + HILDON_COLOR_SELECTOR_BORDER_WIDTH * 2 \ + + HILDON_COLOR_SELECTOR_PADDING_WIDTH * 2 ) + +#define HILDON_COLOR_SELECTOR_COLS 8 +#define HILDON_COLOR_SELECTOR_ROWS 3 + +/* gconf definitions */ +#define HILDON_COLOR_GCONF_PATH "/system/osso/af/color_selector" +#define HILDON_COLOR_GCONF_KEYS "/system/osso/af/color_selector/custom_colors" + +/* Pointer parent class */ +static GtkDialogClass *parent_class; + +struct _HildonColorSelectorPriv +{ + GConfClient *client; + GtkWidget *drawing_area; + GtkWidget *modify_button; + gint selected_index; + gint focused_index; + guint notify_id; + /* one extra place for the modified base color */ + GdkColor color[HILDON_TOTAL_COLOR_NUM + 1]; +}; + +enum +{ + PROP_NONE, + PROP_COLOR +}; + +/* + * Private function prototype definitions + */ +static void +hildon_color_selector_class_init (HildonColorSelectorClass * selector_class); + +static void +hildon_color_selector_init (HildonColorSelector * selector); + +static gboolean +hildon_color_selector_expose (GtkWidget * widget, + GdkEventExpose * event, + gpointer data); + +static gboolean key_pressed (GtkWidget * widget, + GdkEventKey * event); + +static gboolean color_pressed (GtkWidget * widget, + GdkEventButton * event, + gpointer user_data); + +static void select_color_index (HildonColorSelector *selector, + gint idx, + gboolean motion); + +static void select_color (HildonColorSelector * selector, + int event_x, + int event_y, + gboolean motion); + +static gboolean color_moved (GtkWidget * widget, + GdkEventMotion * event, + gpointer data); + +static void +modify_button_clicked (GtkWidget * button, + HildonColorSelector * selector); + +static void modify_focused(HildonColorSelector * colselector); + +static void +hildon_color_selector_set_property(GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec); +static void +hildon_color_selector_get_property(GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec); + +GType +hildon_color_selector_get_type(void) +{ + static GType selector_type = 0; + + if (!selector_type) + { + static const GTypeInfo selector_info = + { + sizeof(HildonColorSelectorClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_color_selector_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonColorSelector), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_color_selector_init, + }; + + selector_type = g_type_register_static(GTK_TYPE_DIALOG, + "HildonColorSelector", + &selector_info, 0); + } + return selector_type; +} + +static void +hildon_color_selector_destroy(GtkObject *obj) +{ + HildonColorSelectorPriv *priv = HILDON_COLOR_SELECTOR(obj)->priv; + + if (priv->client) + { + gconf_client_notify_remove(priv->client, priv->notify_id); + g_object_unref(priv->client); + priv->client = NULL; + } + + GTK_OBJECT_CLASS(parent_class)->destroy(obj); +} + +static void +hildon_color_selector_class_init(HildonColorSelectorClass * selector_class) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(selector_class); + GObjectClass *gobject_class = G_OBJECT_CLASS (selector_class); + + parent_class = g_type_class_peek_parent(selector_class); + + widget_class->key_press_event = key_pressed; + + g_type_class_add_private(selector_class, + sizeof(HildonColorSelectorPriv)); + + GTK_OBJECT_CLASS(selector_class)->destroy = hildon_color_selector_destroy; + + gobject_class->get_property = hildon_color_selector_get_property; + gobject_class->set_property = hildon_color_selector_set_property; + + /** + * HildonColorSelector:color: + * + * The selected color. + */ + g_object_class_install_property (gobject_class, PROP_COLOR, + g_param_spec_boxed ("color", + "Current Color", + "The selected color", + GDK_TYPE_COLOR, + G_PARAM_READWRITE)); +} + + +/** + * hildon_color_selector_new: + * @parent: the parent window. The X window ID of the parent window + * has to be the same as the X window ID of the application + * + * Creates a new #HildonColorSelector dialog with 3x8 layout of + * base colors and 'OK', 'More..' and 'Cancel' buttons. + * + * Returns: new #HildonColorSelector + **/ +GtkWidget *hildon_color_selector_new(GtkWindow * parent) +{ + GtkWidget *dialog = g_object_new(HILDON_TYPE_COLOR_SELECTOR, NULL); + + g_return_val_if_fail(dialog, NULL); + + if (parent) + { + gtk_window_set_transient_for(GTK_WINDOW(dialog), parent); + } + + return dialog; +} + +static void +hildon_color_selector_set_custom_colors( + HildonColorSelector *selector, + GConfValue *value) +{ + GSList *list; + gint i; + + g_assert(HILDON_IS_COLOR_SELECTOR(selector)); + + /* We have to be really careful. At least gconftool's + stress test may generate unexpected value setups */ + if (value == NULL + || value->type != GCONF_VALUE_LIST + || gconf_value_get_list_type(value) != GCONF_VALUE_STRING) + list = NULL; + else + list = gconf_value_get_list(value); + + /* Use list to fill in the selector's color property */ + for ( i = 0; i < HILDON_CUSTOM_COLOR_NUM; ++i) + { + const gchar *color_string = NULL; + + if (list) { + color_string = gconf_value_get_string(list->data); + list = list->next; + } else { + color_string = "#FFFFFF"; + } + +/* g_print("custom_color: %s\n", color_string); */ + + selector->priv->color[i].pixel = 0; + gdk_color_parse (color_string, + &(selector->priv->color[HILDON_BASE_COLOR_NUM+i])); + } +} + +static void +gconf_notify_func(GConfClient *client, + guint cnxn_id, + GConfEntry *entry, + gpointer data) +{ + hildon_color_selector_set_custom_colors(HILDON_COLOR_SELECTOR(data), + gconf_entry_get_value(entry)); + gtk_widget_queue_draw(GTK_WIDGET(data)); +} + +static void +hildon_color_selector_init(HildonColorSelector * selector) +{ + guint i; + GtkWidget *hbox; + GConfValue *value; + + /* 16 standard Windows colors */ + const char base_colours[][HILDON_BASE_COLOR_NUM] = { + "#000000", "#FFFFFF", "#FF0000", "#660000", "#0000FF", "#000066", + "#FF33FF", "#660066", "#33CC33", "#006600", "#FFCC00", "#CC9900", + "#999999", "#666666", "#00CCCC", "#006666" + }; + + selector->priv = + G_TYPE_INSTANCE_GET_PRIVATE(selector, + HILDON_TYPE_COLOR_SELECTOR, + HildonColorSelectorPriv); + + /* ***********test GConf*********** */ + selector->priv->client = gconf_client_get_default (); + gconf_client_set_error_handling (selector->priv->client, + GCONF_CLIENT_HANDLE_UNRETURNED); + + /* Add our directory to the list of directories the GConfClient will + watch. */ + gconf_client_add_dir (selector->priv->client, HILDON_COLOR_GCONF_PATH, + GCONF_CLIENT_PRELOAD_NONE, + NULL); + + /* Use the value directed by GConfValue to set the color */ + value = gconf_client_get(selector->priv->client, + HILDON_COLOR_GCONF_KEYS, NULL); + + hildon_color_selector_set_custom_colors(selector, value); + + if (value) { + gconf_value_free(value); + } + + /* Listen to changes to our key. */ + selector->priv->notify_id = gconf_client_notify_add (selector->priv->client, + HILDON_COLOR_GCONF_KEYS, gconf_notify_func, selector, NULL, NULL); + + /* ************************************ */ + + selector->priv->selected_index = GREYIND; + selector->priv->focused_index = GREYIND; + + /* init base colors for color boxes */ + for (i = 0; i < HILDON_BASE_COLOR_NUM; ++i) + { + selector->priv->color[i].pixel = 0; + gdk_color_parse (base_colours[i], &(selector->priv->color[i])); + } + + gtk_dialog_set_has_separator(GTK_DIALOG(selector), FALSE); + + /* create drawing area */ + hbox = gtk_hbox_new(TRUE, 0); + selector->priv->drawing_area = gtk_drawing_area_new(); + + /* receive focus from dialog buttons */ + GTK_WIDGET_SET_FLAGS (selector->priv->drawing_area, GTK_CAN_FOCUS); + + gtk_widget_add_events (selector->priv->drawing_area, + GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK); + + /* Arrange size of the drawing area. */ + gtk_widget_set_size_request (selector->priv->drawing_area, + (HILDON_COLOR_SELECTOR_COLS * + HILDON_COLOR_SELECTOR_BOX_FULL_WIDTH), + (HILDON_COLOR_SELECTOR_ROWS * + HILDON_COLOR_SELECTOR_BOX_FULL_HEIGHT)); + + gtk_box_pack_start (GTK_BOX(GTK_DIALOG(selector)->vbox), + hbox, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX(hbox), selector->priv->drawing_area, + FALSE, FALSE, 0); + + /* Register callback functions for the drawing area */ + g_signal_connect (selector->priv->drawing_area, "expose_event", + G_CALLBACK(hildon_color_selector_expose), selector); + g_signal_connect (selector->priv->drawing_area, "button_press_event", + G_CALLBACK(color_pressed), selector); + g_signal_connect (selector->priv->drawing_area, "motion-notify-event", + G_CALLBACK(color_moved), selector); + + gtk_dialog_add_button (GTK_DIALOG(selector), + _("ecdg_bd_colour_selector_ok"), GTK_RESPONSE_OK); + + selector->priv->modify_button = + gtk_button_new_with_label(_("ecdg_bd_colour_selector_modify")); + gtk_widget_set_sensitive(selector->priv->modify_button, FALSE); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(selector)->action_area), + selector->priv->modify_button, FALSE, TRUE, 0); + + g_signal_connect(selector->priv->modify_button, "clicked", + G_CALLBACK(modify_button_clicked), selector); + + gtk_dialog_add_button (GTK_DIALOG(selector), + _("ecdg_bd_colour_selector_cancel"), + GTK_RESPONSE_CANCEL); + + gtk_dialog_set_default_response (GTK_DIALOG(selector), GTK_RESPONSE_OK); + + gtk_window_set_title ( GTK_WINDOW(selector), + _("ecdg_ti_colour_selector") ); + gtk_widget_show_all (GTK_DIALOG(selector)->vbox); +} + +static gboolean +hildon_color_selector_expose(GtkWidget * widget, + GdkEventExpose * event, + gpointer data) +{ + HildonColorSelector *selector; + GdkColor color; + GdkGC *gc, *gc_focus; + gint x, y, idx; + + g_return_val_if_fail (GTK_IS_WIDGET(widget), FALSE); + g_return_val_if_fail (event, FALSE); + g_return_val_if_fail (HILDON_IS_COLOR_SELECTOR(data), FALSE); + + if (!GTK_WIDGET_DRAWABLE(widget)) + return FALSE; + + selector = HILDON_COLOR_SELECTOR(data); + gc = gdk_gc_new (widget->window); + + gc_focus = gdk_gc_new(widget->window); + gdk_gc_set_line_attributes(gc_focus, FOCUS_BORDER_WIDTH, + GDK_LINE_SOLID, GDK_CAP_BUTT, + GDK_JOIN_MITER); + + /* draw the color boxes and a focus for one of them */ + for (y = 0, idx = 0; y < HILDON_COLOR_SELECTOR_ROWS; ++y) + { + for (x = 0; x < HILDON_COLOR_SELECTOR_COLS; ++x, ++idx) + { + gint xpos = x * HILDON_COLOR_SELECTOR_BOX_FULL_WIDTH; + gint ypos = y * HILDON_COLOR_SELECTOR_BOX_FULL_HEIGHT; + + /* frames on color box */ + gdk_draw_rectangle(widget->window, widget->style->black_gc, FALSE, + xpos + HILDON_COLOR_SELECTOR_PADDING_WIDTH, + ypos + HILDON_COLOR_SELECTOR_PADDING_WIDTH, + HILDON_COLOR_SELECTOR_BOX_W + + HILDON_COLOR_SELECTOR_PADDING_WIDTH, + HILDON_COLOR_SELECTOR_BOX_H + + HILDON_COLOR_SELECTOR_PADDING_WIDTH); + + /* color box */ + gdk_gc_set_rgb_fg_color(gc, &(selector->priv->color[idx])); + gdk_draw_rectangle(widget->window, gc, + TRUE, /* filled */ + xpos + HILDON_COLOR_SELECTOR_PADDING_WIDTH + + HILDON_COLOR_SELECTOR_BORDER_WIDTH, + ypos + HILDON_COLOR_SELECTOR_PADDING_WIDTH + + HILDON_COLOR_SELECTOR_BORDER_WIDTH, + HILDON_COLOR_SELECTOR_BOX_W, + HILDON_COLOR_SELECTOR_BOX_H); + + /* focus around the selected and focused color box */ + if (idx == selector->priv->selected_index) + { + /* selected color box */ + if (!gtk_style_lookup_logical_color(widget->style, + SELECTION_BORDER_COLOR_NAME, &color)) + { + /* set default color if color looking up fails */ + color.red = color.green = color.blue = 0; + } + + gdk_gc_set_rgb_fg_color(gc_focus, &color); + gdk_draw_rectangle(widget->window, gc_focus, FALSE, + xpos + 1-(FOCUS_BORDER_WIDTH % 2), + ypos + 1-(FOCUS_BORDER_WIDTH % 2), + HILDON_COLOR_SELECTOR_BOX_W + + HILDON_COLOR_SELECTOR_BORDER_WIDTH * 2 + + (FOCUS_BORDER_WIDTH % 2), + HILDON_COLOR_SELECTOR_BOX_H + + HILDON_COLOR_SELECTOR_BORDER_WIDTH * 2 + + (FOCUS_BORDER_WIDTH % 2)); + } + else if (idx == selector->priv->focused_index) + { + /* focused color box. + There's only zero or one so allocate GC in here. */ + gdk_color_parse(FOCUS_BORDER_COLOR, &color); + + gdk_gc_set_rgb_fg_color(gc_focus, &color); + gdk_draw_rectangle(widget->window, gc_focus, FALSE, + xpos + 1-(FOCUS_BORDER_WIDTH % 2), + ypos + 1-(FOCUS_BORDER_WIDTH % 2), + HILDON_COLOR_SELECTOR_BOX_W + + HILDON_COLOR_SELECTOR_BORDER_WIDTH * 2 + + (FOCUS_BORDER_WIDTH % 2), + HILDON_COLOR_SELECTOR_BOX_H + + HILDON_COLOR_SELECTOR_BORDER_WIDTH * 2 + + (FOCUS_BORDER_WIDTH % 2)); + } + } + } + + g_object_unref(gc); + g_object_unref(gc_focus); + return TRUE; +} + +/** + * hildon_color_selector_get_color: + * @selector: a #HildonColorSelector + * + * Returns: the currently selected #GdkColor. The returned pointer must + * not be freed. + */ +G_CONST_RETURN GdkColor *hildon_color_selector_get_color(HildonColorSelector * selector) +{ + g_return_val_if_fail(HILDON_IS_COLOR_SELECTOR(selector), NULL); + return &(selector->priv->color[selector->priv->selected_index]); +} + +/** + * hildon_color_selector_set_color: + * @selector: #HildonColorSelector + * @color: #Gdkcolor to set + * + * Selects the color specified. Does nothing if the color does not + * exist among the standard colors. + */ +void hildon_color_selector_set_color(HildonColorSelector * selector, + GdkColor * color) +{ + gint i; + + g_return_if_fail(HILDON_IS_COLOR_SELECTOR(selector)); + g_return_if_fail(color); + + /* Select the specified color */ + for (i = 0; + i < (HILDON_BASE_COLOR_NUM + HILDON_CUSTOM_COLOR_NUM); + ++i) + { + if (selector->priv->color[i].red == color->red && + selector->priv->color[i].green == color->green && + selector->priv->color[i].blue == color->blue) + { + selector->priv->selected_index = i; + selector->priv->focused_index = i; + + /* The modify button is active if the color index is bigger than + * the number of base colours. + */ + gtk_widget_set_sensitive(selector->priv->modify_button, + selector->priv->focused_index >= HILDON_BASE_COLOR_NUM); + gtk_widget_queue_draw(selector->priv->drawing_area); + break; + } + } + + /* Notify the color selector that the color has changed */ + g_object_notify (G_OBJECT (selector), "color"); +} + +static gboolean +color_pressed(GtkWidget * widget, GdkEventButton * event, + gpointer user_data) +{ + select_color(HILDON_COLOR_SELECTOR(user_data), event->x, event->y, FALSE); + return TRUE; +} + +/* Handle key press of right, left, up, down and return */ +static gboolean key_pressed(GtkWidget * widget, + GdkEventKey * event) +{ + HildonColorSelector *selector; + gint index; + + g_assert(widget); + + selector = HILDON_COLOR_SELECTOR(widget); + index = selector->priv->focused_index; + + /* if dialog buttons has the focus */ + if (GTK_WIDGET_HAS_FOCUS(selector->priv->drawing_area) == FALSE) + return GTK_WIDGET_CLASS(parent_class)->key_press_event(widget, event); + + /* Since wrapping is not allowed, + * move only if the next index is a valid one. + */ + switch (event->keyval) { + case GDK_KP_Right: + case GDK_Right: + if (index == (HILDON_BASE_COLOR_NUM + HILDON_CUSTOM_COLOR_NUM - 1) + || index == (HILDON_CUSTOM_COLOR_NUM - 1) + || index == (2*HILDON_CUSTOM_COLOR_NUM - 1)) + { + return TRUE; + } + index++; + break; + case GDK_KP_Left: + case GDK_Left: + if (index == 0 + || index == (HILDON_CUSTOM_COLOR_NUM) + || index == (2*HILDON_CUSTOM_COLOR_NUM)) + { + return TRUE; + } + index--; + break; + case GDK_KP_Up: + case GDK_Up: + if (index > (HILDON_COLOR_SELECTOR_COLS - 1)) + { + index -= HILDON_COLOR_SELECTOR_COLS; + } + else + { + return GTK_WIDGET_CLASS(parent_class)->key_press_event(widget, event); + } + break; + case GDK_KP_Down: + case GDK_Down: + if (index < (HILDON_COLOR_SELECTOR_COLS + HILDON_CUSTOM_COLOR_NUM)) + { + index += HILDON_COLOR_SELECTOR_COLS; + } + else + { + return GTK_WIDGET_CLASS(parent_class)->key_press_event(widget, event); + } + break; + case GDK_KP_Enter: + case GDK_Return: + if (index < HILDON_BASE_COLOR_NUM) + select_color_index(selector, selector->priv->focused_index, FALSE); + else + modify_focused(selector); + default: + return GTK_WIDGET_CLASS(parent_class)->key_press_event(widget, event); + } + + if (index < (HILDON_BASE_COLOR_NUM + HILDON_CUSTOM_COLOR_NUM)) + { + selector->priv->focused_index = index; + } + else + { + selector->priv->focused_index = + HILDON_BASE_COLOR_NUM + HILDON_CUSTOM_COLOR_NUM - 1; + } + /* The modify button is active if the color index is bigger than + * the number of base colours. + */ + gtk_widget_set_sensitive(selector->priv->modify_button, + selector->priv->focused_index >= HILDON_BASE_COLOR_NUM); + + gtk_widget_queue_draw(selector->priv->drawing_area); + + return TRUE; +} + +static void +select_color_index(HildonColorSelector * selector, gint idx, gboolean motion) +{ + /* If a custom colour is selected, open a popup to modify the colour */ + if (!motion && + selector->priv->focused_index >= HILDON_BASE_COLOR_NUM && + selector->priv->focused_index == idx) + modify_focused(selector); + + selector->priv->focused_index = selector->priv->selected_index = idx; + gtk_widget_set_sensitive(selector->priv->modify_button, + selector->priv->focused_index >= HILDON_BASE_COLOR_NUM); + + gtk_widget_queue_draw(selector->priv->drawing_area); +} + +static void +select_color(HildonColorSelector * selector, gint event_x, gint event_y, + gboolean motion) +{ + gint x, y; + + g_assert(HILDON_IS_COLOR_SELECTOR(selector)); + + /* Get the selection coordinates */ + x = event_x / HILDON_COLOR_SELECTOR_BOX_FULL_WIDTH; + y = event_y / HILDON_COLOR_SELECTOR_BOX_FULL_HEIGHT; + + /* Get the row and column numbers for the selected color */ + if (x > (HILDON_COLOR_SELECTOR_COLS + HILDON_CUSTOM_COLOR_NUM - 1)) + { + x = HILDON_COLOR_SELECTOR_COLS + HILDON_CUSTOM_COLOR_NUM - 1; + } + else if (x < 0) + { + x = 0; + } + if (y > (HILDON_COLOR_SELECTOR_ROWS - 1)) + { + y = HILDON_COLOR_SELECTOR_ROWS - 1; + } + else if (y < 0) + { + y = 0; + } + + select_color_index(selector, (x + y * HILDON_COLOR_SELECTOR_COLS), motion); +} + +static gboolean +color_moved(GtkWidget * widget, GdkEventMotion * event, gpointer data) +{ + if ( event->state & + (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK) ) + { + select_color(HILDON_COLOR_SELECTOR(data), event->x, event->y, TRUE); + return TRUE; + } + return FALSE; +} + +static void +modify_button_clicked(GtkWidget * button, HildonColorSelector * selector) +{ + modify_focused (selector); +} + +static void +modify_focused(HildonColorSelector * colselector) +{ + HildonColorPopup popupdata; + GtkWidget *popup; + + /* Create a HildonColorPopup dialog */ + popup = hildon_color_popup_new(GTK_WINDOW(colselector), + hildon_color_selector_get_color(colselector), &popupdata); + + if ( gtk_dialog_run(GTK_DIALOG(popup) ) == GTK_RESPONSE_OK) + { + GdkColor *color; + + /* We cannot modify a base color */ + if (colselector->priv->focused_index < HILDON_BASE_COLOR_NUM) + { + colselector->priv->color[HILDON_TOTAL_COLOR_NUM] = + colselector->priv->color[colselector->priv->focused_index]; + colselector->priv->focused_index = HILDON_TOTAL_COLOR_NUM; + } + + /* Update the focused color with the color selected in color popup */ + color = &(colselector->priv->color[colselector->priv->focused_index]); + hildon_color_popup_set_color_from_sliders(color, &popupdata); + + /* If we modified a base color we just accept the dialog */ + if( colselector->priv->focused_index >= HILDON_TOTAL_COLOR_NUM) + { + gtk_dialog_response(GTK_DIALOG(colselector), GTK_RESPONSE_OK); + } + else /* If we mofied custom colors we have to save to gconf */ + { + GConfValue *value; + GSList * list; + gint i; + + value = gconf_value_new(GCONF_VALUE_LIST); + gconf_value_set_list_type(value, GCONF_VALUE_STRING); + list = NULL; + + for ( i = HILDON_BASE_COLOR_NUM; i < HILDON_TOTAL_COLOR_NUM; i++) + { + GConfValue *item; + char buffer[32]; + + g_snprintf(buffer, sizeof(buffer), "#%.2X%.2X%.2X", + (colselector->priv->color[i].red>>8)&0xFF, + (colselector->priv->color[i].green>>8)&0xFF, + (colselector->priv->color[i].blue>>8)&0xFF ); + + item = gconf_value_new(GCONF_VALUE_STRING); + gconf_value_set_string(item, buffer); + list = g_slist_append (list, item); + } + + gconf_value_set_list_nocopy(value, list); + + /* gconf client handles the possible error */ + gconf_client_set(colselector->priv->client, + HILDON_COLOR_GCONF_KEYS, value, NULL); + + gconf_value_free(value); + } + } + + gtk_widget_destroy (popup); + gtk_window_present (GTK_WINDOW(colselector)); +} + +static void +hildon_color_selector_set_property(GObject *object, guint param_id, + const GValue *value, GParamSpec *pspec) +{ + HildonColorSelector *selector = HILDON_COLOR_SELECTOR(object); + + switch (param_id) + { + case PROP_COLOR: + hildon_color_selector_set_color(selector, (GdkColor*)g_value_get_boxed(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); + break; + } +} + +static void +hildon_color_selector_get_property(GObject *object, guint param_id, + GValue *value, GParamSpec *pspec) +{ + HildonColorSelector *selector = HILDON_COLOR_SELECTOR(object); + + switch (param_id) + { + case PROP_COLOR: + g_value_set_boxed(value, (gconstpointer)hildon_color_selector_get_color(selector)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); + break; + } +} + diff --git a/src/hildon-color-selector.h b/src/hildon-color-selector.h new file mode 100644 index 0000000..1312c89 --- /dev/null +++ b/src/hildon-color-selector.h @@ -0,0 +1,72 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_COLOR_SELECTOR_H__ +#define __HILDON_COLOR_SELECTOR_H__ + +#include +#include +#include + +G_BEGIN_DECLS +#define HILDON_TYPE_COLOR_SELECTOR \ + ( hildon_color_selector_get_type() ) +#define HILDON_COLOR_SELECTOR(obj) \ + (GTK_CHECK_CAST (obj, HILDON_TYPE_COLOR_SELECTOR, HildonColorSelector)) +#define HILDON_COLOR_SELECTOR_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST ((klass), HILDON_TYPE_COLOR_SELECTOR,\ + HildonColorSelectorClass)) +#define HILDON_IS_COLOR_SELECTOR(obj) \ + (GTK_CHECK_TYPE (obj, HILDON_TYPE_COLOR_SELECTOR)) +#define HILDON_IS_COLOR_SELECTOR_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE ((klass), HILDON_COLOR_SELECTOR_CLASS)) + GType hildon_color_selector_get_type(void); + +typedef struct _HildonColorSelector HildonColorSelector; +typedef struct _HildonColorSelectorClass HildonColorSelectorClass; + +/** + * HildonColorSelectorPriv: + * + * Internal struct for color selector. + */ +typedef struct _HildonColorSelectorPriv HildonColorSelectorPriv; + +struct _HildonColorSelector { + GtkDialog parent; + HildonColorSelectorPriv *priv; +}; + +struct _HildonColorSelectorClass { + GtkDialogClass parent_class; +}; + +GType hildon_color_selector_get_type(void) G_GNUC_CONST; +GtkWidget *hildon_color_selector_new(GtkWindow * parent); +G_CONST_RETURN GdkColor *hildon_color_selector_get_color(HildonColorSelector * selector); +void hildon_color_selector_set_color(HildonColorSelector * selector, + GdkColor * color); + +G_END_DECLS +#endif /* __HILDON_COLOR_SELECTOR_H__ */ diff --git a/src/hildon-composite-widget.c b/src/hildon-composite-widget.c new file mode 100644 index 0000000..ab90aaf --- /dev/null +++ b/src/hildon-composite-widget.c @@ -0,0 +1,79 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include +#include "hildon-composite-widget.h" +#include "hildon-date-editor.h" +#include "hildon-time-editor.h" + +/* This function is a private function of hildon-libs. It hadles focus + * changing for composite hildon widgets: HildonDateEditor, + * HildonNumberEditor, HildonTimeEditor, HildonWeekdayPicker. + * Its purpose is to focus the first widget (from left) inside the container + * regardless of where the focus is coming from. + */ +gboolean +hildon_composite_widget_focus (GtkWidget *widget, GtkDirectionType direction) +{ + GtkWidget *toplevel = NULL; + GtkWidget *focus_widget = NULL; + + /* Get the topmost parent widget */ + toplevel = gtk_widget_get_toplevel (widget); + if (!GTK_IS_WINDOW(toplevel)) + return GTK_WIDGET_CLASS (g_type_class_peek_parent ( + GTK_WIDGET_GET_CLASS (widget)))->focus (widget, direction); + /* Get focus widget in the topmost parent widget */ + focus_widget = GTK_WINDOW (toplevel)->focus_widget; + + if (!GTK_IS_WIDGET (focus_widget)) + return TRUE; + + if (!gtk_widget_is_ancestor (focus_widget, widget)) + { + gtk_widget_grab_focus (widget); + } + else + { + /* Containers grab_focus grabs the focus to the correct widget */ + switch (direction) { + case GTK_DIR_UP: + case GTK_DIR_DOWN: + if (HILDON_IS_DATE_EDITOR(widget) || HILDON_IS_TIME_EDITOR(widget)) + return FALSE; + else + return GTK_WIDGET_CLASS (g_type_class_peek_parent + (GTK_WIDGET_GET_CLASS(widget)))->focus (widget, direction); + break; + + default: + return GTK_WIDGET_CLASS (g_type_class_peek_parent + (GTK_WIDGET_GET_CLASS(widget)))->focus (widget, direction); + break; + } + } + + return TRUE; +} diff --git a/src/hildon-composite-widget.h b/src/hildon-composite-widget.h new file mode 100644 index 0000000..7a0993a --- /dev/null +++ b/src/hildon-composite-widget.h @@ -0,0 +1,53 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/* + * @file + * + * Hildon composite widget includes all features which were not fitting into + * the any current class. A new, separate widget was not created because of the + * amount of current features is low. Need for this kind of class was not known + * when the building of the class hierarchy began. When a new feature is added, + * need for a new class should be re-considered. To make this decision one + * should really consider all the common features which are needed in the + * hildon composite widgets. Class position (for hildon-composite-widget) + * in the class hierarchy is between GtkContainer and any composite widget. + * + */ + +#ifndef __HILDON_COMPOSITE_WIDGET__ +#define __HILDON_COMPOSITE_WIDGET__ + + +G_BEGIN_DECLS + + +gboolean +hildon_composite_widget_focus( GtkWidget *widget, GtkDirectionType direction ); + + +G_END_DECLS + + +#endif /*__HILDON_COMPOSITE_WIDGET__*/ diff --git a/src/hildon-controlbar.c b/src/hildon-controlbar.c new file mode 100644 index 0000000..87e750d --- /dev/null +++ b/src/hildon-controlbar.c @@ -0,0 +1,799 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-controlbar + * @short_description: A widget that allows increasing or decreasing + * a value within a pre-defined range + * + * #HildonControlbar is a horizontally positioned range widget that is + * visually divided into blocks and supports setting a minimum and + * maximum value for the range. + */ + + +#include +#include +#include +#include +#include "hildon-controlbar.h" + +#include +#define _(string) dgettext(PACKAGE, string) + +#define HILDON_CONTROLBAR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ + HILDON_TYPE_CONTROLBAR, HildonControlbarPrivate)); + +#define DEFAULT_WIDTH 234 +#define DEFAULT_HEIGHT 30 +#define DEFAULT_BORDER_WIDTH 2 + +#define HILDON_CONTROLBAR_STEP_INCREMENT 1 +#define HILDON_CONTROLBAR_PAGE_INCREMENT 1 +#define HILDON_CONTROLBAR_PAGE_SIZE 0 +#define HILDON_CONTROLBAR_UPPER_VALUE 10 +#define HILDON_CONTROLBAR_LOWER_VALUE 0.0 +#define HILDON_CONTROLBAR_INITIAL_VALUE 0 + +static GtkScaleClass *parent_class; + +typedef struct _HildonControlbarPrivate HildonControlbarPrivate; + +enum +{ + PROP_MIN = 1, + PROP_MAX, + PROP_VALUE +}; + +enum +{ + END_REACHED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +static void +hildon_controlbar_class_init(HildonControlbarClass * controlbar_class); +static void hildon_controlbar_init(HildonControlbar * controlbar); +static GObject * +hildon_controlbar_constructor(GType type, guint n_construct_properties, + GObjectConstructParam *construct_properties); + +static gint hildon_controlbar_button_press_event(GtkWidget * widget, + GdkEventButton * event); +static gint hildon_controlbar_button_release_event(GtkWidget * widget, + GdkEventButton * event); +static gint +hildon_controlbar_expose_event(GtkWidget * widget, GdkEventExpose * event); +static void +hildon_controlbar_size_request(GtkWidget * self, GtkRequisition * req); +static void +hildon_controlbar_paint(HildonControlbar * self, GdkRectangle * area); +static gboolean +hildon_controlbar_keypress(GtkWidget * widget, GdkEventKey * event); + +static void hildon_controlbar_set_property( GObject *object, guint param_id, + const GValue *value, GParamSpec *pspec ); +static void hildon_controlbar_get_property( GObject *object, guint param_id, + GValue *value, GParamSpec *pspec ); + +static void +hildon_controlbar_value_changed( GtkAdjustment *adj, GtkRange *range ); + +/* + * Purpose of this function is to prevent Up and Down keys from + * changing the widget's value (like Left and Right). Instead they + * are used for changing focus to other widgtes. + */ +static gboolean +hildon_controlbar_change_value( GtkRange *range, GtkScrollType scroll, + gdouble new_value, gpointer data ); + +GType hildon_controlbar_get_type(void) +{ + static GType controlbar_type = 0; + + if (!controlbar_type) { + static const GTypeInfo controlbar_info = { + sizeof(HildonControlbarClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_controlbar_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonControlbar), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_controlbar_init, + }; + controlbar_type = g_type_register_static(GTK_TYPE_SCALE, + "HildonControlbar", + &controlbar_info, 0); + } + return controlbar_type; +} + +struct _HildonControlbarPrivate { + gboolean button_press; + gint old_value; +}; + +static void +hildon_controlbar_class_init(HildonControlbarClass * controlbar_class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(controlbar_class); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(controlbar_class); + + parent_class = g_type_class_peek_parent(controlbar_class); + + g_type_class_add_private(controlbar_class, + sizeof(HildonControlbarPrivate)); + + gobject_class->get_property = hildon_controlbar_get_property; + gobject_class->set_property = hildon_controlbar_set_property; + widget_class->size_request = hildon_controlbar_size_request; + widget_class->button_press_event = hildon_controlbar_button_press_event; + widget_class->button_release_event = hildon_controlbar_button_release_event; + widget_class->expose_event = hildon_controlbar_expose_event; + widget_class->key_press_event = hildon_controlbar_keypress; + G_OBJECT_CLASS(controlbar_class)->constructor = hildon_controlbar_constructor; + controlbar_class->end_reached = NULL; + + /** + * HildonControlbar:min: + * + * Controlbar minimum value. + */ + g_object_class_install_property( gobject_class, PROP_MIN, + g_param_spec_int("min", + "Minimum value", + "Smallest possible value", + G_MININT, G_MAXINT, + HILDON_CONTROLBAR_LOWER_VALUE, + G_PARAM_READABLE | G_PARAM_WRITABLE) ); + + /** + * HildonControlbar:max: + * + * Controlbar maximum value. + */ + g_object_class_install_property( gobject_class, PROP_MAX, + g_param_spec_int("max", + "Maximum value", + "Greatest possible value", + G_MININT, G_MAXINT, + HILDON_CONTROLBAR_UPPER_VALUE, + G_PARAM_READABLE | G_PARAM_WRITABLE) ); + + /** + * HildonControlbar:value: + * + * Controlbar value. + */ + g_object_class_install_property( gobject_class, PROP_VALUE, + g_param_spec_int("value", + "Current value", + "Current value", + G_MININT, G_MAXINT, + HILDON_CONTROLBAR_INITIAL_VALUE, + G_PARAM_READABLE | G_PARAM_WRITABLE) ); + + + gtk_widget_class_install_style_property(widget_class, + g_param_spec_uint("inner_border_width", + "Inner border width", + "The border spacing between the controlbar border and controlbar blocks.", + 0, G_MAXINT, + DEFAULT_BORDER_WIDTH, + G_PARAM_READABLE)); + + signals[END_REACHED] = + g_signal_new("end-reached", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET(HildonControlbarClass, end_reached), + NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, + G_TYPE_BOOLEAN); +} + +static void hildon_controlbar_init(HildonControlbar * controlbar) +{ + GtkRange *range; + HildonControlbarPrivate *priv; + + /* Initialize the private property */ + priv = HILDON_CONTROLBAR_GET_PRIVATE(controlbar); + priv->button_press = FALSE; + priv->old_value = 0; + range = GTK_RANGE(controlbar); + + range->has_stepper_a = TRUE; + range->has_stepper_d = TRUE; + range->round_digits = -1; + + gtk_widget_set_size_request( GTK_WIDGET(controlbar), DEFAULT_WIDTH, + DEFAULT_HEIGHT ); + g_signal_connect( range, "change-value", + G_CALLBACK(hildon_controlbar_change_value), NULL ); +} + +static GObject *hildon_controlbar_constructor(GType type, + guint n_construct_properties, GObjectConstructParam *construct_properties) +{ + GObject *obj; + GtkAdjustment *adj; + + obj = G_OBJECT_CLASS(parent_class)->constructor(type, + n_construct_properties, construct_properties); + + gtk_scale_set_draw_value (GTK_SCALE (obj), FALSE); + + /* Initialize the GtkAdjustment of the controlbar*/ + adj = GTK_RANGE(obj)->adjustment; + adj->step_increment = HILDON_CONTROLBAR_STEP_INCREMENT; + adj->page_increment = HILDON_CONTROLBAR_PAGE_INCREMENT; + adj->page_size = HILDON_CONTROLBAR_PAGE_SIZE; + + g_signal_connect( adj, "value-changed", + G_CALLBACK(hildon_controlbar_value_changed), obj ); + return obj; +} + +static void hildon_controlbar_set_property (GObject *object, guint param_id, + const GValue *value, GParamSpec *pspec) +{ + HildonControlbar *controlbar = HILDON_CONTROLBAR(object); + switch (param_id) + { + case PROP_MIN: + hildon_controlbar_set_min (controlbar, g_value_get_int(value)); + break; + + case PROP_MAX: + hildon_controlbar_set_max (controlbar, g_value_get_int(value)); + break; + + case PROP_VALUE: + hildon_controlbar_set_value (controlbar, g_value_get_int(value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); + break; + } +} + +static void hildon_controlbar_get_property( GObject *object, guint param_id, + GValue *value, GParamSpec *pspec ) +{ + HildonControlbar *controlbar = HILDON_CONTROLBAR(object); + switch (param_id) + { + case PROP_MIN: + g_value_set_int (value, hildon_controlbar_get_min (controlbar)); + break; + + case PROP_MAX: + g_value_set_int (value, hildon_controlbar_get_max (controlbar)); + break; + + case PROP_VALUE: + g_value_set_int (value, hildon_controlbar_get_value (controlbar)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); + break; + } +} + + +static void +hildon_controlbar_value_changed( GtkAdjustment *adj, GtkRange *range ) +{ + HildonControlbarPrivate *priv = HILDON_CONTROLBAR_GET_PRIVATE(range); + + /* Change the controlbar value if the adjusted value is large enough + * otherwise, keep the old value + */ + if( ABS(ceil(adj->value) - priv->old_value) >= 1 ) + { + priv->old_value = ceil(adj->value); + adj->value = priv->old_value; + } + else + g_signal_stop_emission_by_name( adj, "value-changed" ); + gtk_adjustment_set_value( adj, priv->old_value ); +} + +/** + * hildon_controlbar_new: + * + * Creates a new #HildonControlbar widget. + * + * Returns: a #GtkWidget pointer of newly created control bar + * widget + */ +GtkWidget *hildon_controlbar_new(void) +{ + return GTK_WIDGET(g_object_new(HILDON_TYPE_CONTROLBAR, NULL)); +} + +/* This function prevents Up and Down keys from changing the + * widget's value (like Left and Right). + * Instead they are used for changing focus to other widgtes. + */ +static gboolean +hildon_controlbar_keypress(GtkWidget * widget, GdkEventKey * event) +{ + if (event->keyval == GDK_Up || event->keyval == GDK_Down) + return FALSE; + return ((GTK_WIDGET_CLASS(parent_class)->key_press_event) (widget, event)); +} + +static void +hildon_controlbar_size_request(GtkWidget * self, GtkRequisition * req) +{ + if (GTK_WIDGET_CLASS(parent_class)->size_request) + GTK_WIDGET_CLASS(parent_class)->size_request(self, req); + + req->width = DEFAULT_WIDTH; + req->height = DEFAULT_HEIGHT; +} + +/** + * hildon_controlbar_set_value: + * @self: pointer to #HildonControlbar + * @value: value in range of >= 0 && < G_MAX_INT + * + * Change the current value of the control bar to the specified value. + */ +void hildon_controlbar_set_value(HildonControlbar * self, gint value) +{ + GtkAdjustment *adj; + g_return_if_fail (HILDON_IS_CONTROLBAR (self)); + adj = GTK_RANGE(self)->adjustment; + + g_return_if_fail(value >= 0); + + if (value >= adj->upper) + value = adj->upper; + else if (value <= adj->lower) + value = adj->lower; + + adj->value = value; + gtk_adjustment_value_changed(adj); + + g_object_notify (G_OBJECT(self), "value"); +} + +/** + * hildon_controlbar_get_value: + * @self: pointer to #HildonControlbar + * + * Returns: current value as gint + */ +gint hildon_controlbar_get_value(HildonControlbar * self) +{ + GtkAdjustment *adj; + g_return_val_if_fail (HILDON_IS_CONTROLBAR (self), 0); + adj = GTK_RANGE(self)->adjustment; + + return (gint) ceil(adj->value); +} + +/** + * hildon_controlbar_set_max: + * @self: pointer to #HildonControlbar + * @max: maximum value to set. The value needs to be greater than 0. + * + * Set the control bar's maximum to the given value. + * + * If the new maximum is smaller than current value, the value will be + * adjusted so that it equals the new maximum. + */ +void hildon_controlbar_set_max(HildonControlbar * self, gint max) +{ + GtkAdjustment *adj; + g_return_if_fail (HILDON_IS_CONTROLBAR (self)); + adj = GTK_RANGE(self)->adjustment; + + if (max < adj->lower) + max = adj->lower; + + if (adj->value > max) + hildon_controlbar_set_value (self, max); + + adj->upper = max; + gtk_adjustment_changed(adj); + + g_object_notify (G_OBJECT(self), "max"); +} + +/** + * hildon_controlbar_set_min: + * @self: pointer to #HildonControlbar + * @min: minimum value to set. The value needs to be greater than or + * equal to 0. + * + * Set the control bar's minimum to the given value. + * + * If the new minimum is smaller than current value, the value will be + * adjusted so that it equals the new minimum. + */ +void hildon_controlbar_set_min(HildonControlbar * self, gint min) +{ + GtkAdjustment *adj; + g_return_if_fail (HILDON_IS_CONTROLBAR (self)); + adj = GTK_RANGE(self)->adjustment; + + if (min > adj->upper) + min = adj->upper; + + if (adj->value < min) + hildon_controlbar_set_value (self, min); + + adj->lower = min; + gtk_adjustment_changed(adj); + g_object_notify (G_OBJECT(self), "min"); +} + +/** + * hildon_controlbar_set_range: + * @self: pointer to #HildonControlbar + * @max: maximum value to set. The value needs to be greater than 0. + * @min: Minimum value to set. The value needs to be greater than or + * equal to 0. + * + * Set the controlbars range to the given value + * + * If the new maximum is smaller than current value, the value will be + * adjusted so that it equals the new maximum. + * + * If the new minimum is smaller than current value, the value will be + * adjusted so that it equals the new minimum. + */ +void hildon_controlbar_set_range(HildonControlbar * self, gint min, + gint max) +{ + g_return_if_fail (HILDON_IS_CONTROLBAR (self)); + + if (min > max) + min = max; + /* We need to set max first here, because when min is set before + * max is set, it would end up 0, because max can't be bigger than 0. + */ + hildon_controlbar_set_max (self, max); + hildon_controlbar_set_min (self, min); +} + +/** + * hildon_controlbar_get_max: + * @self: a pointer to #HildonControlbar + * + * Returns: maximum value of control bar + */ +gint hildon_controlbar_get_max(HildonControlbar * self) +{ + GtkAdjustment *adj; + g_return_val_if_fail (HILDON_IS_CONTROLBAR (self), 0); + adj = GTK_RANGE(self)->adjustment; + + return (gint) adj->upper; +} + +/** + * hildon_controlbar_get_min: + * @self: a pointer to #HildonControlbar + * + * Returns: minimum value of controlbar + */ +gint hildon_controlbar_get_min(HildonControlbar * self) +{ + GtkAdjustment *adj = GTK_RANGE(self)->adjustment; + return (gint) adj->lower; +} + +/* + * Event handler for button press + * Need to change button1 to button2 before passing this event to + * parent handler. (see specs) + * Also updates button_press variable so that we can draw hilites + * correctly + */ +static gint hildon_controlbar_button_press_event(GtkWidget * widget, + GdkEventButton * event) +{ + HildonControlbar *self; + HildonControlbarPrivate *priv; + gboolean result = FALSE; + + g_return_val_if_fail(widget, FALSE); + g_return_val_if_fail(event, FALSE); + + self = HILDON_CONTROLBAR(widget); + priv = HILDON_CONTROLBAR_GET_PRIVATE(self); + + priv->button_press = TRUE; + event->button = event->button == 1 ? 2 : event->button; + + /* Ugh dirty hack. We manipulate the mouse event location to + compensate for centering the widget in case it is taller than the + default height. */ + if (widget->allocation.height > DEFAULT_HEIGHT) { + gint difference = widget->allocation.height - DEFAULT_HEIGHT; + + if (difference & 1) + difference += 1; + difference = difference / 2; + + event->y -= difference; + } + + + /* call the parent handler */ + if (GTK_WIDGET_CLASS(parent_class)->button_press_event) + result = + GTK_WIDGET_CLASS(parent_class)->button_press_event(widget, event); + + return result; +} + +/* + * Purpose of this function is to prevent Up and Down keys from + * changing the widget's value (like Left and Right). Instead they + * are used for changing focus to other widgtes. + */ +static gboolean +hildon_controlbar_change_value( GtkRange *range, + GtkScrollType scroll, + gdouble new_value, + gpointer data ) +{ + HildonControlbarPrivate *priv; + GtkAdjustment *adj = range->adjustment; + + priv = HILDON_CONTROLBAR_GET_PRIVATE(range); + + /* Emit a signal when upper or lower limit is reached */ + switch (scroll) + { + case GTK_SCROLL_STEP_FORWARD : + case GTK_SCROLL_PAGE_FORWARD : + if( adj->value == priv->old_value ) + if( adj->value == adj->upper ) + g_signal_emit( G_OBJECT(range), signals[END_REACHED], 0, TRUE ); + break; + + case GTK_SCROLL_STEP_BACKWARD : + case GTK_SCROLL_PAGE_BACKWARD : + if( adj->value == priv->old_value ) + if( adj->value == adj->lower ) + g_signal_emit( G_OBJECT(range), signals[END_REACHED], 0, FALSE ); + break; + + default: + break; + } +return FALSE; +} + +/* + * Event handler for button release + * Need to change button1 to button2 before passing this event to + * parent handler. (see specs) + * Also updates button_press variable so that we can draw hilites + * correctly + */ +static gint hildon_controlbar_button_release_event(GtkWidget * widget, + GdkEventButton * event) +{ + HildonControlbar *self; + HildonControlbarPrivate *priv; + gboolean result = FALSE; + + g_return_val_if_fail(widget, FALSE); + g_return_val_if_fail(event, FALSE); + + self = HILDON_CONTROLBAR(widget); + priv = HILDON_CONTROLBAR_GET_PRIVATE(self); + + priv->button_press = FALSE; + event->button = event->button == 1 ? 2 : event->button; + + /* call the parent handler */ + if (GTK_WIDGET_CLASS(parent_class)->button_release_event) + result = + GTK_WIDGET_CLASS(parent_class)->button_release_event(widget, event); + return result; +} + +/* + * Event handler for expose event + */ +static gint hildon_controlbar_expose_event(GtkWidget * widget, + GdkEventExpose * event) +{ + HildonControlbar *self = NULL; + + gboolean result = FALSE; + gint old_height = -1; + gint old_y = -1; + + g_return_val_if_fail(widget, FALSE); + g_return_val_if_fail(event, FALSE); + g_return_val_if_fail(HILDON_IS_CONTROLBAR(widget), FALSE); + + self = HILDON_CONTROLBAR(widget); + + old_height = widget->allocation.height; + old_y = widget->allocation.y; + + if (widget->allocation.height > DEFAULT_HEIGHT) { + int difference = widget->allocation.height - DEFAULT_HEIGHT; + + if (difference & 1) + difference += 1; + difference = difference / 2; + + widget->allocation.y += difference; + widget->allocation.height = DEFAULT_HEIGHT; + } + + /* call the parent handler */ + if (GTK_WIDGET_CLASS(parent_class)->expose_event) + result = GTK_WIDGET_CLASS(parent_class)->expose_event(widget, event); + hildon_controlbar_paint(self, &event->area); + + widget->allocation.height = old_height; + widget->allocation.y = old_y; + + return TRUE; +} + +/* + * Paint method. + * This is where all the work is actually done... + */ +static void hildon_controlbar_paint(HildonControlbar * self, + GdkRectangle * area) +{ + HildonControlbarPrivate *priv; + GtkWidget *widget = GTK_WIDGET(self); + GtkAdjustment *ctrlbar = GTK_RANGE(self)->adjustment; + gint x = widget->allocation.x; + gint y = widget->allocation.y; + gint h = widget->allocation.height; + gint w = widget->allocation.width; + gint max = 0; + gint stepper_size = 0; + gint stepper_spacing = 0; + gint inner_border_width = 0; + gint block_area = 0, block_width = 0, block_x = 0, block_max = 0, block_height,block_y; + /* Number of blocks on the controlbar */ + guint block_count = 0; + /* Number of displayed active blocks */ + guint block_act = 0; + /* Minimum no. of blocks visible */ + guint block_min = 0; + gint separatingpixels = 2; + gint block_remains = 0; + gint i, start_x, end_x, current_width; + GtkStateType state = GTK_STATE_NORMAL; + + g_return_if_fail(area); + + priv = HILDON_CONTROLBAR_GET_PRIVATE(self); + if (GTK_WIDGET_SENSITIVE(self) == FALSE) + state = GTK_STATE_INSENSITIVE; + + gtk_widget_style_get(GTK_WIDGET(self), + "stepper-size", &stepper_size, + "stepper-spacing", &stepper_spacing, + "inner_border_width", &inner_border_width, NULL); + g_object_get(G_OBJECT(self), "minimum_visible_bars", &block_min, NULL); + + block_area = (w - 2 * stepper_size - 2 * stepper_spacing - 2 * inner_border_width); + if (block_area <= 0) + return; + + block_max = ctrlbar->upper - ctrlbar->lower + block_min; + block_act = priv->old_value - GTK_RANGE(self)->adjustment->lower + block_min; + + /* We check border width and maximum value and adjust + * separating pixels for block width here. If the block size would + * become too small, we make the separators smaller. Graceful fallback. + */ + max = ctrlbar->upper; + if( ctrlbar->upper == 0 ) + { + separatingpixels = 3; + } + else if ((block_area - ((max - 1) * 3)) / max >= 4) { + separatingpixels = 3; + } else if ((block_area - ((max - 1) * 2)) / max >= 4) { + separatingpixels = 2; + } else if ((block_area - ((max - 1) * 1)) / max >= 4) { + separatingpixels = 1; + } else + separatingpixels = 0; + + if( block_max == 0 ) + { + /* If block max is 0 then we dim the whole control. */ + state = GTK_STATE_INSENSITIVE; + block_width = block_area; + block_remains = 0; + block_max = 1; + } + else + { + block_width = + (block_area - (separatingpixels * (block_max - 1))) / block_max; + block_remains = + (block_area - (separatingpixels * (block_max - 1))) % block_max; + } + + block_x = x + stepper_size + stepper_spacing + inner_border_width; + block_y = y + inner_border_width; + block_height = h - 2 * inner_border_width; + + block_count = ctrlbar->value - ctrlbar->lower + block_min; + + /* Without this there is vertical block corruption when block_height = + 1. This should work from 0 up to whatever */ + + if (block_height < 2) + block_height = 2; + + /* + * Changed the drawing of the blocks completely, + * because of "do-not-resize-when-changing-max"-specs. + * Now the code calculates from the block_remains when + * it should add one pixel to the block and when not. + */ + + for (i = 1; i <= block_max; i++) { + + /* Here we calculate whether we add one pixel to current_width or + not. */ + start_x = block_width * (i - 1) + ((i - 1) * block_remains) / block_max; + end_x = block_width * i + (i * block_remains) / block_max; + current_width = end_x - start_x; + + gtk_paint_box(widget->style, widget->window, state, + (i <= block_count) ? GTK_SHADOW_IN : GTK_SHADOW_OUT, + NULL, widget, "hildon_block", + block_x, block_y, current_width, + block_height); + + /* We keep the block_x separate because of the + 'separatingpixels' */ + block_x += current_width + separatingpixels; + } + +} diff --git a/src/hildon-controlbar.h b/src/hildon-controlbar.h new file mode 100644 index 0000000..65c41ee --- /dev/null +++ b/src/hildon-controlbar.h @@ -0,0 +1,71 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_CONTROLBAR_H__ +#define __HILDON_CONTROLBAR_H__ + +#include + +G_BEGIN_DECLS +#define HILDON_TYPE_CONTROLBAR ( hildon_controlbar_get_type() ) +#define HILDON_CONTROLBAR(obj) (GTK_CHECK_CAST (obj,\ + HILDON_TYPE_CONTROLBAR, HildonControlbar)) +#define HILDON_CONTROLBAR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass),\ + HILDON_TYPE_CONTROLBAR, HildonControlbarClass)) +#define HILDON_IS_CONTROLBAR(obj) \ + (GTK_CHECK_TYPE (obj, HILDON_TYPE_CONTROLBAR)) +#define HILDON_IS_CONTROLBAR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass),\ + HILDON_TYPE_CONTROLBAR)) + +/** + * HildonControlbar: + * + * Contains gboolean variable named 'button_press' whether a button + * has been pressed. + */ +typedef struct _HildonControlbar HildonControlbar; +typedef struct _HildonControlbarClass HildonControlbarClass; + +struct _HildonControlbar { + GtkScale scale; +}; + +struct _HildonControlbarClass { + GtkScaleClass parent_class; + void (*end_reached) (HildonControlbar *controlbar, gboolean end); +}; + +GType hildon_controlbar_get_type(void); +GtkWidget *hildon_controlbar_new(void); +void hildon_controlbar_set_value(HildonControlbar * self, gint value); +gint hildon_controlbar_get_value(HildonControlbar * self); +gint hildon_controlbar_get_max(HildonControlbar * self); +gint hildon_controlbar_get_min(HildonControlbar * self); +void hildon_controlbar_set_max(HildonControlbar * self, gint max); +void hildon_controlbar_set_min(HildonControlbar * self, gint min); +void hildon_controlbar_set_range(HildonControlbar * self, gint min, + gint max); + +G_END_DECLS +#endif /* __HILDON_CONTROLBAR_H__ */ diff --git a/src/hildon-date-editor.c b/src/hildon-date-editor.c new file mode 100644 index 0000000..ad9ed62 --- /dev/null +++ b/src/hildon-date-editor.c @@ -0,0 +1,1445 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-date-editor + * @short_description: A widget which queries a date from user or opens + * a HildonCalendarPopup + * @see_also: #HildonCalendarPopup, #HildonTimeEditor + * + * HildonDateEditor is a widget with three entry fields (day, month, + * year) and an icon (button): clicking on the icon opens up a + * HildonCalendarPopup. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "hildon-composite-widget.h" +#include "hildon-marshalers.h" +#include "hildon-libs-enum-types.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#define _(string) dgettext(PACKAGE, string) + +#define ENTRY_BORDERS 11 +#define DATE_EDITOR_HEIGHT 30 + +#define DAY_ENTRY_WIDTH 2 +#define MONTH_ENTRY_WIDTH 2 +#define YEAR_ENTRY_WIDTH 4 + +#define DEFAULT_MIN_YEAR 1970 +#define DEFAULT_MAX_YEAR 2037 + +#define HILDON_DATE_EDITOR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj),\ + HILDON_TYPE_DATE_EDITOR, HildonDateEditorPrivate)); + +static GtkContainerClass *parent_class; + +typedef struct _HildonDateEditorPrivate HildonDateEditorPrivate; + +static void +hildon_date_editor_class_init(HildonDateEditorClass * editor_class); + +static void hildon_date_editor_init(HildonDateEditor * editor); + +static gboolean +hildon_date_editor_icon_press(GtkWidget * widget, + gpointer data); + +static gboolean +hildon_date_editor_released(GtkWidget * widget, + gpointer data); + +static gboolean +hildon_date_editor_keypress(GtkWidget * widget, GdkEventKey * event, + gpointer data); + +static gboolean +hildon_date_editor_keyrelease(GtkWidget * widget, GdkEventKey * event, + gpointer data); +static gboolean +hildon_date_editor_clicked(GtkWidget * widget, gpointer data); +static gint +hildon_date_editor_entry_validate(GtkWidget *widget, gpointer data); + +static void +hildon_date_editor_entry_changed(GtkEditable *widget, gpointer data); + +static gboolean +hildon_date_editor_entry_focus_out(GtkWidget * widget, GdkEventFocus * event, + gpointer data); + +static gboolean hildon_date_editor_date_error(HildonDateEditor *editor, + HildonDateEditorErrorType type); + +static gboolean hildon_date_editor_entry_focusin(GtkWidget * widget, + GdkEventFocus * event, + gpointer data); +static void hildon_date_editor_get_property( GObject *object, guint param_id, + GValue *value, GParamSpec *pspec ); +static void hildon_date_editor_set_property (GObject *object, guint param_id, + const GValue *value, GParamSpec *pspec); +static void +hildon_child_forall(GtkContainer * container, + gboolean include_internals, + GtkCallback callback, gpointer callback_data); + +static void hildon_date_editor_destroy(GtkObject * self); + +static void +hildon_date_editor_size_allocate(GtkWidget * widget, + GtkAllocation * allocation); + +static void +hildon_date_editor_size_request(GtkWidget * widget, + GtkRequisition * requisition); + +static gboolean +_hildon_date_editor_entry_select_all(GtkWidget *widget); + +/* Property indices */ +enum +{ + PROP_DAY = 1, + PROP_MONTH, + PROP_YEAR, + PROP_MIN_YEAR, + PROP_MAX_YEAR +}; + +struct _HildonDateEditorPrivate { + /* Cache of values in the entries, used in setting only parts of the date */ + guint year; /* current year in the entry */ + guint month; /* current month in the entry */ + guint day; /* current day in the entry */ + + gboolean calendar_icon_pressed; + + GtkWidget *frame; /* borders around the date */ + GtkWidget *d_button_image; /* icon */ + GtkWidget *d_box_date; /* hbox for date */ + + GtkWidget *d_entry; /* GtkEntry for day */ + GtkWidget *m_entry; /* GtkEntry for month */ + GtkWidget *y_entry; /* GtkEntry for year */ + + GList *delims; /* List of delimeters between the fields (and possible at the ends) */ + GtkWidget *calendar_icon; + + gboolean skip_validation; /* don't validate date at all */ + + gint min_year; /* minimum year allowed */ + gint max_year; /* maximum year allowed */ +}; + +enum { + DATE_ERROR, + LAST_SIGNAL +}; + +static guint date_editor_signals[LAST_SIGNAL] = { 0 }; + +GType hildon_date_editor_get_type(void) +{ + static GType editor_type = 0; + + if (!editor_type) { + static const GTypeInfo editor_info = { + sizeof(HildonDateEditorClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_date_editor_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonDateEditor), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_date_editor_init, + }; + editor_type = g_type_register_static(GTK_TYPE_CONTAINER, + "HildonDateEditor", + &editor_info, 0); + } + return editor_type; +} + +static void +hildon_date_editor_class_init(HildonDateEditorClass * editor_class) +{ + GtkContainerClass *container_class = GTK_CONTAINER_CLASS(editor_class); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(editor_class); + GObjectClass *gobject_class = G_OBJECT_CLASS (editor_class); + + parent_class = g_type_class_peek_parent(editor_class); + + g_type_class_add_private(editor_class, + sizeof(HildonDateEditorPrivate)); + + gobject_class->set_property = hildon_date_editor_set_property; + gobject_class->get_property = hildon_date_editor_get_property; + widget_class->size_request = hildon_date_editor_size_request; + widget_class->size_allocate = hildon_date_editor_size_allocate; + widget_class->focus = hildon_composite_widget_focus; + + container_class->forall = hildon_child_forall; + GTK_OBJECT_CLASS(editor_class)->destroy = hildon_date_editor_destroy; + + editor_class->date_error = hildon_date_editor_date_error; + + date_editor_signals[DATE_ERROR] = + g_signal_new("date-error", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(HildonDateEditorClass, date_error), + g_signal_accumulator_true_handled, NULL, + _hildon_marshal_BOOLEAN__ENUM, + G_TYPE_BOOLEAN, 1, HILDON_TYPE_DATE_EDITOR_ERROR_TYPE); + + /** + * HildonDateEditor:year: + * + * Current year. + */ + g_object_class_install_property( gobject_class, PROP_YEAR, + g_param_spec_uint("year", + "Current year", + "Current year", + 1, 2100, + 2005, + G_PARAM_READABLE | G_PARAM_WRITABLE) ); + + /** + * HildonDateEditor:month: + * + * Current month. + */ + g_object_class_install_property( gobject_class, PROP_MONTH, + g_param_spec_uint("month", + "Current month", + "Current month", + 1, 12, + 1, + G_PARAM_READABLE | G_PARAM_WRITABLE) ); + + /** + * HildonDateEditor:day: + * + * Current day. + */ + g_object_class_install_property( gobject_class, PROP_DAY, + g_param_spec_uint("day", + "Current day", + "Current day", + 1, 31, + 1, + G_PARAM_READABLE | G_PARAM_WRITABLE) ); + + /** + * HildonDateEditor:min-year: + * + * Minimum valid year. + */ + g_object_class_install_property( gobject_class, PROP_MIN_YEAR, + g_param_spec_uint("min-year", + "Minimum valid year", + "Minimum valid year", + 1, 2100, + DEFAULT_MIN_YEAR, + G_PARAM_READWRITE) ); + + /** + * HildonDateEditor:max-year: + * + * Maximum valid year. + */ + g_object_class_install_property( gobject_class, PROP_MAX_YEAR, + g_param_spec_uint("max-year", + "Maximum valid year", + "Maximum valid year", + 1, 2100, + DEFAULT_MAX_YEAR, + G_PARAM_READWRITE) ); +} + +/* Forces setting of the icon to certain state. Used initially + and from the actual setter function */ +static void +real_set_calendar_icon_state(HildonDateEditorPrivate *priv, + gboolean pressed) +{ + gtk_image_set_from_icon_name(GTK_IMAGE(priv->calendar_icon), + pressed ? "qgn_widg_datedit_pr" : "qgn_widg_datedit", + HILDON_ICON_SIZE_WIDG); + + priv->calendar_icon_pressed = pressed; +} + +/* Sets the icon to given state (normal/pressed). Returns + info if the state actually changed. */ +static gboolean +hildon_date_editor_set_calendar_icon_state(HildonDateEditor *editor, + gboolean pressed) +{ + HildonDateEditorPrivate *priv; + + g_assert(HILDON_IS_DATE_EDITOR(editor)); + + priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); + if (pressed != priv->calendar_icon_pressed) { + real_set_calendar_icon_state(priv, pressed); + return TRUE; + } + + return FALSE; +} + +/* Packing day, month and year entries depend on locale settings + We find out the order and all separators by converting a known + date to default format and inspecting the result string */ +static void apply_locale_field_order(HildonDateEditorPrivate *priv) +{ + GDate locale_test_date; + GtkWidget *delim; + gchar buffer[256]; + gchar *iter, *delim_text; + + g_date_set_dmy(&locale_test_date, 1, 2, 1970); + (void) g_date_strftime(buffer, sizeof(buffer), "%x", &locale_test_date); + iter = buffer; + + while (*iter) + { + gchar *endp; + unsigned long value; + + /* Try to convert the current location into number. */ + value = strtoul(iter, &endp, 10); + + /* If the conversion didn't progress or the detected value was + unknown (we used a fixed date, you remember), we treat + current position as a literal */ + switch (value) + { + case 1: + gtk_box_pack_start(GTK_BOX(priv->d_box_date), + priv->d_entry, FALSE, FALSE, 0); + break; + case 2: + gtk_box_pack_start(GTK_BOX(priv->d_box_date), + priv->m_entry, FALSE, FALSE, 0); + break; + case 70: /* %x format uses only 2 numbers for some locales */ + case 1970: + gtk_box_pack_start(GTK_BOX(priv->d_box_date), + priv->y_entry, FALSE, FALSE, 0); + break; + default: + /* All non-number characters starting from current position + form the delimeter */ + for (endp = iter; *endp; endp++) + if (g_ascii_isdigit(*endp)) + break; + + /* Now endp points one place past the delimeter text */ + delim_text = g_strndup(iter, endp - iter); + delim = gtk_label_new(delim_text); + gtk_box_pack_start(GTK_BOX(priv->d_box_date), + delim, FALSE, FALSE, 0); + priv->delims = g_list_append(priv->delims, delim); + g_free(delim_text); + + break; + }; + + iter = endp; + } +} + +static void hildon_date_editor_init(HildonDateEditor * editor) +{ + HildonDateEditorPrivate *priv; + GDate cur_date; + + priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); + + GTK_WIDGET_SET_FLAGS(GTK_WIDGET(editor), GTK_NO_WINDOW); + + gtk_widget_push_composite_child(); + + /* initialize values */ + g_date_clear(&cur_date, 1); + g_date_set_time(&cur_date, time(NULL)); + + priv->day = g_date_get_day(&cur_date); + priv->month = g_date_get_month(&cur_date); + priv->year = g_date_get_year(&cur_date); + priv->min_year = DEFAULT_MIN_YEAR; + priv->max_year = DEFAULT_MAX_YEAR; + + /* make widgets */ + priv->frame = gtk_frame_new(NULL); + gtk_container_set_border_width(GTK_CONTAINER(priv->frame), 0); + + priv->d_entry = gtk_entry_new(); + priv->m_entry = gtk_entry_new(); + priv->y_entry = gtk_entry_new(); + + g_object_set (G_OBJECT(priv->d_entry), "input-mode", + HILDON_INPUT_MODE_HINT_NUMERIC, NULL); + g_object_set (G_OBJECT(priv->m_entry), "input-mode", + HILDON_INPUT_MODE_HINT_NUMERIC, NULL); + g_object_set (G_OBJECT(priv->y_entry), "input-mode", + HILDON_INPUT_MODE_HINT_NUMERIC, NULL); + + /* set entry look */ + gtk_entry_set_width_chars(GTK_ENTRY(priv->d_entry), DAY_ENTRY_WIDTH); + gtk_entry_set_width_chars(GTK_ENTRY(priv->m_entry), MONTH_ENTRY_WIDTH); + gtk_entry_set_width_chars(GTK_ENTRY(priv->y_entry), YEAR_ENTRY_WIDTH); + + gtk_entry_set_max_length(GTK_ENTRY(priv->d_entry), DAY_ENTRY_WIDTH); + gtk_entry_set_max_length(GTK_ENTRY(priv->m_entry), MONTH_ENTRY_WIDTH); + gtk_entry_set_max_length(GTK_ENTRY(priv->y_entry), YEAR_ENTRY_WIDTH); + + gtk_entry_set_has_frame(GTK_ENTRY(priv->d_entry), FALSE); + gtk_entry_set_has_frame(GTK_ENTRY(priv->m_entry), FALSE); + gtk_entry_set_has_frame(GTK_ENTRY(priv->y_entry), FALSE); + + gtk_widget_set_composite_name(priv->d_entry, "day_entry"); + gtk_widget_set_composite_name(priv->m_entry, "month_entry"); + gtk_widget_set_composite_name(priv->y_entry, "year_entry"); + + priv->d_box_date = gtk_hbox_new(FALSE, 0); + + priv->d_button_image = gtk_button_new(); + priv->calendar_icon = gtk_image_new(); + real_set_calendar_icon_state(priv, FALSE); + GTK_WIDGET_UNSET_FLAGS(priv->d_button_image, GTK_CAN_FOCUS | GTK_CAN_DEFAULT); + + apply_locale_field_order(priv); + + gtk_container_add(GTK_CONTAINER(priv->frame), priv->d_box_date); + gtk_container_add(GTK_CONTAINER(priv->d_button_image), priv->calendar_icon); + gtk_button_set_relief(GTK_BUTTON(priv->d_button_image), GTK_RELIEF_NONE); + gtk_button_set_focus_on_click(GTK_BUTTON(priv->d_button_image), FALSE); + + gtk_widget_set_parent(priv->frame, GTK_WIDGET(editor)); + gtk_widget_set_parent(priv->d_button_image, GTK_WIDGET(editor)); + gtk_widget_show_all(priv->frame); + gtk_widget_show_all(priv->d_button_image); + + /* image button signal connects */ + g_signal_connect(GTK_OBJECT(priv->d_button_image), "pressed", + G_CALLBACK(hildon_date_editor_icon_press), editor); + g_signal_connect(GTK_OBJECT(priv->d_button_image), "released", + G_CALLBACK(hildon_date_editor_released), editor); + g_signal_connect(GTK_OBJECT(priv->d_button_image), "clicked", + G_CALLBACK(hildon_date_editor_clicked), editor); + g_signal_connect(GTK_OBJECT(priv->d_button_image), "key_press_event", + G_CALLBACK(hildon_date_editor_keypress), editor); + + /* entry signal connects */ + g_signal_connect(GTK_OBJECT(priv->d_entry), "focus-in-event", + G_CALLBACK(hildon_date_editor_entry_focusin), editor); + + g_signal_connect(GTK_OBJECT(priv->m_entry), "focus-in-event", + G_CALLBACK(hildon_date_editor_entry_focusin), editor); + + g_signal_connect(GTK_OBJECT(priv->y_entry), "focus-in-event", + G_CALLBACK(hildon_date_editor_entry_focusin), editor); + + g_signal_connect(GTK_OBJECT(priv->d_entry), "focus-out-event", + G_CALLBACK(hildon_date_editor_entry_focus_out), editor); + + g_signal_connect(GTK_OBJECT(priv->m_entry), "focus-out-event", + G_CALLBACK(hildon_date_editor_entry_focus_out), editor); + + g_signal_connect(GTK_OBJECT(priv->y_entry), "focus-out-event", + G_CALLBACK(hildon_date_editor_entry_focus_out), editor); + + g_signal_connect(GTK_OBJECT(priv->d_entry), "key-press-event", + G_CALLBACK(hildon_date_editor_keypress), editor); + + g_signal_connect(GTK_OBJECT(priv->m_entry), "key-press-event", + G_CALLBACK(hildon_date_editor_keypress), editor); + + g_signal_connect(GTK_OBJECT(priv->y_entry), "key-press-event", + G_CALLBACK(hildon_date_editor_keypress), editor); + + g_signal_connect(GTK_OBJECT(priv->d_entry), "key-release-event", + G_CALLBACK(hildon_date_editor_keyrelease), editor); + + g_signal_connect(GTK_OBJECT(priv->m_entry), "key-release-event", + G_CALLBACK(hildon_date_editor_keyrelease), editor); + + g_signal_connect(GTK_OBJECT(priv->y_entry), "key-release-event", + G_CALLBACK(hildon_date_editor_keyrelease), editor); + + hildon_date_editor_set_date(editor, priv->year, priv->month, priv->day); + + g_signal_connect(GTK_OBJECT(priv->d_entry), "changed", + G_CALLBACK(hildon_date_editor_entry_changed), editor); + + g_signal_connect(GTK_OBJECT(priv->m_entry), "changed", + G_CALLBACK(hildon_date_editor_entry_changed), editor); + + g_signal_connect(GTK_OBJECT(priv->y_entry), "changed", + G_CALLBACK(hildon_date_editor_entry_changed), editor); + + gtk_widget_pop_composite_child(); +} + +static void hildon_date_editor_set_property (GObject *object, guint param_id, + const GValue *value, GParamSpec *pspec) +{ + HildonDateEditor *editor = HILDON_DATE_EDITOR(object); + HildonDateEditorPrivate *priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); + gint val; + + switch (param_id) + { + case PROP_YEAR: + hildon_date_editor_set_year (editor, g_value_get_uint(value)); + break; + + case PROP_MONTH: + hildon_date_editor_set_month (editor, g_value_get_uint(value)); + break; + + case PROP_DAY: + hildon_date_editor_set_day (editor, g_value_get_uint(value)); + break; + + case PROP_MIN_YEAR: + val = g_value_get_uint(value); + if (val <= priv->max_year) + { + priv->min_year = val; + /* Clamp current year */ + if (hildon_date_editor_get_year (editor) < priv->min_year) + hildon_date_editor_set_year (editor, priv->min_year); + } + else + g_warning("min-year cannot be greater than max-year"); + break; + + case PROP_MAX_YEAR: + val = g_value_get_uint(value); + if (val >= priv->min_year) + { + priv->max_year = val; + /* Clamp current year */ + if (hildon_date_editor_get_year (editor) > priv->max_year) + hildon_date_editor_set_year (editor, priv->max_year); + } + else + g_warning("max-year cannot be less than min-year"); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); + break; + } +} + +static void hildon_date_editor_get_property( GObject *object, guint param_id, + GValue *value, GParamSpec *pspec ) +{ + HildonDateEditor *editor = HILDON_DATE_EDITOR(object); + HildonDateEditorPrivate *priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); + + switch (param_id) + { + case PROP_YEAR: + g_value_set_uint (value, hildon_date_editor_get_year (editor)); + break; + + case PROP_MONTH: + g_value_set_uint (value, hildon_date_editor_get_month (editor)); + break; + + case PROP_DAY: + g_value_set_uint (value, hildon_date_editor_get_day (editor)); + break; + + case PROP_MIN_YEAR: + g_value_set_uint (value, priv->min_year); + break; + + case PROP_MAX_YEAR: + g_value_set_uint (value, priv->max_year); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); + break; + } +} + +static void hildon_child_forall(GtkContainer * container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) +{ + HildonDateEditor *editor; + HildonDateEditorPrivate *priv; + + g_assert(HILDON_IS_DATE_EDITOR(container)); + g_assert(callback); + + editor = HILDON_DATE_EDITOR(container); + priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); + + if (include_internals) { + (*callback) (priv->frame, callback_data); + (*callback) (priv->d_button_image, callback_data); + } +} + +static void hildon_date_editor_destroy(GtkObject * self) +{ + HildonDateEditorPrivate *priv; + + priv = HILDON_DATE_EDITOR_GET_PRIVATE(self); + + if (priv->frame) { + gtk_widget_unparent(priv->frame); + priv->frame = NULL; + } + if (priv->d_button_image) { + gtk_widget_unparent(priv->d_button_image); + priv->d_button_image = NULL; + } + if (priv->delims) { + g_list_free(priv->delims); + priv->delims = NULL; + } + + if (GTK_OBJECT_CLASS(parent_class)->destroy) + GTK_OBJECT_CLASS(parent_class)->destroy(self); +} + +/** + * hildon_date_editor_new: + * + * Creates a new date editor. The current system date + * is shown in the editor. + * + * Returns: pointer to a new @HildonDateEditor widget. + */ +GtkWidget *hildon_date_editor_new(void) +{ + return GTK_WIDGET(g_object_new(HILDON_TYPE_DATE_EDITOR, NULL)); +} + +/** + * hildon_date_editor_set_date: + * @date: the @HildonDateEditor widget + * @year: year + * @month: month + * @day: day + * + * Sets the date shown in the editor. + */ +void hildon_date_editor_set_date(HildonDateEditor * editor, + guint year, guint month, guint day) +{ + HildonDateEditorPrivate *priv; + + g_return_if_fail(HILDON_IS_DATE_EDITOR(editor)); + + /* This function cannot be implemented by calling + component setters, since applying the individual + values one by one can make the date temporarily + invalid (depending on what the previous values were), + which in turn causes that the desired date + is not set (even though it's valid). We must set all the + components at one go and not try to do any validation etc + there in between. */ + + g_return_if_fail(HILDON_IS_DATE_EDITOR(editor)); + priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); + + if (g_date_valid_dmy(day, month, year)) + { + GDate date; + gchar buffer[256]; + + priv->year = year; + priv->month = month; + priv->day = day; + + g_date_set_dmy(&date, day, month, year); + + /* We apply the new values, but do not want automatic focus move + etc to take place */ + g_snprintf(buffer, sizeof(buffer), "%04d", year); + g_signal_handlers_block_by_func(priv->y_entry, + (gpointer) hildon_date_editor_entry_changed, editor); + gtk_entry_set_text(GTK_ENTRY(priv->y_entry), buffer); + g_signal_handlers_unblock_by_func(priv->y_entry, + (gpointer) hildon_date_editor_entry_changed, editor); + + g_date_strftime(buffer, sizeof(buffer), "%m", &date); + g_signal_handlers_block_by_func(priv->m_entry, + (gpointer) hildon_date_editor_entry_changed, editor); + gtk_entry_set_text(GTK_ENTRY(priv->m_entry), buffer); + g_signal_handlers_unblock_by_func(priv->m_entry, + (gpointer) hildon_date_editor_entry_changed, editor); + + g_date_strftime(buffer, sizeof(buffer), "%d", &date); + g_signal_handlers_block_by_func(priv->d_entry, + (gpointer) hildon_date_editor_entry_changed, editor); + gtk_entry_set_text(GTK_ENTRY(priv->d_entry), buffer); + g_signal_handlers_unblock_by_func(priv->d_entry, + (gpointer) hildon_date_editor_entry_changed, editor); + + g_object_notify(G_OBJECT(editor), "year"); + g_object_notify(G_OBJECT(editor), "month"); + g_object_notify(G_OBJECT(editor), "day"); + } +} + +/** + * hildon_date_editor_get_date: + * @date: the @HildonDateEditor widget + * @year: year + * @month: month + * @day: day + * + * Returns: the year, month, and day currently on the + * date editor. + */ +void hildon_date_editor_get_date(HildonDateEditor * date, + guint * year, guint * month, guint * day) +{ + HildonDateEditorPrivate *priv; + + g_return_if_fail(HILDON_IS_DATE_EDITOR(date)); + g_return_if_fail(year); + g_return_if_fail(month); + g_return_if_fail(day); + + priv = HILDON_DATE_EDITOR_GET_PRIVATE(date); + + /* FIXME: The role of priv->{day,month,year} members vs. entry contents + is unclear. They do not neccesarily match and still the texts are + used as return values and members for some internal validation!! + At least a partly reason is to allow empty text to become + 0 return value, while members are restricted to valid ranges?! + However, if we change the current way, we are likely to break + some applications if they rely on some specific way how this + widget currently handles empty values and temporarily invalid values. + + The key issue is this: What should the _get methods return while + user is editing a field and the result is incomplete. The + partial result? The last good result? If we return partial result + we also need a way to inform if the date is not valid. Current + implementation is some kind of hybrid of these two... + + for example: + hildon_date_editor_set_day(editor, hildon_date_editor_get_day(editor)); + + easily fails, since set_day tries to force validity while get_day + doesn't do that. + + Proposal: Always return the same values that are shown in the + fields. We add a separate flag (Or use GDate) to + indicate if the current date is valid. This would allow + setters to make the date invalid as well. + */ + *year = /*priv->year;*/ + (guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->y_entry))); + *month = /*priv->month;*/ + (guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->m_entry))); + *day = /*priv->day;*/ + (guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->d_entry))); +} + +/* icon button press event */ +static gboolean hildon_date_editor_icon_press(GtkWidget * widget, + gpointer data) +{ + g_assert(GTK_IS_WIDGET(widget)); + g_assert(HILDON_IS_DATE_EDITOR(data)); + + hildon_date_editor_set_calendar_icon_state(HILDON_DATE_EDITOR(data), TRUE); + + return FALSE; +} + +static gboolean hildon_date_editor_entry_focusin(GtkWidget * widget, + GdkEventFocus * event, + gpointer data) +{ + g_idle_add((GSourceFunc) + _hildon_date_editor_entry_select_all, GTK_ENTRY(widget)); + + return FALSE; +} + + +static void popup_calendar_dialog(HildonDateEditor *ed) +{ + guint y = 0, m = 0, d = 0; + GtkWidget *popup; + GtkWidget *parent; + guint result; + GValue val = {0, }; + + hildon_date_editor_get_date(ed, &y, &m, &d); + + parent = gtk_widget_get_ancestor(GTK_WIDGET(ed), GTK_TYPE_WINDOW); + popup = hildon_calendar_popup_new(GTK_WINDOW(parent), y, m, d); + + g_value_init(&val, G_TYPE_INT); + /* Set max/min year in calendar popup to date editor values */ + g_object_get_property(G_OBJECT(ed), "min-year", &val); + g_object_set_property(G_OBJECT(popup), "min-year", &val); + g_object_get_property(G_OBJECT(ed), "max-year", &val); + g_object_set_property(G_OBJECT(popup), "max-year", &val); + + /* Pop up calendar */ + result = gtk_dialog_run(GTK_DIALOG(popup)); + switch (result) { + case GTK_RESPONSE_OK: + case GTK_RESPONSE_ACCEPT: + hildon_calendar_popup_get_date(HILDON_CALENDAR_POPUP(popup), &y, + &m, &d); + hildon_date_editor_set_date(ed, y, m, d); + } + + gtk_widget_destroy(popup); +} + +/* button released */ +static gboolean hildon_date_editor_released(GtkWidget * widget, + gpointer data) +{ + HildonDateEditor *ed; + + g_assert(GTK_IS_WIDGET(widget)); + g_assert(HILDON_IS_DATE_EDITOR(data)); + + ed = HILDON_DATE_EDITOR(data); + + /* restores the icon state. The clicked cycle raises the dialog */ + hildon_date_editor_set_calendar_icon_state(ed, FALSE); + + return FALSE; +} + +/* button released */ +static gboolean hildon_date_editor_clicked(GtkWidget * widget, + gpointer data) +{ + HildonDateEditor *ed; + + g_assert(GTK_IS_WIDGET(widget)); + g_assert(HILDON_IS_DATE_EDITOR(data)); + + ed = HILDON_DATE_EDITOR(data); + + /* restores the non-clicked button state and raises the dialog */ + hildon_date_editor_set_calendar_icon_state(ed, FALSE); + popup_calendar_dialog(ed); + + return FALSE; +} + +/* This is called whenever some editor filed loses the focus and + when the all of the fields are filled. + Earlier this was called whenever an entry changed */ +/* FIXME: Validation on focus_out is broken by concept */ +static gint +hildon_date_editor_entry_validate(GtkWidget *widget, gpointer data) +{ + HildonDateEditor *ed; + HildonDateEditorPrivate *priv; + gint d, m, y, max_days; + gboolean r; /* temp return values for signals */ + const gchar *text; + gint error_code = NO_ERROR; + + g_assert(HILDON_IS_DATE_EDITOR(data)); + g_assert(GTK_IS_ENTRY(widget)); + + ed = HILDON_DATE_EDITOR(data); + priv = HILDON_DATE_EDITOR_GET_PRIVATE(ed); + + if (priv->skip_validation) + return error_code; + + /*check if the calling entry is empty*/ + text = gtk_entry_get_text(GTK_ENTRY(widget)); + if(text == NULL || text[0] == 0) + { + if (widget == priv->d_entry) + g_signal_emit(ed, date_editor_signals[DATE_ERROR], 0, EMPTY_DAY, &r); + else if(widget == priv->m_entry) + g_signal_emit(ed, date_editor_signals[DATE_ERROR], 0, EMPTY_MONTH, &r); + else + g_signal_emit(ed, date_editor_signals[DATE_ERROR], 0, EMPTY_YEAR, &r); + + /* restore empty entry to safe value */ + hildon_date_editor_set_date (ed, priv->year, priv->month, priv->day); + return error_code; + } + + /* Ok, we now check validity. Some fields can be empty */ + text = gtk_entry_get_text(GTK_ENTRY(priv->d_entry)); + if (text == NULL || text[0] == 0) return error_code; + d = atoi(text); + text = gtk_entry_get_text(GTK_ENTRY(priv->m_entry)); + if (text == NULL || text[0] == 0) return error_code; + m = atoi(text); + text = gtk_entry_get_text(GTK_ENTRY(priv->y_entry)); + if (text == NULL || text[0] == 0) return error_code; + y = atoi(text); + + /* Did it actually change? */ + if (d != priv->day || m != priv->month || y != priv->year) + { + /* We could/should use hildon_date_editor_set_year and such functions + * to set the date, instead of use gtk_entry_set_text, and then change + * the priv member but hildon_date_editor_set_year and such functions + * check if the date is valid, we do want to do date validation check + * here according to spec */ + + /* Validate month */ + if(widget == priv->m_entry) { + if(m < 1) { + error_code = MIN_MONTH; + m = 1; + } + else if (m > 12) { + error_code = MAX_MONTH; + m = 12; + } + } + + /* Validate year */ + if(widget == priv->y_entry) { + if (y < priv->min_year) { + error_code = MIN_YEAR; + y = priv->min_year; + } + else if (y > priv->max_year) { + error_code = MAX_YEAR; + y = priv->max_year; + } + } + + /* Validate day. We have to do this in every case, since + changing month or year can make the day number to be invalid */ + max_days = g_date_get_days_in_month(m,y); + if(d < 1) { + error_code = MIN_DAY; + d = 1; + } + else if (d > max_days) { + if (d > 31) { + error_code = MAX_DAY; + d = max_days; + } + else { /* the date does not exist (is invalid) */ + error_code = INVALID_DATE; + /* check what was changed and restore previous value */ + if ( widget == priv->y_entry ) + y = priv->year; + else if ( widget == priv->m_entry ) + m = priv->month; + else + d = priv->day; + } + } + + if (error_code != NO_ERROR) + { + g_signal_emit(ed, date_editor_signals[DATE_ERROR], 0, error_code, &r); + + g_idle_add ((GSourceFunc) + _hildon_date_editor_entry_select_all, + widget); + } + } + + /* Fix and reformat the date after error signal is processed. + reformatting can be needed even in a such case that numerical + values of the date components are the same as earlier. */ + hildon_date_editor_set_date(ed, y, m, d); + return error_code; +} + +/* When entry becomes full, we move the focus to the next field. + If we are on the last field, the whole contents are validated. */ +static void +hildon_date_editor_entry_changed(GtkEditable *ed, gpointer data) +{ + GtkEntry *entry; + gint error_code; + HildonDateEditorPrivate *priv; + + g_assert(GTK_IS_ENTRY(ed)); + g_assert(HILDON_IS_DATE_EDITOR(data)); + + entry = GTK_ENTRY(ed); + + /* If day entry is full, move to next entry or validate */ + if (g_utf8_strlen(gtk_entry_get_text(entry), -1) == gtk_entry_get_max_length(entry)) + { + error_code = hildon_date_editor_entry_validate(GTK_WIDGET(entry), data); + if (error_code == NO_ERROR) + { + priv = HILDON_DATE_EDITOR_GET_PRIVATE(HILDON_DATE_EDITOR(data)); + priv->skip_validation = TRUE; + gtk_widget_child_focus(GTK_WIDGET(data), GTK_DIR_RIGHT); + } + } +} + +static gboolean hildon_date_editor_keyrelease(GtkWidget * widget, + GdkEventKey * event, + gpointer data) +{ + HildonDateEditor *ed; + HildonDateEditorPrivate *priv; + + g_return_val_if_fail(data, FALSE); + g_return_val_if_fail(widget, FALSE); + + ed = HILDON_DATE_EDITOR(data); + priv = HILDON_DATE_EDITOR_GET_PRIVATE(ed); + + if (event->keyval == GDK_KP_Enter || event->keyval == GDK_Return || + event->keyval == GDK_ISO_Enter) { + if (hildon_date_editor_set_calendar_icon_state(ed, FALSE)) + { + popup_calendar_dialog(ed); + return TRUE; + } + } else if (event->keyval == GDK_Escape) + priv->skip_validation = FALSE; + + return FALSE; +} + +/* keyboard handling */ +static gboolean hildon_date_editor_keypress(GtkWidget * widget, + GdkEventKey * event, + gpointer data) +{ + HildonDateEditor *ed; + HildonDateEditorPrivate *priv; + gint pos; + gboolean r; + + g_assert(HILDON_IS_DATE_EDITOR(data)); + g_assert(GTK_IS_ENTRY(widget)); + + ed = HILDON_DATE_EDITOR(data); + priv = HILDON_DATE_EDITOR_GET_PRIVATE(ed); + pos = gtk_editable_get_position(GTK_EDITABLE(widget)); + + /* Show error message in case the key pressed is not allowed + (only digits and control characters are allowed )*/ + if (!g_unichar_isdigit(event->keyval) && !(event->keyval & 0xF000)) { + g_signal_emit(ed, date_editor_signals[DATE_ERROR], 0, INVALID_CHAR, &r); + return TRUE; + } + + switch (event->keyval) { + case GDK_Left: + if (pos == 0) { + (void) gtk_widget_child_focus(GTK_WIDGET(data), GTK_DIR_LEFT); + return TRUE; + } + break; + case GDK_Right: + if (pos >= g_utf8_strlen(gtk_entry_get_text(GTK_ENTRY(widget)), -1)) { + (void) gtk_widget_child_focus(GTK_WIDGET(data), GTK_DIR_RIGHT); + return TRUE; + } + break; + case GDK_Return: + case GDK_ISO_Enter: + /* Ignore return value, since we want to handle event at all times. + otherwise vkb would popup when the keyrepeat starts. */ + (void) hildon_date_editor_set_calendar_icon_state(ed, TRUE); + return TRUE; + + case GDK_Escape: + priv->skip_validation = TRUE; + break; + default: + break; + } + + return FALSE; +} + +static gboolean hildon_date_editor_entry_focus_out(GtkWidget * widget, + GdkEventFocus * event, + gpointer data) +{ + HildonDateEditor *ed; + HildonDateEditorPrivate *priv; + + g_assert(HILDON_IS_DATE_EDITOR(data)); + + ed = HILDON_DATE_EDITOR(data); + priv = HILDON_DATE_EDITOR_GET_PRIVATE(ed); + + hildon_date_editor_entry_validate(widget, data); + priv->skip_validation = FALSE; + + return FALSE; +} + +static gboolean +hildon_date_editor_date_error(HildonDateEditor *editor, + HildonDateEditorErrorType type) +{ + HildonDateEditorPrivate *priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); + + switch(type) + { + case MAX_DAY: + gtk_infoprintf(NULL, _("ckct_ib_maximum_value"), 31); + break; + case MAX_MONTH: + gtk_infoprintf(NULL, _("ckct_ib_maximum_value"), 12); + break; + case MAX_YEAR: + gtk_infoprintf(NULL, _("ckct_ib_maximum_value"), priv->max_year); + break; + case MIN_DAY: + case MIN_MONTH: + gtk_infoprintf(NULL, _("ckct_ib_minimum_value"), 1); + break; + case MIN_YEAR: + gtk_infoprintf(NULL, _("ckct_ib_minimum_value"), priv->min_year); + break; + case EMPTY_DAY: + gtk_infoprintf(NULL, _("ckct_ib_set_a_value_within_range"), 1, 31); + break; + case EMPTY_MONTH: + gtk_infoprintf(NULL, _("ckct_ib_set_a_value_within_range"), 1, 12); + break; + case EMPTY_YEAR: + gtk_infoprintf(NULL, _("ckct_ib_set_a_value_within_range"), + priv->min_year, priv->max_year); + break; + case INVALID_CHAR: + gtk_infoprint(NULL, _("ckct_ib_illegal_character")); + break; + case INVALID_DATE: + gtk_infoprint(NULL, _("ckct_ib_date_does_not_exist")); + break; + default: + /*default error message ?*/ + break; + } + return TRUE; +} + +static void hildon_date_editor_size_request(GtkWidget * widget, + GtkRequisition * requisition) +{ + HildonDateEditor *ed; + HildonDateEditorPrivate *priv; + GtkRequisition f_req, img_req; + + g_assert(GTK_IS_WIDGET(widget)); + g_assert(requisition != NULL); + + ed = HILDON_DATE_EDITOR(widget); + priv = HILDON_DATE_EDITOR_GET_PRIVATE(ed); + + /* Our own children affect our size */ + gtk_widget_size_request(priv->frame, &f_req); + gtk_widget_size_request(priv->d_button_image, &img_req); + + /* calculate our size */ + requisition->width = f_req.width + img_req.width + HILDON_MARGIN_DEFAULT; + + /* FIXME: Fixed size is bad! We should use the maximum of our children, but + doing so would break current pixel specifications, since + the text entry by itself is already 30px tall + then frame takes + something */ + requisition->height = DATE_EDITOR_HEIGHT; +} + +static void hildon_date_editor_size_allocate(GtkWidget * widget, + GtkAllocation * allocation) +{ + HildonDateEditor *ed; + HildonDateEditorPrivate *priv; + GtkAllocation f_alloc, img_alloc; + GtkRequisition req; + GtkRequisition max_req; + GList *iter; + + g_assert(GTK_IS_WIDGET(widget)); + g_assert(allocation != NULL); + + ed = HILDON_DATE_EDITOR(widget); + priv = HILDON_DATE_EDITOR_GET_PRIVATE(ed); + + widget->allocation = *allocation; + + gtk_widget_get_child_requisition(widget, &max_req); + + /* Center vertically */ + f_alloc.y = img_alloc.y = allocation->y + + MAX(allocation->height - max_req.height, 0) / 2; + + /* Center horizontally */ + f_alloc.x = img_alloc.x = allocation->x + + MAX(allocation->width - max_req.width, 0) / 2; + + /* allocate frame */ + if (GTK_WIDGET_VISIBLE(priv->frame)) { + gtk_widget_get_child_requisition(priv->frame, &req); + + f_alloc.width = req.width; + f_alloc.height = max_req.height; + gtk_widget_size_allocate(priv->frame, &f_alloc); + } + + /* allocate icon */ + if (GTK_WIDGET_VISIBLE(priv->d_button_image)) { + gtk_widget_get_child_requisition(priv->d_button_image, + &req); + + img_alloc.x += f_alloc.width + HILDON_MARGIN_DEFAULT; + img_alloc.width = req.width; + img_alloc.height = max_req.height; + gtk_widget_size_allocate(priv->d_button_image, &img_alloc); + } + + /* FIXME: We really should not alloc delimeters by hand (since they + are not our own children, but we need to force to appear + higher. This ugly hack is needed to compensate the forced + height in size_request. */ + for (iter = priv->delims; iter; iter = iter->next) + { + GtkWidget *delim; + GtkAllocation alloc; + + delim = GTK_WIDGET(iter->data); + alloc = delim->allocation; + alloc.height = max_req.height; + alloc.y = priv->d_entry->allocation.y - 2; + + gtk_widget_size_allocate(delim, &alloc); + } +} + +/** + * hildon_date_editor_set_year: + * @editor: the @HildonDateEditor widget + * @year: year + * + * Sets the year shown in the editor. + * + * Returns: TRUE if the year is valid + */ +gboolean hildon_date_editor_set_year(HildonDateEditor *editor, guint year) +{ + HildonDateEditorPrivate *priv; + g_return_val_if_fail( HILDON_IS_DATE_EDITOR(editor), FALSE ); + priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); + + if (g_date_valid_dmy(priv->day, priv->month, year)) + { + gchar buffer[256]; + priv->year = year; + + g_snprintf(buffer, sizeof(buffer), "%04d", year); + + /* We apply the new day, but do not want automatic focus move + etc to take place */ + g_signal_handlers_block_by_func(priv->y_entry, + (gpointer) hildon_date_editor_entry_changed, editor); + gtk_entry_set_text(GTK_ENTRY(priv->y_entry), buffer); + g_signal_handlers_unblock_by_func(priv->y_entry, + (gpointer) hildon_date_editor_entry_changed, editor); + + g_object_notify(G_OBJECT(editor), "year"); + return TRUE; + } + + return FALSE; +} + +/** + * hildon_date_editor_set_month: + * @editor: the @HildonDateEditor widget + * @month: month + * + * Sets the month shown in the editor. + * + * Returns: TRUE if the month is valid + */ +gboolean hildon_date_editor_set_month(HildonDateEditor *editor, guint month) +{ + HildonDateEditorPrivate *priv; + g_return_val_if_fail( HILDON_IS_DATE_EDITOR(editor), FALSE ); + priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); + + if (g_date_valid_dmy(priv->day, month, priv->year)) + { + GDate date; + gchar buffer[256]; + + priv->month = month; + g_date_set_dmy(&date, priv->day, month, priv->year); + g_date_strftime(buffer, sizeof(buffer), "%m", &date); + + /* We apply the new day, but do not want automatic focus move + etc to take place */ + g_signal_handlers_block_by_func(priv->m_entry, + (gpointer) hildon_date_editor_entry_changed, editor); + gtk_entry_set_text(GTK_ENTRY(priv->m_entry), buffer); + g_signal_handlers_unblock_by_func(priv->m_entry, + (gpointer) hildon_date_editor_entry_changed, editor); + + g_object_notify(G_OBJECT(editor), "month"); + return TRUE; + } + return FALSE; +} + +/** + * hildon_date_editor_set_day: + * @editor: the @HildonDateEditor widget + * @day: day + * + * Sets the day shown in the editor. + * + * Returns: TRUE if the day is valid + */ +gboolean hildon_date_editor_set_day(HildonDateEditor *editor, guint day) +{ + HildonDateEditorPrivate *priv; + + g_return_val_if_fail( HILDON_IS_DATE_EDITOR(editor), FALSE ); + priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); + + if (g_date_valid_dmy(day, priv->month, priv->year)) + { + GDate date; + gchar buffer[256]; + + priv->day = day; + g_date_set_dmy(&date, day, priv->month, priv->year); + g_date_strftime(buffer, sizeof(buffer), "%d", &date); + + /* We apply the new day, but do not want automatic focus move + etc to take place */ + g_signal_handlers_block_by_func(priv->d_entry, + (gpointer) hildon_date_editor_entry_changed, editor); + gtk_entry_set_text(GTK_ENTRY(priv->d_entry), buffer); + g_signal_handlers_unblock_by_func(priv->d_entry, + (gpointer) hildon_date_editor_entry_changed, editor); + + g_object_notify(G_OBJECT(editor), "day"); + return TRUE; + } + return FALSE; +} + +/** + * hildon_date_editor_get_year: + * @editor: the @HildonDateEditor widget + * + * Returns: the current year shown in the editor. + */ +guint hildon_date_editor_get_year(HildonDateEditor *editor) +{ + HildonDateEditorPrivate *priv; + g_return_val_if_fail( HILDON_IS_DATE_EDITOR(editor), 0 ); + priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); + return (guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->y_entry))); +} + +/** + * hildon_date_editor_get_month: + * @editor: the @HildonDateEditor widget + * + * Gets the month shown in the editor. + * + * Returns: the current month shown in the editor. + */ + +guint hildon_date_editor_get_month(HildonDateEditor *editor) +{ + HildonDateEditorPrivate *priv; + g_return_val_if_fail( HILDON_IS_DATE_EDITOR(editor), 0 ); + priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); + return (guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->m_entry))); +} + +/** + * hildon_date_editor_get_day: + * @editor: the @HildonDateEditor widget + * + * Gets the day shown in the editor. + * + * Returns: the current day shown in the editor + */ + +guint hildon_date_editor_get_day(HildonDateEditor *editor) +{ + HildonDateEditorPrivate *priv; + g_return_val_if_fail( HILDON_IS_DATE_EDITOR(editor), 0 ); + priv = HILDON_DATE_EDITOR_GET_PRIVATE(editor); + return (guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->d_entry))); +} + +/* Idle callback */ +static gboolean +_hildon_date_editor_entry_select_all (GtkWidget *widget) +{ + GDK_THREADS_ENTER (); + gtk_editable_select_region(GTK_EDITABLE(widget), 0, -1); + GDK_THREADS_LEAVE (); + return FALSE; +} diff --git a/src/hildon-date-editor.h b/src/hildon-date-editor.h new file mode 100644 index 0000000..368cc33 --- /dev/null +++ b/src/hildon-date-editor.h @@ -0,0 +1,111 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_DATE_EDITOR_H__ +#define __HILDON_DATE_EDITOR_H__ + +#include + +G_BEGIN_DECLS +/** + * HILDON_TYPE_DATE_EDITOR: + * + * Macro for getting type of date editor. + * Since: 0.12.10 + */ +#define HILDON_TYPE_DATE_EDITOR ( hildon_date_editor_get_type() ) + + +/** + * HILDON_DATE_EDITOR_TYPE: + * + * Deprecated: use #HILDON_TYPE_DATE_EDITOR instead + */ +#define HILDON_DATE_EDITOR_TYPE HILDON_TYPE_DATE_EDITOR + +#define HILDON_DATE_EDITOR(obj) (GTK_CHECK_CAST (obj,\ + HILDON_TYPE_DATE_EDITOR, HildonDateEditor)) +#define HILDON_DATE_EDITOR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass),\ + HILDON_TYPE_DATE_EDITOR, HildonDateEditorClass)) +#define HILDON_IS_DATE_EDITOR(obj) (GTK_CHECK_TYPE (obj,\ + HILDON_TYPE_DATE_EDITOR)) +#define HILDON_IS_DATE_EDITOR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass),\ + HILDON_TYPE_DATE_EDITOR)) + +/** + * HildonDateEditor: + * + * Internal struct for date editor. + */ +typedef struct _HildonDateEditor HildonDateEditor; +typedef struct _HildonDateEditorClass HildonDateEditorClass; + +typedef enum +{ + NO_ERROR = -1, + MAX_DAY, + MAX_MONTH, + MAX_YEAR, + MIN_DAY, + MIN_MONTH, + MIN_YEAR, + EMPTY_DAY, + EMPTY_MONTH, + EMPTY_YEAR, + INVALID_DATE, + INVALID_CHAR + +}HildonDateEditorErrorType; + +struct _HildonDateEditor { + GtkContainer par; +}; + +struct _HildonDateEditorClass { + GtkContainerClass parent_class; + + gboolean (*date_error) (HildonDateEditor *editor, + HildonDateEditorErrorType type); +}; + +GType hildon_date_editor_get_type(void) G_GNUC_CONST; + +GtkWidget *hildon_date_editor_new(void); + +void hildon_date_editor_set_date(HildonDateEditor * date, + guint year, guint month, guint day); + +void hildon_date_editor_get_date(HildonDateEditor * date, + guint * year, guint * month, guint * day); + +gboolean hildon_date_editor_set_year(HildonDateEditor *editor, guint year); +gboolean hildon_date_editor_set_month(HildonDateEditor *editor, guint month); +gboolean hildon_date_editor_set_day(HildonDateEditor *editor, guint day); + +guint hildon_date_editor_get_year(HildonDateEditor *editor); +guint hildon_date_editor_get_month(HildonDateEditor *editor); +guint hildon_date_editor_get_day(HildonDateEditor *editor); + +G_END_DECLS +#endif /* __HILDON_DATE_EDITOR_H__ */ diff --git a/src/hildon-defines.c b/src/hildon-defines.c new file mode 100644 index 0000000..18a239f --- /dev/null +++ b/src/hildon-defines.c @@ -0,0 +1,268 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-defines + * @short_description: Not a widget, just a helper + * + */ + +#include +#include "hildon-defines.h" + +const HildonIconSizes *hildoniconsizes = NULL; +static HildonIconSizes iis; /* hildon internal icon sizes */ + +/** + * hildon_icon_sizes_init: + * + * Initializes the icon sizes. This is automatically + * called when the icon sizes have not been initialized + * and one is requested. + **/ +void hildon_icon_sizes_init (void) +{ + if (hildoniconsizes != NULL) + return; + + hildoniconsizes = &iis; + + iis.icon_size_list = gtk_icon_size_register ("hildon_icon_size_list", 64, 64); + iis.icon_size_small = gtk_icon_size_register ("*icon_size_small", 26, 26); + iis.icon_size_toolbar = gtk_icon_size_register ("icon_size_toolbar", 26, 26); + iis.icon_size_widg = gtk_icon_size_register ("icon_size_widg", 26, 26); + iis.icon_size_widg_wizard = gtk_icon_size_register ("icon_size_widg_wizard", 50, 50); + iis.icon_size_grid = gtk_icon_size_register ("icon_size_grid", 64, 64); + iis.icon_size_big_note = gtk_icon_size_register ("icon_size_big_note", 50, 50); + iis.icon_size_note = gtk_icon_size_register ("icon_size_note", 26, 26); + iis.icon_size_statusbar = gtk_icon_size_register ("icon_size_statusbar", 40, 40); + iis.icon_size_indi_video_player_pre_roll = gtk_icon_size_register ("icon_size_indi_video_player_pre_roll", 64, 64); + iis.icon_size_indi_key_pad_lock = gtk_icon_size_register ("icon_size_indi_key_pad_lock", 50, 50); + iis.icon_size_indi_copy = gtk_icon_size_register ("icon_size_indi_copy", 64, 64); + iis.icon_size_indi_delete = gtk_icon_size_register ("icon_size_indi_delete", 64, 64); + iis.icon_size_indi_process = gtk_icon_size_register ("icon_size_indi_process", 64, 64); + iis.icon_size_indi_progressball = gtk_icon_size_register ("icon_size_indi_progressball", 64, 64); + iis.icon_size_indi_send = gtk_icon_size_register ("icon_size_indi_send", 64, 64); + iis.icon_size_indi_offmode_charging = gtk_icon_size_register ("icon_size_indi_offmode_charging", 50, 50); + iis.icon_size_indi_tap_and_hold = gtk_icon_size_register ("icon_size_indi_tap_and_hold", 34, 34); + iis.icon_size_indi_send_receive = gtk_icon_size_register ("icon_size_indi_send_receive", 64, 64); + iis.icon_size_indi_wlan_strength = gtk_icon_size_register ("icon_size_indi_wlan_strength", 64, 64); + + iis.image_size_indi_nokia_logo = gtk_icon_size_register ("image_size_indi_nokia_logo", 64, 64); + iis.image_size_indi_startup_failed = gtk_icon_size_register ("image_size_indi_startup_failed", 64, 64); + iis.image_size_indi_startup_nokia_logo = gtk_icon_size_register ("image_size_indi_startup_nokia_logo", 64, 64); + iis.image_size_indi_nokia_hands = gtk_icon_size_register ("image_size_indi_nokia_hands", 64, 64); +} + +typedef struct _HildonLogicalData HildonLogicalData; + +struct _HildonLogicalData +{ + GtkRcFlags rcflags; + GtkStateType state; + gchar *logicalcolorstring; + gchar *logicalfontstring; +}; + + +static void hildon_change_style_recursive_from_ld (GtkWidget *widget, GtkStyle *prev_style, HildonLogicalData *ld) +{ + /* Change the style for child widgets */ + if (GTK_IS_CONTAINER (widget)) { + GSList *iterator = gtk_container_get_children (GTK_CONTAINER (widget)); + for (iterator; iterator; iterator = g_list_next (iterator)) + hildon_change_style_recursive_from_ld (iterator->data, prev_style, ld); + } + + /* gtk_widget_modify_*() emit "style_set" signals, so if we got here from + "style_set" signal, we need to block this function from being called + again or we get into inifinite loop. + + FIXME: Compiling with gcc > 3.3 and -pedantic won't allow + conversion between function and object pointers. GLib API however + requires an object pointer for a function, so we have to work + around this. + See http://bugzilla.gnome.org/show_bug.cgi?id=310175 + */ + G_GNUC_EXTENSION + g_signal_handlers_block_matched (G_OBJECT (widget), G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC, + g_signal_lookup ("style_set", G_TYPE_FROM_INSTANCE (widget)), + 0, NULL, + (gpointer) hildon_change_style_recursive_from_ld, + NULL); + + if (ld->logicalcolorstring != NULL) + { + /* Changing logical color */ + GdkColor color; + gtk_widget_ensure_style (widget); + if (gtk_style_lookup_logical_color (widget->style, ld->logicalcolorstring, &color) == TRUE) + switch (ld->rcflags) + { + case GTK_RC_FG: + gtk_widget_modify_fg (widget, ld->state, &color); + break; + case GTK_RC_BG: + gtk_widget_modify_bg (widget, ld->state, &color); + break; + case GTK_RC_TEXT: + gtk_widget_modify_text (widget, ld->state, &color); + break; + case GTK_RC_BASE: + gtk_widget_modify_base (widget, ld->state, &color); + break; + } else + { + g_warning ("Failed to lookup '%s' color!", ld->logicalcolorstring); + } + } + + if (ld->logicalfontstring != NULL) + { + /* Changing logical font */ + GtkStyle *fontstyle = gtk_rc_get_style_by_paths (gtk_settings_get_default (), ld->logicalfontstring, NULL, G_TYPE_NONE); + if (fontstyle != NULL) + { + PangoFontDescription *fontdesc = fontstyle->font_desc; + + if (fontdesc != NULL) + gtk_widget_modify_font (widget, fontdesc); + } + } + + + /* FIXME: Compilation workaround for gcc > 3.3 + -pedantic again */ + G_GNUC_EXTENSION + g_signal_handlers_unblock_matched (G_OBJECT (widget), G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC, + g_signal_lookup ("style_set", G_TYPE_FROM_INSTANCE (widget)), + 0, NULL, + (gpointer) hildon_change_style_recursive_from_ld, + NULL); +} + +static void hildon_logical_data_free (HildonLogicalData *ld) +{ + g_return_if_fail (ld != NULL); + + if (ld->logicalcolorstring) + g_free(ld->logicalcolorstring); + + if (ld->logicalfontstring) + g_free(ld->logicalfontstring); + + g_free(ld); +} + +/** + * hildon_gtk_widget_set_logical_font: + * @widget : A @GtkWidget to assign this logical font for. + * @logicalfontname : A gchar* with the logical font name to assign to the widget with an "osso-" -prefix. + * + * This function assigns a defined logical font to the @widget and all its child widgets. + * It also connects to the "style_set" signal which will retrieve & assign the new font for the given logical name each time the theme is changed. + * The returned signal id can be used to disconnect the signal. + * The previous signal (obtained by calling this function) is disconnected automatically and should not be used. + * + * Return value : The signal id that is triggered every time theme is changed. 0 if font set failed. + **/ +gulong hildon_gtk_widget_set_logical_font (GtkWidget *widget, const gchar *logicalfontname) +{ + HildonLogicalData *ld; + gulong signum = 0; + + g_return_val_if_fail (GTK_IS_WIDGET (widget), 0); + g_return_val_if_fail (logicalfontname != NULL, 0); + + ld = g_malloc (sizeof (HildonLogicalData)); + + ld->rcflags = 0; + ld->state = 0; + ld->logicalcolorstring = NULL; + ld->logicalfontstring = g_strdup(logicalfontname); + + /* Disconnects the previously connected signals. That calls the closure notify + * and effectively disposes the allocated data (hildon_logical_data_free) */ + g_signal_handlers_disconnect_matched (G_OBJECT (widget), G_SIGNAL_MATCH_FUNC, + 0, NULL, NULL, + G_CALLBACK (hildon_change_style_recursive_from_ld), NULL); + + /* Change the font now */ + hildon_change_style_recursive_from_ld (widget, NULL, ld); + + /* Connect to "style_set" so that the font gets changed whenever theme changes. */ + signum = g_signal_connect_data (G_OBJECT (widget), "style_set", + G_CALLBACK (hildon_change_style_recursive_from_ld), + ld, (GClosureNotify) hildon_logical_data_free, 0); + + return signum; +} + +/** + * hildon_gtk_widget_set_logical_color: + * @widget : A @GtkWidget to assign this logical font for. + * @rcflags : @GtkRcFlags enumeration defining whether to assign to FG, BG, TEXT or BASE style. + * @state : @GtkStateType indicating to which state to assign the logical color + * @logicalcolorname : A gchar* with the logical font name to assign to the widget. + * + * This function assigns a defined logical color to the @widget and all it's child widgets. + * It also connects to the "style_set" signal which will retrieve & assign the new color for the given logical name each time the theme is changed. + * The returned signal id can be used to disconnect the signal. + * The previous signal (obtained by calling this function) is disconnected automatically and should not be used. + * + * Example : If the style you want to modify is bg[NORMAL] then set rcflags to GTK_RC_BG and state to GTK_STATE_NORMAL. + * + * Return value : The signal id that is triggered every time theme is changed. 0 if color set failed. + **/ +gulong hildon_gtk_widget_set_logical_color (GtkWidget *widget, GtkRcFlags rcflags, + GtkStateType state, const gchar *logicalcolorname) +{ + HildonLogicalData *ld; + gulong signum = 0; + + g_return_val_if_fail (GTK_IS_WIDGET (widget), 0); + g_return_val_if_fail (logicalcolorname != NULL, 0); + + ld = g_malloc (sizeof (HildonLogicalData)); + + ld->rcflags = rcflags; + ld->state = state; + ld->logicalcolorstring = g_strdup(logicalcolorname); + ld->logicalfontstring = NULL; + + /* Disconnects the previously connected signals. That calls the closure notify + * and effectively disposes the allocated data (hildon_logical_data_free) */ + g_signal_handlers_disconnect_matched (G_OBJECT (widget), G_SIGNAL_MATCH_FUNC, + 0, NULL, NULL, + G_CALLBACK (hildon_change_style_recursive_from_ld), NULL); + + /* Change the colors now */ + hildon_change_style_recursive_from_ld (widget, NULL, ld); + + /* Connect to "style_set" so that the colors gets changed whenever theme */ + signum = g_signal_connect_data (G_OBJECT (widget), "style_set", + G_CALLBACK (hildon_change_style_recursive_from_ld), + ld, (GClosureNotify) hildon_logical_data_free, 0); + + return signum; +} diff --git a/src/hildon-defines.h b/src/hildon-defines.h new file mode 100644 index 0000000..963ca8c --- /dev/null +++ b/src/hildon-defines.h @@ -0,0 +1,143 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_DEFINES_H__ +#define __HILDON_DEFINES_H__ + +#include +#include +#include "hildon-appview.h" + +G_BEGIN_DECLS + +void hildon_icon_sizes_init (void); + +typedef struct _HildonIconSizes HildonIconSizes; + +struct _HildonIconSizes +{ + GtkIconSize icon_size_list; + GtkIconSize icon_size_small; + GtkIconSize icon_size_toolbar; + GtkIconSize icon_size_widg; + GtkIconSize icon_size_widg_wizard; + GtkIconSize icon_size_grid; + GtkIconSize icon_size_big_note; + GtkIconSize icon_size_note; + GtkIconSize icon_size_statusbar; + GtkIconSize icon_size_indi_video_player_pre_roll; + GtkIconSize icon_size_indi_key_pad_lock; + GtkIconSize icon_size_indi_copy; + GtkIconSize icon_size_indi_delete; + GtkIconSize icon_size_indi_process; + GtkIconSize icon_size_indi_progressball; + GtkIconSize icon_size_indi_send; + GtkIconSize icon_size_indi_offmode_charging; + GtkIconSize icon_size_indi_tap_and_hold; + GtkIconSize icon_size_indi_send_receive; + GtkIconSize icon_size_indi_wlan_strength; + GtkIconSize image_size_indi_nokia_logo; + GtkIconSize image_size_indi_startup_failed; + GtkIconSize image_size_indi_startup_nokia_logo; + GtkIconSize image_size_indi_nokia_hands; +}; + +extern const HildonIconSizes *hildoniconsizes; + +#define HILDON_ICON_SIZE_CHECK_AND_GET(iconvar) (!hildoniconsizes ? hildon_icon_sizes_init (), hildoniconsizes->iconvar : hildoniconsizes->iconvar) + +#define HILDON_ICON_SIZE_LIST HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_list) +#define HILDON_ICON_SIZE_SMALL HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_small) +#define HILDON_ICON_SIZE_TOOLBAR HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_toolbar) +#define HILDON_ICON_SIZE_WIDG HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_widg) +#define HILDON_ICON_SIZE_WIDG_WIZARD HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_widg_wizard) +#define HILDON_ICON_SIZE_GRID HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_grid) +#define HILDON_ICON_SIZE_BIG_NOTE HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_big_note) +#define HILDON_ICON_SIZE_NOTE HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_note) +#define HILDON_ICON_SIZE_STATUSBAR HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_statusbar) +#define HILDON_ICON_SIZE_INDI_VIDEO_PLAYER_PRE_ROLL HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_indi_video_player_pre_roll) +#define HILDON_ICON_SIZE_INDI_COPY HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_indi_copy) +#define HILDON_ICON_SIZE_INDI_DELETE HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_indi_delete) +#define HILDON_ICON_SIZE_INDI_PROCESS HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_indi_process) +#define HILDON_ICON_SIZE_INDI_PROGRESSBALL HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_indi_progressball) +#define HILDON_ICON_SIZE_INDI_SEND HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_indi_send) +#define HILDON_ICON_SIZE_INDI_OFFMODE_CHARGING HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_indi_offmode) +#define HILDON_ICON_SIZE_INDI_TAP_AND_HOLD HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_tap_and_hold) +#define HILDON_ICON_SIZE_INDI_SEND_RECEIVE HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_indi_send_receive) +#define HILDON_ICON_SIZE_INDI_WLAN_STRENGTH HILDON_ICON_SIZE_CHECK_AND_GET(icon_size_indi_wlan_strength) + +#define HILDON_IMAGE_SIZE_INDI_NOKIA_LOGO HILDON_ICON_SIZE_CHECK_AND_GET(image_size_indi_nokia_logo) +#define HILDON_IMAGE_SIZE_INDI_STARTUP_FAILED HILDON_ICON_SIZE_CHECK_AND_GET(image_size_indi_startup_nokia_failed) +#define HILDON_IMAGE_SIZE_INDI_STARTUP_NOKIA_LOGO HILDON_ICON_SIZE_CHECK_AND_GET(image_size_indi_startup_nokia_logo) +#define HILDON_IMAGE_SIZE_INDI_NOKIA_HAND HILDON_ICON_SIZE_CHECK_AND_GET(image_size_indi_nokia_hands) + +#define HILDON_ICON_PIXEL_SIZE_LIST 64 +#define HILDON_ICON_PIXEL_SIZE_SMALL 26 +#define HILDON_ICON_PIXEL_SIZE_TOOLBAR 26 +#define HILDON_ICON_PIXEL_SIZE_WIDG 26 +#define HILDON_ICON_PIXEL_SIZE_WIDG_WIZARD 50 +#define HILDON_ICON_PIXEL_SIZE_GRID 64 +#define HILDON_ICON_PIXEL_SIZE_BIG_NOTE 50 +#define HILDON_ICON_PIXEL_SIZE_NOTE 26 +#define HILDON_ICON_PIXEL_SIZE_STATUSBAR 40 +#define HILDON_ICON_PIXEL_SIZE_INDI_VIDEO_PLAYER_PRE_ROLL 64 +#define HILDON_ICON_PIXEL_SIZE_INDI_KEY_PAD_LOCK 50 +#define HILDON_ICON_PIXEL_SIZE_INDI_COPY 64 +#define HILDON_ICON_PIXEL_SIZE_INDI_DELETE 64 +#define HILDON_ICON_PIXEL_SIZE_INDI_PROCESS 64 +#define HILDON_ICON_PIXEL_SIZE_INDI_PROGRESSBALL 64 +#define HILDON_ICON_PIXEL_SIZE_INDI_SEND 64 +#define HILDON_ICON_PIXEL_SIZE_INDI_OFFMODE_CHARGING 50 +#define HILDON_ICON_PIXEL_SIZE_INDI_TAP_AND_HOLD 34 +#define HILDON_ICON_PIXEL_SIZE_INDI_SEND_RECEIVE 64 +#define HILDON_ICON_PIXEL_SIZE_INDI_WLAN_STRENGTH 64 + +#define HILDON_IMAGE_PIXEL_SIZE_INDI_NOKIA_LOGO 64 +#define HILDON_IMAGE_PIXEL_SIZE_INDI_STARTUP_FAILED 64 +#define HILDON_IMAGE_PIXEL_SIZE_INDI_STARTUP_NOKIA_LOGO 64 +#define HILDON_IMAGE_PIXEL_SIZE_INDI_NOKIA_HANDS 64 + +#define HILDON_MARGIN_HALF 3 +#define HILDON_MARGIN_DEFAULT 6 +#define HILDON_MARGIN_DOUBLE 12 +#define HILDON_MARGIN_TRIPLE 18 + +#define HILDON_HARDKEY_UP GDK_Up +#define HILDON_HARDKEY_LEFT GDK_Left +#define HILDON_HARDKEY_RIGHT GDK_Right +#define HILDON_HARDKEY_DOWN GDK_Down +#define HILDON_HARDKEY_SELECT GDK_Return +#define HILDON_HARDKEY_MENU GDK_F4 +#define HILDON_HARDKEY_HOME GDK_F5 +#define HILDON_HARDKEY_ESC GDK_Escape +#define HILDON_HARDKEY_FULLSCREEN GDK_F6 +#define HILDON_HARDKEY_INCREASE GDK_F7 +#define HILDON_HARDKEY_DECREASE GDK_F8 + +gulong hildon_gtk_widget_set_logical_font (GtkWidget *widget, const gchar *logicalfontname); +gulong hildon_gtk_widget_set_logical_color (GtkWidget *widget, GtkRcFlags rcflags, + GtkStateType state, const gchar *logicalcolorname); + +G_END_DECLS +#endif /* HILDON_DEFINES_H */ diff --git a/src/hildon-dialoghelp.c b/src/hildon-dialoghelp.c new file mode 100644 index 0000000..82f828f --- /dev/null +++ b/src/hildon-dialoghelp.c @@ -0,0 +1,190 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-dialoghelp + * @short_description: A helper which contains a button in a normal dialog to + * open a help if required + * + * #HildonDialoghelp is a helper that provides an API for enabling or + * disabling a help button in the titlebar area of normal dialogs that + * are derived from GtkDialog. + */ + +#include +#include +#include "hildon-dialoghelp.h" + +static guint help_signal = 0; + +static GdkFilterReturn +handle_xevent(GdkXEvent * xevent, GdkEvent * event, gpointer dialog) +{ + XAnyEvent *eventti = xevent; + + if (eventti->type == ClientMessage) { + Atom help_atom, wm_atom; + Display *disp; + XClientMessageEvent *cm; + + disp = GDK_DISPLAY(); + cm = xevent; + + help_atom = XInternAtom(disp, "_NET_WM_CONTEXT_HELP", True); + wm_atom = XInternAtom(disp, "WM_PROTOCOLS", True); + + if (cm->message_type == wm_atom && cm->data.l[0] == help_atom) { + /* XClientMessageEvent *cm = xevent; */ + g_signal_emit(G_OBJECT(dialog), help_signal, 0); + } + + return GDK_FILTER_REMOVE; /* Event handled, don't process + further */ + } + + return GDK_FILTER_CONTINUE; /* Event not handled */ +} + +/** + * gtk_dialog_help_enable: + * @dialog: The dialog for which help is to be enabled. + * + * Enables context help button for a given dialog. The signal "help" can be + * connected to handler by normal GTK methods. Note that this function + * has to be called before the dialog is shown. + * + * The "help" signal itself has no other parameters than the dialog where + * it is connected to, ie.: + * void user_function(GtkDialog *dialog, gpointer user_data); + */ +void gtk_dialog_help_enable(GtkDialog * dialog) +{ + GdkWindow *window; + GdkDisplay *display; + Atom *protocols; + Atom *list; + Atom helpatom; + int amount = 0; + int n = 0; + int i = 0; + int help_enabled = 0; + + /* Create help signal if it didn't exist */ + if (help_signal == 0) { + help_signal = g_signal_new("help", GTK_TYPE_DIALOG, + G_SIGNAL_ACTION, (guint) - 1, NULL, + NULL, g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + } + + g_return_if_fail(GTK_IS_DIALOG(dialog)); + + gtk_widget_realize(GTK_WIDGET(dialog)); + window = GTK_WIDGET(dialog)->window; + display = gdk_drawable_get_display (window); + + /* Create a list of atoms stored in GdkWindow */ + XGetWMProtocols(GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), + &list, &amount); + + protocols = (Atom *) malloc ((amount+1) * sizeof (Atom)); + helpatom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_CONTEXT_HELP"); + + /* Enable the dialoghelp if help_atom is in the atoms' list */ + for (i=0; iwindow; + display = gdk_drawable_get_display (window); + + /* Create a list of atoms stored in GdkWindow */ + XGetWMProtocols(GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), + &list, &amount); + + helpatom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_CONTEXT_HELP"); + protocols = (Atom *) malloc (amount * sizeof (Atom)); + + /* Remove the help_atom if it is in the atoms' list */ + for (i=0; i + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_DIALOG_HELP_H__ +#define __HILDON_DIALOG_HELP_H__ + +#include + +G_BEGIN_DECLS + +void gtk_dialog_help_enable (GtkDialog * dialog); +void gtk_dialog_help_disable (GtkDialog * dialog); + +G_END_DECLS + +#endif /* __HILDON_DIALOG_HELP_H__ */ diff --git a/src/hildon-file-handling-note.c b/src/hildon-file-handling-note.c new file mode 100644 index 0000000..4b54c01 --- /dev/null +++ b/src/hildon-file-handling-note.c @@ -0,0 +1,379 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-file-handling-note + * @short_description: Displaying the notification when a move + * operation is in progress. + * @see_also: #HildonFileHandlingNote + * + * This is the notification displayed when a move operation is in + * progress. The notification uses a progress bar to indicate the + * progress of the operation. For operation containing multiple items, a + * separe progress bar is shown for each item. The notification has a + * single button, which allows users to stop the move operation. + */ + +#include "hildon-note.h" +#include "hildon-file-handling-note.h" +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +/* Note types */ +#define MOVING_TYPE 0 +#define DELETING_TYPE 1 +#define OPENING_TYPE 2 +#define SAVING_TYPE 3 + +/*#define _(String) dgettext(PACKAGE, String)*/ +#define _(String) dgettext("hildon-fm", String) /* FIXME: this file should be moved to hildon-fm */ + +#define HILDON_FILE_HANDLING_NOTE_GET_PRIVATE(obj)\ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_FILE_HANDLING_NOTE, HildonFileHandlingNotePrivate)); + +typedef struct _HildonFileHandlingNotePrivate + HildonFileHandlingNotePrivate; + +struct _HildonFileHandlingNotePrivate { + guint note_type; +}; + + +static HildonNote *parent_class; + + +/* standard forbids empty source file, therefore the ifdef must be + placed here. */ + +static void +hildon_file_handling_note_class_init(HildonFileHandlingNoteClass * class); + +static void hildon_file_handling_note_init(HildonFileHandlingNote * + dialog); + +static void hildon_file_handling_note_finalize(GObject * obj_self); + + + + +GType hildon_file_handling_note_get_type() +{ + static GType dialog_type = 0; + + if (!dialog_type) { + static const GTypeInfo dialog_info = { + sizeof(HildonFileHandlingNoteClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_file_handling_note_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonFileHandlingNote), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_file_handling_note_init + }; + + dialog_type = g_type_register_static(HILDON_TYPE_NOTE, + "HildonFileHandlingNote", + &dialog_info, 0); + } + return dialog_type; +} + +static void +hildon_file_handling_note_class_init(HildonFileHandlingNoteClass * class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(class); + + parent_class = g_type_class_peek_parent(class); + g_type_class_add_private(class, sizeof(HildonFileHandlingNotePrivate)); + object_class->finalize = hildon_file_handling_note_finalize; +} + +static void hildon_file_handling_note_init(HildonFileHandlingNote * dialog) +{ + HildonFileHandlingNotePrivate *priv; + + priv = HILDON_FILE_HANDLING_NOTE_GET_PRIVATE(dialog); + priv->note_type = OPENING_TYPE; +} + +static void hildon_file_handling_note_finalize(GObject * obj_self) +{ + if (G_OBJECT_CLASS(parent_class)->finalize) + G_OBJECT_CLASS(parent_class)->finalize(obj_self); +} + +/** + * hildon_file_handling_note_set_counter_and_name: + * @note: the #HildonFileHandlingNote widget + * @current: progress, current item being processed + * @maximum: maximum value for counter (number of items) + * @name: filename + * + * This function sets current counter value, maximum + * counter value and filename for dialog + * + * DEPRECATED: use hildon-note instead of hildon-file-handling-note. + */ +void hildon_file_handling_note_set_counter_and_name(HildonFileHandlingNote + * note, guint current, + guint maximum, + const gchar * name) +{ + gchar str[255]; + HildonNote *p_note = HILDON_NOTE(note); + HildonFileHandlingNotePrivate *priv; + + priv = HILDON_FILE_HANDLING_NOTE_GET_PRIVATE(note); + + if (priv->note_type == MOVING_TYPE) { + if (maximum == 1) + { + g_snprintf(str, 255, _("sfil_nw_moving_file"), name); + hildon_note_set_button_text(p_note, _("sfil_bd_moving_file")); + } else { + g_snprintf(str, 255, _("docm_nw_moving_files"), + current, maximum, name); + hildon_note_set_button_text(p_note, _("docm_bd_moving_files")); + } + } else if (priv->note_type == SAVING_TYPE) { + if (maximum == 1) + { + g_snprintf(str, 255, _("docm_nw_saving_file"), name); + hildon_note_set_button_text(p_note, _("docm_bd_saving_file")); + } else { + g_snprintf(str, 255, _("docm_nw_saving_files"), + current, maximum, name); + hildon_note_set_button_text(p_note, _("docm_bd_saving_files")); + } + } else if (priv->note_type == OPENING_TYPE) { + if (maximum == 1) + { + g_snprintf(str, 255, _("docm_nw_opening_file"), name); + hildon_note_set_button_text(p_note, _("docm_bd_opening_file")); + } else { + g_snprintf(str, 255, _("docm_nw_opening_files"), + current, maximum, name); + hildon_note_set_button_text(p_note, _("docm_bd_opening_files")); + } + } else if (priv->note_type == DELETING_TYPE) { + if (maximum == 1) + { + g_snprintf(str, 255, _("docm_nw_deleting_file"), name); + hildon_note_set_button_text(p_note, _("docm_bd_deleting_file")); + } else { + g_snprintf(str, 255, _("docm_nw_deleting_files"), + current, maximum, name); + hildon_note_set_button_text(p_note, _("docm_bd_deleting_files")); + } + } + + g_object_set(p_note, "description", str, NULL); +} + +/** + * hildon_file_handling_note_set_name: + * @note: the @HildonFileHandlingNote widget + * @name: filename + * + * This function sets the filename for dialog + * DEPRECATED: use hildon-note instead of hildon-file-handling-note. + */ +void hildon_file_handling_note_set_name(HildonFileHandlingNote * note, + const gchar * name) +{ + gchar str[255]; + HildonNote *p_note = HILDON_NOTE(note); + HildonFileHandlingNotePrivate *priv = + HILDON_FILE_HANDLING_NOTE_GET_PRIVATE(note); + + if (priv->note_type == MOVING_TYPE) { + g_snprintf(str, 255, _("sfil_nw_moving_file"), name); + } else if (priv->note_type == SAVING_TYPE) { + g_snprintf(str, 255, _("docm_nw_saving_file"), name); + } else if (priv->note_type == OPENING_TYPE) { + g_snprintf(str, 255, _("docm_nw_opening_file"), name); + } else if (priv->note_type == DELETING_TYPE) { + g_snprintf(str, 255, _("docm_nw_deleting_file"), name); + } + + g_object_set(p_note, "description", str, NULL); +} + +/** + * hildon_file_handling_note_set_fraction: + * @note: the @HildonFileHandlingNote widget + * @frac: value for progress bar + + * This function sets fraction value for + * progress bar. + * DEPRECATED: use hildon-note instead of hildon-file-handling-note. + */ +void hildon_file_handling_note_set_fraction(HildonFileHandlingNote * note, + gfloat frac) +{ + GtkWidget *progbar; + + g_object_get(note, "progressbar", &progbar, NULL); + gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progbar), frac); +} + +/** + * hildon_file_handling_note_new_moving: + * @parent: parent GtkWindow + * + * This function creates new dialog + * which is "moving" type. + * + * Returns: a new #HildonFileHandlingNote + * DEPRECATED: use hildon-note instead of hildon-file-handling-note. + */ +GtkWidget *hildon_file_handling_note_new_moving(GtkWindow * parent) +{ + GtkWidget *progbar; + HildonFileHandlingNote *file_note; + HildonFileHandlingNotePrivate *priv; + + progbar = gtk_progress_bar_new(); + + file_note = g_object_new(HILDON_TYPE_FILE_HANDLING_NOTE, + "note_type", HILDON_NOTE_PROGRESSBAR_TYPE, + "description", _("sfil_nw_moving_file"), + "progressbar", progbar, NULL); + + priv = HILDON_FILE_HANDLING_NOTE_GET_PRIVATE(file_note); + priv->note_type = MOVING_TYPE; + + if (parent != NULL) + gtk_window_set_transient_for(GTK_WINDOW(file_note), parent); + + return GTK_WIDGET(file_note); +} + +/** + * hildon_file_handling_note_new_deleting: + * @parent: parent GtkWindow + * + * This function creates new dialog + * which is "deleting" type. + * + * Returns: a new #HildonFileHandlingNote + * DEPRECATED: use hildon-note instead of hildon-file-handling-note. + */ +GtkWidget *hildon_file_handling_note_new_deleting(GtkWindow * parent) +{ + GtkWidget *progbar; + HildonFileHandlingNote *file_note; + HildonFileHandlingNotePrivate *priv; + + progbar = gtk_progress_bar_new(); + + file_note = g_object_new(HILDON_TYPE_FILE_HANDLING_NOTE, + "note_type", HILDON_NOTE_PROGRESSBAR_TYPE, + "description", _("docm_nw_deleting_file"), + "progressbar", progbar, NULL); + + priv = HILDON_FILE_HANDLING_NOTE_GET_PRIVATE(file_note); + priv->note_type = DELETING_TYPE; + + if (parent != NULL) + gtk_window_set_transient_for(GTK_WINDOW(file_note), parent); + + return GTK_WIDGET(file_note); +} + +/** + * hildon_file_handling_note_new_opening: + * @parent: parent GtkWindow + * + * This function creates new dialog + * which is "opening" type + * + * Returns: a new #HildonFileHandlingNote + * DEPRECATED: use hildon-note instead of hildon-file-handling-note. + */ +GtkWidget *hildon_file_handling_note_new_opening(GtkWindow * parent) +{ + GtkWidget *progbar; + HildonFileHandlingNote *file_note; + HildonFileHandlingNotePrivate *priv; + + progbar = gtk_progress_bar_new(); + + file_note = g_object_new(HILDON_TYPE_FILE_HANDLING_NOTE, + "note_type", HILDON_NOTE_PROGRESSBAR_TYPE, + "description", _("docm_nw_opening_file"), + "progressbar", progbar, NULL); + + priv = HILDON_FILE_HANDLING_NOTE_GET_PRIVATE(file_note); + priv->note_type = OPENING_TYPE; + + if (parent != NULL) + gtk_window_set_transient_for(GTK_WINDOW(file_note), parent); + + return GTK_WIDGET(file_note); +} + +/** + * hildon_file_handling_note_new_saving: + * @parent: parent GtkWindow + * + * This function creates new dialog + * which is "saving" type. + * + * Returns: a new #HildonFileHandlingNote + * DEPRECATED: use hildon-note instead of hildon-file-handling-note. + */ +GtkWidget *hildon_file_handling_note_new_saving(GtkWindow * parent) +{ + GtkWidget *progbar; + HildonFileHandlingNote *file_note; + HildonFileHandlingNotePrivate *priv; + + progbar = gtk_progress_bar_new(); + + file_note = g_object_new(HILDON_TYPE_FILE_HANDLING_NOTE, + "note_type", HILDON_NOTE_PROGRESSBAR_TYPE, + "description", _("docm_nw_saving_file"), + "progressbar", progbar, NULL); + + priv = HILDON_FILE_HANDLING_NOTE_GET_PRIVATE(file_note); + priv->note_type = SAVING_TYPE; + + if (parent != NULL) + gtk_window_set_transient_for(GTK_WINDOW(file_note), parent); + + return GTK_WIDGET(file_note); +} + diff --git a/src/hildon-file-handling-note.h b/src/hildon-file-handling-note.h new file mode 100644 index 0000000..4da000b --- /dev/null +++ b/src/hildon-file-handling-note.h @@ -0,0 +1,77 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ +#ifndef __HILDON_FILE_HANDLING_NOTE_H__ +#define __HILDON_FILE_HANDLING_NOTE_H__ + + +#ifndef HILDON_DISABLE_DEPRECATED + +#include "hildon-note.h" + +G_BEGIN_DECLS +#define HILDON_TYPE_FILE_HANDLING_NOTE \ + ( hildon_file_handling_note_get_type() ) +#define HILDON_FILE_HANDLING_NOTE(obj) \ + (GTK_CHECK_CAST (obj, HILDON_TYPE_FILE_HANDLING_NOTE,\ + HildonFileHandlingNote)) +#define HILDON_FILE_HANDLING_NOTE_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST ((klass), HILDON_TYPE_FILE_HANDLING_NOTE,\ + HildonFileHandlingNoteClass)) +#define HILDON_IS_FILE_HANDLING_NOTE(obj) (GTK_CHECK_TYPE (obj,\ + HILDON_TYPE_FILE_HANDLING_NOTE)) +#define HILDON_IS_FILE_HANDLING_NOTE_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_FILE_HANDLING_NOTE)) +typedef struct _HildonFileHandlingNote HildonFileHandlingNote; +typedef struct _HildonFileHandlingNoteClass HildonFileHandlingNoteClass; + +struct _HildonFileHandlingNote { + HildonNote parent; +}; + +struct _HildonFileHandlingNoteClass { + HildonNoteClass parent_class; +}; + +/* Note creation functions */ +GtkWidget *hildon_file_handling_note_new_moving(GtkWindow * parent); +GtkWidget *hildon_file_handling_note_new_deleting(GtkWindow * parent); +GtkWidget *hildon_file_handling_note_new_opening(GtkWindow * parent); +GtkWidget *hildon_file_handling_note_new_saving(GtkWindow * parent); + +/* Function for progressbar status setting */ +void hildon_file_handling_note_set_fraction(HildonFileHandlingNote * note, + gfloat frac); +void hildon_file_handling_note_set_counter_and_name(HildonFileHandlingNote + * note, guint current, + guint maximum, + const gchar * name); +void hildon_file_handling_note_set_name(HildonFileHandlingNote * note, + const gchar * name); + +GType hildon_file_handling_note_get_type(void); + +G_END_DECLS +#endif /* HILDON_DISABLE_DEPRECATED */ + +#endif /* __HILDON_FILE_HANDLING_NOTE_H__ */ diff --git a/src/hildon-find-toolbar.c b/src/hildon-find-toolbar.c new file mode 100644 index 0000000..33a9e69 --- /dev/null +++ b/src/hildon-find-toolbar.c @@ -0,0 +1,667 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-find-toolbar + * @short_description: A special toolbar to be used with HildonAppView + * @see_also: #HildonAppView + * + * HildonFindToolbar is a predefined toolbar for text searching purpose. + * It contains a GtkListStore which has the text items that the user has + * searched. But once the application is terminated, or HildonFindToolbar + * is trashed. Programmer is responsible for getting the GtkListStore through + * property "list", if he/she wants to use the information in the future. + * And through the same property, programmer is able to set the GtkListStore. + * Note, once the search button is pressed, string in the GtkComboxEntry is + * automatically added to the existing model, unless it is empty. + */ + +#include "hildon-find-toolbar.h" +#include "hildon-defines.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#define _(String) dgettext(PACKAGE, String) + +/*same define as gtkentry.c as entry will further handle this*/ +#define MAX_SIZE G_MAXUSHORT +#define FIND_LABEL_XPADDING 6 +#define FIND_LABEL_YPADDING 0 + +enum +{ + SEARCH = 0, + CLOSE, + INVALID_INPUT, + HISTORY_APPEND, + + LAST_SIGNAL +}; + +enum +{ + PROP_LABEL = 1, + PROP_PREFIX, + PROP_LIST, + PROP_COLUMN, + PROP_MAX, + PROP_HISTORY_LIMIT +}; + +struct _HildonFindToolbarPrivate +{ + GtkWidget* label; + GtkComboBoxEntry* entry_combo_box; + GtkToolItem* find_button; + GtkToolItem* separator; + GtkToolItem* close_button; + + gint history_limit; +}; +static guint HildonFindToolbar_signal[LAST_SIGNAL] = {0}; + +G_DEFINE_TYPE(HildonFindToolbar, hildon_find_toolbar, GTK_TYPE_TOOLBAR) + +static GtkTreeModel * +hildon_find_toolbar_get_list_model(HildonFindToolbarPrivate *priv) +{ + GtkTreeModel *filter_model = + gtk_combo_box_get_model(GTK_COMBO_BOX(priv->entry_combo_box)); + + return filter_model == NULL ? NULL : + gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(filter_model)); +} + +static GtkEntry * +hildon_find_toolbar_get_entry(HildonFindToolbarPrivate *priv) +{ + return GTK_ENTRY(gtk_bin_get_child(GTK_BIN(priv->entry_combo_box))); +} + +static gboolean +hildon_find_toolbar_filter(GtkTreeModel *model, + GtkTreeIter *iter, + gpointer self) +{ + GtkTreePath *path; + const gint *indices; + gint n; + gint limit; + gint total; + + total = gtk_tree_model_iter_n_children(model, NULL); + g_object_get(self, "history_limit", &limit, NULL); + path = gtk_tree_model_get_path(model, iter); + indices = gtk_tree_path_get_indices (path); + + /* set the row's index, list store has only one level */ + n = indices[0]; + gtk_tree_path_free(path); + + /*if the row is among the latest "history_limit" additions of the + * model, then we show it */ + if( (total - limit <= n) && (n < total) ) + return TRUE; + else + return FALSE; +} + +static void +hildon_find_toolbar_apply_filter(HildonFindToolbar *self, GtkTreeModel *model) +{ + GtkTreeModel *filter; + HildonFindToolbarPrivate *priv = self->priv; + + /* Create a filter for the given model. Its only purpose is to hide + the oldest entries so only "history_limit" entries are visible. */ + filter = gtk_tree_model_filter_new(model, NULL); + + gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(filter), + hildon_find_toolbar_filter, + self, NULL); + gtk_combo_box_set_model(GTK_COMBO_BOX(priv->entry_combo_box), filter); + + /* ComboBox keeps the only needed reference to the filter */ + g_object_unref(filter); +} + +static void +hildon_find_toolbar_get_property(GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + HildonFindToolbarPrivate *priv = HILDON_FIND_TOOLBAR(object)->priv; + const gchar *string; + gint c_n, max_len; + + switch (prop_id) + { + case PROP_LABEL: + string = gtk_label_get_text(GTK_LABEL(priv->label)); + g_value_set_string(value, string); + break; + case PROP_PREFIX: + string = gtk_entry_get_text(hildon_find_toolbar_get_entry(priv)); + g_value_set_string(value, string); + break; + case PROP_LIST: + g_value_set_object(value, hildon_find_toolbar_get_list_model(priv)); + break; + case PROP_COLUMN: + c_n = gtk_combo_box_entry_get_text_column(priv->entry_combo_box); + g_value_set_int(value, c_n); + break; + case PROP_MAX: + max_len = gtk_entry_get_max_length(hildon_find_toolbar_get_entry(priv)); + g_value_set_int(value, max_len); + break; + case PROP_HISTORY_LIMIT: + g_value_set_int(value, priv->history_limit); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +hildon_find_toolbar_set_property(GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + HildonFindToolbar *self = HILDON_FIND_TOOLBAR(object); + HildonFindToolbarPrivate *priv = self->priv; + GtkTreeModel *model; + const gchar *string; + + switch (prop_id) + { + case PROP_LABEL: + string = g_value_get_string(value); + gtk_label_set_text(GTK_LABEL(priv->label), string); + break; + case PROP_PREFIX: + string = g_value_get_string(value); + gtk_entry_set_text(hildon_find_toolbar_get_entry(priv), string); + break; + case PROP_LIST: + model = GTK_TREE_MODEL(g_value_get_object(value)); + hildon_find_toolbar_apply_filter(self, model); + break; + case PROP_COLUMN: + gtk_combo_box_entry_set_text_column(priv->entry_combo_box, + g_value_get_int(value)); + break; + case PROP_MAX: + gtk_entry_set_max_length(hildon_find_toolbar_get_entry(priv), + g_value_get_int(value)); + break; + case PROP_HISTORY_LIMIT: + priv->history_limit = g_value_get_int(value); + + /* Re-apply the history limit to the model. */ + model = hildon_find_toolbar_get_list_model(priv); + if (model != NULL) + { + /* Note that refilter function doesn't update the status of the + combobox popup arrow, so we'll just recreate the filter. */ + hildon_find_toolbar_apply_filter(self, model); + + if (gtk_combo_box_entry_get_text_column(priv->entry_combo_box) == -1) + { + /* FIXME: This is only for backwards compatibility, although + probably nothing actually relies on it. The behavior was only + an accidental side effect of original code */ + gtk_combo_box_entry_set_text_column(priv->entry_combo_box, 0); + } + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +hildon_find_toolbar_find_string(HildonFindToolbar *self, + GtkTreeIter *iter, + gint column, + const gchar *string) +{ + GtkTreeModel *model = NULL; + gchar *old_string; + + model = hildon_find_toolbar_get_list_model(self->priv); + + if (gtk_tree_model_get_iter_first(model, iter)) + { + do { + gtk_tree_model_get(model, iter, column, &old_string, -1); + if (old_string != NULL && strcmp(string, old_string) == 0) + { + /* Found it */ + return TRUE; + } + } while (gtk_tree_model_iter_next(model, iter)); + } + + return FALSE; +} + +static gboolean +hildon_find_toolbar_history_append(HildonFindToolbar *self, + gpointer data) +{ + HildonFindToolbarPrivate *priv = HILDON_FIND_TOOLBAR(self)->priv; + gchar *string; + gint column = 0; + GtkTreeModel *model = NULL; + GtkListStore *list = NULL; + GtkTreeIter iter; + gboolean self_create = FALSE; + + g_object_get(self, "prefix", &string, NULL); + + if (*string == '\0') + { + /* empty prefix, ignore */ + g_free(string); + return TRUE; + } + + + /* If list store is set, get it */ + model = hildon_find_toolbar_get_list_model(priv); + if(model != NULL) + { + list = GTK_LIST_STORE(model); + g_object_get(self, "column", &column, NULL); + + if (column < 0) + { + /* Column number is -1 if "column" property hasn't been set but + "list" property is. */ + g_free(string); + return TRUE; + } + + /* Latest string is always the first one in list. If the string + already exists, remove it so there are no duplicates in list. */ + if (hildon_find_toolbar_find_string(self, &iter, column, string)) + gtk_list_store_remove(list, &iter); + } + else + { + /* No list store set. Create our own. */ + list = gtk_list_store_new(1, G_TYPE_STRING); + model = GTK_TREE_MODEL(list); + self_create = TRUE; + } + + /* Add the string to first in list */ + gtk_list_store_append(list, &iter); + gtk_list_store_set(list, &iter, column, string, -1); + + if(self_create) + { + /* Add the created list to ComboBoxEntry */ + hildon_find_toolbar_apply_filter(self, model); + /* ComboBoxEntry keeps the only needed reference to this list */ + g_object_unref(list); + + /* Set the column only after ComboBoxEntry's model is set + in hildon_find_toolbar_apply_filter() */ + g_object_set(self, "column", 0, NULL); + } + else + { + /* Refilter to get the oldest entry hidden from history */ + gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER( + gtk_combo_box_get_model(GTK_COMBO_BOX(priv->entry_combo_box)))); + } + + g_free(string); + + return TRUE; +} + +static void +hildon_find_toolbar_emit_search(GtkButton *button, gpointer self) +{ + gboolean rb; + + /* Clicked search button. Perform search and add search prefix to history */ + g_signal_emit_by_name(self, "search", NULL); + g_signal_emit_by_name(self, "history_append", &rb, NULL); +} + +static void +hildon_find_toolbar_emit_close(GtkButton *button, gpointer self) +{ + HildonFindToolbarPrivate *priv = HILDON_FIND_TOOLBAR(self)->priv; + GtkWidget *entry = gtk_bin_get_child(GTK_BIN(priv->entry_combo_box)); + if (GTK_WIDGET_HAS_FOCUS(entry)) + { + hildon_gtk_im_context_hide(GTK_ENTRY(entry)->im_context); + } + /* Clicked close button */ + g_signal_emit_by_name(self, "close", NULL); +} + +static void +hildon_find_toolbar_emit_invalid_input(GtkEntry *entry, + GtkInvalidInputType type, + gpointer self) +{ + if(type == GTK_INVALID_INPUT_MAX_CHARS_REACHED) + g_signal_emit_by_name(self, "invalid_input", NULL); +} + +static void +hildon_find_toolbar_entry_activate (GtkWidget *widget, + gpointer user_data) +{ + GtkWidget *find_toolbar = GTK_WIDGET(user_data); + gboolean rb; + + /* NB#40936 stop focus from moving to next widget */ + g_signal_stop_emission_by_name (widget, "activate"); + + g_signal_emit_by_name(find_toolbar, "search", NULL); + g_signal_emit_by_name(find_toolbar, "history_append", &rb, NULL); +} + +static void +hildon_find_toolbar_class_init(HildonFindToolbarClass *klass) +{ + GObjectClass *object_class; + + g_type_class_add_private(klass, sizeof(HildonFindToolbarPrivate)); + + object_class = G_OBJECT_CLASS(klass); + + object_class->get_property = hildon_find_toolbar_get_property; + object_class->set_property = hildon_find_toolbar_set_property; + + klass->history_append = hildon_find_toolbar_history_append; + + g_object_class_install_property(object_class, PROP_LABEL, + g_param_spec_string("label", + "Label", "Displayed name for" + " find-toolbar", + _("ecdg_ti_find_toolbar_label"), + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property(object_class, PROP_PREFIX, + g_param_spec_string("prefix", + "Prefix", "Search string", NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property(object_class, PROP_LIST, + g_param_spec_object("list", + "List"," GtkListStore model where " + "history list is kept", + GTK_TYPE_LIST_STORE, + G_PARAM_READWRITE)); + + g_object_class_install_property(object_class, PROP_COLUMN, + g_param_spec_int("column", + "Column", "Column number in GtkListStore " + "where history list strings are kept", + 0, G_MAXINT, + 0, G_PARAM_READWRITE)); + + g_object_class_install_property(object_class, PROP_MAX, + g_param_spec_int("max_characters", + "Maximum number of characters", + "Maximum number of characters " + "in search string", + 0, MAX_SIZE, + 0, G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property(object_class, PROP_HISTORY_LIMIT, + g_param_spec_int("history_limit", + "Maximum number of history items", + "Maximum number of history items " + "in search combobox", + 0, G_MAXINT, + 5, G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + /** + * HildonFindToolbar::search: + * @toolbar: the toolbar which received the signal + * + * Gets emitted when the find button is pressed. + */ + HildonFindToolbar_signal[SEARCH] = + g_signal_new( + "search", HILDON_TYPE_FIND_TOOLBAR, + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET + (HildonFindToolbarClass, search), + NULL, NULL, gtk_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * HildonFindToolbar::close: + * @toolbar: the toolbar which received the signal + * + * Gets emitted when the close button is pressed. + */ + HildonFindToolbar_signal[CLOSE] = + g_signal_new( + "close", HILDON_TYPE_FIND_TOOLBAR, + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET + (HildonFindToolbarClass, close), + NULL, NULL, gtk_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * HildonFindToolbar::invalid-input: + * @toolbar: the toolbar which received the signal + * + * Gets emitted when the maximum search prefix length is reached and + * user tries to type more. + */ + HildonFindToolbar_signal[INVALID_INPUT] = + g_signal_new( + "invalid_input", HILDON_TYPE_FIND_TOOLBAR, + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET + (HildonFindToolbarClass, invalid_input), + NULL, NULL, gtk_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * HildonFindToolbar::history-append: + * @toolbar: the toolbar which received the signal + * + * Gets emitted when the current search prefix should be added to history. + */ + HildonFindToolbar_signal[HISTORY_APPEND] = + g_signal_new( + "history_append", HILDON_TYPE_FIND_TOOLBAR, + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET + (HildonFindToolbarClass, history_append), + g_signal_accumulator_true_handled, NULL, + gtk_marshal_BOOLEAN__VOID, + G_TYPE_BOOLEAN, 0); +} + +static void +hildon_find_toolbar_init(HildonFindToolbar *self) +{ + GtkToolItem *label_container; + GtkToolItem *entry_combo_box_container; + + self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self, + HILDON_TYPE_FIND_TOOLBAR, + HildonFindToolbarPrivate); + + /* Create the label */ + self->priv->label = gtk_label_new(_("ecdg_ti_find_toolbar_label")); + + gtk_misc_set_padding (GTK_MISC(self->priv->label), FIND_LABEL_XPADDING, + FIND_LABEL_YPADDING); + + label_container = gtk_tool_item_new(); + gtk_container_add(GTK_CONTAINER(label_container), + self->priv->label); + gtk_widget_show_all(GTK_WIDGET(label_container)); + gtk_toolbar_insert (GTK_TOOLBAR(self), label_container, -1); + + /* ComboBoxEntry for search prefix string / history list */ + self->priv->entry_combo_box = GTK_COMBO_BOX_ENTRY(gtk_combo_box_entry_new()); + g_signal_connect(hildon_find_toolbar_get_entry(self->priv), + "invalid_input", + G_CALLBACK(hildon_find_toolbar_emit_invalid_input), self); + entry_combo_box_container = gtk_tool_item_new(); + gtk_tool_item_set_expand(entry_combo_box_container, TRUE); + gtk_container_add(GTK_CONTAINER(entry_combo_box_container), + GTK_WIDGET(self->priv->entry_combo_box)); + gtk_widget_show_all(GTK_WIDGET(entry_combo_box_container)); + gtk_toolbar_insert (GTK_TOOLBAR(self), entry_combo_box_container, -1); + g_signal_connect(hildon_find_toolbar_get_entry(self->priv), + "activate", + G_CALLBACK(hildon_find_toolbar_entry_activate), self); + + /* Find button */ + self->priv->find_button = gtk_tool_button_new ( + gtk_image_new_from_icon_name ("qgn_toolb_browser_gobutton", + HILDON_ICON_SIZE_TOOLBAR), + "Find"); + g_signal_connect(self->priv->find_button, "clicked", + G_CALLBACK(hildon_find_toolbar_emit_search), self); + gtk_widget_show_all(GTK_WIDGET(self->priv->find_button)); + gtk_toolbar_insert (GTK_TOOLBAR(self), self->priv->find_button, -1); + if ( GTK_WIDGET_CAN_FOCUS( GTK_BIN(self->priv->find_button)->child) ) + GTK_WIDGET_UNSET_FLAGS( + GTK_BIN(self->priv->find_button)->child, GTK_CAN_FOCUS); + + /* Separator */ + self->priv->separator = gtk_separator_tool_item_new(); + gtk_widget_show(GTK_WIDGET(self->priv->separator)); + gtk_toolbar_insert (GTK_TOOLBAR(self), self->priv->separator, -1); + + /* Close button */ + self->priv->close_button = gtk_tool_button_new ( + gtk_image_new_from_icon_name ("qgn_toolb_gene_close", + HILDON_ICON_SIZE_TOOLBAR), + "Close"); + g_signal_connect(self->priv->close_button, "clicked", + G_CALLBACK(hildon_find_toolbar_emit_close), self); + gtk_widget_show_all(GTK_WIDGET(self->priv->close_button)); + gtk_toolbar_insert (GTK_TOOLBAR(self), self->priv->close_button, -1); + if ( GTK_WIDGET_CAN_FOCUS( GTK_BIN(self->priv->close_button)->child) ) + GTK_WIDGET_UNSET_FLAGS( + GTK_BIN(self->priv->close_button)->child, GTK_CAN_FOCUS); +} + +/*Public functions*/ + +/** + * hildon_find_toolbar_new: + * @label: label for the find_toolbar, NULL to set the label to + * default "Find" + * + * Returns a new HildonFindToolbar. + * + * Returns: a new HildonFindToolbar + */ + +GtkWidget * +hildon_find_toolbar_new(const gchar *label) +{ + GtkWidget *findtoolbar; + + findtoolbar = GTK_WIDGET(g_object_new(HILDON_TYPE_FIND_TOOLBAR, NULL)); + if(label != NULL) + g_object_set(findtoolbar, "label", label, NULL); + + return findtoolbar; +} + +/** + * hildon_find_toolbar_new_with_model + * @label: label for the find_toolbar, NULL to set the label to + * default "Find" + * @model: a @GtkListStore + * @column: indicating which column the search histry list will + * retreive string from + * + * Returns a new HildonFindToolbar, with a model. + * + * Returns: a new #HildonFindToolbar + */ +GtkWidget * +hildon_find_toolbar_new_with_model(const gchar *label, + GtkListStore *model, + gint column) +{ + GtkWidget *findtoolbar; + + findtoolbar = hildon_find_toolbar_new(label); + g_object_set(findtoolbar, "list", model, + "column", column, NULL); + + return findtoolbar; +} + +/** + * hildon_find_toolbar_highlight_entry + * @ftb: find Toolbar whose entry is to be highlighted + * @get_focus: if user passes TRUE to this value, then the text in + * the entry will not only get highlighted, but also get focused. + * + */ +void +hildon_find_toolbar_highlight_entry(HildonFindToolbar *ftb, + gboolean get_focus) +{ + GtkEntry *entry = NULL; + + g_return_if_fail(HILDON_IS_FIND_TOOLBAR(ftb)); + + entry = hildon_find_toolbar_get_entry(ftb->priv); + + gtk_editable_select_region(GTK_EDITABLE(entry), 0, -1); + + if(get_focus) + gtk_widget_grab_focus(GTK_WIDGET(entry)); +} diff --git a/src/hildon-find-toolbar.h b/src/hildon-find-toolbar.h new file mode 100644 index 0000000..2f5919c --- /dev/null +++ b/src/hildon-find-toolbar.h @@ -0,0 +1,80 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_FIND_TOOLBAR_H__ +#define __HILDON_FIND_TOOLBAR_H__ + +#include +#include + +G_BEGIN_DECLS + +#define HILDON_TYPE_FIND_TOOLBAR (hildon_find_toolbar_get_type()) +#define HILDON_FIND_TOOLBAR(object) \ + (G_TYPE_CHECK_INSTANCE_CAST((object), HILDON_TYPE_FIND_TOOLBAR, \ + HildonFindToolbar)) +#define HILDON_FIND_TOOLBARClass(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), HILDON_TYPE_FIND_TOOLBAR, \ + HildonFindToolbarClass)) +#define HILDON_IS_FIND_TOOLBAR(object) \ + (G_TYPE_CHECK_INSTANCE_TYPE((object), HILDON_TYPE_FIND_TOOLBAR)) +#define HILDON_IS_FIND_TOOLBAR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), HILDON_TYPE_FIND_TOOLBAR)) +#define HILDON_FIND_TOOLBAR_GET_CLASS(object) \ + (G_TYPE_INSTANCE_GET_CLASS((object), HILDON_TYPE_FIND_TOOLBAR, \ + HildonFindToolbarClass)) + +typedef struct _HildonFindToolbar HildonFindToolbar; +typedef struct _HildonFindToolbarClass HildonFindToolbarClass; +typedef struct _HildonFindToolbarPrivate HildonFindToolbarPrivate; + +struct _HildonFindToolbar +{ + GtkToolbar parent; + + HildonFindToolbarPrivate *priv; +}; + +struct _HildonFindToolbarClass +{ + GtkToolbarClass parent_class; + + void (*search) (HildonFindToolbar *toolbar); + void (*close) (HildonFindToolbar *toolbar); + void (*invalid_input) (HildonFindToolbar *toolbar); + gboolean (*history_append) (HildonFindToolbar *tooblar); +}; + +GType hildon_find_toolbar_get_type (void) G_GNUC_CONST; +GtkWidget* hildon_find_toolbar_new (const gchar *label); +GtkWidget* hildon_find_toolbar_new_with_model (const gchar *label, + GtkListStore* + model, + gint column); +void hildon_find_toolbar_highlight_entry (HildonFindToolbar *ftb, + gboolean get_focus); + +G_END_DECLS + +#endif /* __HILDON_FIND_TOOLBAR_H__ */ diff --git a/src/hildon-font-selection-dialog.c b/src/hildon-font-selection-dialog.c new file mode 100644 index 0000000..1ffa8c0 --- /dev/null +++ b/src/hildon-font-selection-dialog.c @@ -0,0 +1,1998 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-font-selection-dialog + * @short_description: A widget used to allow users to select a font + * with certain properties + * + * Font selection can be made using this widget. Users can select font name, + * size, style, etc. Users can also preview text in the selected font. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hildon-font-selection-dialog.h" +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#define _(String) dgettext(PACKAGE, String) + +#define SUPERSCRIPT_RISE 3333 +#define SUBSCRIPT_LOW -3333 +#define ON_BIT 0x01 +#define OFF_BIT 0x02 + +/* + * These are what we use as the standard font sizes, for the size list. + */ +static const guint16 font_sizes[] = +{ + 6, 8, 10, 12, 16, 24, 32 +}; + +#define HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(obj) \ +(G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_FONT_SELECTION_DIALOG, \ + HildonFontSelectionDialogPrivate)) + +/*None of designed api function works, so now it all comes down to + *use properties to achieve what we are supposed to achieve*/ +enum +{ + PROP_FAMILY = 1, + PROP_FAMILY_SET, + PROP_SIZE, + PROP_SIZE_SET, + PROP_COLOR, + PROP_COLOR_SET, + PROP_BOLD, + PROP_BOLD_SET, + PROP_ITALIC, + PROP_ITALIC_SET, + PROP_UNDERLINE, + PROP_UNDERLINE_SET, + PROP_STRIKETHROUGH, + PROP_STRIKETHROUGH_SET, + PROP_POSITION, + PROP_POSITION_SET, + PROP_PREVIEW_TEXT, + PROP_FONT_SCALING +}; + +typedef struct +_HildonFontSelectionDialogPrivate HildonFontSelectionDialogPrivate; + +struct _HildonFontSelectionDialogPrivate +{ + GtkNotebook *notebook; + + gchar *preview_text; + + /*Tab one*/ + GtkWidget *cbx_font_type; + GtkWidget *cbx_font_size; + GtkWidget *font_color_button; + + /*Tab two*/ + GtkWidget *chk_bold; + GtkWidget *chk_italic; + GtkWidget *chk_underline; + + /*Tab three*/ + GtkWidget *chk_strikethrough; + GtkWidget *cbx_positioning; + + /*Every family*/ + PangoFontFamily **families; + gint n_families; + + /*color_set is used to show whether the color is inconsistent + * The handler id is used to block the signal emission + * when we change the color setting*/ + + gboolean color_set; + + /* font_scaling is the scaling factor applied to font + * scale in the preview dialog */ + + gdouble font_scaling; + gulong color_modified_signal_handler; +}; + +/*combo box active row indicator -2--inconsistent, -1--undefined + * please make sure that you use settings_init settings_apply + * and settings_destroy, dont even try to touch this structure + * without using the three above interface functions, of course + * if you know what you are doing, do as you please ;-)*/ +typedef struct +{ + HildonFontSelectionDialog + *fsd; /*pointer to our font selection dialog*/ + + gint family; /*combo box indicator*/ + gint size; /*combo box indicator*/ + GdkColor *color; /*free after read the setting*/ + gboolean color_inconsist; + gint weight; /*bit mask*/ + gint style; /*bit mask*/ + gint underline; /*bit mask*/ + gint strikethrough; /*bit mask*/ + gint position; /*combo box indicator*/ + +}HildonFontSelectionDialogSettings; + +static gboolean + hildon_font_selection_dialog_preview_key_press + (GtkWidget * widget, + GdkEventKey * event, + gpointer unused); + +/*Some tools from gtk_font_selection*/ +static int cmp_families (const void *a, const void *b); + +static void hildon_font_selection_dialog_show_preview + (HildonFontSelectionDialog + *fontsel); + +static PangoAttrList* + hildon_font_selection_dialog_create_attrlist + (HildonFontSelectionDialog + *fontsel, guint start_index, + guint len); + +static void hildon_font_selection_dialog_show_available_positionings + (HildonFontSelectionDialogPrivate + *priv); + +static void hildon_font_selection_dialog_show_available_fonts + (HildonFontSelectionDialog + *fontsel); + +static void hildon_font_selection_dialog_show_available_sizes + (HildonFontSelectionDialogPrivate + *priv); + +static void hildon_font_selection_dialog_class_init + (HildonFontSelectionDialogClass + *klass); + +static void hildon_font_selection_dialog_init + (HildonFontSelectionDialog + *fontseldiag); + +static void hildon_font_selection_dialog_finalize + (GObject * object); + +static void hildon_font_selection_dialog_construct_notebook + (HildonFontSelectionDialog + *fontsel); + +static void color_modified_cb (HildonColorButton *button, + GParamSpec *pspec, + gpointer fsd_priv); + +static void check_tags (gpointer data, + gpointer user_data); + +static void settings_init (HildonFontSelectionDialogSettings + *setttings, + HildonFontSelectionDialog + *fsd); + +static void settings_apply (HildonFontSelectionDialogSettings + *setttings); + +static void settings_destroy (HildonFontSelectionDialogSettings + *setttings); + +static void bit_mask_toggle (gint mask, GtkToggleButton* + button, GObject *object, + const gchar *prop, + const gchar *prop_set); + +static void combo_active (gint active, GtkComboBox *box, + GObject *object, + const gchar *prop, + const gchar *prop_set); + +static void add_preview_text_attr (PangoAttrList *list, + PangoAttribute *attr, + guint start, + guint len); + +static void toggle_clicked (GtkButton *button, + gpointer unused); + + + +static GtkDialogClass *font_selection_dialog_parent_class = NULL; + +GType hildon_font_selection_dialog_get_type(void) +{ + static GType font_selection_dialog_type = 0; + + if (!font_selection_dialog_type) { + static const GTypeInfo fontsel_diag_info = { + sizeof(HildonFontSelectionDialogClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_font_selection_dialog_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonFontSelectionDialog), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_font_selection_dialog_init, + }; + + font_selection_dialog_type = + g_type_register_static(GTK_TYPE_DIALOG, + "HildonFontSelectionDialog", + &fontsel_diag_info, 0); + } + + return font_selection_dialog_type; +} + +static void +hildon_font_selection_dialog_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + gint i; + GdkColor *color = NULL; + + HildonFontSelectionDialogPrivate *priv = + HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE( + HILDON_FONT_SELECTION_DIALOG(object)); + + + switch (prop_id) + { + case PROP_FAMILY: + i = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->cbx_font_type)); + if(i >= 0 && i < priv->n_families) + g_value_set_string(value, + pango_font_family_get_name(priv->families[i])); + else + g_value_set_string(value, "Sans"); + break; + + case PROP_FAMILY_SET: + i = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->cbx_font_type)); + if(i >= 0 && i < priv->n_families) + g_value_set_boolean(value, TRUE); + else + g_value_set_boolean(value, FALSE); + break; + + case PROP_SIZE: + i = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->cbx_font_size)); + if(i >= 0 && i < G_N_ELEMENTS(font_sizes)) + g_value_set_int(value, font_sizes[i]); + else + g_value_set_int(value, 16); + break; + + case PROP_SIZE_SET: + i = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->cbx_font_size)); + if(i >= 0 && i < G_N_ELEMENTS(font_sizes)) + g_value_set_boolean(value, TRUE); + else + g_value_set_boolean(value, FALSE); + break; + + case PROP_COLOR: + color = hildon_color_button_get_color + (HILDON_COLOR_BUTTON(priv->font_color_button)); + g_value_set_boxed(value, (gconstpointer) color); + if(color != NULL) + gdk_color_free(color); + break; + + case PROP_COLOR_SET: + g_value_set_boolean(value, priv->color_set); + break; + + case PROP_BOLD: + g_value_set_boolean(value, + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->chk_bold))); + break; + + case PROP_BOLD_SET: + g_value_set_boolean(value, + !gtk_toggle_button_get_inconsistent + (GTK_TOGGLE_BUTTON(priv->chk_bold))); + break; + + case PROP_ITALIC: + g_value_set_boolean(value, + gtk_toggle_button_get_active + (GTK_TOGGLE_BUTTON(priv->chk_italic))); + break; + + case PROP_ITALIC_SET: + g_value_set_boolean(value, + !gtk_toggle_button_get_inconsistent + (GTK_TOGGLE_BUTTON(priv->chk_italic))); + break; + + case PROP_UNDERLINE: + g_value_set_boolean(value, + gtk_toggle_button_get_active + (GTK_TOGGLE_BUTTON(priv->chk_underline))); + break; + + case PROP_UNDERLINE_SET: + g_value_set_boolean(value, + !gtk_toggle_button_get_inconsistent + (GTK_TOGGLE_BUTTON(priv->chk_underline))); + break; + + case PROP_STRIKETHROUGH: + g_value_set_boolean(value, + gtk_toggle_button_get_active + (GTK_TOGGLE_BUTTON(priv->chk_strikethrough))); + break; + + case PROP_STRIKETHROUGH_SET: + g_value_set_boolean(value, + !gtk_toggle_button_get_inconsistent + (GTK_TOGGLE_BUTTON(priv->chk_strikethrough))); + break; + + case PROP_POSITION: + i = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->cbx_positioning)); + if(i == 1)/*super*/ + g_value_set_int(value, 1); + else if(i == 2)/*sub*/ + g_value_set_int(value, -1); + else + g_value_set_int(value, 0); + break; + + case PROP_FONT_SCALING: + g_value_set_double(value, priv->font_scaling); + break; + + case PROP_POSITION_SET: + i = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->cbx_positioning)); + if(i >= 0 && i < 3) + g_value_set_boolean(value, TRUE); + else + g_value_set_boolean(value, FALSE); + break; + + case PROP_PREVIEW_TEXT: + g_value_set_string(value, + hildon_font_selection_dialog_get_preview_text( + HILDON_FONT_SELECTION_DIALOG(object))); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +hildon_font_selection_dialog_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + gint i, size; + const gchar *str; + gboolean b; + GdkColor *color = NULL; + GdkColor black; + + HildonFontSelectionDialogPrivate *priv = + HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE( + HILDON_FONT_SELECTION_DIALOG(object)); + black.red = black.green = black.blue = 0; + + switch (prop_id) + { + case PROP_FAMILY: + str = g_value_get_string(value); + for(i = 0; i < priv->n_families; i++) + { + if(strcmp(str, pango_font_family_get_name(priv->families[i])) + == 0) + { + gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_font_type), i); + break; + } + } + break; + + case PROP_FAMILY_SET: + b = g_value_get_boolean(value); + if(!b) + gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_font_type), -1); + break; + + case PROP_SIZE: + size = g_value_get_int(value); + for(i = 0; i < G_N_ELEMENTS(font_sizes); i++) + { + if(size == font_sizes[i]) + { + gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_font_size), i); + break; + } + } + break; + + case PROP_SIZE_SET: + b = g_value_get_boolean(value); + if(!b) + gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_font_size), -1); + break; + + case PROP_COLOR: + color = (GdkColor *) g_value_get_boxed(value); + if(color != NULL) + hildon_color_button_set_color(HILDON_COLOR_BUTTON + (priv->font_color_button), + color); + else + hildon_color_button_set_color(HILDON_COLOR_BUTTON + (priv->font_color_button), + &black); + break; + + case PROP_COLOR_SET: + priv->color_set = g_value_get_boolean(value); + if(!priv->color_set) + { + /*set color to black, but block our signal handler*/ + g_signal_handler_block((gpointer) priv->font_color_button, + priv->color_modified_signal_handler); + + hildon_color_button_set_color(HILDON_COLOR_BUTTON + (priv->font_color_button), + &black); + + g_signal_handler_unblock((gpointer) priv->font_color_button, + priv->color_modified_signal_handler); + } + break; + + case PROP_BOLD: + /*this call will make sure that we dont get extra clicked signal*/ + gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(priv->chk_bold), + FALSE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->chk_bold), + g_value_get_boolean(value)); + break; + + case PROP_BOLD_SET: + gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(priv->chk_bold), + !g_value_get_boolean(value)); + break; + + case PROP_ITALIC: + gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(priv->chk_italic), + FALSE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->chk_italic), + g_value_get_boolean(value)); + break; + + case PROP_ITALIC_SET: + gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(priv->chk_italic), + !g_value_get_boolean(value)); + break; + + case PROP_UNDERLINE: + gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON + (priv->chk_underline), + FALSE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->chk_underline), + g_value_get_boolean(value)); + break; + + case PROP_UNDERLINE_SET: + gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(priv->chk_underline), + !g_value_get_boolean(value)); + break; + + case PROP_STRIKETHROUGH: + gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON + (priv->chk_strikethrough), + FALSE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->chk_strikethrough), + g_value_get_boolean(value)); + break; + + case PROP_STRIKETHROUGH_SET: + gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON + (priv->chk_strikethrough), + !g_value_get_boolean(value)); + break; + + case PROP_POSITION: + i = g_value_get_int(value); + if( i == 1 ) + gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_positioning), 1); + else if(i == -1) + gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_positioning), 2); + else + gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_positioning), 0); + break; + + case PROP_FONT_SCALING: + priv->font_scaling = g_value_get_double(value); + break; + + case PROP_POSITION_SET: + b = g_value_get_boolean(value); + if(!b) + gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_positioning), -1); + break; + + case PROP_PREVIEW_TEXT: + hildon_font_selection_dialog_set_preview_text( + HILDON_FONT_SELECTION_DIALOG(object), + g_value_get_string(value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +hildon_font_selection_dialog_class_init(HildonFontSelectionDialogClass * + klass) +{ + GObjectClass *gobject_class; + + font_selection_dialog_parent_class = g_type_class_peek_parent(klass); + gobject_class = G_OBJECT_CLASS(klass); + gobject_class->finalize = hildon_font_selection_dialog_finalize; + gobject_class->get_property = hildon_font_selection_dialog_get_property; + gobject_class->set_property = hildon_font_selection_dialog_set_property; + + /* Install property to the class */ + g_object_class_install_property(gobject_class, PROP_FAMILY, + g_param_spec_string("family", + "Font family", "String defines" + " the font family", "Sans", + G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, PROP_FAMILY_SET, + g_param_spec_boolean ("family-set", + "family inconsistent state", + "Whether the family property" + " is inconsistent", FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property(gobject_class, PROP_SIZE, + g_param_spec_int ("size", + "Font size", + "Font size in Pt", + 6, 32, 16, + G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, PROP_SIZE_SET, + g_param_spec_boolean ("size-set", + "size inconsistent state", + "Whether the size property" + " is inconsistent", FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property(gobject_class, PROP_COLOR, + g_param_spec_boxed ("color", + "text color", + "gdk color for the text", + GDK_TYPE_COLOR, + G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, PROP_COLOR_SET, + g_param_spec_boolean ("color-set", + "color inconsistent state", + "Whether the color property" + " is inconsistent", FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property(gobject_class, PROP_BOLD, + g_param_spec_boolean ("bold", + "text weight", + "Whether the text is bold", + FALSE, + G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, PROP_BOLD_SET, + g_param_spec_boolean ("bold-set", + "bold inconsistent state", + "Whether the bold" + " is inconsistent", FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property(gobject_class, PROP_ITALIC, + g_param_spec_boolean ("italic", + "text style", + "Whether the text is italic", + FALSE, + G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, PROP_ITALIC_SET, + g_param_spec_boolean ("italic-set", + "italic inconsistent state", + "Whether the italic" + " is inconsistent", FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property(gobject_class, PROP_UNDERLINE, + g_param_spec_boolean ("underline", + "text underline", + "Whether the text is underlined", + FALSE, + G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, PROP_UNDERLINE_SET, + g_param_spec_boolean ("underline-set", + "underline inconsistent state", + "Whether the underline" + " is inconsistent", FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property(gobject_class, PROP_STRIKETHROUGH, + g_param_spec_boolean ("strikethrough", + "strikethroughed text", + "Whether the text is strikethroughed", + FALSE, + G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, PROP_STRIKETHROUGH_SET, + g_param_spec_boolean ("strikethrough-set", + "strikethrough inconsistent state", + "Whether the strikethrough" + " is inconsistent", FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property(gobject_class, PROP_POSITION, + g_param_spec_int ("position", + "Font position", + "Font position super or subscript", + -1, 1, 0, + G_PARAM_READWRITE)); + + /* FIXME This was introduced in 0.14.1. We don't have documentation for + * properties anyways, but once it's there it needs to be marked as + * Since: 0.14.1 */ + g_object_class_install_property(gobject_class, PROP_FONT_SCALING, + g_param_spec_double ("font-scaling", + "Font scaling", + "Font scaling for the preview dialog", + 0, 10, 1, + G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, PROP_POSITION_SET, + g_param_spec_boolean ("position-set", + "position inconsistent state", + "Whether the position" + " is inconsistent", FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property(gobject_class, PROP_PREVIEW_TEXT, + g_param_spec_string("preview-text", + "Preview Text", + "the text in preview dialog, which does" + "not include the reference text", + "", + G_PARAM_READWRITE)); + + + g_type_class_add_private(klass, + sizeof(struct _HildonFontSelectionDialogPrivate)); +} + + +static void +hildon_font_selection_dialog_init(HildonFontSelectionDialog *fontseldiag) +{ + HildonFontSelectionDialogPrivate *priv = + HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fontseldiag); + GtkWidget *preview_button; + + priv->notebook = GTK_NOTEBOOK(gtk_notebook_new()); + + hildon_font_selection_dialog_construct_notebook(fontseldiag); + + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fontseldiag)->vbox), + GTK_WIDGET(priv->notebook), TRUE, TRUE, 0); + + /* Add dialog buttons */ + gtk_dialog_add_button(GTK_DIALOG(fontseldiag), + _("ecdg_bd_font_dialog_ok"), + GTK_RESPONSE_OK); + + preview_button = gtk_button_new_with_label(_("ecdg_bd_font_dialog_preview")); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fontseldiag)->action_area), + preview_button, FALSE, TRUE, 0); + g_signal_connect_swapped(preview_button, "clicked", + G_CALLBACK + (hildon_font_selection_dialog_show_preview), + fontseldiag); + gtk_widget_show(preview_button); + + gtk_dialog_add_button(GTK_DIALOG(fontseldiag), + _("ecdg_bd_font_dialog_cancel"), + GTK_RESPONSE_CANCEL); + + /*Set default preview text*/ + priv->preview_text = g_strdup(_("ecdg_fi_preview_font_preview_text")); + + gtk_window_set_title(GTK_WINDOW(fontseldiag), _("ecdg_ti_font")); + /*here is the line to make sure that notebook has the default focus*/ + gtk_container_set_focus_child(GTK_CONTAINER(GTK_DIALOG(fontseldiag)->vbox), + GTK_WIDGET(priv->notebook)); +} + +static void +hildon_font_selection_dialog_construct_notebook (HildonFontSelectionDialog + *fontsel) +{ + gint i; + GtkWidget *vbox_tab[3]; + GtkWidget *font_color_box; + GtkWidget *caption_control; + GtkSizeGroup *group; + + HildonFontSelectionDialogPrivate *priv = + HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fontsel); + + for (i = 0; i < 3; i++) + vbox_tab[i] = gtk_vbox_new(TRUE, 0); + + group = + GTK_SIZE_GROUP(gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL)); + + /* Build the first page of the GtkNotebook: font style */ + priv->cbx_font_type = gtk_combo_box_new_text(); + hildon_font_selection_dialog_show_available_fonts(fontsel); + caption_control = hildon_caption_new(group, + _("ecdg_fi_font_font"), + priv->cbx_font_type, + NULL, + HILDON_CAPTION_OPTIONAL); + gtk_box_pack_start(GTK_BOX(vbox_tab[0]), caption_control, + FALSE, FALSE, 0); + + priv->cbx_font_size = gtk_combo_box_new_text(); + hildon_font_selection_dialog_show_available_sizes(priv); + caption_control = hildon_caption_new(group, + _("ecdg_fi_font_size"), + priv->cbx_font_size, + NULL, + HILDON_CAPTION_OPTIONAL); + gtk_box_pack_start(GTK_BOX(vbox_tab[0]), caption_control, + FALSE, FALSE, 0); + + font_color_box = gtk_hbox_new(FALSE, 0); + priv->font_color_button = hildon_color_button_new(); + priv->color_set = FALSE; + priv->font_scaling = 1.0; + priv->color_modified_signal_handler = + g_signal_connect(G_OBJECT(priv->font_color_button), "notify::color", + G_CALLBACK(color_modified_cb), (gpointer) priv); + gtk_box_pack_start(GTK_BOX(font_color_box), + priv->font_color_button, FALSE, FALSE, 0); + + caption_control = + hildon_caption_new(group, _("ecdg_fi_font_colour_selector"), + font_color_box, + NULL, HILDON_CAPTION_OPTIONAL); + + gtk_box_pack_start(GTK_BOX(vbox_tab[0]), caption_control, + FALSE, FALSE, 0); + + /* Build the second page of the GtkNotebook: font formatting */ + priv->chk_bold = gtk_check_button_new(); + caption_control = hildon_caption_new(group, + _("ecdg_fi_font_bold"), + priv->chk_bold, + NULL, + HILDON_CAPTION_OPTIONAL); + gtk_box_pack_start(GTK_BOX(vbox_tab[1]), caption_control, + FALSE, FALSE, 0); + g_signal_connect(G_OBJECT(priv->chk_bold), "clicked", + G_CALLBACK(toggle_clicked), NULL); + + priv->chk_italic = gtk_check_button_new(); + caption_control = + hildon_caption_new(group, _("ecdg_fi_font_italic"), + priv->chk_italic, + NULL, HILDON_CAPTION_OPTIONAL); + gtk_box_pack_start(GTK_BOX(vbox_tab[1]), caption_control, + FALSE, FALSE, 0); + g_signal_connect(G_OBJECT(priv->chk_italic), "clicked", + G_CALLBACK(toggle_clicked), NULL); + + priv->chk_underline = gtk_check_button_new(); + caption_control = + hildon_caption_new(group, _("ecdg_fi_font_underline"), + priv->chk_underline, NULL, + HILDON_CAPTION_OPTIONAL); + gtk_box_pack_start(GTK_BOX(vbox_tab[1]), caption_control, + FALSE, FALSE, 0); + g_signal_connect(G_OBJECT(priv->chk_underline), "clicked", + G_CALLBACK(toggle_clicked), NULL); + + /* Build the third page of the GtkNotebook: other font properties */ + priv->chk_strikethrough = gtk_check_button_new(); + caption_control = + hildon_caption_new(group, _("ecdg_fi_font_strikethrough"), + priv->chk_strikethrough, NULL, + HILDON_CAPTION_OPTIONAL); + gtk_box_pack_start(GTK_BOX(vbox_tab[2]), caption_control, + FALSE, FALSE, 0); + g_signal_connect(G_OBJECT(priv->chk_strikethrough), "clicked", + G_CALLBACK(toggle_clicked), NULL); + + priv->cbx_positioning = gtk_combo_box_new_text(); + hildon_font_selection_dialog_show_available_positionings(priv); + caption_control = + hildon_caption_new(group, _("ecdg_fi_font_special"), + priv->cbx_positioning, NULL, + HILDON_CAPTION_OPTIONAL); + gtk_box_pack_start(GTK_BOX(vbox_tab[2]), caption_control, + FALSE, FALSE, 0); + + /* Populate notebook */ + gtk_notebook_insert_page(priv->notebook, vbox_tab[0], NULL, 0); + gtk_notebook_insert_page(priv->notebook, vbox_tab[1], NULL, 1); + gtk_notebook_insert_page(priv->notebook, vbox_tab[2], NULL, 2); + gtk_notebook_set_tab_label_text(priv->notebook, vbox_tab[0], + _("ecdg_ti_font_dialog_style")); + gtk_notebook_set_tab_label_text(priv->notebook, vbox_tab[1], + _("ecdg_ti_font_dialog_format")); + gtk_notebook_set_tab_label_text(priv->notebook, vbox_tab[2], + _("ecdg_ti_font_dialog_other")); + + gtk_widget_show_all(GTK_WIDGET(priv->notebook)); +} + +static void +color_modified_cb(HildonColorButton *button, + GParamSpec *pspec, + gpointer fsd_priv) +{ + HildonFontSelectionDialogPrivate *priv = + (HildonFontSelectionDialogPrivate *) fsd_priv; + + priv->color_set = TRUE; +} + +static void +hildon_font_selection_dialog_finalize(GObject * object) +{ + HildonFontSelectionDialogPrivate *priv; + HildonFontSelectionDialog *fontsel; + + g_assert(HILDON_IS_FONT_SELECTION_DIALOG(object)); + fontsel = HILDON_FONT_SELECTION_DIALOG(object); + + priv = HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fontsel); + + g_free(priv->preview_text); + g_free(priv->families); + + if (G_OBJECT_CLASS(font_selection_dialog_parent_class)->finalize) + G_OBJECT_CLASS(font_selection_dialog_parent_class)->finalize(object); +} + +static int +cmp_families(const void *a, const void *b) +{ + const char *a_name = + pango_font_family_get_name(*(PangoFontFamily **) a); + const char *b_name = + pango_font_family_get_name(*(PangoFontFamily **) b); + + return g_utf8_collate(a_name, b_name); +} + +/* Exits the preview dialog with GTK_RESPONSE_CANCEL if Esc key + * was pressed */ +static gboolean +hildon_font_selection_dialog_preview_key_press(GtkWidget * widget, + GdkEventKey * event, + gpointer unused) +{ + g_assert(widget); + g_assert(event); + + if (event->keyval == GDK_Escape) + { + gtk_dialog_response(GTK_DIALOG(widget), GTK_RESPONSE_CANCEL); + return TRUE; + } + + return FALSE; +} + +static void +add_preview_text_attr(PangoAttrList *list, PangoAttribute *attr, + guint start, guint len) +{ + attr->start_index = start; + attr->end_index = start + len; + pango_attr_list_insert(list, attr); +} + +static PangoAttrList* +hildon_font_selection_dialog_create_attrlist(HildonFontSelectionDialog * + fontsel, guint start_index, guint len) +{ + PangoAttrList *list; + PangoAttribute *attr; + gint size, position; + gboolean family_set, size_set, color_set, bold, bold_set, + italic, italic_set, underline, underline_set, + strikethrough, strikethrough_set, position_set; + GdkColor *color = NULL; + gchar *family = NULL; + gdouble font_scaling = 1.0; + + list = pango_attr_list_new(); + + g_object_get(G_OBJECT(fontsel), + "family", &family, "family-set", &family_set, + "size", &size, "size-set", &size_set, + "color", &color, "color-set", &color_set, + "bold", &bold, "bold-set", &bold_set, + "italic", &italic, "italic-set", &italic_set, + "underline", &underline, "underline-set", &underline_set, + "strikethrough", &strikethrough, "strikethrough-set", + &strikethrough_set, "position", &position, + "position-set", &position_set, + "font-scaling", &font_scaling, + NULL); + + /*family*/ + if(family_set) + { + attr = pango_attr_family_new(family); + add_preview_text_attr(list, attr, start_index, len); + } + g_free(family); + + /*size*/ + if(size_set) + { + attr = pango_attr_size_new(size * PANGO_SCALE); + add_preview_text_attr(list, attr, start_index, len); + } + + /*color*/ + if(color_set) + { + attr = pango_attr_foreground_new(color->red, color->green, color->blue); + add_preview_text_attr(list, attr, start_index, len); + } + + if(color != NULL) + gdk_color_free(color); + + /*weight*/ + if(bold_set) + { + if(bold) + attr = pango_attr_weight_new(PANGO_WEIGHT_BOLD); + else + attr = pango_attr_weight_new(PANGO_WEIGHT_NORMAL); + + add_preview_text_attr(list, attr, start_index, len); + } + + /*style*/ + if(italic_set) + { + if(italic) + attr = pango_attr_style_new(PANGO_STYLE_ITALIC); + else + attr = pango_attr_style_new(PANGO_STYLE_NORMAL); + + add_preview_text_attr(list, attr, start_index, len); + } + + /*underline*/ + if(underline_set) + { + if(underline) + attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); + else + attr = pango_attr_underline_new(PANGO_UNDERLINE_NONE); + + add_preview_text_attr(list, attr, start_index, len); + } + + /*strikethrough*/ + if(strikethrough_set) + { + if(strikethrough) + attr = pango_attr_strikethrough_new(TRUE); + else + attr = pango_attr_strikethrough_new(FALSE); + + add_preview_text_attr(list, attr, start_index, len); + } + + /*position*/ + if(position_set) + { + switch(position) + { + case 1: /*super*/ + attr = pango_attr_rise_new(SUPERSCRIPT_RISE); + break; + case -1: /*sub*/ + attr = pango_attr_rise_new(SUBSCRIPT_LOW); + break; + default: /*normal*/ + attr = pango_attr_rise_new(0); + break; + } + + add_preview_text_attr(list, attr, start_index, len); + } + + /*font scaling for preview*/ + if(font_scaling) + { + attr = pango_attr_scale_new(font_scaling); + add_preview_text_attr(list, attr, 0, len + start_index); + } + + return list; +} + +static void +hildon_font_selection_dialog_show_preview(HildonFontSelectionDialog * + fontsel) +{ + HildonFontSelectionDialogPrivate *priv = + HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fontsel); + gint size; + gboolean family_set, size_set; + PangoAttribute *attr; + PangoAttrList *list; + GtkWidget *preview_dialog; + GtkWidget *preview_label; + gchar *str = NULL; + gboolean position_set = FALSE; + gint position = 0; + gboolean show_ref = FALSE; + + g_object_get(G_OBJECT(fontsel), "position-set", &position_set, NULL); + if (position_set) { + g_object_get(G_OBJECT(fontsel), "position", &position, NULL); + if (position == 1 || position == -1) + show_ref = TRUE; + } + + /*Preview dialog init*/ + preview_dialog= + gtk_dialog_new_with_buttons(_("ecdg_ti_preview_font"), NULL, + GTK_DIALOG_MODAL | + GTK_DIALOG_DESTROY_WITH_PARENT | + GTK_DIALOG_NO_SEPARATOR, + _("ecdg_bd_font_dialog_ok"), + GTK_RESPONSE_ACCEPT, + NULL); + + str = (show_ref) ? g_strconcat(_("ecdg_fi_preview_font_preview_reference"), priv->preview_text, 0) : + g_strdup (priv->preview_text); + + preview_label = gtk_label_new(str); + gtk_label_set_line_wrap(GTK_LABEL(preview_label), TRUE); + + g_free(str); + str = NULL; + + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(preview_dialog)->vbox), + preview_label); + + + /* set keypress handler (ESC hardkey) */ + g_signal_connect(G_OBJECT(preview_dialog), "key-press-event", + G_CALLBACK(hildon_font_selection_dialog_preview_key_press), + NULL); + + + /*Set the font*/ + list = (show_ref) ? hildon_font_selection_dialog_create_attrlist(fontsel, + strlen(_("ecdg_fi_preview_font_preview_reference")), + strlen(priv->preview_text)) : + hildon_font_selection_dialog_create_attrlist(fontsel, + 0, + strlen(priv->preview_text)); + + g_object_get(G_OBJECT(fontsel), "family", &str, "family-set", + &family_set, "size", &size, "size-set", &size_set, + NULL); + + /* FIXME: This is a slightly ugly hack to force the width of the window so that + * the whole text fits with various font sizes. It's being done in such a way, + * because of some GtkLabel wrapping issues and other mysterious bugs related to + * truncating ellipsizing. Needs a rethink in future. (MDK) */ + + gint dialog_width = (size_set && size > 24) ? 600 : 500; + gtk_window_set_default_size (GTK_WINDOW(preview_dialog), dialog_width, -1); + + /*make reference text to have the same fontface and size*/ + if(family_set) + { + attr = pango_attr_family_new(str); + add_preview_text_attr(list, attr, 0, strlen(_("ecdg_fi_preview_font_preview_reference"))); + } + g_free(str); + + /*size*/ + if(size_set) + { + attr = pango_attr_size_new(size * PANGO_SCALE); + add_preview_text_attr(list, attr, 0, strlen(_("ecdg_fi_preview_font_preview_reference"))); + } + + gtk_label_set_attributes(GTK_LABEL(preview_label), list); + pango_attr_list_unref(list); + + /*And show the dialog*/ + gtk_window_set_transient_for(GTK_WINDOW(preview_dialog), + GTK_WINDOW(fontsel)); + + gtk_widget_show_all(preview_dialog); + gtk_dialog_run(GTK_DIALOG(preview_dialog)); + gtk_widget_destroy(preview_dialog); +} + + +static gboolean is_internal_font(const gchar * name){ + return strcmp(name, "DeviceSymbols") == 0 + || strcmp(name, "Nokia Smiley" ) == 0 + || strcmp(name, "NewCourier" ) == 0 + || strcmp(name, "NewTimes" ) == 0 + || strcmp(name, "SwissA" ) == 0 + || strcmp(name, "Nokia Sans" ) == 0 + || strcmp(name, "Nokia Sans Cn") == 0; +} + +static void filter_out_internal_fonts(PangoFontFamily **families, int *n_families){ + int i; + int n; /* counts valid fonts */ + const gchar * name = NULL; + + for(i = 0, n = 0; i < *n_families; i++){ + + name = pango_font_family_get_name(families[i]); + + if(!is_internal_font(name)){ + + if(i!=n){ /* there are filtered out families */ + families[n] = families[i]; /* shift the current family */ + } + + n++; /* count one more valid */ + } + }/* foreach font family */ + + *n_families = n; +} + + +static void +hildon_font_selection_dialog_show_available_fonts(HildonFontSelectionDialog + *fontsel) + +{ + gint i; + + HildonFontSelectionDialogPrivate *priv = + HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fontsel); + + pango_context_list_families(gtk_widget_get_pango_context + (GTK_WIDGET(fontsel)), &priv->families, + &priv->n_families); + + filter_out_internal_fonts(priv->families, &priv->n_families); + + qsort(priv->families, priv->n_families, sizeof(PangoFontFamily *), + cmp_families); + + + for (i = 0; i < priv->n_families; i++) + { + const gchar *name = pango_font_family_get_name(priv->families[i]); + + gtk_combo_box_append_text(GTK_COMBO_BOX(priv->cbx_font_type), + name); + } +} + + +static void +hildon_font_selection_dialog_show_available_positionings + (HildonFontSelectionDialogPrivate + *priv) +{ + gtk_combo_box_append_text(GTK_COMBO_BOX(priv->cbx_positioning), + _("ecdg_va_font_printpos_1")); + gtk_combo_box_append_text(GTK_COMBO_BOX(priv->cbx_positioning), + _("ecdg_va_font_printpos_2")); + gtk_combo_box_append_text(GTK_COMBO_BOX(priv->cbx_positioning), + _("ecdg_va_font_printpos_3")); +} + +/*Loads the sizes from a pre-allocated table*/ +static void +hildon_font_selection_dialog_show_available_sizes + (HildonFontSelectionDialogPrivate + *priv) +{ + gchar *size_str; + gint i; + + for (i = 0; i < G_N_ELEMENTS(font_sizes); i++) + { + size_str = g_strdup_printf ("%i%s", + font_sizes[i], + _("ecdg_va_font_size_trailer")); + + gtk_combo_box_append_text(GTK_COMBO_BOX(priv->cbx_font_size), + size_str); + g_free (size_str); + } +} + +/* WARNING: This function is called only from deprecated API */ +static +void check_tags(gpointer data, gpointer user_data) +{ + gchar *font_family; + GdkColor *fore_color = NULL; + gint p_size, p_weight, p_style, p_underline, p_rise; + gboolean b_st, ff_s, size_s, fgc_s, w_s, ss_s, u_s, sth_s, r_s; + + GtkTextTag *tag = (GtkTextTag*) data; + HildonFontSelectionDialogSettings *settings = + (HildonFontSelectionDialogSettings *) user_data; + HildonFontSelectionDialogPrivate *priv = + HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(settings->fsd); + + /*get all the properties*/ + g_object_get(G_OBJECT(tag), + "family", &font_family, "family-set", &ff_s, + "size", &p_size, "size-set", &size_s, + "foreground-gdk", &fore_color, "foreground-set", &fgc_s, + "weight", &p_weight, "weight-set", &w_s, + "style", &p_style, "style-set", &ss_s, + "underline", &p_underline, "underline-set", &u_s, + "strikethrough", &b_st, "strikethrough-set", &sth_s, + "rise", &p_rise, "rise-set", & r_s, + NULL); + + /* Check that the given values are valid. + * If not, set the combobox row indicator to 'inconsistent' */ + if(ff_s) + { + gint new_f = -1; + gint i; + + for(i = 0; i < priv->n_families; i++) + { + if(strcmp(font_family, + pango_font_family_get_name(priv->families[i])) == 0) + { + new_f = i; + break; + } + } + + if(settings->family == -1) + settings->family = new_f; + else if(settings->family != -2 && + settings->family != new_f) + settings->family = -2;/*inconsist*/ + + g_free(font_family); + } + + if(size_s) + { + gint new_size = -1; + gint i; + + for(i = 0; i < G_N_ELEMENTS(font_sizes); i++) + { + if(p_size == font_sizes[i] * PANGO_SCALE) + { + new_size = i; + break; + } + } + + if(settings->size == -1) + settings->size = new_size; + else if(settings->size != -2 && + settings->size != new_size) + settings->size = -2;/*inconsist*/ + } + + if(fgc_s && settings->color == NULL + && !settings->color_inconsist) + settings->color = fore_color; + else if(fore_color != NULL) + { + if(!gdk_color_equal(fore_color, settings->color) + && fgc_s) + settings->color_inconsist = TRUE; + + gdk_color_free(fore_color); + } + + if(w_s) + settings->weight |= p_weight == PANGO_WEIGHT_NORMAL ? OFF_BIT : ON_BIT; + + if(ss_s) + settings->style |= p_style == PANGO_STYLE_NORMAL ? OFF_BIT : ON_BIT; + + if(u_s) + settings->underline |= + p_underline == PANGO_UNDERLINE_NONE ? OFF_BIT : ON_BIT; + + if(sth_s) + settings->strikethrough |= b_st ? ON_BIT : OFF_BIT; + + if(r_s) + { + gint new_rs = -1; + + if(p_rise == 0) + new_rs = 0;/*normal*/ + else if (p_rise > 0) + new_rs = 1;/*super*/ + else + new_rs = 2;/*sub*/ + + if(settings->position == -1) + settings->position = new_rs; + else if(settings->position != -2 && + settings->position != new_rs) + settings->position = -2;/*inconsist*/ + } +} + +/* WARNING: This function is called only from deprecated API */ +static +void check_attrs(gpointer data, gpointer user_data) +{ + PangoAttribute *attr = (PangoAttribute *) data; + HildonFontSelectionDialogSettings *settings = + (HildonFontSelectionDialogSettings *) user_data; + HildonFontSelectionDialogPrivate *priv = + HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(settings->fsd); + + gchar *family; + GdkColor color; + gint i; + gint size, weight, style, underline, strikethrough, rise; + gint new_f = -1, new_size = -1, new_rise = -1; + + /* Check that the given values are valid. + * If not, set the combobox row indicator to 'inconsistent' */ + switch(attr->klass->type) + { + case PANGO_ATTR_FAMILY: + family = ((PangoAttrString *) attr)->value; + + for(i = 0; i < priv->n_families; i++) + { + if(strcmp(family, + pango_font_family_get_name(priv->families[i])) == 0) + { + new_f = i; + break; + } + } + + if(settings->family == -1) + settings->family = new_f; + else if(settings->family != -2 && + settings->family != new_f) + settings->family = -2;/*inconsist*/ + + break; + case PANGO_ATTR_SIZE: + size = ((PangoAttrInt *) attr)->value; + + for(i = 0; i < G_N_ELEMENTS(font_sizes); i++) + { + if(size == font_sizes[i] * PANGO_SCALE) + { + new_size = i; + break; + } + } + + if(settings->size == -1) + settings->size = new_size; + else if(settings->size != -2 && + settings->size != new_size) + settings->size = -2;/*inconsist*/ + + break; + case PANGO_ATTR_FOREGROUND: + color.red = ((PangoAttrColor *) attr)->color.red; + color.green = ((PangoAttrColor *) attr)->color.green; + color.blue = ((PangoAttrColor *) attr)->color.blue; + + if(!settings->color_inconsist && settings->color == NULL) + settings->color = gdk_color_copy(&color); + else if(settings->color != NULL && + !gdk_color_equal(&color, settings->color)) + settings->color_inconsist = TRUE; + + break; + case PANGO_ATTR_WEIGHT: + weight = ((PangoAttrInt *) attr)->value; + + settings->weight |= weight == PANGO_WEIGHT_NORMAL ? OFF_BIT : ON_BIT; + + break; + case PANGO_ATTR_STYLE: + style = ((PangoAttrInt *) attr)->value; + + settings->style |= style == PANGO_STYLE_NORMAL ? OFF_BIT : ON_BIT; + + break; + case PANGO_ATTR_UNDERLINE: + underline = ((PangoAttrInt *) attr)->value; + + settings->underline |= + underline == PANGO_UNDERLINE_NONE ? OFF_BIT : ON_BIT; + + break; + case PANGO_ATTR_STRIKETHROUGH: + strikethrough = ((PangoAttrInt *) attr)->value; + + settings->strikethrough |= strikethrough ? ON_BIT : OFF_BIT; + + break; + case PANGO_ATTR_RISE: + rise = ((PangoAttrInt *) attr)->value; + + if(rise == 0) + new_rise = 0;/*normal*/ + else if (rise > 0) + new_rise = 1;/*super*/ + else + new_rise = 2;/*sub*/ + + if(settings->position == -1) + settings->position = new_rise; + else if(settings->position != -2 && + settings->position != new_rise) + settings->position = -2;/*inconsist*/ + + break; + default: + break; + } + + pango_attribute_destroy(attr); +} + +/* WARNING: This function is called only from deprecated API */ +static void +settings_init(HildonFontSelectionDialogSettings *settings, + HildonFontSelectionDialog *fsd) +{ + settings->fsd = fsd; + settings->family = -1; + settings->size = -1; + settings->color = NULL; + settings->color_inconsist = FALSE; + settings->weight = 0; + settings->style = 0; + settings->underline = 0; + settings->strikethrough = 0; + settings->position = -1; +} + +/* WARNING: This function is called only from deprecated API */ +static void +bit_mask_toggle(gint mask, GtkToggleButton *button, + GObject *object, const gchar *prop, + const gchar *prop_set) +{ + + if(mask == 3) + gtk_toggle_button_set_inconsistent(button, TRUE); + else + { + gtk_toggle_button_set_inconsistent(button, FALSE); + + if(mask == 1) + gtk_toggle_button_set_active(button, TRUE); + else + gtk_toggle_button_set_active(button, FALSE); + + g_object_notify(object, prop); + } + + g_object_notify(object, prop_set); +} + +/* WARNING: This function is called only from deprecated API */ +static void +combo_active(gint active, GtkComboBox *box, + GObject *object, const gchar *prop, const gchar *prop_set) +{ + /*probaly not the best function, but we need all these + * parameters to keep things together*/ + + + if(active >= 0) + { + gtk_combo_box_set_active(box, active); + g_object_notify(object, prop); + } + else + gtk_combo_box_set_active(box, -1); + + g_object_notify(object, prop_set); +} + +/* WARNING: This function is called only from deprecated API */ +static void +settings_apply(HildonFontSelectionDialogSettings *settings) +{ + + HildonFontSelectionDialogPrivate *priv = + HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(settings->fsd); + + /*family*/ + combo_active(settings->family, GTK_COMBO_BOX(priv->cbx_font_type), + G_OBJECT(settings->fsd), "family", "family-set"); + + /*size*/ + combo_active(settings->size, GTK_COMBO_BOX(priv->cbx_font_size), + G_OBJECT(settings->fsd), "size", "size-set"); + + /*block our signal handler indicating color has been changed by + * the user before set the color, and unblock it after setting + * is done*/ + + if(settings->color == NULL || settings->color_inconsist) + { + GdkColor black; + + black.red = black.green = black.blue = 0; + g_signal_handler_block((gpointer) priv->font_color_button, + priv->color_modified_signal_handler); + + g_object_set(G_OBJECT(settings->fsd), "color", &black, "color-set", + FALSE, NULL); + + g_signal_handler_unblock((gpointer) priv->font_color_button, + priv->color_modified_signal_handler); + } + else + g_object_set(G_OBJECT(settings->fsd), "color", settings->color, NULL); + + /*weight*/ + bit_mask_toggle(settings->weight, GTK_TOGGLE_BUTTON(priv->chk_bold), + G_OBJECT(settings->fsd), "bold", "bold-set"); + + /*style*/ + bit_mask_toggle(settings->style, GTK_TOGGLE_BUTTON(priv->chk_italic), + G_OBJECT(settings->fsd), "italic", "italic-set"); + + /*underline*/ + bit_mask_toggle(settings->underline, + GTK_TOGGLE_BUTTON(priv->chk_underline), + G_OBJECT(settings->fsd), "underline", "underline-set"); + + /*strikethrough*/ + bit_mask_toggle(settings->strikethrough, + GTK_TOGGLE_BUTTON(priv->chk_strikethrough), + G_OBJECT(settings->fsd), "strikethrough", + "strikethrough-set"); + + /*position*/ + combo_active(settings->position, GTK_COMBO_BOX(priv->cbx_positioning), + G_OBJECT(settings->fsd), "position", "position-set"); +} + +static void +settings_destroy(HildonFontSelectionDialogSettings *settings) +{ + if(settings->color != NULL) + gdk_color_free(settings->color); +} + +static void +toggle_clicked(GtkButton *button, gpointer unused) +{ + GtkToggleButton *t_b = GTK_TOGGLE_BUTTON(button); + + /*we have to remove the inconsistent state ourselves*/ + if(gtk_toggle_button_get_inconsistent(t_b)) + { + gtk_toggle_button_set_inconsistent(t_b, FALSE); + gtk_toggle_button_set_active(t_b, FALSE); + } +} + +/*******************/ +/*Public functions*/ +/*******************/ + +/** + * hildon_font_selection_dialog_new: + * @parent: the parent window + * @title: the title of font selection dialog + * + * If NULL is passed for title, then default title + * "Font" will be used. + * + * Returns: a new #HildonFontSelectionDialog + */ +GtkWidget * +hildon_font_selection_dialog_new(GtkWindow * parent, + const gchar * title) +{ + HildonFontSelectionDialog *fontseldiag; + + fontseldiag = g_object_new(HILDON_TYPE_FONT_SELECTION_DIALOG, + "has-separator", FALSE, NULL); + + if (title) + gtk_window_set_title(GTK_WINDOW(fontseldiag), title); + + if (parent) + gtk_window_set_transient_for(GTK_WINDOW(fontseldiag), parent); + + return GTK_WIDGET(fontseldiag); +} + +/** + * hildon_font_selection_dialog_get_preview_text: + * @fsd: the font selection dialog + * + * Gets the text in preview dialog, which does not include the + * reference text. The returned string must be freed by the user. + * + * Returns: a string pointer + */ +gchar * +hildon_font_selection_dialog_get_preview_text(HildonFontSelectionDialog * fsd) +{ + HildonFontSelectionDialogPrivate *priv; + + g_return_val_if_fail(HILDON_IS_FONT_SELECTION_DIALOG(fsd), FALSE); + priv = HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fsd); + return g_strdup(priv->preview_text); +} + +/** + * hildon_font_selection_dialog_set_preview_text: + * @fsd: the font selection dialog + * @text: the text to be displayed in the preview dialog + * + * The default preview text is + * "The quick brown fox jumped over the lazy dogs" + */ +void +hildon_font_selection_dialog_set_preview_text(HildonFontSelectionDialog * + fsd, const gchar * text) +{ + HildonFontSelectionDialogPrivate *priv = NULL; + + g_return_if_fail(HILDON_IS_FONT_SELECTION_DIALOG(fsd)); + g_return_if_fail(text); + + priv = HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fsd); + + g_free(priv->preview_text); + priv->preview_text = g_strdup(text); + g_object_notify (G_OBJECT (fsd), "preview-text"); +} + +/** + * hildon_font_selection_dialog_get_text_tag: + * @fsd: the font selection dialog + * + * Get the #GtkTextTag for selections. This function + * is deprecated. The best way to use + * the text tags is to reuse them as much as possible. + * The recommended way is to get the properties of the font + * selection dialog on GTK_RESPONSE_OK, and according to + * these properties use the tags that you have pre-created. + * + * Returns: a #GtkTextTag having corresponding properties + * set + */ +GtkTextTag * +hildon_font_selection_dialog_get_text_tag (HildonFontSelectionDialog *fsd) +{ + GtkTextTag *tag; + gint size, position; + gboolean family_set, size_set, color_set, bold, bold_set, + italic, italic_set, underline, underline_set, + strikethrough, strikethrough_set, position_set; + GdkColor *color = NULL; + gchar *family = NULL; + + tag = gtk_text_tag_new(NULL); + + g_object_get(G_OBJECT(fsd), + "family", &family, "family-set", &family_set, + "size", &size, "size-set", &size_set, + "color", &color, "color-set", &color_set, + "bold", &bold, "bold-set", &bold_set, + "italic", &italic, "italic-set", &italic_set, + "underline", &underline, "underline-set", &underline_set, + "strikethrough", &strikethrough, "strikethrough-set", + &strikethrough_set, "position", &position, + "position-set", &position_set, NULL); + /*family*/ + if(family_set) + g_object_set(G_OBJECT(tag), "family", + family, "family-set", TRUE, NULL); + else + g_object_set(G_OBJECT(tag), "family-set", FALSE, NULL); + + g_free(family); + + /*size*/ + if(size_set) + g_object_set(G_OBJECT(tag), "size", size * PANGO_SCALE, + "size-set", TRUE, NULL); + else + g_object_set(G_OBJECT(tag), "size-set", FALSE, NULL); + + /*color*/ + if(color_set) + g_object_set(G_OBJECT(tag), "foreground-gdk", color, + "foreground-set", TRUE ,NULL); + else + g_object_set(G_OBJECT(tag), "foreground-set", FALSE, NULL); + + if(color != NULL) + gdk_color_free(color); + + /*weight*/ + if(bold_set) + { + if(bold) + g_object_set(G_OBJECT(tag), "weight", PANGO_WEIGHT_BOLD, NULL); + else + g_object_set(G_OBJECT(tag), "weight", PANGO_WEIGHT_NORMAL, NULL); + + g_object_set(G_OBJECT(tag), "weight-set", TRUE, NULL); + } + else + g_object_set(G_OBJECT(tag), "weight-set", FALSE, NULL); + + /*style*/ + if(italic_set) + { + if(italic) + g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_ITALIC, NULL); + else + g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_NORMAL, NULL); + + g_object_set(G_OBJECT(tag), "style-set", TRUE, NULL); + } + else + g_object_set(G_OBJECT(tag), "style-set", FALSE, NULL); + + /*underline*/ + if(underline_set) + { + if(underline) + g_object_set(G_OBJECT(tag), "underline", PANGO_UNDERLINE_SINGLE, NULL); + else + g_object_set(G_OBJECT(tag), "underline", PANGO_UNDERLINE_NONE, NULL); + + g_object_set(G_OBJECT(tag), "underline-set", TRUE, NULL); + } + else + g_object_set(G_OBJECT(tag), "underline-set", FALSE, NULL); + + /*strikethrough*/ + if(strikethrough_set) + { + if(strikethrough) + g_object_set(G_OBJECT(tag), "strikethrough", TRUE, NULL); + else + g_object_set(G_OBJECT(tag), "strikethrough", FALSE, NULL); + + g_object_set(G_OBJECT(tag), "strikethrough-set", TRUE, NULL); + } + else + g_object_set(G_OBJECT(tag), "strikethrough-set", FALSE, NULL); + + /*position*/ + if(position_set) + { + switch(position) + { + case 1: /*super*/ + g_object_set(G_OBJECT(tag), "rise", SUPERSCRIPT_RISE, NULL); + break; + case -1: /*sub*/ + g_object_set(G_OBJECT(tag), "rise", SUBSCRIPT_LOW, NULL); + break; + case 0: /*normal*/ + g_object_set(G_OBJECT(tag), "rise", 0, NULL); + break; + } + g_object_set(G_OBJECT(tag), "rise-set", TRUE, NULL); + } + else + g_object_set(G_OBJECT(tag), "rise-set", FALSE, NULL); + + return tag; +} + +/** + * hildon_font_selection_dialog_set_buffer: + * @fsd: the font selection dialog + * @buffer: a #GtkTextBuffer containing the text to which the selections will + * be applied. Applying is responsibility of application. + * + * This is deprecated. GtkTextBuffer is not enough + * to get the attributes of currently selected text. Please + * inspect the attributes yourself, and set the properties of + * font selection dialog to reflect your inspection. + */ +void +hildon_font_selection_dialog_set_buffer (HildonFontSelectionDialog *fsd, + GtkTextBuffer *buffer) +{ + GtkTextIter begin, end, iter; + HildonFontSelectionDialogSettings settings; + + gtk_text_buffer_get_selection_bounds(buffer, &begin, &end); + + settings_init(&settings, fsd); + + iter = begin; + + /* Keep original settings if the selection includes nothing */ + if(gtk_text_iter_compare(&iter, &end) == 0) + { + GSList *slist; + + slist = gtk_text_iter_get_tags(&iter); + g_slist_foreach(slist, check_tags, (gpointer) &settings); + g_slist_free(slist); + } + + /* Apply the user settings to the selected text */ + while(gtk_text_iter_compare(&iter, &end) < 0) + { + GSList *slist; + + slist = gtk_text_iter_get_tags(&iter); + g_slist_foreach(slist, check_tags, (gpointer) &settings); + g_slist_free(slist); + + if(!gtk_text_iter_forward_cursor_position(&iter)) + break; + } + + settings_apply(&settings); + settings_destroy(&settings); +} + +/** + * hildon_font_selection_dialog_get_font: + * @fsd: the font selection dialog + * + * This is deprecated. @PangoAttrList needs + * starting index, and end index on construction. + * + * Returns: pointer to @PangoAttrList + */ +PangoAttrList +*hildon_font_selection_dialog_get_font(HildonFontSelectionDialog * fsd) +{ + HildonFontSelectionDialogPrivate *priv + = HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fsd); + + g_return_val_if_fail(HILDON_IS_FONT_SELECTION_DIALOG(fsd), FALSE); + /*an approve of none working api, should have ask for start_index, + * and length in bytes of the string, currently using preview_text + * length, KLUDGE!*/ + + return hildon_font_selection_dialog_create_attrlist(fsd, + 0, strlen(priv->preview_text)); +} + +/** + * hildon_font_selection_dialog_set_font: + * @fsd: the font selection dialog + * @list: the pango attribute list + * + * This is a deprecated. + * + * Sets the font to the dialog. + */ +void +hildon_font_selection_dialog_set_font(HildonFontSelectionDialog * fsd, + PangoAttrList * list) +{ + PangoAttrIterator *iter; + HildonFontSelectionDialogSettings settings; + + iter = pango_attr_list_get_iterator(list); + + settings_init(&settings, fsd); + + while(iter != NULL) + { + GSList *slist; + + slist = pango_attr_iterator_get_attrs(iter); + g_slist_foreach(slist, check_attrs, (gpointer) &settings); + g_slist_free(slist); + + if(!pango_attr_iterator_next(iter)) + break; + } + + pango_attr_iterator_destroy(iter); + + settings_apply(&settings); + settings_destroy(&settings); +} diff --git a/src/hildon-font-selection-dialog.h b/src/hildon-font-selection-dialog.h new file mode 100644 index 0000000..da8134b --- /dev/null +++ b/src/hildon-font-selection-dialog.h @@ -0,0 +1,100 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ +#ifndef __HILDON_FONT_SELECTION_DIALOG_H__ +#define __HILDON_FONT_SELECTION_DIALOG_H__ + +#include +#include + +G_BEGIN_DECLS + +#define HILDON_TYPE_FONT_SELECTION_DIALOG \ + (hildon_font_selection_dialog_get_type ()) +#define HILDON_FONT_SELECTION_DIALOG(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj),\ + HILDON_TYPE_FONT_SELECTION_DIALOG, HildonFontSelectionDialog)) +#define HILDON_FONT_SELECTION_DIALOG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass),\ + HILDON_TYPE_FONT_SELECTION_DIALOG,\ + HildonFontSelectionDialogClass)) +#define HILDON_IS_FONT_SELECTION_DIALOG(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\ + HILDON_TYPE_FONT_SELECTION_DIALOG)) +#define HILDON_IS_FONT_SELECTION_DIALOG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass),\ + HILDON_TYPE_FONT_SELECTION_DIALOG)) +#define HILDON_FONT_SELECTION_DIALOG_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj),\ + HILDON_TYPE_FONT_SELECTION_DIALOG,\ + HildonFontSelectionDialogClass)) + +typedef struct _HildonFontSelectionDialog HildonFontSelectionDialog; +typedef struct _HildonFontSelectionDialogClass HildonFontSelectionDialogClass; + +struct _HildonFontSelectionDialog +{ + GtkDialog parent; +}; + +struct _HildonFontSelectionDialogClass +{ + GtkDialogClass parent_class; + + /* Padding for future expansion */ + void (*_gtk_reserved1) (void); + void (*_gtk_reserved2) (void); + void (*_gtk_reserved3) (void); + void (*_gtk_reserved4) (void); +}; + +#ifndef HILDON_DISABLE_DEPRECATED +PangoAttrList* hildon_font_selection_dialog_get_font(HildonFontSelectionDialog *fsd); + +void hildon_font_selection_dialog_set_font(HildonFontSelectionDialog *fsd, + PangoAttrList *list); +#endif + + +GType hildon_font_selection_dialog_get_type (void) G_GNUC_CONST; + +GtkWidget* hildon_font_selection_dialog_new (GtkWindow *parent, + const gchar *title); + + +#ifndef HILDON_DISABLE_DEPRECATED +void hildon_font_selection_dialog_set_buffer (HildonFontSelectionDialog *fsd, + GtkTextBuffer *buffer); + +GtkTextTag* hildon_font_selection_dialog_get_text_tag (HildonFontSelectionDialog *fsd); +#endif + + +gchar* hildon_font_selection_dialog_get_preview_text (HildonFontSelectionDialog *fsd); + +void hildon_font_selection_dialog_set_preview_text (HildonFontSelectionDialog *fsd, + const gchar * text); + +G_END_DECLS + +#endif /* __HILDON_FONT_SELECTION_DIALOG_H__ */ diff --git a/src/hildon-get-password-dialog.c b/src/hildon-get-password-dialog.c new file mode 100644 index 0000000..45bd412 --- /dev/null +++ b/src/hildon-get-password-dialog.c @@ -0,0 +1,569 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-get-password-dialog + * @short_description: A widget used to get a password + * @see_also: #HildonSetPasswordDialog + * + * HildonGetPasswordDialog prompts the user for a password. It allows + * inputting password, with an optional configurable label eg. for + * showing the domain. The maximum length of the password can be set. + */ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "gtk-infoprint.h" +#include "hildon-input-mode-hint.h" + +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#define _(String) dgettext(PACKAGE, String) + +static GtkDialogClass * parent_class; + +typedef struct _HildonGetPasswordDialogPrivate + HildonGetPasswordDialogPrivate; + +struct _HildonGetPasswordDialogPrivate { + GtkButton *okButton; + GtkButton *cancelButton; + + GtkLabel *domainLabel; + HildonCaption *passwordEntry; + gboolean get_old; +}; + + +#define HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_GET_PASSWORD_DIALOG, HildonGetPasswordDialogPrivate)); + +static void +hildon_get_password_dialog_class_init(HildonGetPasswordDialogClass * + class); +static void hildon_get_password_dialog_init(HildonGetPasswordDialog * + widget); +static void hildon_get_password_set_property(GObject * object, + guint prop_id, + const GValue * value, + GParamSpec * pspec); +static void hildon_get_password_get_property(GObject * object, + guint prop_id, GValue * value, + GParamSpec * pspec); +static void create_contents(HildonGetPasswordDialog *dialog); +static void _invalid_input(GtkWidget *widget, GtkInvalidInputType reason, + gpointer unused); + +enum{ + PROP_NONE = 0, + PROP_DOMAIN, + PROP_PASSWORD, + PROP_NUMBERS_ONLY, + PROP_CAPTION_LABEL, + PROP_MAX_CHARS, + PROP_GET_OLD +}; + +/* Private functions */ +static void +hildon_get_password_set_property(GObject * object, + guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + HildonGetPasswordDialog *dialog = HILDON_GET_PASSWORD_DIALOG(object); + HildonGetPasswordDialogPrivate *priv; + + priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE(dialog); + + switch (prop_id) { + case PROP_DOMAIN: + /* Set label text representing password domain */ + gtk_label_set_text(priv->domainLabel, g_value_get_string(value)); + break; + case PROP_PASSWORD: + gtk_entry_set_text(GTK_ENTRY + (hildon_caption_get_control (priv->passwordEntry)), + g_value_get_string(value)); + break; + case PROP_NUMBERS_ONLY: + /* Set input mode for the password entry */ + g_object_set(G_OBJECT(hildon_caption_get_control(priv->passwordEntry)), + "input-mode", + (g_value_get_boolean(value) + ? HILDON_INPUT_MODE_HINT_NUMERIC + : HILDON_INPUT_MODE_HINT_ALPHANUMERICSPECIAL), + NULL); + break; + case PROP_CAPTION_LABEL: + hildon_get_password_dialog_set_caption(dialog, g_value_get_string(value)); + break; + case PROP_MAX_CHARS: + hildon_get_password_dialog_set_max_characters(dialog, + g_value_get_int(value)); + break; + case PROP_GET_OLD: + priv->get_old = g_value_get_boolean(value); + create_contents(dialog); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +hildon_get_password_get_property(GObject * object, + guint prop_id, + GValue * value, GParamSpec * pspec) +{ + HildonGetPasswordDialog *dialog = HILDON_GET_PASSWORD_DIALOG(object); + HildonGetPasswordDialogPrivate *priv; + const gchar *string; + gint max_length; + gint input_mode; + + priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE(dialog); + + switch (prop_id) { + case PROP_DOMAIN: + string = gtk_label_get_text(priv->domainLabel); + g_value_set_string(value, string); + break; + case PROP_PASSWORD: + string = gtk_entry_get_text(GTK_ENTRY (hildon_caption_get_control(priv->passwordEntry))); + g_value_set_string(value, string); + break; + case PROP_NUMBERS_ONLY: + /* This property is set if and only if the input mode + of the password entry has been set to numeric only */ + g_object_get(G_OBJECT(hildon_caption_get_control(priv->passwordEntry)), + "input-mode", &input_mode, NULL); + g_value_set_boolean(value, + (input_mode == HILDON_INPUT_MODE_HINT_NUMERIC)); + break; + case PROP_CAPTION_LABEL: + string = hildon_caption_get_label(priv->passwordEntry); + g_value_set_string(value, string); + break; + case PROP_MAX_CHARS: + max_length = gtk_entry_get_max_length( + GTK_ENTRY (hildon_caption_get_control (priv->passwordEntry))); + g_value_set_int(value, max_length); + break; + case PROP_GET_OLD: + g_value_set_boolean(value, priv->get_old); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +hildon_get_password_dialog_class_init(HildonGetPasswordDialogClass * class) +{ + + GObjectClass *object_class = G_OBJECT_CLASS(class); + + parent_class = g_type_class_peek_parent(class); + + /* Override virtual functions */ + object_class->set_property = hildon_get_password_set_property; + object_class->get_property = hildon_get_password_get_property; + + /* Install new properties */ + g_object_class_install_property + (object_class, + PROP_DOMAIN, + g_param_spec_string ("domain", + "Domain", + "Set domain(content) for optional label.", + NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property + (object_class, + PROP_PASSWORD, + g_param_spec_string ("password", + "Password", + "Set content for password entry", + "DEFAULT", + G_PARAM_READWRITE)); + + g_object_class_install_property + (object_class, + PROP_NUMBERS_ONLY, + g_param_spec_boolean ("numbers_only", + "NumbersOnly", + "Set entry to accept only numeric values", + FALSE, + G_PARAM_READWRITE)); + + g_object_class_install_property + (object_class, + PROP_CAPTION_LABEL, + g_param_spec_string ("caption-label", + "Caption Label", + "The text to be set as the caption label", + NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property + (object_class, + PROP_MAX_CHARS, + g_param_spec_int ("max-characters", + "Maximum Characters", + "The maximum number of characters the password" + " dialog accepts", + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + g_object_class_install_property + (object_class, + PROP_GET_OLD, + g_param_spec_boolean ("get-old", + "Get Old Password", + "TRUE if dialog is a get old password dialog, " + "FALSE if dialog is a get password dialog", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + /* Install private structure */ + g_type_class_add_private(class, + sizeof(HildonGetPasswordDialogPrivate)); +} + +static void +hildon_get_password_dialog_init(HildonGetPasswordDialog * dialog) +{ + /* Set initial properties for the dialog; the actual contents are + created once the 'get-old' property is set with g_object_new */ + gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); + gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); + gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); +} + +static void +create_contents(HildonGetPasswordDialog *dialog) +{ + HildonGetPasswordDialogPrivate *priv; + GtkSizeGroup * group; + GtkWidget *control; + + /* Cache private pointer for faster member access */ + priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE(dialog); + + /* Sizegroup for captions */ + group = GTK_SIZE_GROUP(gtk_size_group_new + (GTK_SIZE_GROUP_HORIZONTAL)); + + /* Dialog title */ + gtk_window_set_title(GTK_WINDOW(dialog), + priv->get_old + ? _(HILDON_GET_PASSWORD_DIALOG_TITLE) + : _(HILDON_GET_PASSWORD_VERIFY_DIALOG_TITLE)); + + /* Optional password domain label */ + priv->domainLabel = GTK_LABEL(gtk_label_new(NULL)); + + /* Create buttons */ + priv->okButton = + GTK_BUTTON(gtk_dialog_add_button(GTK_DIALOG(dialog), + (priv->get_old + ? _(HILDON_GET_PASSWORD_DIALOG_OK) + : _(HILDON_GET_PASSWORD_VERIFY_DIALOG_OK)), + + GTK_RESPONSE_OK)); + priv->cancelButton = + GTK_BUTTON(gtk_dialog_add_button(GTK_DIALOG(dialog), + (priv->get_old + ? _(HILDON_GET_PASSWORD_DIALOG_CANCEL) + : _(HILDON_GET_PASSWORD_VERIFY_DIALOG_CANCEL)), + GTK_RESPONSE_CANCEL)); + + /* Create password text entry */ + control = gtk_entry_new(); + gtk_entry_set_width_chars (GTK_ENTRY (control), 20); + + g_object_set (control, "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL); + gtk_entry_set_visibility(GTK_ENTRY(control), FALSE); + priv->passwordEntry = HILDON_CAPTION + (hildon_caption_new(group, + (priv->get_old + ? _(HILDON_GET_PASSWORD_DIALOG_PASSWORD) + : _(HILDON_GET_PASSWORD_VERIFY_DIALOG_PASSWORD)), + control, NULL, + HILDON_CAPTION_OPTIONAL)); + hildon_caption_set_separator(HILDON_CAPTION(priv->passwordEntry), ""); + + /* Do the basic layout */ + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), + GTK_WIDGET(priv->domainLabel), FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), + GTK_WIDGET(priv->passwordEntry), FALSE, FALSE, 0); + gtk_widget_show_all(GTK_DIALOG(dialog)->vbox); + + /* Ensure group is freed when all its contents have been removed */ + g_object_unref(group); +} + + +/* Public functions */ + +/** + * hildon_get_password_dialog_get_type: + * + * Returns GType for HildonGetPasswordDialog as produced by + * g_type_register_static(). + * + * Returns: HildonGetPasswordDialog type + */ +GType hildon_get_password_dialog_get_type(void) +{ + static GType dialog_type = 0; + + if (!dialog_type) { + static const GTypeInfo dialog_info = { + sizeof(HildonGetPasswordDialogClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_get_password_dialog_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonGetPasswordDialog), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_get_password_dialog_init + }; + + dialog_type = g_type_register_static(GTK_TYPE_DIALOG, + "HildonGetPasswordDialog", + &dialog_info, 0); + } + return dialog_type; +} + +/** + * hildon_get_password_dialog_new: + * @parent: parent window; can be NULL + * @get_old: FALSE creates a new get password dialog and + * TRUE creates a new get old password dialog. That is, + * if the password to be obtained is the old password, + * this parameter is specified TRUE. + * + * Construct a new HildonGetPasswordDialog. + * + * Returns: a new #GtkWidget of type HildonGetPasswordDialog + */ +GtkWidget *hildon_get_password_dialog_new(GtkWindow * parent, + gboolean get_old) +{ + HildonGetPasswordDialog *dialog = g_object_new + (HILDON_TYPE_GET_PASSWORD_DIALOG, + "get-old", get_old, NULL); + + if (parent != NULL) { + gtk_window_set_transient_for(GTK_WINDOW(dialog), parent); + } + + return GTK_WIDGET(dialog); +} + +/** + * hildon_get_password_dialog_new_with_default: + * @parent: parent window; can be NULL + * @password: a default password to be shown in password field + * @get_old: FALSE creates a new get password dialog and + * TRUE creates a new get old password dialog.That is, + * if the password to be obtained is the old password, + * this parameter is specified TRUE. + * + * + * Same as #hildon_get_password_dialog_new but with a default password + * in password field. + * + * Returns: a new #GtkWidget of type HildonGetPasswordDialog + */ +GtkWidget *hildon_get_password_dialog_new_with_default (GtkWindow * parent, + const gchar *password, + gboolean get_old) +{ + GtkWidget *dialog; + + dialog = hildon_get_password_dialog_new(parent, get_old); + if(password != NULL) + g_object_set(G_OBJECT(dialog), "password", password, NULL); + + return GTK_WIDGET(dialog); +} + +/** + * hildon_get_password_dialog_get_password: + * @dialog: pointer to HildonSetPasswordDialog + * + * Gets the currently inputted password. + * + * Returns: current password ( if the dialog is successfully + * accepted with 'OK' ) + */ +const gchar + *hildon_get_password_dialog_get_password(HildonGetPasswordDialog * + dialog) +{ + GtkEntry *entry1; + gchar *text1; + + HildonGetPasswordDialogPrivate *priv; + + g_return_val_if_fail (HILDON_IS_GET_PASSWORD_DIALOG(dialog), NULL); + priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE(dialog); + + /* Retrieve the password entry widget */ + entry1 = GTK_ENTRY (hildon_caption_get_control(priv->passwordEntry)); + text1 = GTK_ENTRY(entry1)->text; + + return text1; +} + +/** + * hildon_get_password_dialog_set_domain(GtkWidget *dialog, + * @dialog: the dialog + * @domain: the domain or some other descriptive text to be set + * + * Sets the optional descriptive text. + */ + +void hildon_get_password_dialog_set_domain(HildonGetPasswordDialog *dialog, + const gchar *domain) +{ + HildonGetPasswordDialogPrivate *priv; + + g_return_if_fail (HILDON_IS_GET_PASSWORD_DIALOG(dialog)); + + priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE(dialog); + gtk_label_set_text(priv->domainLabel, domain); + +} + +/** + * hildon_get_password_dialog_set_title: + * @dialog: the dialog + * @new_title: the text to be set as the dialog title + * + * Sets the dialog title. + * + * DEPRECATED! use gtk_window_set_title instead. + */ +void hildon_get_password_dialog_set_title(HildonGetPasswordDialog *dialog, + const gchar *new_title) + +{ + /* FIXME: This method is completely useless, should be deprecated/removed */ + g_return_if_fail (HILDON_IS_GET_PASSWORD_DIALOG(dialog)); + g_return_if_fail (new_title !=NULL); + gtk_window_set_title(GTK_WINDOW(dialog), + new_title); +} + +/** + * hildon_get_password_dialog_set_caption: + * @dialog: the dialog + * @new_caption: the text to be set as the caption label + * + * Sets the password entry field's neigbouring label. + */ + +void hildon_get_password_dialog_set_caption(HildonGetPasswordDialog *dialog, + const gchar *new_caption) +{ + + + HildonGetPasswordDialogPrivate *priv; + + g_return_if_fail (HILDON_IS_GET_PASSWORD_DIALOG(dialog)); + g_return_if_fail (new_caption != NULL); + + priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE(dialog); + hildon_caption_set_label(priv->passwordEntry, new_caption); + +} + +/** + * hildon_get_password_dialog_set_max_characters: + * @dialog: the dialog + * @max_characters: the maximum number of characters the password dialog + * accepts + * @new_caption: the text to be set as the caption label + * + * sets the maximum number of characters allowed as the password + */ + +void hildon_get_password_dialog_set_max_characters (HildonGetPasswordDialog *dialog, gint max_characters ) +{ + HildonGetPasswordDialogPrivate *priv; + + g_return_if_fail (max_characters > 0); + g_return_if_fail (HILDON_IS_GET_PASSWORD_DIALOG(dialog)); + + priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE(dialog); + + /* Apply the given length to password entry */ + gtk_entry_set_max_length(GTK_ENTRY + (hildon_caption_get_control + (priv->passwordEntry)), + max_characters); + + /* Connect callback to show error banner if the limit is exceeded */ + g_signal_connect(GTK_ENTRY + (hildon_caption_get_control + (priv->passwordEntry)), + "invalid_input", + G_CALLBACK(_invalid_input), + NULL + ); +} + +static void _invalid_input(GtkWidget *widget, GtkInvalidInputType reason, + gpointer unused) +{ + if (reason==GTK_INVALID_INPUT_MAX_CHARS_REACHED) { + gtk_infoprint(GTK_WINDOW(widget), _(HILDON_GET_PASSWORD_DIALOG_MAX_CHARS)); + } +} diff --git a/src/hildon-get-password-dialog.h b/src/hildon-get-password-dialog.h new file mode 100644 index 0000000..bca82da --- /dev/null +++ b/src/hildon-get-password-dialog.h @@ -0,0 +1,99 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_GET_PASSWORD_DIALOG_H__ +#define __HILDON_GET_PASSWORD_DIALOG_H__ + +#include + +G_BEGIN_DECLS + +#define HILDON_TYPE_GET_PASSWORD_DIALOG ( hildon_get_password_dialog_get_type() ) + +#define HILDON_GET_PASSWORD_DIALOG(obj) \ + (GTK_CHECK_CAST (obj, HILDON_TYPE_GET_PASSWORD_DIALOG,\ + HildonGetPasswordDialog)) + +#define HILDON_GET_PASSWORD_DIALOG_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST ((klass), HILDON_TYPE_GET_PASSWORD_DIALOG, \ + HildonGetPasswordDialogClass)) + +#define HILDON_IS_GET_PASSWORD_DIALOG(obj) \ + (GTK_CHECK_TYPE (obj, HILDON_TYPE_GET_PASSWORD_DIALOG)) + +#define HILDON_IS_GET_PASSWORD_DIALOG_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_GET_PASSWORD_DIALOG)) + + +#define HILDON_GET_PASSWORD_DIALOG_TITLE "ecdg_ti_get_old_password" +#define HILDON_GET_PASSWORD_DIALOG_PASSWORD "ecdg_fi_get_old_pwd_enter_pwd" +#define HILDON_GET_PASSWORD_DIALOG_OK "ecdg_bd_get_old_password_dialog_ok" +#define HILDON_GET_PASSWORD_DIALOG_CANCEL "ecdg_bd_get_old_password_dialog_cancel" + +#define HILDON_GET_PASSWORD_VERIFY_DIALOG_TITLE "ecdg_ti_verify_password" +#define HILDON_GET_PASSWORD_VERIFY_DIALOG_PASSWORD "ecdg_fi_verify_pwd_enter_pwd" +#define HILDON_GET_PASSWORD_VERIFY_DIALOG_OK "ecdg_bd_verify_password_dialog_ok" +#define HILDON_GET_PASSWORD_VERIFY_DIALOG_CANCEL "ecdg_bd_verify_password_dialog_cancel" + +#define HILDON_GET_PASSWORD_DIALOG_MAX_CHARS "ckdg_ib_maximum_characters_reached" + +typedef struct _HildonGetPasswordDialog HildonGetPasswordDialog; +typedef struct _HildonGetPasswordDialogClass HildonGetPasswordDialogClass; + +struct _HildonGetPasswordDialog { + GtkDialog parent; +}; + +struct _HildonGetPasswordDialogClass { + GtkDialogClass parent_class; +}; + +GType hildon_get_password_dialog_get_type(void) G_GNUC_CONST; + +GtkWidget *hildon_get_password_dialog_new (GtkWindow *parent, + gboolean get_old); + +GtkWidget *hildon_get_password_dialog_new_with_default (GtkWindow *parent, + const gchar *password, + gboolean get_old); + +void hildon_get_password_dialog_set_domain (HildonGetPasswordDialog *dialog, + const gchar *domain); + +void hildon_get_password_dialog_set_caption (HildonGetPasswordDialog *dialog, + const gchar *new_caption); + +void hildon_get_password_dialog_set_max_characters(HildonGetPasswordDialog *dialog, + gint max_characters); + +const gchar * hildon_get_password_dialog_get_password(HildonGetPasswordDialog * dialog); + + +#ifndef HILDON_DISABLE_DEPRECATED +void hildon_get_password_dialog_set_title (HildonGetPasswordDialog *dialog, + const gchar *new_title); +#endif /* HILDON_DISABLE_DEPRECATED */ + +G_END_DECLS +#endif /* __HILDON_GET_PASSWORD_DIALOG_H__ */ diff --git a/src/hildon-grid-item-private.h b/src/hildon-grid-item-private.h new file mode 100644 index 0000000..23ed7db --- /dev/null +++ b/src/hildon-grid-item-private.h @@ -0,0 +1,71 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/* + * @file hildon-grid-item-private.h + * + * This file is a private header file for he implementation of + * HildonGridItem. HildonGridItem is an item mainly used in HildonGrid. It + * has an icon, emblem and a label. This private header file exists so that + * grid can call semi-public functions of an item. + */ + +#ifndef __HILDON_GRID_ITEM_PRIVATE_H__ +#define __HILDON_GRID_ITEM_PRIVATE_H__ + +#include + +G_BEGIN_DECLS + + +void _hildon_grid_item_set_label(HildonGridItem *item, + const gchar *label); + +void _hildon_grid_item_set_emblem_size(HildonGridItem *item, + const gint emblem_size); +void _hildon_grid_item_set_label_pos(HildonGridItem *item, + HildonGridPositionType label_pos); + +void _hildon_grid_item_set_icon_size(HildonGridItem *item, + HildonGridItemIconSizeType icon_size); + +void _hildon_grid_item_set_focus_margin(HildonGridItem *item, + const gint focus_margin); +void _hildon_grid_item_set_label_height(HildonGridItem *item, + const gint label_height); +void _hildon_grid_item_set_label_icon_margin(HildonGridItem *item, + const gint label_icon_margin); +void _hildon_grid_item_set_icon_width(HildonGridItem *item, + const gint icon_width); +void _hildon_grid_item_set_icon_height(HildonGridItem *item, + const gint icon_height); +void _hildon_grid_item_set_label_height(HildonGridItem *item, + const gint label_height); + +void _hildon_grid_item_done_updating_settings(HildonGridItem *item); + + +G_END_DECLS + +#endif /* __HILDON_GRID_ITEM_PRIVATE_H__ */ diff --git a/src/hildon-grid-item.c b/src/hildon-grid-item.c new file mode 100644 index 0000000..2edd68c --- /dev/null +++ b/src/hildon-grid-item.c @@ -0,0 +1,1020 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-grid-item + * @short_description: Creating grid items used by #HildonGrid + * @see_also: #HildonGrid + * + * HildonGridItem is used to create grid items used by #HildonGrid. The + * grid item consists of an icon and a label. Based on the displaying + * mode employed by #HildonGrid, the label is justified to the right or + * the bottom. + */ + +/* + * TODO: + * - play with libtool to get _-functions private but accesable from grid + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "hildon-grid-item-private.h" +#include + +#include +#define _(String) dgettext(PACKAGE, String) + +#define HILDON_GRID_ITEM_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_GRID_ITEM, \ + HildonGridItemPrivate)) + +typedef struct _HildonGridItemPrivate HildonGridItemPrivate; + + +/* Default icon. */ +#define DEFAULT_ICON_BASENAME "qgn_list_gene_unknown_file" +#define HILDON_GRID_ICON_SIZE 26 +#define HILDON_GRID_EMBLEM_SIZE 16 + +/* Use some alpha-thing for emblems. */ +#define USE_DIRTY_ALPHA + +struct _HildonGridItemPrivate { + gchar *icon_basename; + gint icon_size; + GtkWidget *icon; + + gchar *emblem_basename; + gint emblem_size; + + GtkWidget *label; /* TODO use pango! */ + HildonGridPositionType label_pos; + + gint focus_margin; + gint label_height; + gint label_icon_margin; + gint column_margin; + gint icon_width; + gint icon_height; + gint row_height; + + gint pending_icon_size; + gint pending_emblem_size; + HildonGridPositionType pending_label_pos; + gint pending_focus_margin; + gint pending_label_height; + gint pending_label_icon_margin; + gint pending_icon_width; + gint pending_icon_height; + + gboolean selected; +}; + +enum{ + PROP_NONE = 0, + PROP_EMBLEM_TYPE, + PROP_ICON_BASENAME +}; + +/* Prototypes. */ +static void hildon_grid_item_class_init(HildonGridItemClass * klass); +static void hildon_grid_item_init(HildonGridItem * item); +static gboolean hildon_grid_item_expose(GtkWidget * widget, + GdkEventExpose * event); +static void hildon_grid_item_size_request(GtkWidget * widget, + GtkRequisition * requisition); +static void hildon_grid_item_size_allocate(GtkWidget * widget, + GtkAllocation * allocation); +static void hildon_grid_item_forall(GtkContainer * container, + gboolean include_int, + GtkCallback callback, + gpointer callback_data); +static void hildon_grid_item_remove(GtkContainer * container, + GtkWidget * child); + +static void hildon_grid_item_finalize(GObject * object); + +static void update_icon(HildonGridItem * item); +static void set_label_justify(HildonGridItem * item); + +static void hildon_grid_item_set_icon_size(HildonGridItem *item, + HildonGridItemIconSizeType icon_size); + +static void hildon_grid_item_set_property(GObject * object, + guint prop_id, + const GValue * value, + GParamSpec * pspec); + +static void hildon_grid_item_get_property(GObject * object, + guint prop_id, GValue * value, + GParamSpec * pspec); + + +static GtkContainerClass *parent_class = NULL; + +/* Private functions */ +static void +hildon_grid_item_set_property(GObject * object, + guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + HildonGridItem *item = HILDON_GRID_ITEM(object); + HildonGridItemPrivate *priv; + + priv = HILDON_GRID_ITEM_GET_PRIVATE(item); + + switch (prop_id) { + case PROP_EMBLEM_TYPE: + hildon_grid_item_set_emblem_type(item, g_value_get_string(value)); + break; + case PROP_ICON_BASENAME: + if(priv->icon_basename) + g_free(priv->icon_basename); + + priv->icon_basename = g_strdup(g_value_get_string(value)); + update_icon(item); + + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +hildon_grid_item_get_property(GObject * object, + guint prop_id, + GValue * value, GParamSpec * pspec) +{ + HildonGridItem *item = HILDON_GRID_ITEM(object); + HildonGridItemPrivate *priv; + const gchar *string; + + priv = HILDON_GRID_ITEM_GET_PRIVATE(item); + + switch (prop_id) { + case PROP_EMBLEM_TYPE: + string = hildon_grid_item_get_emblem_type(item); + g_value_set_string(value, string); + break; + case PROP_ICON_BASENAME: + g_value_set_string(value, priv->icon_basename); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + + +GType +hildon_grid_item_get_type(void) +{ + static GType grid_item_type = 0; + + if (!grid_item_type) { + static const GTypeInfo grid_item_info = { + sizeof(HildonGridItemClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_grid_item_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonGridItem), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_grid_item_init, + }; + grid_item_type = g_type_register_static(GTK_TYPE_CONTAINER, + "HildonGridItem", + &grid_item_info, 0); + } + + return grid_item_type; +} + +static void +hildon_grid_item_class_init(HildonGridItemClass *klass) +{ + GtkWidgetClass *widget_class; + GtkContainerClass *container_class; + GObjectClass *gobject_class; + + widget_class = GTK_WIDGET_CLASS(klass); + gobject_class = G_OBJECT_CLASS(klass); + container_class = GTK_CONTAINER_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + g_type_class_add_private(klass, sizeof(HildonGridItemPrivate)); + + gobject_class->finalize = hildon_grid_item_finalize; + + widget_class->expose_event = hildon_grid_item_expose; + widget_class->size_request = hildon_grid_item_size_request; + widget_class->size_allocate = hildon_grid_item_size_allocate; + + container_class->forall = hildon_grid_item_forall; + container_class->remove = hildon_grid_item_remove; + + gobject_class->set_property = hildon_grid_item_set_property; + gobject_class->get_property = hildon_grid_item_get_property; + + g_object_class_install_property + (gobject_class, + PROP_EMBLEM_TYPE, + g_param_spec_string ("emblem-type", + "Emblem Type", + "The emblem's basename", + NULL, + G_PARAM_WRITABLE)); + + g_object_class_install_property + (gobject_class, + PROP_ICON_BASENAME, + g_param_spec_string ("icon-basename", + "Icon Basename", + "The icon's basename", + NULL, + G_PARAM_WRITABLE)); + +} + +static void +hildon_grid_item_init(HildonGridItem *item) +{ + HildonGridItemPrivate *priv; + + priv = HILDON_GRID_ITEM_GET_PRIVATE(item); + + priv->icon_basename = NULL; + priv->pending_icon_size = priv->icon_size = HILDON_GRID_ICON_SIZE; + priv->icon = NULL; + + priv->emblem_basename = NULL; + priv->pending_emblem_size = priv->emblem_size = HILDON_GRID_EMBLEM_SIZE; + + priv->label = NULL; + priv->pending_label_pos = priv->label_pos = + HILDON_GRID_ITEM_LABEL_POS_BOTTOM; + + priv->selected = FALSE; + + priv->pending_focus_margin = priv->focus_margin = 6; + priv->pending_label_height = priv->label_height = 30; + priv->pending_label_icon_margin = priv->label_icon_margin = 6; + priv->pending_icon_width = priv->icon_width = 64; + priv->pending_icon_height = priv->icon_height = 54; + priv->pending_label_height = priv->label_height = 30; + + + GTK_WIDGET_SET_FLAGS(GTK_WIDGET(item), GTK_CAN_FOCUS); + + priv->label = gtk_label_new(NULL); + gtk_widget_set_name(priv->label, "hildon-grid-item-label"); + gtk_widget_set_parent(priv->label, GTK_WIDGET(item)); + + update_icon(item); + set_label_justify(item); + + gtk_widget_show(priv->label); +} + +/** + * hildon_grid_item_new: + * @icon_basename: icon base name + * + * Creates a new #HildonGridItem. + * + * Returns: a new #HildonGridItem + */ +GtkWidget * +hildon_grid_item_new(const gchar *icon_basename) +{ + HildonGridItem *item; + + item = g_object_new(HILDON_TYPE_GRID_ITEM, "icon-basename", icon_basename, NULL); + + return GTK_WIDGET(item); +} + +/** + * hildon_grid_item_new_with_label: + * @icon_basename: icon base name + * @label: text label for icon + * + * Creates a new #HildonGridItem with a specified label for the icon. + * + * Returns: a new #HildonGridItem + */ +GtkWidget * +hildon_grid_item_new_with_label(const gchar *icon_basename, + const gchar *label) +{ + HildonGridItem *item; + + item = g_object_new(HILDON_TYPE_GRID_ITEM, "icon-basename", icon_basename, NULL); + + hildon_grid_item_set_label(item, label); + + return GTK_WIDGET(item); +} + + +static void +update_icon(HildonGridItem *item) +{ + GtkIconTheme *icon_theme; + GdkPixbuf *icon; + GdkPixbuf *emblem_icon; + HildonGridItemPrivate *priv; + GError *error; + + priv = HILDON_GRID_ITEM_GET_PRIVATE(item); + + if (priv->icon != NULL) { + if (GTK_WIDGET_VISIBLE(priv->icon)) + gtk_widget_hide(priv->icon); + gtk_widget_unparent(priv->icon); + } + + icon_theme = gtk_icon_theme_get_default(); + + /* Load icon. Fall to default if loading fails. */ + icon = NULL; + if (priv->icon_basename) + { + error = NULL; + icon = gtk_icon_theme_load_icon(icon_theme, + priv->icon_basename, + priv->icon_size, 0, &error); + if (icon == NULL) { + g_warning("Couldn't load icon \"%s\": %s", priv->icon_basename, + error->message); + g_error_free(error); + } + } + + if (icon == NULL) { + error = NULL; + icon = gtk_icon_theme_load_icon(icon_theme, + DEFAULT_ICON_BASENAME, + priv->icon_size, 0, &error); + if (icon == NULL) { + g_warning("Couldn't load default icon: %s!\n", error->message); + g_error_free(error); + } + } + priv->icon_width = gdk_pixbuf_get_width(icon); + priv->icon_height = gdk_pixbuf_get_height(icon); + + + /* Load and merge emblem if one is specified. */ + if (priv->emblem_basename != NULL) { + error = NULL; + emblem_icon = gtk_icon_theme_load_icon(icon_theme, + priv->emblem_basename, + priv->emblem_size, + 0, &error); + if (emblem_icon == NULL) { + g_warning("Couldn't load emblem \"%s\": %s", + priv->emblem_basename, error->message); + g_error_free(error); + } else { + gint icon_height; + gint width, height, y; + +#ifdef USE_DIRTY_ALPHA + GdkPixbuf *tmp; +#endif + + icon_height = gdk_pixbuf_get_height(icon); + width = MIN(gdk_pixbuf_get_width(emblem_icon), + gdk_pixbuf_get_width(icon)); + height = MIN(gdk_pixbuf_get_height(emblem_icon), icon_height); + y = icon_height - height; +#ifndef USE_DIRTY_ALPHA + gdk_pixbuf_copy_area(emblem_icon, 0, 0, width, height, + icon, 0, y); +#else + /* + * Using composite to copy emblem to lower left corner creates + * some garbage on top of emblem. This way it can be avoided. + */ + tmp = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, + 8, width, icon_height); + gdk_pixbuf_fill(tmp, 0x00000000); + gdk_pixbuf_copy_area(emblem_icon, 0, 0, width, height, + tmp, 0, y); + gdk_pixbuf_composite(tmp, icon, + 0, 0, width, icon_height, + 0.0, 0.0, 1.0, 1.0, + GDK_INTERP_NEAREST, 255); + g_object_unref(tmp); +#endif /* ifndef else USE_DIRTY_ALPHA */ + g_object_unref(emblem_icon); + } + } + + priv->icon = gtk_image_new_from_pixbuf(icon); + g_object_unref(icon); + + gtk_widget_set_parent(priv->icon, GTK_WIDGET(item)); + gtk_widget_show(priv->icon); + + gtk_widget_queue_draw(priv->icon); +} + +void +hildon_grid_item_set_label(HildonGridItem *item, const gchar *label) +{ + HildonGridItemPrivate *priv; + + g_return_if_fail(HILDON_IS_GRID_ITEM(item)); + + if (label == NULL) + label = ""; + + priv = HILDON_GRID_ITEM_GET_PRIVATE(item); + if (strcmp (gtk_label_get_label (GTK_LABEL (priv->label)), label) == 0) + return; + gtk_label_set_label(GTK_LABEL(priv->label), label); +} + +static void +hildon_grid_item_set_icon_size(HildonGridItem *item, + HildonGridItemIconSizeType icon_size) +{ + HildonGridItemPrivate *priv; + + g_return_if_fail(HILDON_IS_GRID_ITEM(item)); + + priv = HILDON_GRID_ITEM_GET_PRIVATE(item); + if (priv->pending_icon_size == icon_size) { + return; + } + priv->pending_icon_size = icon_size; +} + + +void +_hildon_grid_item_set_label_pos(HildonGridItem *item, + HildonGridPositionType label_pos) +{ + HildonGridItemPrivate *priv; + + g_return_if_fail(HILDON_IS_GRID_ITEM(item)); + + priv = HILDON_GRID_ITEM_GET_PRIVATE(item); + if (priv->pending_label_pos == label_pos) { + return; + } + priv->pending_label_pos = label_pos; +} + + +void +_hildon_grid_item_set_emblem_size(HildonGridItem *item, gint emblem_size) +{ + HildonGridItemPrivate *priv; + + g_return_if_fail(HILDON_IS_GRID_ITEM(item)); + + priv = HILDON_GRID_ITEM_GET_PRIVATE(item); + if (priv->pending_emblem_size == emblem_size) { + return; + } + priv->pending_emblem_size = emblem_size; +} + + +void +_hildon_grid_item_set_focus_margin(HildonGridItem *item, + const gint focus_margin) +{ + HildonGridItemPrivate *priv; + + g_return_if_fail(HILDON_IS_GRID_ITEM(item)); + + priv = HILDON_GRID_ITEM_GET_PRIVATE(item); + if (priv->pending_focus_margin == focus_margin) { + return; + } + priv->pending_focus_margin = focus_margin; +} + + +void +_hildon_grid_item_set_label_height(HildonGridItem *item, + const gint label_height) +{ + HildonGridItemPrivate *priv; + + g_return_if_fail(HILDON_IS_GRID_ITEM(item)); + + priv = HILDON_GRID_ITEM_GET_PRIVATE(item); + if (priv->pending_label_height == label_height) { + return; + } + priv->pending_label_height = label_height; +} + + +void +_hildon_grid_item_set_label_icon_margin(HildonGridItem *item, + const gint label_icon_margin) +{ + HildonGridItemPrivate *priv; + + g_return_if_fail(HILDON_IS_GRID_ITEM(item)); + + priv = HILDON_GRID_ITEM_GET_PRIVATE(item); + if (priv->pending_label_icon_margin == label_icon_margin) { + return; + } + priv->pending_label_icon_margin = label_icon_margin; +} + + +void +_hildon_grid_item_set_icon_height(HildonGridItem *item, + const gint icon_height) +{ + HildonGridItemPrivate *priv; + + g_return_if_fail(HILDON_IS_GRID_ITEM(item)); + + priv = HILDON_GRID_ITEM_GET_PRIVATE(item); + if (priv->pending_icon_height == icon_height) { + return; + } + priv->pending_icon_height = icon_height; +} + + +void +_hildon_grid_item_set_icon_width(HildonGridItem *item, + const gint icon_width) +{ + HildonGridItemPrivate *priv; + + g_return_if_fail(HILDON_IS_GRID_ITEM(item)); + + hildon_grid_item_set_icon_size(item, icon_width); + + priv = HILDON_GRID_ITEM_GET_PRIVATE(item); + if (priv->pending_icon_width == icon_width) { + return; + } + priv->pending_icon_width = icon_width; +} + + +static void +set_label_justify(HildonGridItem *item) +{ + HildonGridItemPrivate *priv; + + priv = HILDON_GRID_ITEM_GET_PRIVATE(item); + + if (priv->label != NULL) { + switch (priv->label_pos) { + case HILDON_GRID_ITEM_LABEL_POS_BOTTOM: + gtk_misc_set_alignment(GTK_MISC(priv->label), 0.5, 0.5); + break; + + case HILDON_GRID_ITEM_LABEL_POS_RIGHT: + gtk_misc_set_alignment(GTK_MISC(priv->label), 0.0, 0.5); + break; + + default: + g_warning("Invalid position!"); + break; + } + } +} + +static void +hildon_grid_item_remove(GtkContainer *container, GtkWidget *child) +{ + HildonGridItem *item; + HildonGridItemPrivate *priv; + + item = HILDON_GRID_ITEM(container); + priv = HILDON_GRID_ITEM_GET_PRIVATE(item); + + g_return_if_fail(GTK_IS_WIDGET(child)); + g_return_if_fail(child == priv->label || child == priv->icon); + + if (child == priv->label) { + gtk_widget_unparent(child); + priv->label = NULL; + } else if (child == priv->icon) { + gtk_widget_unparent(child); + priv->icon = NULL; + } +} + +static gboolean +hildon_grid_item_expose(GtkWidget *widget, GdkEventExpose *event) +{ + HildonGridItem *item; + HildonGridItemPrivate *priv; + + g_return_val_if_fail(widget, FALSE); + g_return_val_if_fail(HILDON_IS_GRID_ITEM(widget), FALSE); + g_return_val_if_fail(event, FALSE); + + item = HILDON_GRID_ITEM(widget); + priv = HILDON_GRID_ITEM_GET_PRIVATE(item); + + if (priv->label == NULL && priv->icon == NULL) { + return FALSE; + } + if (GTK_WIDGET_HAS_FOCUS(GTK_WIDGET(item))) { + GdkRectangle clip; + GtkWidget *focused; + + if (priv->label != NULL) { + focused = priv->label; + } else { + focused = priv->icon; + } + + /* Determine the coordinates and size of clip */ + switch (priv->label_pos) { + case HILDON_GRID_ITEM_LABEL_POS_BOTTOM: + clip.x = focused->allocation.x - priv->focus_margin; + clip.y = focused->allocation.y; + clip.width = focused->allocation.width + priv->focus_margin * 2; + clip.height = focused->allocation.height; + if (clip.x < widget->allocation.x || + clip.width > widget->allocation.width) { + clip.x = widget->allocation.x; + clip.width = widget->allocation.width; + } + if (clip.y + clip.height > + widget->allocation.y + widget->allocation.height) { + clip.height = widget->allocation.y + + widget->allocation.height - clip.y; + } + break; + + case HILDON_GRID_ITEM_LABEL_POS_RIGHT: + clip.x = widget->allocation.x; + clip.y = widget->allocation.y; + clip.width = widget->allocation.width; + clip.height = widget->allocation.height; + break; + } + + /* Build painting box for the exposure event */ + gtk_paint_box(focused->style, + gtk_widget_get_toplevel(focused)->window, + GTK_STATE_SELECTED, + GTK_SHADOW_NONE, + &clip, focused, "selected", + clip.x, clip.y, clip.width, clip.height); + } + + /* + * Items are not exposed unless they are visible. + * -> No need to "optimize" by checking if they need exposing. + */ + gtk_container_propagate_expose(GTK_CONTAINER(widget), + priv->icon, event); + gtk_container_propagate_expose(GTK_CONTAINER(widget), + priv->label, event); + return TRUE; +} + + +static void +hildon_grid_item_size_request(GtkWidget *widget, GtkRequisition *requisition) +{ + HildonGridItem *item; + HildonGridItemPrivate *priv; + GtkRequisition label_req; + gint label_margin; + + item = HILDON_GRID_ITEM(widget); + priv = HILDON_GRID_ITEM_GET_PRIVATE(item); + + label_margin = priv->focus_margin; + + gtk_widget_size_request(priv->icon, requisition); + gtk_widget_size_request(priv->label, &label_req); + + switch (priv->label_pos) { + case HILDON_GRID_ITEM_LABEL_POS_BOTTOM: + requisition->width = MAX(requisition->width, label_req.width); + requisition->height += label_req.height + label_margin; + break; + + case HILDON_GRID_ITEM_LABEL_POS_RIGHT: + requisition->width += label_req.width + label_margin; + requisition->height = MAX(requisition->height, label_req.height); + break; + default: + g_warning("bad position"); + return; + break; + } +} + +static void +hildon_grid_item_size_allocate(GtkWidget *widget, GtkAllocation *allocation) +{ + HildonGridItem *item; + HildonGridItemPrivate *priv; + GtkRequisition l_req; + GtkAllocation i_alloc, l_alloc; + + g_return_if_fail(widget); + g_return_if_fail(allocation); + + item = HILDON_GRID_ITEM(widget); + priv = HILDON_GRID_ITEM_GET_PRIVATE(item); + widget->allocation = *allocation; + + /* If creating label and icon failed, don't show a thing... */ + if (priv->label == NULL && priv->icon == NULL) { + return; + } + if (priv->label != NULL) { + gtk_widget_get_child_requisition(priv->label, &l_req); + } else { + l_req.width = l_req.height = 0; + } + + /* Determine icon and label allocation based on label position */ + switch (priv->label_pos) { + case HILDON_GRID_ITEM_LABEL_POS_BOTTOM: + i_alloc.x = (allocation->width - priv->icon_width) / 2 + + allocation->x; + if (priv->label != NULL) { + i_alloc.y = allocation->y + (allocation->height - + priv->label_height - + priv->label_icon_margin - + priv->icon_height) / 2; + } else { + i_alloc.y = (allocation->height - priv->icon_height) / 2 + + allocation->y; + } + + if (priv->label != NULL) { + l_alloc.x = allocation->x + priv->focus_margin; + l_alloc.y = i_alloc.y + priv->icon_height + + priv->label_icon_margin; + l_alloc.width = allocation->width - priv->focus_margin * 2; + l_alloc.height = priv->label_height; + } + break; + + case HILDON_GRID_ITEM_LABEL_POS_RIGHT: + i_alloc.x = allocation->x + priv->focus_margin; + i_alloc.y = allocation->y + + (priv->label_height - priv->icon_height) / 2; + + if (priv->label != NULL) { + l_alloc.x = allocation->x + priv->focus_margin + + priv->icon_width + priv->label_icon_margin; + l_alloc.y = allocation->y; + l_alloc.width = allocation->width - priv->focus_margin * 2 - + priv->label_icon_margin - priv->icon_width; + l_alloc.height = priv->label_height; + } + break; + default: + g_warning("bad label position"); + return; + break; + } + + if (i_alloc.y < allocation->y) { + i_alloc.height -= i_alloc.height - allocation->height; + i_alloc.y = allocation->y; + } + if (i_alloc.y + i_alloc.height > allocation->y + allocation->height) { + i_alloc.height-= i_alloc.y + i_alloc.height - + allocation->y - allocation->height; + } + + + i_alloc.width = priv->icon_width; + i_alloc.height = priv->icon_height; + + if (priv->label != NULL) { + gtk_widget_size_allocate(priv->label, &l_alloc); + } + if (priv->icon != NULL) { + gtk_widget_size_allocate(priv->icon, &i_alloc); + } +} + +static void +hildon_grid_item_forall(GtkContainer *container, + gboolean include_int, + GtkCallback callback, + gpointer callback_data) +{ + HildonGridItem *item; + HildonGridItemPrivate *priv; + + g_return_if_fail(container); + g_return_if_fail(callback); + + item = HILDON_GRID_ITEM(container); + priv = HILDON_GRID_ITEM_GET_PRIVATE(item); + + /* Connect callback functions to the item */ + if (priv->icon != NULL) { + (*callback) (priv->icon, callback_data); + } + if (priv->label != NULL) { + (*callback) (priv->label, callback_data); + } +} + +static void +hildon_grid_item_finalize(GObject *object) +{ + HildonGridItem *item; + HildonGridItemPrivate *priv; + + item = HILDON_GRID_ITEM(object); + priv = HILDON_GRID_ITEM_GET_PRIVATE(item); + + g_free(priv->icon_basename); + if (priv->emblem_basename != NULL) { + g_free(priv->emblem_basename); + } + + G_OBJECT_CLASS(parent_class)->finalize(object); +} + +#if 0 +static int hildon_time_get_font_width(GtkWidget * widget) +{ + PangoContext *context; + PangoFontMetrics *metrics; + gint digit_width; + + context = gtk_widget_get_pango_context(widget); + metrics = pango_context_get_metrics(context, + widget->style->font_desc, + pango_context_get_language + (context)); + + digit_width = pango_font_metrics_get_approximate_digit_width(metrics); + digit_width = PANGO_PIXELS(digit_width); + + pango_font_metrics_unref(metrics); + + return digit_width; +} +#endif + + +/** + * hildon_grid_item_set_emblem_type: + * @item: #HildonGridItem + * @emblem_basename: emblem's basename + * + * Sets item emblem type. + */ +void +hildon_grid_item_set_emblem_type(HildonGridItem *item, + const gchar *emblem_basename) +{ + HildonGridItemPrivate *priv; + + g_return_if_fail(HILDON_IS_GRID_ITEM(item)); + + priv = HILDON_GRID_ITEM_GET_PRIVATE(item); + + if (priv->emblem_basename != NULL) { + g_free(priv->emblem_basename); + } + + priv->emblem_basename = g_strdup(emblem_basename); + + update_icon(item); + + g_object_notify (G_OBJECT (item), "emblem-type"); +} + +/** + * hildon_grid_item_get_emblem_type: + * @item: #HildonGridItem + * + * Returns: emblem's basename. Must not be changed or freed. + */ +const gchar * +hildon_grid_item_get_emblem_type(HildonGridItem *item) +{ + g_return_val_if_fail(HILDON_IS_GRID_ITEM(item), NULL); + + return HILDON_GRID_ITEM_GET_PRIVATE(item)->emblem_basename; +} + + + +void +_hildon_grid_item_done_updating_settings(HildonGridItem *item) +{ + gboolean need_update_icon; + gboolean need_resize; + + HildonGridItemPrivate *priv; + g_return_if_fail(HILDON_IS_GRID_ITEM(item)); + priv = HILDON_GRID_ITEM_GET_PRIVATE(item); + + need_update_icon = need_resize = FALSE; + + if (priv->pending_icon_size != priv->icon_size) { + if (priv->pending_icon_size > 0) { + priv->icon_size = priv->pending_icon_size; + } else { + priv->icon_size = 1; + } + need_update_icon = TRUE; + } + if (priv->pending_emblem_size != priv->emblem_size) { + priv->emblem_size = priv->pending_emblem_size; + need_update_icon = TRUE; + } + if (priv->pending_label_pos != priv->label_pos) { + priv->label_pos = priv->pending_label_pos; + /* No refresh here, grid will do it. */ + set_label_justify(item); + } + /* + * grid will take care of this + * + if (priv->pending_focus_margin != priv->focus_margin) { + priv->focus_margin = priv->pending_focus_margin; + need_resize = TRUE; + } + if (priv->pending_label_height != priv->label_height) { + priv->label_height = priv->pending_label_height; + need_resize = TRUE; + } + if (priv->pending_label_icon_margin != priv->label_icon_margin) { + priv->label_icon_margin = priv->pending_label_icon_margin; + need_resize = TRUE; + } + if (priv->pending_icon_height != priv->icon_height) { + priv->icon_height = priv->pending_icon_height; + need_resize = TRUE; + } + if (priv->pending_icon_width != priv->icon_width) { + priv->icon_width = priv->pending_icon_width; + need_resize = TRUE; + } + */ + + if (need_update_icon == TRUE) { + update_icon(HILDON_GRID_ITEM(item)); + } + /* + if (need_resize == TRUE) { + gtk_widget_queue_resize(GTK_WIDGET(item)); + } + */ +} diff --git a/src/hildon-grid-item.h b/src/hildon-grid-item.h new file mode 100644 index 0000000..89a5984 --- /dev/null +++ b/src/hildon-grid-item.h @@ -0,0 +1,92 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/* + * @file hildon-grid-item.h + * + * This file is a header file for he implementation of HildonGridItem. + * HildonGridItem is an item mainly used in HildonGrid. It has an icon, + * emblem and a label. + */ + +#ifndef __HILDON_GRID_ITEM_H__ +#define __HILDON_GRID_ITEM_H__ + +#include +#include + +G_BEGIN_DECLS +#define HILDON_TYPE_GRID_ITEM (hildon_grid_item_get_type ()) +#define HILDON_GRID_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + HILDON_TYPE_GRID_ITEM, \ + HildonGridItem)) +#define HILDON_GRID_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),\ + HILDON_TYPE_GRID_ITEM, \ + HildonGridItemClass)) +#define HILDON_IS_GRID_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + HILDON_TYPE_GRID_ITEM)) +#define HILDON_IS_GRID_ITEM_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_GRID_ITEM)) +#define HILDON_GRID_ITEM_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + HILDON_TYPE_GRID_ITEM, HildonGridItemClass)) + +typedef enum { + HILDON_GRID_ITEM_LABEL_POS_BOTTOM = 1, + HILDON_GRID_ITEM_LABEL_POS_RIGHT +} HildonGridPositionType; + +typedef enum { + HILDON_GRID_ITEM_ICON_27x27 = 1, + HILDON_GRID_ITEM_ICON_128x128 +} HildonGridItemIconSizeType; + + +typedef struct _HildonGridItem HildonGridItem; +typedef struct _HildonGridItemClass HildonGridItemClass; + + +struct _HildonGridItem { + GtkContainer parent; +}; + +struct _HildonGridItemClass { + GtkContainerClass parent_class; +}; + + + +GType hildon_grid_item_get_type(void); +GtkWidget *hildon_grid_item_new(const gchar * icon_basename); +GtkWidget *hildon_grid_item_new_with_label(const gchar * icon_basename, + const gchar * label); + +void hildon_grid_item_set_emblem_type(HildonGridItem * item, + const gchar * emblem_basename); +const gchar *hildon_grid_item_get_emblem_type(HildonGridItem * item); +void hildon_grid_item_set_label(HildonGridItem *item, const gchar *label); + + +G_END_DECLS +#endif /* __HILDON_GRID_ITEM_H__ */ diff --git a/src/hildon-grid.c b/src/hildon-grid.c new file mode 100644 index 0000000..286c75e --- /dev/null +++ b/src/hildon-grid.c @@ -0,0 +1,2348 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-grid + * @short_description: Being used where ever a number of single tap + * activatable items need to be presented (e.g. Control Panel applets) + * @see_also: #HildonGridItem + * + * HildonGrid is a set of application-defineable items that are presented in a + * table. There are two modes for the form of the table; large icon mode + * and small icon mode. + * + * In large icon mode, the Grid View items are presented with a large + * icon and a label under it. In small icon mode, the items are + * presented with a small icon and a label on the right side of the + * icon. + * + * The label has a solid background as wide as the maximum text width. + * This allows the text to have focus as well as be legible when + * displayed upon a black or dark background image. Long names are + * truncated with an ellipsis ("...") appended. + */ + +/* + * TODO + * - there must be a predefined place for the "no items" -label... + * - performance :-) + * - dimmed items & scrolling by scrollbar + */ + + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "hildon-grid-item-private.h" +#include "hildon-marshalers.h" +#include "hildon-app.h" +#include +#include + +#include +#define _(String) dgettext(PACKAGE, String) + +#define HILDON_GRID_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_GRID, \ + HildonGridPrivate)) + + +#define DEFAULT_STYLE "largeicons-home" + +#define DEFAULT_N_COLUMNS 3 +#define GRID_LABEL_POS_PAD 16 + +#define DRAG_SENSITIVITY 6 + + +enum { + ACTIVATE_CHILD, + POPUP_CONTEXT, + LAST_SIGNAL +}; + +enum { + PROP_0, + PROP_EMPTY_LABEL, + PROP_STYLE, + PROP_SCROLLBAR_POS +}; + + +typedef struct _HildonGridChild HildonGridChild; +typedef struct _HildonGridPrivate HildonGridPrivate; + + +struct _HildonGridChild { + GtkWidget *widget; +}; + + +struct _HildonGridPrivate { + GList *children; + GtkWidget *scrollbar; + gint old_sb_pos; + GdkWindow *event_window; + + gchar *style; + gint emblem_size; + GtkWidget *empty_label; + + gint item_width; + gint item_height; + gint h_margin; + gint v_margin; + gint focus_margin; + gint icon_label_margin; + gint icon_width; + gint num_columns; + HildonGridPositionType label_pos; + gint label_height; + + gint focus_index; + guint click_x; + guint click_y; + + /* Handy variables outsize _allocate. */ + gint area_height; + gint area_rows; + gint scrollbar_width; + + gint first_index; + GdkEventType last_button_event; + gint old_item_height; +}; + + + +/* Prototypes. */ +static void hildon_grid_class_init(HildonGridClass * klass); +static void hildon_grid_init(HildonGrid * grid); +static void hildon_grid_realize(GtkWidget * widget); +static void hildon_grid_unrealize(GtkWidget * widget); +static void hildon_grid_map(GtkWidget * widget); +static void hildon_grid_unmap(GtkWidget * widget); +static gboolean hildon_grid_expose(GtkWidget * widget, + GdkEventExpose * event); +static void hildon_grid_size_request(GtkWidget * widget, + GtkRequisition * requisition); +static void hildon_grid_size_allocate(GtkWidget * widget, + GtkAllocation * allocation); +static void hildon_grid_add(GtkContainer * container, GtkWidget * widget); +static void hildon_grid_remove(GtkContainer * container, + GtkWidget * widget); +static void hildon_grid_set_focus_child(GtkContainer * container, + GtkWidget * widget); +static void hildon_grid_forall(GtkContainer * container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data); +static void hildon_grid_tap_and_hold_setup(GtkWidget * widget, + GtkWidget * menu, + GtkCallback func, + GtkWidgetTapAndHoldFlags flags); + +static GType hildon_grid_child_type(GtkContainer * container); + + +static void hildon_grid_set_property(GObject * object, + guint prop_id, + const GValue * value, + GParamSpec * pspec); +static void hildon_grid_get_property(GObject * object, + guint prop_id, + GValue * value, GParamSpec * pspec); + +static void hildon_grid_set_empty_label(HildonGrid *grid, + const gchar *empty_label); +static const gchar *hildon_grid_get_empty_label(HildonGrid * grid); +static void hildon_grid_set_num_columns(HildonGrid *grid, gint num_cols); +static void hildon_grid_set_label_pos(HildonGrid *grid, + HildonGridPositionType label_pos); +static void hildon_grid_set_focus_margin(HildonGrid *grid, + gint focus_margin); +static void hildon_grid_set_icon_label_margin(HildonGrid *grid, + gint icon_label_margin); +static void hildon_grid_set_icon_width(HildonGrid *grid, gint icon_width); +static void hildon_grid_set_emblem_size(HildonGrid *grid, gint emblem_size); +static void hildon_grid_set_label_height(HildonGrid *grid, + gint label_height); +static void hildon_grid_destroy(GtkObject * self); +static void hildon_grid_finalize(GObject * object); + +/* Signal handlers. */ +static gboolean hildon_grid_button_pressed(GtkWidget * widget, + GdkEventButton * event); +static gboolean hildon_grid_button_released(GtkWidget * widget, + GdkEventButton * event); +static gboolean hildon_grid_key_pressed(GtkWidget * widget, + GdkEventKey * event); +static gboolean hildon_grid_scrollbar_moved(GtkWidget * widget, + gpointer data); +static gboolean hildon_grid_state_changed(GtkWidget * widget, + GtkStateType state, + gpointer data); + +/* Other internal functions. */ +static void get_style_properties(HildonGrid * grid); +static gint get_child_index(HildonGridPrivate * priv, GtkWidget * child); +static gint get_child_index_by_coord(HildonGridPrivate * priv, + gint x, gint y); +static GtkWidget *get_child_by_index(HildonGridPrivate * priv, gint index); + +static gboolean jump_scrollbar_to_focused(HildonGrid * grid); +static gboolean adjust_scrollbar_height(HildonGrid * grid); +static gboolean update_contents(HildonGrid * grid); +static void set_focus(HildonGrid * grid, + GtkWidget * widget, gboolean refresh_view); + +static GtkContainerClass *parent_class = NULL; +static guint grid_signals[LAST_SIGNAL] = { 0 }; + + +GType hildon_grid_get_type(void) +{ + static GType grid_type = 0; + + if (!grid_type) { + static const GTypeInfo grid_info = { + sizeof(HildonGridClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_grid_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonGrid), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_grid_init, + }; + grid_type = g_type_register_static(GTK_TYPE_CONTAINER, + "HildonGrid", &grid_info, 0); + } + + return grid_type; +} + + + +static void hildon_grid_class_init(HildonGridClass * klass) +{ + GObjectClass *gobject_class; + GtkWidgetClass *widget_class; + GtkContainerClass *container_class; + + widget_class = GTK_WIDGET_CLASS(klass); + container_class = GTK_CONTAINER_CLASS(klass); + gobject_class = G_OBJECT_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + g_type_class_add_private(klass, sizeof(HildonGridPrivate)); + + GTK_OBJECT_CLASS(klass)->destroy = hildon_grid_destroy; + gobject_class->finalize = hildon_grid_finalize; + gobject_class->set_property = hildon_grid_set_property; + gobject_class->get_property = hildon_grid_get_property; + + widget_class->realize = hildon_grid_realize; + widget_class->unrealize = hildon_grid_unrealize; + widget_class->map = hildon_grid_map; + widget_class->unmap = hildon_grid_unmap; + widget_class->expose_event = hildon_grid_expose; + widget_class->size_request = hildon_grid_size_request; + widget_class->size_allocate = hildon_grid_size_allocate; + widget_class->tap_and_hold_setup = hildon_grid_tap_and_hold_setup; + widget_class->key_press_event = hildon_grid_key_pressed; + widget_class->button_press_event = hildon_grid_button_pressed; + widget_class->button_release_event = hildon_grid_button_released; + + container_class->add = hildon_grid_add; + container_class->remove = hildon_grid_remove; + container_class->forall = hildon_grid_forall; + container_class->child_type = hildon_grid_child_type; + container_class->set_focus_child = hildon_grid_set_focus_child; + + /* Install properties to the class */ + g_object_class_install_property(gobject_class, PROP_EMPTY_LABEL, + g_param_spec_string("empty_label", + "Empty label", + "Label to show when grid has no items", + _("ckct_wi_grid_no_items"), G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, PROP_STYLE, + g_param_spec_string("style", + "Style", + "Widget's Style. Setting style sets widget size, " + "spacing, label position, number of columns, " + "and icon sizeLabel to show when grid has no items", + DEFAULT_STYLE, G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, PROP_SCROLLBAR_POS, + g_param_spec_int("scrollbar-position", + "Scrollbar Position", + "View (scrollbar) position.", + G_MININT, G_MAXINT, 0, G_PARAM_READWRITE)); + + gtk_widget_class_install_style_property(widget_class, + g_param_spec_uint("item_width", + "Item width", + "Total width of an item (obsolete)", + 1, G_MAXINT, 212, G_PARAM_READABLE)); + + gtk_widget_class_install_style_property(widget_class, + g_param_spec_uint("item_height", + "Item height", + "Total height of an item", + 1, G_MAXINT, 96, G_PARAM_READABLE)); + + gtk_widget_class_install_style_property(widget_class, + g_param_spec_uint("item_hspacing", + "Item horizontal spacing", + "Margin between two columns and labels", + 0, G_MAXINT, 12, G_PARAM_READABLE)); + + gtk_widget_class_install_style_property(widget_class, + g_param_spec_uint("item_vspacing", + "Item vertical spacing", + "Icon on right: Margin between rows / Icon at bottom: Vertical margin betweeb label and icon", + 0, G_MAXINT, 6, G_PARAM_READABLE)); + + gtk_widget_class_install_style_property(widget_class, + g_param_spec_uint("label_hspacing", + "Focus margin", + "Margin between focus edge and item edge", + 0, G_MAXINT, 6, G_PARAM_READABLE)); + + gtk_widget_class_install_style_property(widget_class, + g_param_spec_uint("label_vspacing", + "Vertical label spacing", + "Vertical margin between item and label", + 0, G_MAXINT, 6, G_PARAM_READABLE)); + + gtk_widget_class_install_style_property(widget_class, + g_param_spec_uint("label_height", + "Label height", + "Height of icon label", + 1, G_MAXINT, 30, G_PARAM_READABLE)); + + gtk_widget_class_install_style_property(widget_class, + g_param_spec_uint("n_columns", + "Columns", + "Number of columns", + 0, G_MAXINT, DEFAULT_N_COLUMNS, G_PARAM_READABLE)); + + gtk_widget_class_install_style_property(widget_class, + g_param_spec_uint("label_pos", + "Label position", + "Position of label related to the icon", + 1, 2, 1, G_PARAM_READABLE)); + + gtk_widget_class_install_style_property(widget_class, + g_param_spec_uint("icon_size", + "Icon size", + "Size of the icon in pixels (width)", + 1, G_MAXINT, 64, G_PARAM_READABLE)); + + gtk_widget_class_install_style_property(widget_class, + g_param_spec_uint("emblem_size", + "Emblem size", + "Size of the emblem in pixels", + 1, G_MAXINT, 25, G_PARAM_READABLE)); + + /** + * HildonGrid::activate-child: + * + * Emitted when a child (@HildonGridItem) is activated either by + * tapping on it or by pressing enter. + */ + grid_signals[ACTIVATE_CHILD] = + g_signal_new("activate-child", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(HildonGridClass, activate_child), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, HILDON_TYPE_GRID_ITEM); + + /** + * HildonGrid::popup-context-menu: + * + * Emitted when popup-menu is supposed to open. Used for tap-and-hold. + */ + grid_signals[POPUP_CONTEXT] = + g_signal_new("popup-context-menu", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(HildonGridClass, popup_context_menu), + NULL, NULL, + _hildon_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, HILDON_TYPE_GRID_ITEM); +} + + + +/* + * hildon_grid_set_empty_label: + * @grid: #HildonGrid + * @empty_label: New label + * + * Sets empty label. + */ +static void +hildon_grid_set_empty_label(HildonGrid * grid, const gchar * empty_label) +{ + /* No need to worry about update -- label receives a signal for it. */ + gtk_label_set_label(GTK_LABEL(HILDON_GRID_GET_PRIVATE + (grid)->empty_label), + empty_label == NULL ? "" : empty_label); +} + +/* + * _hildon_grid_get_empty_label: + * @grid: #HildonGrid + * + * Returns: empty label. Label must not be modified nor freed. + */ +static const gchar * +hildon_grid_get_empty_label(HildonGrid * grid) +{ + return gtk_label_get_label(GTK_LABEL(HILDON_GRID_GET_PRIVATE + (grid)->empty_label)); +} + +/* + * hildon_grid_set_num_columns: + * @grid: #HildonGrid + * @columns: Number of columns + * + * Sets number of columns. + */ +static void +hildon_grid_set_num_columns(HildonGrid * grid, gint columns) +{ + HildonGridPrivate *priv; + + g_return_if_fail(HILDON_IS_GRID(grid)); + priv = HILDON_GRID_GET_PRIVATE(grid); + + if (priv->num_columns == columns) { + return; + } + + if (columns != 0) + priv->num_columns = columns; + else + priv->num_columns = DEFAULT_N_COLUMNS; + + /* Update estimated row-count for jump_scrollbar... */ + priv->area_rows = MAX(priv->area_height / priv->num_columns, 1); + + /* Size could have changed. Scroll view so there's something to show. */ + adjust_scrollbar_height(grid); + jump_scrollbar_to_focused(grid); + gtk_widget_queue_resize(GTK_WIDGET(grid)); +} + +/* + * hildon_grid_set_label_pos: + * @grid: #HildonGrid + * @label_pos: Label position + * + * Sets icon label position. + */ +static void +hildon_grid_set_label_pos(HildonGrid * grid, + HildonGridPositionType label_pos) +{ + HildonGridPrivate *priv; + GList *list; + GtkWidget *child; + + priv = HILDON_GRID_GET_PRIVATE(grid); + + if (label_pos == priv->label_pos) + return; + + /* gtknotebook doesn't check if we use valid values -- why should + we?-) */ + + priv->label_pos = label_pos; + + /* Set label position to each HildonGridItem */ + for (list = priv->children; list != NULL; list = list->next) { + child = ((HildonGridChild *) list->data)->widget; + + _hildon_grid_item_set_label_pos(HILDON_GRID_ITEM(child), + label_pos); + } +} + +/* + * hildon_grid_set_focus_margin: + * @grid: #HildonGrid + * @focus_margin: Focus margin + * + * Sets margin between icon edge and label edge + */ +static void +hildon_grid_set_focus_margin(HildonGrid *grid, gint focus_margin) +{ + HildonGridPrivate *priv; + GList *list; + GtkWidget *child; + + priv = HILDON_GRID_GET_PRIVATE(grid); + if (focus_margin == priv->focus_margin) + return; + + priv->focus_margin = focus_margin; + + /* Update children. */ + for (list = priv->children; list != NULL; list = list->next) { + child = ((HildonGridChild *) list->data)->widget; + + _hildon_grid_item_set_focus_margin(HILDON_GRID_ITEM(child), + priv->focus_margin); + } +} + + +/* + * hildon_grid_set_icon_label_margin: + * @grid: #HildonGrid + * @hspacing: Vertical spacing + * + * Sets vertical spacing for label. + * XXX + */ +static void +hildon_grid_set_icon_label_margin(HildonGrid *grid, gint icon_label_margin) +{ + HildonGridPrivate *priv; + + priv = HILDON_GRID_GET_PRIVATE(grid); + if (icon_label_margin == priv->icon_label_margin) + return; + + priv->icon_label_margin = icon_label_margin; +} + + +/* + * hildon_grid_set_icon_width: + * @grid: #HildonGrid + * @icon_size: Icon size (width) + * + * Sets icon size (in pixels). + */ +static void +hildon_grid_set_icon_width(HildonGrid * grid, gint icon_width) +{ + HildonGridPrivate *priv; + GList *list; + GtkWidget *child; + + priv = HILDON_GRID_GET_PRIVATE(grid); + + if (icon_width == priv->icon_width) + return; + + priv->icon_width = icon_width; + + for (list = priv->children; list != NULL; list = list->next) { + child = ((HildonGridChild *) list->data)->widget; + + _hildon_grid_item_set_icon_width(HILDON_GRID_ITEM(child), + icon_width); + } +} + + +/* + * hildon_grid_set_emblem_size: + * @grid: #HildonGrid + * @emblem_size: Emblem size + * + * Sets emblem size (in pixels). + */ +static void +hildon_grid_set_emblem_size(HildonGrid *grid, gint emblem_size) +{ + HildonGridPrivate *priv; + GList *list; + GtkWidget *child; + + priv = HILDON_GRID_GET_PRIVATE(grid); + + if (emblem_size == priv->emblem_size) + return; + + priv->emblem_size = emblem_size; + + for (list = priv->children; list != NULL; list = list->next) { + child = ((HildonGridChild *) list->data)->widget; + + _hildon_grid_item_set_emblem_size(HILDON_GRID_ITEM(child), + emblem_size); + } +} + + +static void +hildon_grid_set_label_height(HildonGrid *grid, + gint label_height) +{ + HildonGridPrivate *priv; + GList *list; + GtkWidget *child; + + priv = HILDON_GRID_GET_PRIVATE(grid); + + if (label_height == priv->label_height) + return; + + priv->label_height = label_height; + + for (list = priv->children; list != NULL; list = list->next) { + child = ((HildonGridChild *) list->data)->widget; + + _hildon_grid_item_set_label_height(HILDON_GRID_ITEM(child), + label_height); + } +} + + +static GType hildon_grid_child_type(GtkContainer * container) +{ + return GTK_TYPE_WIDGET; +} + +static void hildon_grid_init(HildonGrid * grid) +{ + HildonGridPrivate *priv; + + priv = HILDON_GRID_GET_PRIVATE(grid); + + GTK_CONTAINER(grid)->focus_child = NULL; + priv->focus_index = -1; + + priv->scrollbar = gtk_vscrollbar_new(NULL); + priv->empty_label = gtk_label_new(_("ckct_wi_grid_no_items")); + priv->style = NULL; + + priv->area_height = 1; + priv->area_rows = 1; + priv->children = NULL; + + priv->first_index = 0; + priv->click_x = 0; + priv->click_y = 0; + + priv->item_height = 96; + priv->h_margin = 12; + priv->v_margin = 6; + priv->focus_margin = 6; + priv->icon_label_margin = 6; + priv->icon_width = 64; + priv->label_pos = HILDON_GRID_ITEM_LABEL_POS_BOTTOM; + + priv->old_sb_pos = -1; + priv->old_item_height = -1; + + gtk_widget_set_parent(priv->scrollbar, GTK_WIDGET(grid)); + gtk_widget_set_parent(priv->empty_label, GTK_WIDGET(grid)); + + priv->last_button_event = GDK_NOTHING; + + GTK_WIDGET_SET_FLAGS(grid, GTK_NO_WINDOW); + + /* Signal for scrollbar. */ + g_signal_connect(G_OBJECT(priv->scrollbar), "value-changed", + G_CALLBACK(hildon_grid_scrollbar_moved), grid); + + /* Signal for key press. */ + GTK_WIDGET_SET_FLAGS(GTK_WIDGET(grid), GTK_CAN_FOCUS); + gtk_widget_set_events(GTK_WIDGET(grid), GDK_KEY_PRESS_MASK); + + GTK_WIDGET_UNSET_FLAGS(priv->scrollbar, GTK_CAN_FOCUS); + hildon_grid_set_style(grid, DEFAULT_STYLE); +} + +/** + * hildon_grid_new: + * + * Creates a new #HildonGrid. + * + * Returns: a new #HildonGrid + */ +GtkWidget *hildon_grid_new(void) +{ + + HildonGrid *grid; + + grid = g_object_new(HILDON_TYPE_GRID, NULL); + + return GTK_WIDGET(grid); +} + + +static void hildon_grid_realize(GtkWidget * widget) +{ + HildonGrid *grid; + HildonGridPrivate *priv; + GdkWindowAttr attr; + gint attr_mask; + + + GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED); + + grid = HILDON_GRID(widget); + priv = HILDON_GRID_GET_PRIVATE(grid); + + /* Create GdkWindow for catching events. */ + attr.x = widget->allocation.x; + attr.y = widget->allocation.y; + attr.width = widget->allocation.width - priv->scrollbar_width; + attr.height = widget->allocation.height; + attr.window_type = GDK_WINDOW_CHILD; + attr.event_mask = gtk_widget_get_events(widget) + | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK; + + widget->window = gtk_widget_get_parent_window(widget); + g_object_ref(widget->window); + + attr.wclass = GDK_INPUT_ONLY; + attr_mask = GDK_WA_X | GDK_WA_Y; + + priv->event_window = gdk_window_new(widget->window, &attr, attr_mask); + gdk_window_set_user_data(priv->event_window, widget); + + widget->style = gtk_style_attach(widget->style, widget->window); + + gtk_style_set_background(widget->style, + widget->window, GTK_STATE_NORMAL); +} + + +static void hildon_grid_unrealize(GtkWidget * widget) +{ + HildonGridPrivate *priv; + + priv = HILDON_GRID_GET_PRIVATE(HILDON_GRID(widget)); + + if (priv->event_window != NULL) { + gdk_window_set_user_data(priv->event_window, NULL); + gdk_window_destroy(priv->event_window); + priv->event_window = NULL; + } + + if (GTK_WIDGET_CLASS(parent_class)->unrealize) { + (*GTK_WIDGET_CLASS(parent_class)->unrealize) (widget); + } +} + + + +static void hildon_grid_map(GtkWidget * widget) +{ + HildonGrid *grid; + HildonGridPrivate *priv; + GList *list; + GtkWidget *child; + + g_return_if_fail(HILDON_IS_GRID(widget)); + + if (!GTK_WIDGET_VISIBLE(widget)) + return; + + grid = HILDON_GRID(widget); + priv = HILDON_GRID_GET_PRIVATE(grid); + + (*GTK_WIDGET_CLASS(parent_class)->map) (widget); + + /* We shouldn't really need the following...*/ + if (priv->scrollbar != NULL && GTK_WIDGET_VISIBLE(priv->scrollbar)) { + if (!GTK_WIDGET_MAPPED(priv->scrollbar)) { + gtk_widget_map(priv->scrollbar); + } + } + + if (priv->empty_label != NULL && + GTK_WIDGET_VISIBLE(priv->empty_label)) { + if (!GTK_WIDGET_MAPPED(priv->empty_label)) { + gtk_widget_map(priv->empty_label); + } + } + + for (list = priv->children; list != NULL; list = list->next) { + child = ((HildonGridChild *) list->data)->widget; + + if (GTK_WIDGET_VISIBLE(child)) { + if (!GTK_WIDGET_MAPPED(child)) { + gtk_widget_map(child); + } + } + } + /* END OF don't really need */ + + /* Also make event window visible. */ + gdk_window_show(priv->event_window); +} + + + +static void hildon_grid_unmap(GtkWidget * widget) +{ + HildonGridPrivate *priv; + + priv = HILDON_GRID_GET_PRIVATE(HILDON_GRID(widget)); + + if (priv->event_window != NULL) { + gdk_window_hide(priv->event_window); + } + + (*GTK_WIDGET_CLASS(parent_class)->unmap) (widget); +} + + + +static gboolean +hildon_grid_expose(GtkWidget * widget, GdkEventExpose * event) +{ + HildonGrid *grid; + HildonGridPrivate *priv; + GtkContainer *container; + GList *list; + gint child_no; + + g_return_val_if_fail(widget, FALSE); + g_return_val_if_fail(HILDON_IS_GRID(widget), FALSE); + g_return_val_if_fail(event, FALSE); + + grid = HILDON_GRID(widget); + priv = HILDON_GRID_GET_PRIVATE(grid); + container = GTK_CONTAINER(grid); + + /* If grid has no children, + * propagate the expose event to the label is one exists */ + if (priv->children == NULL || g_list_length(priv->children) == 0) { + if (priv->empty_label != NULL) { + gtk_container_propagate_expose(container, + priv->empty_label, event); + } + return FALSE; + } + + /* Only expose visible children. */ + + /* Jump over invisible. */ + for (list = priv->children, child_no = 0; + list != NULL && child_no < priv->first_index; + list = list->next, child_no++) { + ; /* Nothing here. */ + } + + for (; list != NULL && child_no < priv->first_index + + priv->num_columns * priv->area_rows; list = list->next) { + gtk_container_propagate_expose(container, + ((HildonGridChild *) list->data) + ->widget, event); + } + + /* Keep focused item focused. */ + if (container->focus_child != NULL + && !GTK_WIDGET_HAS_FOCUS(container->focus_child)) { + set_focus(grid, container->focus_child, FALSE); + } + if (priv->scrollbar_width > 0 && priv->scrollbar != NULL) { + gtk_container_propagate_expose(container, priv->scrollbar, event); + } + + return FALSE; +} + + +static void +hildon_grid_size_request(GtkWidget * widget, GtkRequisition * requisition) +{ + HildonGrid *grid; + HildonGridPrivate *priv; + GList *list; + GtkWidget *child; + GtkRequisition req; + + g_return_if_fail(widget); + g_return_if_fail(requisition); + + grid = HILDON_GRID(widget); + priv = HILDON_GRID_GET_PRIVATE(grid); + + /* Want as big as possible. */ + requisition->width = 0x7fff; /* Largest possible gint16 */ + requisition->height = 0x7fff; /* Largest possible gint16 */ + + if (priv->children == NULL) { + if (priv->empty_label != NULL && + GTK_WIDGET_VISIBLE(priv->empty_label)) { + gtk_widget_size_request(priv->empty_label, &req); + } + } + + if (priv->scrollbar != NULL && GTK_WIDGET_VISIBLE(priv->scrollbar)) { + gtk_widget_size_request(priv->scrollbar, &req); + } + + for (list = priv->children; list != NULL; list = list->next) { + child = ((HildonGridChild *) list->data)->widget; + + gtk_widget_size_request(child, &req); + } +} + +/* + * hildon_grid_size_allocate: + * + * Supposingly called when size of grid changes and after view have moved so + * that items need to be relocated. + */ +static void +hildon_grid_size_allocate(GtkWidget * widget, GtkAllocation * allocation) +{ + HildonGrid *grid; + HildonGridPrivate *priv; + GList *list; + GtkWidget *child; + gint child_no; + gint y_offset; + gint row_margin; + + GtkAllocation alloc; + GtkRequisition req; + + g_return_if_fail(widget); + g_return_if_fail(allocation); + + grid = HILDON_GRID(widget); + priv = HILDON_GRID_GET_PRIVATE(grid); + widget->allocation = *allocation; + + get_style_properties(grid); + + /* First of all, make sure GdkWindow is over our widget. */ + if (priv->event_window != NULL) { + gdk_window_move_resize(priv->event_window, + widget->allocation.x, + widget->allocation.y, + widget->allocation.width - + priv->scrollbar_width, + widget->allocation.height); + } + /* Show the label if there are no items. */ + if (priv->children == NULL) { + /* + * We probably don't need this as scrollbar should be hidden when + * removing items, but one can never be too sure... + */ + if (priv->scrollbar != NULL && + GTK_WIDGET_VISIBLE(priv->scrollbar)) { + priv->scrollbar_width = 0; + gtk_widget_hide(priv->scrollbar); + } + + /* Show label if creating one actually worked. */ + if (priv->empty_label != NULL) { + gtk_widget_get_child_requisition(priv->empty_label, &req); + + /* ...for sure we must have a position for the label here... */ + alloc.x = allocation->x + GRID_LABEL_POS_PAD; + alloc.y = allocation->y + GRID_LABEL_POS_PAD; + alloc.width = MIN(req.width, allocation->width - + GRID_LABEL_POS_PAD); + alloc.height = MIN(req.height, allocation->height - + GRID_LABEL_POS_PAD); + + /* Make sure we don't use negative values. */ + if (alloc.width < 0) { + alloc.width = 0; + } + if (alloc.height < 0) { + alloc.height = 0; + } + + gtk_widget_size_allocate(priv->empty_label, &alloc); + + if (!GTK_WIDGET_VISIBLE(priv->empty_label)) { + gtk_widget_show(priv->empty_label); + } + } + + return; + } + + /* As we have some items, hide label if it was visible. */ + if (priv->empty_label != NULL && + GTK_WIDGET_VISIBLE(priv->empty_label)) { + gtk_widget_hide(priv->empty_label); + } + + priv->area_height = allocation->height; + priv->area_rows = allocation->height / priv->item_height; + + /* Adjust/show/hide scrollbar. */ + adjust_scrollbar_height(grid); + if (priv->old_item_height != priv->item_height) { + priv->old_item_height = priv->item_height; + jump_scrollbar_to_focused(grid); + } + + /* Update item width. */ + if (priv->num_columns == 1) { + priv->item_width = allocation->width - priv->scrollbar_width - + priv->h_margin - priv->scrollbar_width; + } else { + priv->item_width = (allocation->width - priv->scrollbar_width) / + priv->num_columns; + } + + priv->first_index = + (int) gtk_range_get_value(GTK_RANGE(priv->scrollbar)) / + priv->item_height * priv->num_columns; + + /* Hide items before visible ones. */ + for (list = priv->children, child_no = 0; + list != NULL && child_no < priv->first_index; + list = list->next, child_no++) { + child = ((HildonGridChild *) list->data)->widget; + + if (GTK_WIDGET_VISIBLE(child)) { + gtk_widget_hide(child); + } + } + + /* Allocate visible items. */ + alloc.width = priv->item_width - priv->h_margin; + switch (priv->label_pos) { + case HILDON_GRID_ITEM_LABEL_POS_BOTTOM: + row_margin = priv->icon_label_margin; + break; + case HILDON_GRID_ITEM_LABEL_POS_RIGHT: + row_margin = priv->v_margin; + break; + default: + row_margin = 0; + break; + } + alloc.height = priv->item_height - row_margin; + + for (y_offset = priv->first_index / priv->num_columns * priv->item_height; + list != NULL && child_no < priv->first_index + + priv->area_rows * priv->num_columns; + list = list->next, child_no++) { + child = ((HildonGridChild *) list->data)->widget; + + if (!GTK_WIDGET_VISIBLE(child)) { + gtk_widget_show(child); + } + + /* Don't update icons which are not visible... */ + alloc.y = (child_no / priv->num_columns) * priv->item_height + + allocation->y - y_offset + row_margin; + alloc.x = (child_no % priv->num_columns) * priv->item_width + + allocation->x; + + _hildon_grid_item_done_updating_settings(HILDON_GRID_ITEM(child)); + gtk_widget_size_allocate(child, &alloc); + } + + /* Hide items after visible items. */ + for (; list != NULL; list = list->next) { + child = ((HildonGridChild *) list->data)->widget; + + if (GTK_WIDGET_VISIBLE(child)) { + gtk_widget_hide(child); + } + } +} + + + +/** + * hildon_grid_add: + * @container: container (#HildonGrid) to add HildonGridItem into + * @widget: #GtkWidget (#HildonGridItem) to add + * + * Adds a new HildonGridItem into HildonGrid. + */ +static void hildon_grid_add(GtkContainer * container, GtkWidget * widget) +{ + HildonGrid *grid; + HildonGridPrivate *priv; + HildonGridChild *child; + + + g_return_if_fail(HILDON_IS_GRID(container)); + g_return_if_fail(HILDON_IS_GRID_ITEM(widget)); + + grid = HILDON_GRID(container); + priv = HILDON_GRID_GET_PRIVATE(HILDON_GRID(grid)); + GTK_WIDGET_SET_FLAGS(widget, GTK_NO_WINDOW); + + child = g_new(HildonGridChild, 1); + if (child == NULL) { + g_critical("no memory for child - not adding"); + return; + } + child->widget = widget; + + _hildon_grid_item_set_label_pos (HILDON_GRID_ITEM(widget), priv->label_pos); + _hildon_grid_item_set_focus_margin(HILDON_GRID_ITEM(widget), priv->focus_margin); + _hildon_grid_item_set_icon_width (HILDON_GRID_ITEM(widget), priv->icon_width); + _hildon_grid_item_set_emblem_size (HILDON_GRID_ITEM(widget), priv->emblem_size); + + /* Add the new item to the grid */ + priv->children = g_list_append(priv->children, child); + gtk_widget_set_parent(widget, GTK_WIDGET(grid)); + + /* Property changes (child's set_sensitive) */ + g_signal_connect_after(G_OBJECT(widget), "state-changed", + G_CALLBACK(hildon_grid_state_changed), grid); + + /* Matches both empty grid and all-dimmed grid. */ + if (GTK_CONTAINER(grid)->focus_child == NULL) + set_focus(grid, widget, TRUE); + + /* + * If item was added in visible area, relocate items. Otherwise update + * scrollbar and see if items need relocating. + */ + if (g_list_length(priv->children) < priv->first_index + + priv->area_rows * priv->num_columns) { + gtk_widget_queue_resize(GTK_WIDGET(grid)); + } else { + gboolean updated; + + updated = adjust_scrollbar_height(grid); + /* Basically this other test is useless -- shouldn't need to jump. + */ + updated |= jump_scrollbar_to_focused(grid); + + if (updated) { + gtk_widget_queue_resize(GTK_WIDGET(grid)); + } + } +} + +/** + * hildon_grid_remove: + * @container: container (#HildonGrid) to remove #HildonGridItem from + * @widget: widget (#HildonGridItem) to be removed + * + * Removes HildonGridItem from HildonGrid. + */ +static void +hildon_grid_remove(GtkContainer * container, GtkWidget * widget) +{ + HildonGrid *grid; + HildonGridPrivate *priv; + HildonGridChild *child; + GtkWidget *child_widget; + GList *list; + gint index, old_index; + gboolean deleted; + gboolean updated; + + g_return_if_fail(HILDON_IS_GRID(container)); + g_return_if_fail(HILDON_IS_GRID_ITEM(widget)); + + grid = HILDON_GRID(container); + priv = HILDON_GRID_GET_PRIVATE(container); + + old_index = priv->focus_index; + updated = GTK_WIDGET_VISIBLE(widget); + + for (list = priv->children, index = 0, deleted = FALSE; + list != NULL; list = list->next, index++) { + child = (HildonGridChild *) list->data; + child_widget = child->widget; + + /* Remove the Item if it is found in the grid */ + if (child_widget == widget) { + gtk_widget_unparent(child_widget); + priv->children = g_list_remove_link(priv->children, list); + g_list_free(list); + g_free(child); + + deleted = TRUE; + + break; + } + } + + /* Emit warning if the item is not found */ + if (!deleted) { + g_warning("tried to remove unexisting item"); + return; + } + + /* Move focus somewhere. */ + if (old_index == index) { + if (old_index == g_list_length(priv->children)) { + if (index == 0) { + set_focus(grid, NULL, TRUE); + } else { + set_focus(grid, + get_child_by_index(priv, old_index - 1), TRUE); + } + } else { + set_focus(grid, get_child_by_index(priv, old_index), TRUE); + } + } else { + set_focus(grid, GTK_CONTAINER(grid)->focus_child, TRUE); + } + + updated |= adjust_scrollbar_height(grid); + updated |= jump_scrollbar_to_focused(grid); + + if (updated) { + gtk_widget_queue_resize(GTK_WIDGET(grid)); + } +} + +/** + * hildon_grid_set_focus_child: + * @container: HildonGrid + * @widget: HildonGridItem + * + * Sets focus. + */ +static void +hildon_grid_set_focus_child(GtkContainer * container, GtkWidget * widget) +{ + HildonGrid *grid; + HildonGridPrivate *priv; + + g_return_if_fail(HILDON_IS_GRID(container)); + g_return_if_fail(HILDON_IS_GRID_ITEM(widget) || widget == NULL); + + grid = HILDON_GRID(container); + priv = HILDON_GRID_GET_PRIVATE(grid); + + if (GTK_CONTAINER(grid)->focus_child == widget || widget == NULL) + return; + + set_focus(grid, widget, TRUE); +} + + + +static void +set_focus(HildonGrid * grid, GtkWidget * widget, gboolean refresh_view) +{ + HildonGridPrivate *priv; + GtkContainer *container; + gboolean view_updated; + + + priv = HILDON_GRID_GET_PRIVATE(grid); + container = GTK_CONTAINER(grid); + + /* If widget is NULL -> unfocus */ + if (widget == NULL && container->focus_child != NULL) + GTK_WIDGET_UNSET_FLAGS(container->focus_child, GTK_HAS_FOCUS); + + GTK_CONTAINER(grid)->focus_child = widget; + if (widget == NULL) { + priv->focus_index = -1; + return; + } + + /* Get the child index which the user wanted to focus */ + priv->focus_index = get_child_index(priv, widget); + + gtk_widget_grab_focus(widget); + + if (refresh_view) { + view_updated = jump_scrollbar_to_focused(grid); + } else { + view_updated = FALSE; + } + + if (view_updated) { + hildon_grid_size_allocate(GTK_WIDGET(grid), + >K_WIDGET(grid)->allocation); + } +} + +static void +hildon_grid_forall(GtkContainer * container, + gboolean include_internals, + GtkCallback callback, gpointer callback_data) +{ + HildonGrid *grid; + HildonGridPrivate *priv; + GList *list; + + g_return_if_fail(container); + g_return_if_fail(callback); + + grid = HILDON_GRID(container); + priv = HILDON_GRID_GET_PRIVATE(grid); + + /* Connect callback functions */ + if (include_internals) { + if (priv->scrollbar != NULL) { + (*callback) (priv->scrollbar, callback_data); + } + if (priv->empty_label != NULL) { + (*callback) (priv->empty_label, callback_data); + } + } + + for (list = priv->children; list != NULL; list = list->next) { + (*callback) (((HildonGridChild *) list->data)->widget, + callback_data); + } +} + +static void hildon_grid_destroy(GtkObject * self) +{ + HildonGridPrivate *priv; + + g_return_if_fail(self != NULL); + g_return_if_fail(HILDON_IS_GRID(self)); + + priv = HILDON_GRID_GET_PRIVATE(self); + + if (GTK_WIDGET(self)->window != NULL) { + g_object_unref(G_OBJECT(GTK_WIDGET(self)->window)); + } + + gtk_container_forall(GTK_CONTAINER(self), + (GtkCallback) gtk_object_ref, NULL); + gtk_container_forall(GTK_CONTAINER(self), + (GtkCallback) gtk_widget_unparent, NULL); + + GTK_OBJECT_CLASS(parent_class)->destroy(self); +} + +static void hildon_grid_finalize(GObject * object) +{ + HildonGrid *grid; + HildonGridPrivate *priv; + + grid = HILDON_GRID(object); + priv = HILDON_GRID_GET_PRIVATE(grid); + + gtk_container_forall(GTK_CONTAINER(object), + (GtkCallback) gtk_object_unref, NULL); + + if (priv->style != NULL) { + g_free(priv->style); + } + if (G_OBJECT_CLASS(parent_class)->finalize) { + G_OBJECT_CLASS(parent_class)->finalize(object); + } +} + +/* + * hildon_grid_key_pressed: + * @widget: Widget where we get the signal from + * @event: EventKey + * @data: #HildonGrid + * + * Handle user key press (keyboard navigation). + * + * And here's how it works if some items are dimmed (moving to right): + * . . . . . . # . . 2 # . . # . . + * . 1 # 2 . 1 # # 1 # # # 1 # # # + * . . . . . 2 . . . . 2 . + * + * '.' = item, + * '#' = dimmed item, + * '1' = starting position, + * '2' = final position + * + * ...although only the first example is implemented right now. + * + * Return value: Signal handled + */ +static gboolean +hildon_grid_key_pressed(GtkWidget * widget, + GdkEventKey * event) +{ + GtkAdjustment *adjustment; + GtkContainer *container; + GtkWidget *new_focus; + HildonGrid *grid; + HildonGridPrivate *priv; + gboolean shift; + gint keyval; + gint x, y; + gint focus_index; + gint child_count, child_rows; + gint t; + gint addition, max_add; + + g_return_val_if_fail(widget, FALSE); + + grid = HILDON_GRID(widget); + priv = HILDON_GRID_GET_PRIVATE(grid); + + /* + * If focus was never lost, we could just see if an item is focused - + * if not, there's nothing else to focus... + */ + + /* No items? */ + if (priv->children == NULL || g_list_length(priv->children) == 0) + return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event); + + /* Focused item is dimmed? */ + /* If we have no focus, allow non-existing focus to move... */ + container = GTK_CONTAINER(grid); + if (container->focus_child != NULL + && !GTK_WIDGET_IS_SENSITIVE(container->focus_child)) { + return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event); + } + /* At the moment we don't want to do anything here if alt or control + or MODX is pressed, so return now. Shift + TAB are accepted (from + hildon-table-grid) And right now modifiers do not make any + difference... */ + + /* Said somewhere that "foo = a == b" is not desirable. */ + if (event->state & GDK_SHIFT_MASK) { + shift = TRUE; + } else { + shift = FALSE; + } + + keyval = event->keyval; + if (gtk_widget_get_default_direction() == GTK_TEXT_DIR_RTL) { + switch (event->keyval) { + case GDK_Left: + keyval = GDK_Right; + break; + case GDK_KP_Left: + keyval = GDK_KP_Right; + break; + case GDK_Right: + keyval = GDK_Left; + break; + case GDK_KP_Right: + keyval = GDK_KP_Left; + break; + } + } + + child_count = g_list_length(priv->children); + child_rows = (child_count - 1) / priv->num_columns + 1; + + if (priv->focus_index != -1) { + x = priv->focus_index % priv->num_columns; + y = priv->focus_index / priv->num_columns; + } else { + x = y = 0; + } + + switch (keyval) { + case GDK_KP_Page_Up: + case GDK_Page_Up: + if (priv->first_index == 0) { + if (priv->focus_index == 0) { + return TRUE; + } + set_focus(grid, get_child_by_index(priv, 0), TRUE); + return TRUE; + } + + t = MAX(priv->first_index / priv->num_columns - priv->area_rows, 0); + adjustment = gtk_range_get_adjustment(GTK_RANGE(priv->scrollbar)); + adjustment->value = (gdouble) (t * priv->item_height); + gtk_range_set_adjustment(GTK_RANGE(priv->scrollbar), adjustment); + gtk_widget_queue_draw(priv->scrollbar); + update_contents(grid); + + /* Want to update now. */ + hildon_grid_size_allocate(GTK_WIDGET(grid), + >K_WIDGET(grid)->allocation); + + return TRUE; + break; + + case GDK_KP_Page_Down: + case GDK_Page_Down: + if (priv->first_index / priv->num_columns == + child_rows - priv->area_rows) { + if (priv->focus_index == child_count - 1) { + return TRUE; + } + set_focus(grid, get_child_by_index(priv, child_count - 1), + TRUE); + return TRUE; + } + + t = MIN(priv->first_index / priv->num_columns + + priv->area_rows, child_rows - priv->area_rows); + adjustment = gtk_range_get_adjustment(GTK_RANGE(priv->scrollbar)); + adjustment->value = (gdouble) (t * priv->item_height); + gtk_range_set_adjustment(GTK_RANGE(priv->scrollbar), adjustment); + gtk_widget_queue_draw(priv->scrollbar); + update_contents(grid); + + /* Want to update now. */ + hildon_grid_size_allocate(GTK_WIDGET(grid), + >K_WIDGET(grid)->allocation); + + return TRUE; + break; + + case GDK_KP_Up: + case GDK_Up: + if (y <= 0) { + return TRUE; + } + addition = -priv->num_columns; + max_add = y; + y--; + break; + + case GDK_KP_Down: + case GDK_Down: + if (y >= (child_count - 1) / priv->num_columns) { + return TRUE; + } + t = child_count % priv->num_columns; + if (t == 0) { + t = priv->num_columns; + } + if (y == (child_count - 1) / priv->num_columns - 1 && x >= t) { + x = t - 1; + } + y++; + addition = priv->num_columns; + max_add = child_rows - y; + break; + + case GDK_KP_Left: + case GDK_Left: + if (x <= 0) { + return TRUE; + } + addition = -1; + max_add = x; + x--; + break; + + case GDK_KP_Right: + case GDK_Right: + if (x >= priv->num_columns - 1) { + return TRUE; + } + if (y == 0 && x >= child_count - 1) { + return TRUE; + } + x++; + addition = 1; + max_add = priv->num_columns - x; + if (y * priv->num_columns + x == child_count) { + y--; + } + break; + case GDK_KP_Enter: + case GDK_Return: + hildon_grid_activate_child(grid, + HILDON_GRID_ITEM + (GTK_CONTAINER(grid)->focus_child)); + return TRUE; + break; + default: + return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event); + break; + } + + focus_index = y * priv->num_columns + x; + new_focus = get_child_by_index(priv, focus_index); + + while (new_focus != NULL && + focus_index < child_count && !GTK_WIDGET_SENSITIVE(new_focus)) { + max_add--; + + if (max_add == 0) { + return TRUE; + } + focus_index += addition; + new_focus = get_child_by_index(priv, focus_index); + } + + if (new_focus != NULL) { + set_focus(grid, new_focus, TRUE); + } + return TRUE; +} + + +/* + * hildon_grid_button_pressed: + * @widget: Widget where signal is coming from + * @event: #EventButton + * @data: #HildonGrid + * + * Handle mouse button press. + * + * Return value: Signal handled + */ +static gboolean +hildon_grid_button_pressed(GtkWidget * widget, + GdkEventButton * event) +{ + HildonGrid *grid; + HildonGridPrivate *priv; + GtkWidget *child; + int child_no; + + grid = HILDON_GRID(widget); + priv = HILDON_GRID_GET_PRIVATE(grid); + +/* Watch out for double/triple click press events */ + + if (event->type == GDK_2BUTTON_PRESS || + event->type == GDK_3BUTTON_PRESS) { + priv->last_button_event = event->type; + return FALSE; + } + + priv->last_button_event = event->type; + + if (event->type != GDK_BUTTON_PRESS) + return FALSE; + + + child_no = get_child_index_by_coord(priv, event->x, event->y); + + if (child_no == -1 || child_no >= g_list_length(priv->children)) + return FALSE; + + child = get_child_by_index(priv, child_no); + if (!GTK_WIDGET_IS_SENSITIVE(child)) + return FALSE; + + priv->click_x = event->x; + priv->click_y = event->y; + + return FALSE; +} + +/* + * hildon_grid_button_released: + * @widget: Widget the signal is coming from + * @event: #EventButton + * @data: #HildonGrid + * + * Handle mouse button release. + * + * Return value: Signal handled + */ +static gboolean +hildon_grid_button_released(GtkWidget * widget, + GdkEventButton * event) +{ + HildonGrid *grid; + HildonGridPrivate *priv; + GtkWidget *child; + int child_no; + gboolean already_selected; + + grid = HILDON_GRID(widget); + priv = HILDON_GRID_GET_PRIVATE(grid); + + /* In case of double/triple click, silently ignore the release event */ + + if (priv->last_button_event == GDK_2BUTTON_PRESS || + priv->last_button_event == GDK_3BUTTON_PRESS) { + priv->last_button_event = event->type; + return FALSE; + } + + child_no = get_child_index_by_coord(priv, event->x, event->y); + + if (child_no == -1 || child_no >= g_list_length(priv->children)) { + return FALSE; + } + child = get_child_by_index(priv, child_no); + if (!GTK_WIDGET_IS_SENSITIVE(child)) { + return FALSE; + } + if (abs(priv->click_x - event->x) >= DRAG_SENSITIVITY + && abs(priv->click_y - event->y) >= DRAG_SENSITIVITY) { + return FALSE; + } + + /* Check if this element was already selected */ + already_selected = (priv->focus_index == child_no); + + set_focus(grid, child, TRUE); + priv->last_button_event = event->type; + + /* If this is not the first click in this element, activate it */ + if (already_selected) + hildon_grid_activate_child(grid, HILDON_GRID_ITEM(child)); + + return FALSE; +} + +/* + * hildon_grid_scrollbar_moved: + * @widget: Widget which sent the signal + * @data: #HildonGrid + * + * Update HildonGrid contents when scrollbar is moved. + * + * Return value: Signal handeld + */ +static gboolean +hildon_grid_scrollbar_moved(GtkWidget * widget, gpointer data) +{ + HildonGrid *grid; + HildonGridPrivate *priv; + gboolean updated = FALSE; + + grid = HILDON_GRID(data); + priv = HILDON_GRID_GET_PRIVATE(grid); + updated = update_contents(grid); + + /* + * If grid changes focus while dragging scrollbar and pointer leaves + * scrollbar, focus is moved to prev_focus... This prevents that. + */ + gtk_window_set_prev_focus_widget(GTK_WINDOW + (gtk_widget_get_toplevel(widget)), + GTK_CONTAINER(grid)->focus_child); + + if (updated) + /* Don't just queue it, let's do it now! */ + hildon_grid_size_allocate(GTK_WIDGET(grid), + >K_WIDGET(grid)->allocation); + + return TRUE; +} + + +/* + * update_contents: + * @grid: #HildonGrid + * + * Update the view if scrollbar has moved so that first visible row + * should've changed. Returns true if location actually changed. + * + * Return value: Content changed + */ +static gboolean update_contents(HildonGrid * grid) +{ + HildonGridPrivate *priv; + gint new_row; + + priv = HILDON_GRID_GET_PRIVATE(grid); + new_row = (int) gtk_range_get_value(GTK_RANGE(priv->scrollbar)) + / priv->item_height; + + if (new_row != priv->old_sb_pos) { + priv->old_sb_pos = new_row; + priv->first_index = new_row * priv->num_columns; + + return TRUE; + } + return FALSE; +} + +/* + * jump_scrollbar_to_focused: + * @grid: #HildonGrid + * + * Moves scrollbar position so that focused item will be shown + * in visible area. + * Returns TRUE if visible position of widgets have changed. + * + * Return value: Content changed + */ +static gboolean jump_scrollbar_to_focused(HildonGrid * grid) +{ + HildonGridPrivate *priv; + GtkAdjustment *adjustment; + gint child_count; + gint empty_grids; + gint new_row; + + priv = HILDON_GRID_GET_PRIVATE(grid); + /* If we don't have scrollbar, let the focus be broken, too. */ + g_return_val_if_fail(priv->scrollbar != NULL, FALSE); + + /* Make sure "first widget" is something sensible. */ + priv->first_index = priv->first_index - + priv->first_index % priv->num_columns; + + child_count = g_list_length(priv->children); + empty_grids = priv->num_columns * priv->area_rows - child_count + + priv->first_index; + + /* Determine the position of the new row */ + if (priv->focus_index < priv->first_index) { + new_row = priv->focus_index / priv->num_columns; + } else if (priv->focus_index >= priv->first_index + + priv->area_rows * priv->num_columns) { + gint last_top_row; + new_row = priv->focus_index / priv->num_columns - + priv->area_rows + 1; + last_top_row = child_count / priv->num_columns - priv->area_rows + 1; + if (child_count % priv->num_columns != 0) { + last_top_row++; + } + if (new_row > last_top_row) { + new_row = last_top_row; + } + } else if (empty_grids >= priv->num_columns) { + new_row = ((child_count - 1) / priv->num_columns + 1) + - priv->area_rows; + if (new_row < 0) { + new_row = 0; + } + } else { + return FALSE; + } + + /* Move scrollbar accordingly. */ + adjustment = gtk_range_get_adjustment(GTK_RANGE(priv->scrollbar)); + adjustment->value = (gdouble) (new_row * priv->item_height); + gtk_range_set_adjustment(GTK_RANGE(priv->scrollbar), adjustment); + priv->first_index = new_row * priv->num_columns; + priv->old_sb_pos = new_row; + + gtk_widget_queue_draw(priv->scrollbar); + + return TRUE; +} + + +/* + * adjust_scrollbar_height: + * @grid: HildonGridPrivate + * + * Return value: View should change + * + * Adjust scrollbar according the #HildonGrid contents. + * Show/hide scrollbar if + * appropriate. Also sets priv->first_index. + */ +static gboolean adjust_scrollbar_height(HildonGrid * grid) +{ + HildonGridPrivate *priv; + GtkRequisition req; + GtkAdjustment *adj; + GtkAllocation alloc; + GtkAllocation *gridalloc; + gint old_upper; + gint need_rows; + gint need_pixels; + gboolean updated; + + priv = HILDON_GRID_GET_PRIVATE(grid); + g_return_val_if_fail(priv->scrollbar != NULL, FALSE); + + updated = FALSE; + gridalloc = >K_WIDGET(grid)->allocation; + + /* See if we need scrollbar at all. */ + if (priv->num_columns == 0) { + priv->num_columns = DEFAULT_N_COLUMNS; + } else { + priv->num_columns = MAX(1, priv->num_columns); + } + + if (g_list_length(priv->children) != 0) { + need_rows = (g_list_length(priv->children) - 1) / + priv->num_columns + 1; + } else { + need_rows = 0; + } + + if (need_rows <= priv->area_rows) { + updated = priv->first_index != 0; + priv->scrollbar_width = 0; + + priv->first_index = 0; + if (GTK_WIDGET_VISIBLE(priv->scrollbar)) { + GtkWidget *parent = gtk_widget_get_toplevel (GTK_WIDGET (grid)); + if (HILDON_IS_APP (parent)) + g_object_set (parent, "scroll-control", FALSE, NULL); + gtk_widget_hide(priv->scrollbar); + updated = TRUE; + } + + return updated; + } + + /* All right then, we need scrollbar. Place scrollbar on the screen. */ + gtk_widget_get_child_requisition(priv->scrollbar, &req); + priv->scrollbar_width = req.width; + + alloc.width = req.width; + alloc.height = gridalloc->height; + alloc.x = gridalloc->width - req.width + gridalloc->x; + alloc.y = gridalloc->y; + gtk_widget_size_allocate(priv->scrollbar, &alloc); + + if (!GTK_WIDGET_VISIBLE(priv->scrollbar)) { + GtkWidget *parent = gtk_widget_get_toplevel (GTK_WIDGET (grid)); + if (HILDON_IS_APP (parent)) + g_object_set (parent, "scroll-control", TRUE, NULL); + gtk_widget_show(priv->scrollbar); + updated = TRUE; + } + + + need_pixels = need_rows * priv->item_height; + + /* Once we know how much space we need, update the scrollbar. */ + adj = gtk_range_get_adjustment(GTK_RANGE(priv->scrollbar)); + old_upper = (int) adj->upper; + adj->lower = 0.0; + adj->upper = (gdouble) need_pixels; + adj->step_increment = (gdouble) priv->item_height; + adj->page_increment = (gdouble) (priv->area_rows * priv->item_height); + adj->page_size = + (gdouble) (priv->area_height - priv->area_height % priv->item_height); + + /* Also update position if needed to show focused item. */ + + gtk_range_set_adjustment(GTK_RANGE(priv->scrollbar), adj); + + /* Then set first_index. */ + priv->first_index = (int) adj->value / priv->item_height * + priv->num_columns; + + /* Finally, ask Gtk to redraw the scrollbar. */ + if (old_upper != (int) adj->upper) { + gtk_widget_queue_draw(priv->scrollbar); + } + return updated; +} + +/* + * get_child_index_by_coord: + * @priv: HildonGridPrivate + * @x: X-coordinate + * @y: Y-coordinate + * + * Returns index of child at given coordinates, -1 if no child. + * + * Return value: Index + */ +static gint +get_child_index_by_coord(HildonGridPrivate * priv, gint x, gint y) +{ + int xgap, ygap; + int t; + + if (priv->item_width==0 || priv->item_height==0) { + return -1; + } + + xgap = x % priv->item_width; + ygap = y % priv->item_height; + + if (xgap > priv->item_width - priv->h_margin) { /*FIXME*/ + return -1; + } + + /* Event may come from outside of the grid. Skipping those events */ + if (x >= priv->item_width * priv->num_columns) + return -1; + + t = y / priv->item_height * priv->num_columns + + x / priv->item_width + priv->first_index; + + if (t >= priv->first_index + priv->area_rows * priv->num_columns || + t >= g_list_length(priv->children) || t < 0) { + return -1; + } + return t; +} + +/* + * get_child_by_index: + * @priv: HildonGridPrivate + * @index: Index of child + * + * Returns child that is #th in HildonGrid or NULL if child was not found + * among the children. + * + * Return value: GtkWidget + */ +static GtkWidget *get_child_by_index(HildonGridPrivate * priv, gint index) +{ + GList *list; + int i = 0; + + if (index >= g_list_length(priv->children) || index < 0) { + return NULL; + } + for (list = priv->children, i = 0; list != NULL; + list = list->next, i++) { + if (index == i) { + return ((HildonGridChild *) list->data)->widget; + } + } + + g_warning("no such child"); + return NULL; +} + +/* + * get_child_index: + * @priv: HildonGridPrivate + * @child: #GtkWidget to look for + * + * Returns index of a child or -1 if child was not found among the + * children. + * + * Return value: Index + */ +static gint get_child_index(HildonGridPrivate * priv, GtkWidget * child) +{ + GList *list; + gint index; + + if (child == NULL) + return -1; + + for (list = priv->children, index = 0; + list != NULL; list = list->next, index++) { + if (((HildonGridChild *) list->data)->widget == child) { + return index; + } + } + + g_warning("no such child"); + return -1; +} + + +/** + * hildon_grid_activate_child: + * @grid: #HildonGrid + * @item: #HildonGridItem + * + * Sends a signal to indicate that this HildonGridItem is activated. + */ +void hildon_grid_activate_child(HildonGrid * grid, HildonGridItem * item) +{ + g_return_if_fail(HILDON_IS_GRID(grid)); + + g_signal_emit(grid, grid_signals[ACTIVATE_CHILD], 0, item); +} + + + +/** + * hildon_grid_set_style: + * @grid: #HildonGrid + * @style_name: style name + * + * Sets style. Setting style sets widget size, spacing, label position, + * number of columns, and icon size. + */ +void hildon_grid_set_style(HildonGrid * grid, const gchar * style_name) +{ + HildonGridPrivate *priv; + + g_return_if_fail(HILDON_IS_GRID(grid)); + + + priv = HILDON_GRID_GET_PRIVATE(grid); + if (priv->style != NULL) { + g_free((gpointer) priv->style); + } + if (style_name != NULL) { + priv->style = g_strdup(style_name); + } else { + priv->style = NULL; + } + + gtk_widget_set_name(GTK_WIDGET(grid), style_name); + get_style_properties(grid); + + gtk_widget_queue_resize(GTK_WIDGET(grid)); +} + +/** + * hildon_grid_get_style: + * @grid: #HildonGrid + * + * Returns the name of style currently used in HildonGrid. + * + * Returns: style name + */ +const gchar *hildon_grid_get_style(HildonGrid * grid) +{ + g_return_val_if_fail(HILDON_IS_GRID(grid), NULL); + + return gtk_widget_get_name(GTK_WIDGET(grid)); +} + +/* + * get_style_properties: + * @grid: #HildonGrid + * + * Gets widget size and other properties from gtkrc. If some properties + * have changed, notify children of this, too. + */ +static void get_style_properties(HildonGrid * grid) +{ + GList *iter; + gint num_columns; + HildonGridPositionType label_pos; + gint emblem_size; + + gint h_margin, v_margin; + gint item_height; + gint icon_width; + gint focus_margin, icon_label_margin; + gint label_height; + + HildonGridPrivate *priv; + g_return_if_fail(HILDON_IS_GRID(grid)); + priv = HILDON_GRID_GET_PRIVATE(grid); + + gtk_widget_style_get(GTK_WIDGET(grid), + "item_hspacing", &h_margin, + "item_vspacing", &v_margin, + "item_height", &item_height, + "icon_size", &icon_width, + "n_columns", &num_columns, + "label_pos", &label_pos, + "label_hspacing", &focus_margin, + "label_vspacing", &icon_label_margin, + "emblem_size", &emblem_size, + "label_height", &label_height, + NULL); + + hildon_grid_set_icon_width(grid, icon_width); + hildon_grid_set_num_columns(grid, num_columns); + hildon_grid_set_label_pos(grid, label_pos); + hildon_grid_set_focus_margin(grid, focus_margin); + hildon_grid_set_icon_label_margin(grid, icon_label_margin); + hildon_grid_set_emblem_size(grid, emblem_size); + hildon_grid_set_label_height(grid, label_height); + + priv->h_margin = h_margin; + priv->v_margin = v_margin; + priv->item_height = item_height; + + iter = NULL; + /* + for (iter = priv->children; iter != NULL; iter = iter->next) { + HildonGridItem *child; + child = HILDON_GRID_ITEM(((HildonGridChild *) iter->data)->widget); + _hildon_grid_item_done_updating_settings(child); + } + */ +} + + + +/** + * hildon_grid_set_scrollbar_pos: + * @grid: #HildonGrid + * @scrollbar_pos: new position (in pixels) + * + * Sets view (scrollbar) to specified position. + */ +void hildon_grid_set_scrollbar_pos(HildonGrid * grid, gint scrollbar_pos) +{ + HildonGridPrivate *priv; + GtkAdjustment *adjustment; + + g_return_if_fail(HILDON_IS_GRID(grid)); + + priv = HILDON_GRID_GET_PRIVATE(grid); + adjustment = gtk_range_get_adjustment(GTK_RANGE(priv->scrollbar)); + adjustment->value = (gdouble) scrollbar_pos; + + gtk_range_set_adjustment(GTK_RANGE(priv->scrollbar), adjustment); + + g_object_notify (G_OBJECT (grid), "scrollbar-position"); + + /* If grid isn't drawable, updating anything could mess up focus. */ + if (!GTK_WIDGET_DRAWABLE(GTK_WIDGET(grid))) + return; + + update_contents(grid); +} + +/** + * hildon_grid_get_scrollbar_pos: + * @grid: #HildonGrid + * + * Returns: position of scrollbar (in pixels). + */ +gint hildon_grid_get_scrollbar_pos(HildonGrid * grid) +{ + GtkAdjustment *adjustment; + + g_return_val_if_fail(HILDON_IS_GRID(grid), -1); + + adjustment = gtk_range_get_adjustment(GTK_RANGE + (HILDON_GRID_GET_PRIVATE + (grid)->scrollbar)); + return (int) adjustment->value; +} + +static void +hildon_grid_set_property(GObject * object, + guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + HildonGrid *grid; + + grid = HILDON_GRID(object); + + switch (prop_id) { + case PROP_EMPTY_LABEL: + hildon_grid_set_empty_label(grid, g_value_get_string(value)); + break; + + case PROP_STYLE: + hildon_grid_set_style(grid, g_value_get_string(value)); + break; + + case PROP_SCROLLBAR_POS: + hildon_grid_set_scrollbar_pos(grid, g_value_get_int(value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +hildon_grid_get_property(GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + HildonGrid *grid; + + grid = HILDON_GRID(object); + + switch (prop_id) { + case PROP_EMPTY_LABEL: + g_value_set_string(value, hildon_grid_get_empty_label(grid)); + break; + + case PROP_STYLE: + g_value_set_string(value, hildon_grid_get_style(grid)); + break; + + case PROP_SCROLLBAR_POS: + g_value_set_int(value, hildon_grid_get_scrollbar_pos(grid)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static gboolean +hildon_grid_state_changed(GtkWidget * widget, + GtkStateType state, gpointer data) +{ + HildonGrid *grid; + HildonGridPrivate *priv; + GList *list; + GtkWidget *current; + GtkWidget *prev_focusable, *next_focusable; + gboolean found_old; + + g_return_val_if_fail(HILDON_IS_GRID(data), FALSE); + g_return_val_if_fail(HILDON_IS_GRID_ITEM(widget), FALSE); + + grid = HILDON_GRID(data); + priv = HILDON_GRID_GET_PRIVATE(grid); + + + if (GTK_WIDGET_IS_SENSITIVE(widget)) + return FALSE; + + prev_focusable = next_focusable = NULL; + found_old = FALSE; + + for (list = priv->children; list != NULL; list = list->next) { + current = ((HildonGridChild *) list->data)->widget; + + if (GTK_WIDGET_IS_SENSITIVE(current)) { + if (found_old) { + next_focusable = current; + break; + } else { + prev_focusable = current; + } + } else if (current == widget) { + found_old = TRUE; + } + } + + if (next_focusable == NULL) { + next_focusable = prev_focusable; + } + + gtk_container_set_focus_child(GTK_CONTAINER(grid), next_focusable); + + return FALSE; +} + + + +static void +hildon_grid_tap_and_hold_setup(GtkWidget * widget, + GtkWidget * menu, + GtkCallback func, + GtkWidgetTapAndHoldFlags flags) +{ + g_return_if_fail(HILDON_IS_GRID(widget) && GTK_IS_MENU(menu)); + + parent_class->parent_class.tap_and_hold_setup + (widget, menu, func, flags | GTK_TAP_AND_HOLD_NO_INTERNALS); +} diff --git a/src/hildon-grid.h b/src/hildon-grid.h new file mode 100644 index 0000000..4863566 --- /dev/null +++ b/src/hildon-grid.h @@ -0,0 +1,107 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/* + * @file hildon-grid.h + * + * This file is a header file for hildon-grid.c, the implementation of + * #HildonGrid. #HildonGrid is used in views like Home and Control Panel + * which have single-tap activated items. + */ + +#ifndef __HILDON_GRID_H__ +#define __HILDON_GRID_H__ + +#include +#include + +G_BEGIN_DECLS +#define HILDON_TYPE_GRID (hildon_grid_get_type ()) +#define HILDON_GRID(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + HILDON_TYPE_GRID, \ + HildonGrid)) +#define HILDON_GRID_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \ + HILDON_TYPE_GRID, \ + HildonGridClass)) +#define HILDON_IS_GRID(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + HILDON_TYPE_GRID)) +#define HILDON_IS_GRID_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + HILDON_TYPE_GRID)) +#define HILDON_GRID_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + HILDON_TYPE_GRID, \ + HildonGridClass)) +typedef struct _HildonGrid HildonGrid; +typedef struct _HildonGridClass HildonGridClass; + + + +struct _HildonGrid { + GtkContainer parent; +}; + +struct _HildonGridClass { + GtkContainerClass parent_class; + + void (*activate_child) (HildonGrid * grid, HildonGridItem * item); + void (*popup_context_menu) (HildonGrid * grid, HildonGridItem * item); +}; + +GType hildon_grid_get_type(void); +GtkWidget *hildon_grid_new(void); + +/* + * Use GtkContainer API: + * + * void gtk_container_set_focus_child (GtkContainer *container, + * GtkWidget *child); + * + * GTK_CONTAINER (grid)->focus_child can be used to get focused child. + */ + +void hildon_grid_set_style(HildonGrid * grid, const gchar * style_name); +const gchar *hildon_grid_get_style(HildonGrid * grid); + +void hildon_grid_set_scrollbar_pos(HildonGrid * grid, gint scrollbar_pos); +gint hildon_grid_get_scrollbar_pos(HildonGrid * grid); + + +/* + * We are going to use gtk_container_add/remove, so these are internal. + * If GridView is not visible, it won't update the view, so it should be + * hidden when doing massive modifications. + * + * + * Use GtkContainer API: + * + * void gtk_container_add (GtkContainer *container, + * GtkWidget *widget); + * + * void gtk_container_remove (GtkContainer *container, + * GtkWidget *widget); + */ + +void hildon_grid_activate_child(HildonGrid * grid, HildonGridItem * item); + +G_END_DECLS +#endif /* __HILDON_GRID_H__ */ diff --git a/src/hildon-hvolumebar.c b/src/hildon-hvolumebar.c new file mode 100644 index 0000000..c3d7a10 --- /dev/null +++ b/src/hildon-hvolumebar.c @@ -0,0 +1,330 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-hvolumebar + * @short_description: A widget that displays a horizontal volume bar + * @see_also: #HildonVVolumebar, #HildonVolumebar + * + * The #HildonHVolumebar widget displays a horizontal volume bar that allows + * increasing or decreasing volume within a pre-defined range, and includes + * a mute icon which users can click to mute the sound. + */ + + +/* Horizontal volumebar subclass */ + +#include +#include "hildon-hvolumebar.h" +#include "hildon-volumebar.h" +#include "hildon-volumebar-range.h" +#include "hildon-volumebar-private.h" + +/* Defines for normal version of HVolumebar */ +/* Toggle button */ +#define DEFAULT_TBUTTON_WIDTH 26 +#define DEFAULT_TBUTTON_HEIGHT 26 +/* Volume bar */ +#define MINIMUM_BAR_WIDTH 147 +#define DEFAULT_BAR_HEIGHT 58 +#define DEFAULT_ENDING_SIZE 20 + +/* Gap to leave for mute button */ +#define VERTICAL_MUTE_GAP 16 +#define HORIZONTAL_MUTE_GAP 6 + +/* Sizes inside a toolbar */ +/* Toggle button */ +#define TOOL_DEFAULT_TBUTTON_WIDTH 26 +#define TOOL_DEFAULT_TBUTTON_HEIGHT 26 +/* Volumebar */ +#define TOOL_MINIMUM_BAR_WIDTH 121 +#define TOOL_DEFAULT_BAR_HEIGHT 40 +#define TOOL_DEFAULT_ENDING_SIZE 0 +#define TOOL_VERTICAL_MUTE_GAP ((TOOL_DEFAULT_BAR_HEIGHT - TOOL_DEFAULT_TBUTTON_HEIGHT) / 2) + +static HildonVolumebarClass *parent_class; +static void hildon_hvolumebar_class_init(HildonHVolumebarClass * klass); +static void hildon_hvolumebar_init(HildonHVolumebar * hvolumebar); + +static gboolean hildon_hvolumebar_expose(GtkWidget * widget, + GdkEventExpose * event); +static void hildon_hvolumebar_size_request(GtkWidget * widget, + GtkRequisition * requisition); +static void hildon_hvolumebar_size_allocate(GtkWidget * widget, + GtkAllocation * allocation); +static void hildon_hvolumebar_map(GtkWidget * widget); + + +GType hildon_hvolumebar_get_type(void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo info = { + sizeof(HildonHVolumebarClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_hvolumebar_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonHVolumebar), + 0, + (GInstanceInitFunc) hildon_hvolumebar_init, + }; + type = g_type_register_static(HILDON_TYPE_VOLUMEBAR, + "HildonHVolumebar", &info, 0); + } + return type; +} + + +static void hildon_hvolumebar_class_init(HildonHVolumebarClass * klass) +{ + GtkWidgetClass *volumebar_class = GTK_WIDGET_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + volumebar_class->size_request = hildon_hvolumebar_size_request; + volumebar_class->size_allocate = hildon_hvolumebar_size_allocate; + volumebar_class->map = hildon_hvolumebar_map; + volumebar_class->expose_event = hildon_hvolumebar_expose; +} + + +static void hildon_hvolumebar_init(HildonHVolumebar * hvolumebar) +{ + HildonVolumebarPrivate *priv; + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(hvolumebar); + + priv->volumebar = + HILDON_VOLUMEBAR_RANGE(hildon_volumebar_range_new + (GTK_ORIENTATION_HORIZONTAL)); + + GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(hvolumebar), GTK_CAN_FOCUS); + + gtk_widget_set_parent(GTK_WIDGET(priv->tbutton), GTK_WIDGET(hvolumebar)); + gtk_widget_set_parent(GTK_WIDGET(priv->volumebar), GTK_WIDGET(hvolumebar)); + + gtk_scale_set_draw_value(GTK_SCALE(priv->volumebar), FALSE); + + /* Signals */ + g_signal_connect_swapped(G_OBJECT(priv->volumebar), "value-changed", + G_CALLBACK(hildon_volumebar_level_change), + hvolumebar); + g_signal_connect_swapped(priv->tbutton, "toggled", + G_CALLBACK(_hildon_volumebar_mute_toggled), hvolumebar); + + gtk_widget_show(GTK_WIDGET(priv->volumebar)); +} + +/** + * hildon_hvolumebar_new: + * + * Creates a new #HildonHVolumebar widget. + * + * Returns: a new #HildonHVolumebar + */ +GtkWidget *hildon_hvolumebar_new(void) +{ + return GTK_WIDGET(g_object_new(HILDON_TYPE_HVOLUMEBAR, NULL)); +} + +static void hildon_hvolumebar_map(GtkWidget * widget) +{ + HildonVolumebarPrivate *priv; + GtkWidget *parent; + + g_assert(HILDON_IS_HVOLUMEBAR(widget)); + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget); + parent = gtk_widget_get_ancestor(GTK_WIDGET(widget), GTK_TYPE_TOOLBAR); + + /* Check if the volumebar is in a toolbar */ + if (parent) + priv->is_toolbar = TRUE; + + GTK_WIDGET_CLASS(parent_class)->map(widget); +} + +static gboolean hildon_hvolumebar_expose(GtkWidget * widget, + GdkEventExpose * event) +{ + HildonVolumebarPrivate *priv; + + g_assert(HILDON_IS_HVOLUMEBAR(widget)); + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(HILDON_VOLUMEBAR(widget)); + + if (GTK_WIDGET_DRAWABLE(widget)) { + /* Paint background */ + gtk_paint_box(widget->style, widget->window, + GTK_WIDGET_STATE(priv->volumebar), GTK_SHADOW_OUT, + NULL, widget, "background", + widget->allocation.x, + widget->allocation.y, + widget->allocation.width, + widget->allocation.height); + + /* The contents of the widget can paint themselves */ + (*GTK_WIDGET_CLASS(parent_class)->expose_event) (widget, event); + } + + return FALSE; +} + +static void +hildon_hvolumebar_size_request(GtkWidget * widget, + GtkRequisition * requisition) +{ + HildonVolumebarPrivate *priv; + + g_assert(HILDON_IS_HVOLUMEBAR(widget)); + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(HILDON_VOLUMEBAR(widget)); + + /* Volumebar has different dimensions in toolbar */ + requisition->width = (priv->is_toolbar + ? TOOL_MINIMUM_BAR_WIDTH + : MINIMUM_BAR_WIDTH); + requisition->height = (priv->is_toolbar + ? TOOL_DEFAULT_BAR_HEIGHT + : DEFAULT_BAR_HEIGHT); +} + +static void +hildon_hvolumebar_size_allocate(GtkWidget * widget, + GtkAllocation * allocation) +{ + HildonVolumebarPrivate *priv; + GtkAllocation button_allocation, range_allocation; + + g_assert(HILDON_IS_HVOLUMEBAR(widget)); + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget); + + button_allocation.x = 0; + button_allocation.width = 0; + + /* Center the widget vertically */ + if (priv->is_toolbar && allocation->height > TOOL_DEFAULT_BAR_HEIGHT) { + allocation->y += (allocation->height - TOOL_DEFAULT_BAR_HEIGHT) / 2; + allocation->height = TOOL_DEFAULT_BAR_HEIGHT; + } + if (!priv->is_toolbar && allocation->height > DEFAULT_BAR_HEIGHT) { + allocation->y += (allocation->height - DEFAULT_BAR_HEIGHT) / 2; + allocation->height = DEFAULT_BAR_HEIGHT; + } + + GTK_WIDGET_CLASS(parent_class)->size_allocate(widget, allocation); + + if (priv->tbutton && GTK_WIDGET_VISIBLE(priv->tbutton)) { + + /* Allocate space for the mute button */ + if (priv->is_toolbar) { + button_allocation.x = allocation->x; + button_allocation.y = allocation->y + TOOL_VERTICAL_MUTE_GAP; + button_allocation.width = TOOL_DEFAULT_TBUTTON_WIDTH; + button_allocation.height = TOOL_DEFAULT_TBUTTON_HEIGHT; + } else { + button_allocation.x = allocation->x + DEFAULT_ENDING_SIZE; + button_allocation.y = allocation->y + VERTICAL_MUTE_GAP; + button_allocation.width = DEFAULT_TBUTTON_WIDTH; + button_allocation.height = DEFAULT_TBUTTON_HEIGHT; + } + gtk_widget_size_allocate(GTK_WIDGET(priv->tbutton), + &button_allocation); + } + if (priv->volumebar && GTK_WIDGET_VISIBLE(priv->volumebar)) { + + /* Allocate space for the slider */ + range_allocation.y = allocation->y; + + if (priv->tbutton && GTK_WIDGET_VISIBLE(priv->tbutton)) + { + /* Leave room for the mute button */ + range_allocation.x = button_allocation.x + + button_allocation.width + + HORIZONTAL_MUTE_GAP; + + if (priv->is_toolbar) + { + /* In toolbar with mute button */ + range_allocation.width = MAX(0, + allocation->width + - 2 * TOOL_DEFAULT_ENDING_SIZE + - TOOL_DEFAULT_TBUTTON_WIDTH + - HORIZONTAL_MUTE_GAP); + + range_allocation.height = TOOL_DEFAULT_BAR_HEIGHT; + + } + + else + { + /* Standalone with mute button */ + range_allocation.width = MAX(0, + allocation->width + - 2 * DEFAULT_ENDING_SIZE + - DEFAULT_TBUTTON_WIDTH + - HORIZONTAL_MUTE_GAP); + + range_allocation.height = DEFAULT_BAR_HEIGHT; + } + + } + + else + { + if (priv->is_toolbar) + { + /* In toolbar without mute button */ + range_allocation.x = allocation->x; + + range_allocation.width = MAX(0, + allocation->width + - 2 * TOOL_DEFAULT_ENDING_SIZE ); + + range_allocation.height = TOOL_DEFAULT_BAR_HEIGHT; + + } + + else + { + /* Standalone without mute button */ + range_allocation.x = allocation->x + DEFAULT_ENDING_SIZE; + + range_allocation.width = MAX(0, + allocation->width + - 2 * DEFAULT_ENDING_SIZE ); + + range_allocation.height = DEFAULT_BAR_HEIGHT; + } + } + + gtk_widget_size_allocate(GTK_WIDGET(priv->volumebar), + &range_allocation); + } +} diff --git a/src/hildon-hvolumebar.h b/src/hildon-hvolumebar.h new file mode 100644 index 0000000..1b13432 --- /dev/null +++ b/src/hildon-hvolumebar.h @@ -0,0 +1,58 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_HVOLUMEBAR_H__ +#define __HILDON_HVOLUMEBAR_H__ + +#include + +G_BEGIN_DECLS + +#define HILDON_TYPE_HVOLUMEBAR ( hildon_hvolumebar_get_type() ) +#define HILDON_HVOLUMEBAR(obj) (GTK_CHECK_CAST (obj,\ + HILDON_TYPE_HVOLUMEBAR, HildonHVolumebar)) +#define HILDON_HVOLUMEBAR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass),\ + HILDON_TYPE_HVOLUMEBAR, HildonHVolumebarClass)) +#define HILDON_IS_HVOLUMEBAR(obj) (GTK_CHECK_TYPE (obj,\ + HILDON_TYPE_HVOLUMEBAR)) +#define HILDON_IS_HVOLUMEBAR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass),\ + HILDON_TYPE_HVOLUMEBAR)) + +typedef struct _HildonHVolumebar HildonHVolumebar; +typedef struct _HildonHVolumebarClass HildonHVolumebarClass; + +struct _HildonHVolumebar { + /* This is our parent class */ + HildonVolumebar volumebar; +}; + +struct _HildonHVolumebarClass { + HildonVolumebarClass parent_class; +}; + +GType hildon_hvolumebar_get_type(void) G_GNUC_CONST; +GtkWidget *hildon_hvolumebar_new(void); + +G_END_DECLS +#endif /* __HILDON_HVOLUMEBAR_H__ */ diff --git a/src/hildon-input-mode-hint.h b/src/hildon-input-mode-hint.h new file mode 100644 index 0000000..f6833fc --- /dev/null +++ b/src/hildon-input-mode-hint.h @@ -0,0 +1,70 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_INPUT_MODE_HINT_H__ +#define __HILDON_INPUT_MODE_HINT_H__ + +G_BEGIN_DECLS + +/* Hildon wrapper for setting the input mode in a GtkEntry + * Usage: g_object_set(G_OBJECT(entry), HILDON_INPUT_MODE_HINT, HILDON_INPUT_MODE_HINT_HEXA, NULL); + */ +#define HILDON_INPUT_MODE_HINT "input-mode" + +/* Hildon wrapper for setting the autocapitalization in text widgets. + * Usage: g_object_set(G_OBJECT(entry), HILDON_AUTOCAP, FALSE, NULL); + */ +#define HILDON_AUTOCAP "autocap" + +/** + * HildonInputModeHint: + * @HILDON_INPUT_MODE_HINT_ALPHANUMERICSPECIAL: accept all characters. + * @HILDON_INPUT_MODE_HINT_NUMERIC: accept only NUMERIC characters. + * @HILDON_INPUT_MODE_HINT_ALPHA: accept only ALPHA characters + * @HILDON_INPUT_MODE_HINT_NUMERICSPECIAL: accept only NUMERIC and SPECIAL + * @HILDON_INPUT_MODE_HINT_ALPHASPECIAL: accept only ALPHA and SPECIAL + * @HILDON_INPUT_MODE_HINT_ALPHANUMERIC: accept only ALPHA and NUMERIC + * @HILDON_INPUT_MODE_HINT_HEXA: accept only HEXA + * @HILDON_INPUT_MODE_HINT_HEXASPECIAL: accept only HEXA and SPECIAL + * @HILDON_INPUT_MODE_HINT_TELE: accept only TELEPHONE + * @HILDON_INPUT_MODE_HINT_TELESPECIAL: accept only TELEPHONE and SPECIAL + * + * Keys to set the mode in a GtkEntry widget into ALPHANUMERIC or NUMERIC mode. Note that this is only a hint; it only shows VKB with specified layout. Use it by calling 'g_object_set(G_OBJECT(entry), "input-mode", HILDON_INPUT_MODE_HINT_NUMERIC, NULL);'. + */ +typedef enum { + HILDON_INPUT_MODE_HINT_ALPHANUMERICSPECIAL = 0, + HILDON_INPUT_MODE_HINT_NUMERIC, + HILDON_INPUT_MODE_HINT_ALPHA, + HILDON_INPUT_MODE_HINT_NUMERICSPECIAL, + HILDON_INPUT_MODE_HINT_ALPHASPECIAL, + HILDON_INPUT_MODE_HINT_ALPHANUMERIC, + HILDON_INPUT_MODE_HINT_HEXA, + HILDON_INPUT_MODE_HINT_HEXASPECIAL, + HILDON_INPUT_MODE_HINT_TELE, + HILDON_INPUT_MODE_HINT_TELESPECIAL + +} HildonInputModeHint; + +G_END_DECLS +#endif /* __HILDON_INPUT_MODE_HINT_H__ */ diff --git a/src/hildon-marshalers.c b/src/hildon-marshalers.c new file mode 100644 index 0000000..b5dd899 --- /dev/null +++ b/src/hildon-marshalers.c @@ -0,0 +1,134 @@ +#include + +#include + + +#ifdef G_ENABLE_DEBUG +#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) +#define g_marshal_value_peek_char(v) g_value_get_char (v) +#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) +#define g_marshal_value_peek_int(v) g_value_get_int (v) +#define g_marshal_value_peek_uint(v) g_value_get_uint (v) +#define g_marshal_value_peek_long(v) g_value_get_long (v) +#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) +#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) +#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) +#define g_marshal_value_peek_enum(v) g_value_get_enum (v) +#define g_marshal_value_peek_flags(v) g_value_get_flags (v) +#define g_marshal_value_peek_float(v) g_value_get_float (v) +#define g_marshal_value_peek_double(v) g_value_get_double (v) +#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) +#define g_marshal_value_peek_param(v) g_value_get_param (v) +#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) +#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) +#define g_marshal_value_peek_object(v) g_value_get_object (v) +#else /* !G_ENABLE_DEBUG */ +/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. + * Do not access GValues directly in your code. Instead, use the + * g_value_get_*() functions + */ +#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int +#define g_marshal_value_peek_char(v) (v)->data[0].v_int +#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint +#define g_marshal_value_peek_int(v) (v)->data[0].v_int +#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint +#define g_marshal_value_peek_long(v) (v)->data[0].v_long +#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 +#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 +#define g_marshal_value_peek_enum(v) (v)->data[0].v_long +#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong +#define g_marshal_value_peek_float(v) (v)->data[0].v_float +#define g_marshal_value_peek_double(v) (v)->data[0].v_double +#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +#endif /* !G_ENABLE_DEBUG */ + + +/* BOOLEAN:ENUM (hildon-marshalers.list:26) */ +void +_hildon_marshal_BOOLEAN__ENUM (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef gboolean (*GMarshalFunc_BOOLEAN__ENUM) (gpointer data1, + gint arg_1, + gpointer data2); + register GMarshalFunc_BOOLEAN__ENUM callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + gboolean v_return; + + g_return_if_fail (return_value != NULL); + g_return_if_fail (n_param_values == 2); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_BOOLEAN__ENUM) (marshal_data ? marshal_data : cc->callback); + + v_return = callback (data1, + g_marshal_value_peek_enum (param_values + 1), + data2); + + g_value_set_boolean (return_value, v_return); +} + +/* BOOLEAN:INT,INT,INT (hildon-marshalers.list:27) */ +void +_hildon_marshal_BOOLEAN__INT_INT_INT (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef gboolean (*GMarshalFunc_BOOLEAN__INT_INT_INT) (gpointer data1, + gint arg_1, + gint arg_2, + gint arg_3, + gpointer data2); + register GMarshalFunc_BOOLEAN__INT_INT_INT callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + gboolean v_return; + + g_return_if_fail (return_value != NULL); + g_return_if_fail (n_param_values == 4); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_BOOLEAN__INT_INT_INT) (marshal_data ? marshal_data : cc->callback); + + v_return = callback (data1, + g_marshal_value_peek_int (param_values + 1), + g_marshal_value_peek_int (param_values + 2), + g_marshal_value_peek_int (param_values + 3), + data2); + + g_value_set_boolean (return_value, v_return); +} + +/* VOID:OBJECT (hildon-marshalers.list:28) */ + diff --git a/src/hildon-marshalers.h b/src/hildon-marshalers.h new file mode 100644 index 0000000..f616e9d --- /dev/null +++ b/src/hildon-marshalers.h @@ -0,0 +1,31 @@ + +#ifndef ___HILDON_MARSHALERS_H__ +#define ___HILDON_MARSHALERS_H__ + +#include + +G_BEGIN_DECLS + +/* BOOLEAN:ENUM (hildon-marshalers.list:26) */ +extern void _hildon_marshal_BOOLEAN__ENUM (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +/* BOOLEAN:INT,INT,INT (hildon-marshalers.list:27) */ +extern void _hildon_marshal_BOOLEAN__INT_INT_INT (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +/* VOID:OBJECT (hildon-marshalers.list:28) */ +#define _hildon_marshal_VOID__OBJECT g_cclosure_marshal_VOID__OBJECT + +G_END_DECLS + +#endif /* __HILDON_MARSHALERS_H__ */ + diff --git a/src/hildon-marshalers.list b/src/hildon-marshalers.list new file mode 100644 index 0000000..d8596b2 --- /dev/null +++ b/src/hildon-marshalers.list @@ -0,0 +1,28 @@ +# A copy of gtkmarshalers.list header for convenience +# +# see glib-genmarshal(1) for a detailed description of the file format, +# possible parameter types are: +# VOID indicates no return type, or no extra +# parameters. if VOID is used as the parameter +# list, no additional parameters may be present. +# BOOLEAN for boolean types (gboolean) +# CHAR for signed char types (gchar) +# UCHAR for unsigned char types (guchar) +# INT for signed integer types (gint) +# UINT for unsigned integer types (guint) +# LONG for signed long integer types (glong) +# ULONG for unsigned long integer types (gulong) +# ENUM for enumeration types (gint) +# FLAGS for flag enumeration types (guint) +# FLOAT for single-precision float types (gfloat) +# DOUBLE for double-precision float types (gdouble) +# STRING for string types (gchar*) +# BOXED for boxed (anonymous but reference counted) types (GBoxed*) +# POINTER for anonymous pointer types (gpointer) +# OBJECT for GObject or derived types (GObject*) +# NONE deprecated alias for VOID +# BOOL deprecated alias for BOOLEAN + +BOOLEAN:ENUM +BOOLEAN:INT,INT,INT +VOID:OBJECT diff --git a/src/hildon-name-password-dialog.c b/src/hildon-name-password-dialog.c new file mode 100644 index 0000000..327e1f0 --- /dev/null +++ b/src/hildon-name-password-dialog.c @@ -0,0 +1,382 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-name-password-dialog + * @short_description: A widget which allows a user to enter an username + * and a password + * @see_also: #HildonGetPasswordDialog, #HildonSetPasswordDialog + * + * #HildonNamePasswordDialog is used to enter a username and password + * when accessing a password protected function. The widget performs no + * input checking and is used only for retrieving a user name and a + * password. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#define _(String) dgettext(PACKAGE, String) + +static GtkDialogClass *parent_class; + +typedef struct _HildonNamePasswordDialogPrivate + HildonNamePasswordDialogPrivate; + +struct _HildonNamePasswordDialogPrivate { + GtkButton *okButton; + GtkButton *closeButton; + + GtkLabel *domainLabel; + GtkEntry *nameEntry; + GtkEntry *passwordEntry; +}; + +/* Macro to access the private data of the object instance */ +#define HILDON_NAME_PASSWORD_DIALOG_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), HILDON_TYPE_NAME_PASSWORD_DIALOG,\ + HildonNamePasswordDialogPrivate)) + +enum{ + PROP_NONE = 0, + PROP_CONTENT, + PROP_USERNAME, + PROP_PASSWORD +}; + +static void +hildon_name_password_dialog_class_init(HildonNamePasswordDialogClass *class); +static void hildon_name_password_dialog_init(HildonNamePasswordDialog *widget); +static void hildon_name_password_dialog_set_property(GObject * object, + guint prop_id, + const GValue * value, + GParamSpec * pspec); +static void hildon_name_password_dialog_get_property(GObject * object, + guint prop_id, + GValue * value, + GParamSpec * pspec); + +static void +hildon_name_password_dialog_set_property(GObject * object, + guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + HildonNamePasswordDialog *dialog = NULL; + HildonNamePasswordDialogPrivate *priv = NULL; + + dialog = HILDON_NAME_PASSWORD_DIALOG(object); + priv = HILDON_NAME_PASSWORD_DIALOG_GET_PRIVATE(dialog); + + switch (prop_id) { + case PROP_CONTENT: + /* Set the password domain text */ + hildon_name_password_dialog_set_domain(dialog, g_value_get_string(value)); + break; + case PROP_USERNAME: + /* Set the current username displayed in the dialog */ + gtk_entry_set_text(priv->nameEntry, g_value_get_string(value)); + break; + case PROP_PASSWORD: + /* Set the currently entered password */ + gtk_entry_set_text(priv->passwordEntry, g_value_get_string(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +hildon_name_password_dialog_get_property(GObject * object, + guint prop_id, + GValue * value, GParamSpec * pspec) +{ + HildonNamePasswordDialog *dialog = NULL; + HildonNamePasswordDialogPrivate *priv = NULL; + + dialog = HILDON_NAME_PASSWORD_DIALOG(object); + priv = HILDON_NAME_PASSWORD_DIALOG_GET_PRIVATE(dialog); + + switch (prop_id) { + case PROP_CONTENT: + g_value_set_string(value, gtk_label_get_text(priv->domainLabel)); + break; + case PROP_USERNAME: + g_value_set_string(value, hildon_name_password_dialog_get_name(dialog)); + break; + case PROP_PASSWORD: + g_value_set_string(value, hildon_name_password_dialog_get_password(dialog)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +hildon_name_password_dialog_class_init(HildonNamePasswordDialogClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(class); + + parent_class = g_type_class_peek_parent(class); + + /* Override virtual functions */ + object_class->set_property = hildon_name_password_dialog_set_property; + object_class->get_property = hildon_name_password_dialog_get_property; + + /* Install new properties */ + g_object_class_install_property(object_class, + PROP_CONTENT, + g_param_spec_string ("content", + "Content", + "Set content for content label.", + NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property(object_class, + PROP_USERNAME, + g_param_spec_string ("username", + "Username", + "Set content for name entry.", + "DEFAULT", + G_PARAM_READWRITE)); + + g_object_class_install_property(object_class, + PROP_PASSWORD, + g_param_spec_string ("password", + "Password", + "Set content for password entry", + "DEFAULT", + G_PARAM_READWRITE)); + + /* Install private data structure */ + g_type_class_add_private(class, + sizeof(HildonNamePasswordDialogPrivate)); +} + +static void +hildon_name_password_dialog_init(HildonNamePasswordDialog * dialog) +{ + /* Access private structure */ + HildonNamePasswordDialogPrivate *priv = + HILDON_NAME_PASSWORD_DIALOG_GET_PRIVATE(dialog); + + /* Size group for captions */ + GtkSizeGroup *group = + GTK_SIZE_GROUP(gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL)); + HildonCaption *caption; + + /* Initialize dialog */ + gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); + gtk_window_set_title(GTK_WINDOW(dialog), _(HILDON_NAME_PASSWORD_DIALOG_TITLE)); + + /* Optional domain name label */ + priv->domainLabel = GTK_LABEL(gtk_label_new(NULL)); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), + GTK_WIDGET(priv->domainLabel), FALSE, FALSE, 0); + + /* Create buttons */ + priv->okButton = + GTK_BUTTON(gtk_dialog_add_button(GTK_DIALOG(dialog), + _(HILDON_NAME_PASSWORD_DIALOG_OK), + GTK_RESPONSE_OK)); + priv->closeButton = + GTK_BUTTON(gtk_dialog_add_button(GTK_DIALOG(dialog), + _(HILDON_NAME_PASSWORD_DIALOG_CANCEL), + GTK_RESPONSE_CANCEL)); + + /* Setup user name entry */ + priv->nameEntry = GTK_ENTRY(gtk_entry_new()); + g_object_set (priv->nameEntry, "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL); + gtk_entry_set_visibility(GTK_ENTRY(priv->nameEntry), FALSE); + caption = HILDON_CAPTION(hildon_caption_new + (group, + _(HILDON_NAME_PASSWORD_DIALOG_NAME ), + GTK_WIDGET(priv->nameEntry), NULL, + HILDON_CAPTION_OPTIONAL)); + hildon_caption_set_separator(caption, ""); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), + GTK_WIDGET(caption), FALSE, FALSE, 0); + + /* Setup password entry */ + priv->passwordEntry = GTK_ENTRY(gtk_entry_new()); + g_object_set (priv->passwordEntry, "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL); + gtk_entry_set_visibility(GTK_ENTRY(priv->passwordEntry), FALSE); + caption = + HILDON_CAPTION(hildon_caption_new(group, + _(HILDON_NAME_PASSWORD_DIALOG_PASSWORD), + GTK_WIDGET(priv->passwordEntry), + NULL, + HILDON_CAPTION_OPTIONAL)); + hildon_caption_set_separator(caption, ""); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), + GTK_WIDGET(caption), FALSE, FALSE, 0); + + gtk_widget_show_all(GTK_DIALOG(dialog)->vbox); + gtk_widget_show_all(GTK_DIALOG(dialog)->action_area); + gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); + + /* Ensure group is freed when all its contents have been removed */ + g_object_unref(group); +} + +GType hildon_name_password_dialog_get_type(void) +{ + static GType dialog_type = 0; + + if (!dialog_type) { + static const GTypeInfo dialog_info = { + sizeof(HildonNamePasswordDialogClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_name_password_dialog_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonNamePasswordDialog), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_name_password_dialog_init + }; + dialog_type = g_type_register_static(GTK_TYPE_DIALOG, + "HildonNamePasswordDialog", + &dialog_info, 0); + } + + return dialog_type; +} + +/** + * hildon_name_password_dialog_new: + * @parent: the parent window of the dialog + * + * Creates a new #HildonNamePasswordDialog widget with Ok and Close + * buttons. + * + * Returns: the newly created #HildonNamePasswordDialog + */ +GtkWidget *hildon_name_password_dialog_new(GtkWindow * parent) +{ + GtkWidget *self = g_object_new(HILDON_TYPE_NAME_PASSWORD_DIALOG,NULL); + + if (parent) + gtk_window_set_transient_for(GTK_WINDOW(self), parent); + + return self; +} + +/** + * hildon_name_password_dialog_new_with_default: + * @parent: the parent window of the dialog + * @name: default username, NULL if unset + * @password: default password, NULL if unset + * + * Same as #hildon_name_password_dialog_new, but with a + * default name and password. + * + * Returns: the newly created #HildonNamePasswordDialog + */ +GtkWidget *hildon_name_password_dialog_new_with_default(GtkWindow *parent, + const gchar *name, + const gchar *password) +{ + GtkWidget *self = hildon_name_password_dialog_new(parent); + + if(name != NULL) + g_object_set(G_OBJECT(self), "username", name, NULL); + if(password != NULL) + g_object_set(G_OBJECT(self), "password", password, NULL); + + return self; +} + +/** + * hildon_name_password_dialog_get_name: + * @dialog: the dialog + * + * Gets the text that's in the name entry. + * + * Returns: a pointer to the name string. + */ +const gchar *hildon_name_password_dialog_get_name(HildonNamePasswordDialog + * dialog) +{ + HildonNamePasswordDialogPrivate *priv; + + g_return_val_if_fail(HILDON_IS_NAME_PASSWORD_DIALOG(dialog), NULL); + + priv = HILDON_NAME_PASSWORD_DIALOG_GET_PRIVATE(dialog); + + return gtk_entry_get_text(priv->nameEntry); +} + +/** + * hildon_name_password_dialog_get_password: + * @dialog: the dialog + * + * Gets the text that's in the password entry. + * + * Returns: a pointer to the password string + */ +const gchar *hildon_name_password_dialog_get_password(HildonNamePasswordDialog + * dialog) +{ + HildonNamePasswordDialogPrivate *priv; + + g_return_val_if_fail(HILDON_IS_NAME_PASSWORD_DIALOG(dialog), NULL); + + priv = HILDON_NAME_PASSWORD_DIALOG_GET_PRIVATE(dialog); + + return gtk_entry_get_text(priv->passwordEntry); +} + +/** + * hildon_name_password_dialog_set_domain(GtkWidget *dialog, + * @dialog: the dialog + * @domain: the domain or some other descriptive text to be set + * + * sets the optional descriptive text + */ + +void hildon_name_password_dialog_set_domain(HildonNamePasswordDialog *dialog, + const gchar *domain) +{ + HildonNamePasswordDialogPrivate *priv; + + g_return_if_fail(HILDON_IS_NAME_PASSWORD_DIALOG(dialog)); + + priv = HILDON_NAME_PASSWORD_DIALOG_GET_PRIVATE(dialog); + gtk_label_set_text(priv->domainLabel, domain); +} diff --git a/src/hildon-name-password-dialog.h b/src/hildon-name-password-dialog.h new file mode 100644 index 0000000..25783b4 --- /dev/null +++ b/src/hildon-name-password-dialog.h @@ -0,0 +1,85 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_NAME_PASSWORD_DIALOG_H__ +#define __HILDON_NAME_PASSWORD_DIALOG_H__ + +#include + +G_BEGIN_DECLS +#define HILDON_TYPE_NAME_PASSWORD_DIALOG \ + ( hildon_name_password_dialog_get_type() ) +#define HILDON_NAME_PASSWORD_DIALOG(obj) \ + (GTK_CHECK_CAST (obj, HILDON_TYPE_NAME_PASSWORD_DIALOG,\ + HildonNamePasswordDialog)) +#define HILDON_NAME_PASSWORD_DIALOG_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST ((klass), HILDON_TYPE_NAME_PASSWORD_DIALOG, \ + HildonNamePasswordDialogClass)) +#define HILDON_IS_NAME_PASSWORD_DIALOG(obj) \ + (GTK_CHECK_TYPE (obj, HILDON_TYPE_NAME_PASSWORD_DIALOG)) +#define HILDON_IS_NAME_PASSWORD_DIALOG_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_NAME_PASSWORD_DIALOG)) + +#define HILDON_NAME_PASSWORD_DIALOG_TITLE "frw_ti_get_user_name_and_pwd" +#define HILDON_NAME_PASSWORD_DIALOG_NAME \ + "frw_ti_get_user_name_and_pwd_enter_user_name" +#define HILDON_NAME_PASSWORD_DIALOG_PASSWORD \ + "frw_ti_get_user_name_and_pwd_enter_pwd" +#define HILDON_NAME_PASSWORD_DIALOG_OK "frw_bd_get_user_name_and_pwd_ok" +#define HILDON_NAME_PASSWORD_DIALOG_CANCEL \ + "frw_bd_get_user_name_and_pwd_cancel" + + +typedef struct _HildonNamePasswordDialog HildonNamePasswordDialog; +typedef struct _HildonNamePasswordDialogClass + HildonNamePasswordDialogClass; + +struct _HildonNamePasswordDialog { + GtkDialog parent; +}; + +struct _HildonNamePasswordDialogClass { + GtkDialogClass parent_class; +}; + +GType hildon_name_password_dialog_get_type(void) G_GNUC_CONST; + +GtkWidget *hildon_name_password_dialog_new(GtkWindow * parent); + +GtkWidget *hildon_name_password_dialog_new_with_default(GtkWindow *parent, + const gchar *name, + const gchar *pass); + + +const gchar *hildon_name_password_dialog_get_name(HildonNamePasswordDialog + * dialog); + +const gchar *hildon_name_password_dialog_get_password(HildonNamePasswordDialog + * dialog); + +void hildon_name_password_dialog_set_domain(HildonNamePasswordDialog *dialog, + const gchar *domain); + +G_END_DECLS +#endif /* __HILDON_NAME_PASSWORD_DIALOG_H__ */ diff --git a/src/hildon-note.c b/src/hildon-note.c new file mode 100644 index 0000000..a58ca02 --- /dev/null +++ b/src/hildon-note.c @@ -0,0 +1,869 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-note + * @short_description: A widget to ask confirmation from the user + * + * Notes are used to for confirmation (OK/Cancel/etc.) from the user. + * A simple note contains an information text and an OK button to be + * pressed. Additional features such as progress bars or animation can + * also be included. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "hildon-note.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for _hildon_gtk_label_set_text_n_lines */ + +#include +#include + +/* FIXME: Can these be included from somewhere? */ +#define CONFIRMATION_SOUND_PATH "/usr/share/sounds/ui-confirmation_note.wav" +#define INFORMATION_SOUND_PATH "/usr/share/sounds/ui-information_note.wav" +#define HILDON_NOTE_CONFIRMATION_ICON "qgn_note_confirm" +#define HILDON_NOTE_INFORMATION_ICON "qgn_note_info" + +#define _(String) dgettext(PACKAGE, String) + +static GtkDialogClass *parent_class; + +#define HILDON_NOTE_GET_PRIVATE(obj)\ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_NOTE, HildonNotePrivate)); + +typedef struct _HildonNotePrivate HildonNotePrivate; + +static void hildon_note_class_init(HildonNoteClass * class); +static void hildon_note_init(HildonNote * dialog); + +static void hildon_note_rebuild(HildonNote *note); +static void hildon_note_finalize(GObject * obj_self); +static void hildon_note_realize (GtkWidget *widget); + +static void hildon_note_set_property(GObject * object, + guint prop_id, + const GValue * value, + GParamSpec * pspec); +static void hildon_note_get_property(GObject * object, + guint prop_id, + GValue * value, GParamSpec * pspec); + +static gboolean +sound_handling(GtkWidget * widget, GdkEventExpose *event, gpointer data); + +struct _HildonNotePrivate { + GtkWidget *okButton; + GtkWidget *cancelButton; + GtkWidget *label; + GtkWidget *box; + GtkWidget *icon; + + HildonNoteType note_n; + GtkWidget *progressbar; + gulong sound_signal_handler; + + gchar *original_description; +}; + +enum { + PROP_NONE = 0, + PROP_HILDON_NOTE_TYPE, + PROP_HILDON_NOTE_DESCRIPTION, + PROP_HILDON_NOTE_ICON, + PROP_HILDON_NOTE_PROGRESSBAR, + PROP_HILDON_NOTE_STOCK_ICON +}; + +static void +hildon_note_set_property(GObject * object, + guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + HildonNote *note = HILDON_NOTE(object); + HildonNotePrivate *priv; + GtkWidget *widget; + + priv = HILDON_NOTE_GET_PRIVATE(note); + + switch (prop_id) { + case PROP_HILDON_NOTE_TYPE: + priv->note_n = g_value_get_enum(value); + hildon_note_rebuild(note); + break; + case PROP_HILDON_NOTE_DESCRIPTION: + g_free(priv->original_description); + priv->original_description = g_value_dup_string(value); + + _hildon_gtk_label_set_text_n_lines(GTK_LABEL(priv->label), + priv->original_description, + priv->note_n == HILDON_NOTE_PROGRESSBAR_TYPE ? 1 : 5); + + break; + case PROP_HILDON_NOTE_ICON: + gtk_image_set_from_icon_name(GTK_IMAGE(priv->icon), + g_value_get_string(value), HILDON_ICON_SIZE_BIG_NOTE); + break; + case PROP_HILDON_NOTE_STOCK_ICON: + gtk_image_set_from_stock(GTK_IMAGE(priv->icon), + g_value_get_string(value), HILDON_ICON_SIZE_BIG_NOTE); + break; + case PROP_HILDON_NOTE_PROGRESSBAR: + widget = g_value_get_object(value); + if (widget != priv->progressbar) + { + if (priv->progressbar) + g_object_unref(priv->progressbar); + + priv->progressbar = widget; + + if (widget) + { + g_object_ref(widget); + gtk_object_sink(GTK_OBJECT(widget)); + } + + hildon_note_rebuild(note); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +hildon_note_get_property(GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + HildonNote *note = HILDON_NOTE(object); + HildonNotePrivate *priv; + + priv = HILDON_NOTE_GET_PRIVATE(note); + + switch (prop_id) { + case PROP_HILDON_NOTE_TYPE: + g_value_set_enum(value, priv->note_n); + break; + case PROP_HILDON_NOTE_DESCRIPTION: + g_value_set_string(value, priv->original_description); + break; + case PROP_HILDON_NOTE_ICON: + g_object_get_property(G_OBJECT(priv->icon), "icon-name", value); + break; + case PROP_HILDON_NOTE_STOCK_ICON: + g_object_get_property(G_OBJECT(priv->icon), "stock", value); + break; + case PROP_HILDON_NOTE_PROGRESSBAR: + g_value_set_object(value, priv->progressbar); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +GType hildon_note_type_get_type (void) +{ + static GType notetype = 0; + if (notetype == 0) { + static const GEnumValue values[] = { + { HILDON_NOTE_CONFIRMATION_TYPE, "HILDON_NOTE_CONFIRMATION_TYPE", "confirmation" }, + { HILDON_NOTE_CONFIRMATION_BUTTON_TYPE, "HILDON_NOTE_CONFIRMATION_BUTTON_TYPE", "confirmation-button" }, + { HILDON_NOTE_INFORMATION_TYPE, "HILDON_NOTE_INFORMATION_TYPE", "note-information" }, + { HILDON_NOTE_INFORMATION_THEME_TYPE, "HILDON_NOTE_INFORMATION_THEME_TYPE", "note-information-theme" }, + { HILDON_NOTE_PROGRESSBAR_TYPE, "HILDON_NOTE_PROGRESSBAR_TYPE", "note-progressbar" }, + { 0, NULL, NULL } + }; + notetype = g_enum_register_static ("HildonNoteType", values); + } + return notetype; +} + + +GType hildon_note_get_type() +{ + static GType dialog_type = 0; + + if (!dialog_type) { + static const GTypeInfo dialog_info = { + sizeof(HildonNoteClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_note_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonNote), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_note_init + }; + dialog_type = g_type_register_static(GTK_TYPE_DIALOG, + "HildonNote", + &dialog_info, 0); + } + return dialog_type; +} + +static void hildon_note_class_init(HildonNoteClass * class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(class); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(class); + + /* set the global parent_class */ + parent_class = g_type_class_peek_parent(class); + + g_type_class_add_private(class, sizeof(HildonNotePrivate)); + + object_class->finalize = hildon_note_finalize; + object_class->set_property = hildon_note_set_property; + object_class->get_property = hildon_note_get_property; + widget_class->realize = hildon_note_realize; + + g_object_class_install_property(object_class, + PROP_HILDON_NOTE_TYPE, + g_param_spec_enum("note_type", + "note type", + "The type of the note dialog", + hildon_note_type_get_type(), + HILDON_NOTE_CONFIRMATION_TYPE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + /** + * HildonNote:description: + * + * Description for note. + */ + g_object_class_install_property(object_class, + PROP_HILDON_NOTE_DESCRIPTION, + g_param_spec_string("description", + "note description", + "The text that appears in the note dialog", + "", + G_PARAM_READWRITE)); + + /** + * HildonNote:icon: + * + * Icon for note. + */ + g_object_class_install_property(object_class, + PROP_HILDON_NOTE_ICON, + g_param_spec_string("icon", + "note icon", + "The name of the icon that appears in the note dialog", + "", + G_PARAM_READWRITE)); + + /** + * HildonNote:stock-icon: + * + * Stock icon for note. + */ + g_object_class_install_property(object_class, + PROP_HILDON_NOTE_STOCK_ICON, + g_param_spec_string("stock-icon", + "Stock note icon", + "The stock name of the icon that appears in the note dialog", + "", + G_PARAM_READWRITE)); + + /** + * HildonNote:progressbar: + * + * Progressbar for note. + */ + g_object_class_install_property(object_class, + PROP_HILDON_NOTE_PROGRESSBAR, + g_param_spec_object("progressbar", + "Progressbar widget", + "The progressbar that appears in the note dialog", + GTK_TYPE_PROGRESS_BAR, + G_PARAM_READWRITE)); +} + +static void hildon_note_init(HildonNote * dialog) +{ + HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE(dialog); + + priv->label = gtk_label_new(NULL); + priv->icon = gtk_image_new(); + + /* Acquire real references to our internal children, since + they are not nessecarily packed into container in each + layout */ + g_object_ref(priv->label); + g_object_ref(priv->icon); + gtk_object_sink(GTK_OBJECT(priv->label)); + gtk_object_sink(GTK_OBJECT(priv->icon)); + + gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); + gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); +} + + +static void hildon_note_finalize(GObject * obj_self) +{ + HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE(obj_self); + + /* Free internal data */ + g_object_unref(priv->label); + g_object_unref(priv->icon); + if (priv->progressbar) + g_object_unref(priv->progressbar); + + g_free(priv->original_description); + + G_OBJECT_CLASS(parent_class)->finalize(obj_self); +} + +static void +hildon_note_realize (GtkWidget *widget) +{ + HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE(widget); + + /* Make widget->window accessible */ + GTK_WIDGET_CLASS (parent_class)->realize (widget); + + /* Border only, no titlebar */ + gdk_window_set_decorations (widget->window, GDK_DECOR_BORDER); + + /* Because ESD is synchronous, we wish to play sound after the + note is already on screen to avoid blocking its appearance */ + if (priv->sound_signal_handler == 0) + priv->sound_signal_handler = g_signal_connect_after(widget, + "expose-event", G_CALLBACK(sound_handling), NULL); +} + +/* Helper function for removing a widget from it's container. + we own a separate reference to each object we try to unpack, + so extra referencing is not needed. */ +static void unpack_widget(GtkWidget *widget) +{ + g_assert(widget == NULL || GTK_IS_WIDGET(widget)); + + if (widget && widget->parent) + gtk_container_remove(GTK_CONTAINER(widget->parent), widget); +} + +static void +hildon_note_rebuild(HildonNote *note) +{ + GtkDialog *dialog; + HildonNotePrivate *priv; + gboolean IsHorizontal = TRUE; + + g_assert(HILDON_IS_NOTE(note)); + + priv = HILDON_NOTE_GET_PRIVATE (note); + dialog = GTK_DIALOG(note); + + /* Reuse exiting content widgets for new layout */ + unpack_widget(priv->label); + unpack_widget(priv->icon); + unpack_widget(priv->progressbar); + + /* Destroy old layout and buttons */ + if (priv->box) { + gtk_widget_destroy(priv->box); + priv->box = NULL; + } + if (priv->okButton) { + gtk_widget_destroy(priv->okButton); + priv->okButton = NULL; + } + if (priv->cancelButton) { + gtk_widget_destroy(priv->cancelButton); + priv->cancelButton = NULL; + } + + /* Add needed buttons and images for each note type */ + switch (priv->note_n) + { + case HILDON_NOTE_CONFIRMATION_TYPE: + priv->okButton = gtk_dialog_add_button(dialog, + _("ecdg_bd_confirmation_note_ok"), GTK_RESPONSE_OK); + priv->cancelButton = gtk_dialog_add_button(dialog, + _("ecdg_bd_confirmation_note_cancel"), GTK_RESPONSE_CANCEL); + + /* Fall through */ + case HILDON_NOTE_CONFIRMATION_BUTTON_TYPE: + gtk_image_set_from_icon_name(GTK_IMAGE(priv->icon), + HILDON_NOTE_CONFIRMATION_ICON, + HILDON_ICON_SIZE_BIG_NOTE); + break; + + case HILDON_NOTE_INFORMATION_THEME_TYPE: + case HILDON_NOTE_INFORMATION_TYPE: + /* Add clickable OK button (cancel really, + but doesn't matter since this is info) */ + priv->cancelButton = gtk_dialog_add_button(dialog, + _("ecdg_bd_information_note_ok"), GTK_RESPONSE_CANCEL); + gtk_image_set_from_icon_name(GTK_IMAGE(priv->icon), + HILDON_NOTE_INFORMATION_ICON, + HILDON_ICON_SIZE_BIG_NOTE); + break; + + case HILDON_NOTE_PROGRESSBAR_TYPE: + priv->cancelButton = gtk_dialog_add_button(dialog, + _("ecdg_bd_cancel_note_cancel"), GTK_RESPONSE_CANCEL); + IsHorizontal = FALSE; + break; + + default: + break; + } + + if (IsHorizontal) { + /* Pack item with label horizontally */ + priv->box = gtk_hbox_new(FALSE, HILDON_MARGIN_DEFAULT); + gtk_container_add(GTK_CONTAINER(dialog->vbox), priv->box); + + if (priv->icon) { + GtkWidget *alignment = gtk_alignment_new(0, 0, 0, 0); + + gtk_box_pack_start(GTK_BOX(priv->box), alignment, FALSE, FALSE, 0); + gtk_container_add(GTK_CONTAINER(alignment), priv->icon); + } + gtk_box_pack_start(GTK_BOX(priv->box), priv->label, TRUE, TRUE, 0); + + } else { + /* Pack item with label vertically */ + priv->box = gtk_vbox_new(FALSE, HILDON_MARGIN_DOUBLE); + gtk_container_add(GTK_CONTAINER(dialog->vbox), priv->box); + gtk_box_pack_start(GTK_BOX(priv->box), priv->label, TRUE, TRUE, 0); + + if (priv->progressbar) + gtk_box_pack_start(GTK_BOX(priv->box), priv->progressbar, FALSE, FALSE, 0); + } + + gtk_widget_show_all(priv->box); +} + +/** + * hildon_note_new_confirmation_add_buttons: + * @parent: the parent window. The X window ID of the parent window + * has to be the same as the X window ID of the application. This is + * important so that the window manager could handle the windows + * correctly. + * In GTK the X window ID can be checked using + * GDK_WINDOW_XID(GTK_WIDGET(parent)->window). + * @description: the message to confirm + * @Varargs: arguments pairs for new buttons(label and return value). + * Terminate the list with %NULL value. + * + * Create a new confirmation note with custom buttons. Confirmation + * note has a text and any number of buttons. It's important to note + * that even though the name of the function might suggest, the + * default ok/cancel buttons are not appended but you have to provide + * all of the buttons. + * + * FIXME: This doc seems to be wrong, the two buttons aren't added so + * it would only contain the "additional" buttons? However, changing + * this would break those applications that rely on current behaviour. + * + * Returns: A #GtkWidget pointer of the note + */ +GtkWidget *hildon_note_new_confirmation_add_buttons(GtkWindow *parent, + const gchar *description, + ...) +{ + va_list args; + char *message; + int value; + + g_return_val_if_fail(parent == NULL || GTK_IS_WINDOW(parent), NULL); + + GtkWidget *conf_note = + g_object_new(HILDON_TYPE_NOTE, + "note_type", HILDON_NOTE_CONFIRMATION_BUTTON_TYPE, + "description", description, + "icon", HILDON_NOTE_CONFIRMATION_ICON, + NULL); + + if (parent != NULL) + gtk_window_set_transient_for(GTK_WINDOW(conf_note), parent); + + /* Add the buttons from varargs */ + va_start(args, description); + + while (TRUE) { + message = va_arg(args, char *); + + if (!message) { + break; + } + value = va_arg(args, int); + + gtk_dialog_add_button(GTK_DIALOG(conf_note), message, value); + } + + va_end(args); + + return conf_note; +} + + +/** + * hildon_note_new_confirmation: + * @parent: the parent window. The X window ID of the parent window + * has to be the same as the X window ID of the application. This is + * important so that the window manager could handle the windows + * correctly. In GTK the X window ID can be checked using + * GDK_WINDOW_XID(GTK_WIDGET(parent)->window). + * @description: the message to confirm + * + * Create a new confirmation note. Confirmation note has text (description) + * that you specify, two buttons and a default confirmation stock icon. + * + * Returns: a #GtkWidget pointer of the note + */ +GtkWidget *hildon_note_new_confirmation(GtkWindow * parent, + const gchar * description) +{ + return hildon_note_new_confirmation_with_icon_name + (parent, description, HILDON_NOTE_CONFIRMATION_ICON); +} + + +/** + * hildon_note_new_confirmation_with_icon_stock: + * @parent: the parent window. The X window ID of the parent window + * has to be the same as the X window ID of the application. This is + * important so that the window manager could handle the windows + * correctly. In GTK the X window ID can be checked using + * GDK_WINDOW_XID(GTK_WIDGET(parent)->window). + * @description: the message to confirm + * @stock_id: icon to be displayed. If NULL, default icon is used. + * + * Create a new confirmation note. Confirmation note has text (description) + * that you specify, two buttons and an icon. + * + * Deprecated: this function is broken, and really should not be used by anyone! + * + * Returns: a #GtkWidget pointer of the note + */ +GtkWidget *hildon_note_new_confirmation_with_icon_stock(GtkWindow * parent, + const gchar * + description, + const gchar * + stock_id) +{ + GtkWidget *dialog = g_object_new(HILDON_TYPE_NOTE, + "note_type", + HILDON_NOTE_CONFIRMATION_TYPE, + "description", description, "stock-icon", + stock_id, NULL); + + if (parent != NULL) + gtk_window_set_transient_for(GTK_WINDOW(dialog), parent); + + return dialog; +} + +/** + * hildon_note_new_confirmation_with_icon_name: + * @parent: the parent window. The X window ID of the parent window + * has to be the same as the X window ID of the application. This is + * important so that the window manager could handle the windows + * correctly. In GTK the X window ID can be checked using + * GDK_WINDOW_XID(GTK_WIDGET(parent)->window). + * @description: the message to confirm + * @icon_name: icon to be displayed. If NULL, default icon is used. + * + * Create a new confirmation note. Confirmation note has text(description) + * that you specify, two buttons and an icon. + * + * Returns: a #GtkWidget pointer of the note + */ +GtkWidget *hildon_note_new_confirmation_with_icon_name(GtkWindow * parent, + const gchar * + description, + const gchar * + icon_name) +{ + GtkWidget *dialog = NULL; + + g_return_val_if_fail(parent == NULL || GTK_IS_WINDOW(parent), NULL); + + dialog = g_object_new(HILDON_TYPE_NOTE, + "note_type", + HILDON_NOTE_CONFIRMATION_TYPE, + "description", description, "icon", + icon_name, NULL); + if (parent != NULL) + gtk_window_set_transient_for(GTK_WINDOW(dialog), parent); + + return dialog; +} + +/** + * hildon_note_new_information: + * @parent: the parent window. The X window ID of the parent window + * has to be the same as the X window ID of the application. This is + * important so that the window manager could handle the windows + * correctly. In GTK the X window ID can be checked using + * GDK_WINDOW_XID(GTK_WIDGET(parent)->window). + * @description: the message to confirm + * + * Create a new information note. Information note has a text(description) + * that you specify, an OK button and an icon. + * + * Returns: a #GtkWidget pointer of the note + */ +GtkWidget *hildon_note_new_information(GtkWindow * parent, + const gchar * description) +{ + return hildon_note_new_information_with_icon_name + (parent, description, HILDON_NOTE_INFORMATION_ICON); +} + +/** + * hildon_note_new_information_with_icon_stock: + * @parent: the parent window. The X window ID of the parent window + * has to be the same as the X window ID of the application. This is + * important so that the window manager could handle the windows + * correctly. In GTK the X window ID can be checked using + * GDK_WINDOW_XID(GTK_WIDGET(parent)->window). + * @description: the message to confirm + * @stock_id: icon to be displayed. If NULL, default icon is used. + * + * Create a new information note. Information note has text(description) + * that you specify, an OK button and a default stock note icon. + * + * Note! This function is broken and deprecated and should not be + * used by anybody. Since the platform doesn't use stock icons, + * use #hildon_note_new_information_with_icon_name instead. + * + * Returns: a #GtkWidget pointer of the note + */ +GtkWidget *hildon_note_new_information_with_icon_stock(GtkWindow * parent, + const gchar * + description, + const gchar * + stock_id) +{ + GtkWidget *dialog = NULL; + + g_return_val_if_fail(parent == NULL || GTK_IS_WINDOW(parent), NULL); + + dialog = g_object_new(HILDON_TYPE_NOTE, + "note_type", + HILDON_NOTE_INFORMATION_TYPE, + "description", description, + "icon", stock_id, NULL); + if (parent != NULL) + gtk_window_set_transient_for(GTK_WINDOW(dialog), parent); + + return dialog; +} + +/** + * hildon_note_new_information_with_icon_name: + * @parent: the parent window. The X window ID of the parent window + * has to be the same as the X window ID of the application. This is + * important so that the window manager could handle the windows + * correctly. In GTK the X window ID can be checked using + * GDK_WINDOW_XID(GTK_WIDGET(parent)->window). + * @description: the message to confirm + * @icon_name: icon to be displayed. If NULL, default icon is used. + * + * Create a new information note. Information note has text(description) + * that you specify, an OK button and an icon. + * + * Returns: a #GtkWidget pointer of the note + */ +GtkWidget *hildon_note_new_information_with_icon_name(GtkWindow * parent, + const gchar * + description, + const gchar * + icon_name) +{ + GtkWidget *dialog = NULL; + + g_return_val_if_fail(parent == NULL || GTK_IS_WINDOW(parent), NULL); + + dialog = g_object_new(HILDON_TYPE_NOTE, + "note_type", + HILDON_NOTE_INFORMATION_THEME_TYPE, + "description", description, + "icon", icon_name, NULL); + if (parent != NULL) + gtk_window_set_transient_for(GTK_WINDOW(dialog), parent); + + return dialog; +} + +/** + * hildon_note_new_information_with_icon_theme: + * @parent: the parent window. The X window ID of the parent window + * has to be the same as the X window ID of the application. This is + * important so that the window manager could handle the windows + * correctly. In GTK the X window ID can be checked using + * GDK_WINDOW_XID(GTK_WIDGET(parent)->window). + * @description: the message to confirm + * @icon: #GtkIconTheme icon to be displayed + * + * This function is deprecated. Use + * #hildon_note_new_information_with_icon_name instead. + * + * Create a new information note. Information note has text(description) + * that you specify, an OK button and an icon. + * + * Returns: a #GtkWidget pointer of the note. + */ +GtkWidget *hildon_note_new_information_with_icon_theme(GtkWindow *parent, + const gchar *description, + const gchar *icon) +{ + return hildon_note_new_information_with_icon_name(parent, description, icon); +} + +/** + * hildon_note_new_cancel_with_progress_bar: + * @parent: the parent window. The X window ID of the parent window + * has to be the same as the X window ID of the application. This is + * important so that the window manager could handle the windows + * correctly. In GTK the X window ID can be checked using + * GDK_WINDOW_XID(GTK_WIDGET(parent)->window). + * @description: the action to cancel + * @progressbar: a pointer to #GtkProgressBar to be filled with the + * progressbar assigned to this note. Use this to set the fraction of + * progressbar done. This parameter can be %NULL as well, in which + * case plain text cancel note appears. + * + * Create a new cancel note with a progress bar. Cancel note has + * text(description) that you specify, a Cancel button and a progress bar. + * + * Returns: a #GtkDialog. Use this to get rid of this note when you + * no longer need it. + */ +GtkWidget *hildon_note_new_cancel_with_progress_bar(GtkWindow * parent, + const gchar * + description, + GtkProgressBar * + progressbar) +{ + GtkWidget *dialog = NULL; + + g_return_val_if_fail(parent == NULL || GTK_IS_WINDOW(parent), NULL); + + dialog = g_object_new(HILDON_TYPE_NOTE, + "note_type", + HILDON_NOTE_PROGRESSBAR_TYPE, + "description", description, + "progressbar", + progressbar, NULL); + if (parent != NULL) + gtk_window_set_transient_for(GTK_WINDOW(dialog), parent); + + return dialog; +} + + +/** + * hildon_note_set_button_text: + * @note: a #HildonNote + * @text: sets the button text and if there is two buttons in dialog, + * the button texts will be <text>, "Cancel". + * + * Sets the button text to be used by the hildon_note widget. + */ +void hildon_note_set_button_text(HildonNote * note, const gchar * text) +{ + HildonNotePrivate *priv; + + g_return_if_fail(HILDON_IS_NOTE(note)); + + priv = HILDON_NOTE_GET_PRIVATE(HILDON_NOTE(note)); + if (priv->okButton) { + gtk_button_set_label(GTK_BUTTON(priv->okButton), text); + gtk_button_set_label(GTK_BUTTON(priv->cancelButton), + _("ecdg_bd_confirmation_note_cancel")); + } else { + gtk_button_set_label(GTK_BUTTON(priv->cancelButton), text); + } +} + +/** + * hildon_note_set_button_texts: + * @note: a #HildonNote + * @textOk: the new text of the default OK button + * @textCancel: the new text of the default cancel button + * + * Sets the button texts to be used by this hildon_note widget. + */ +void hildon_note_set_button_texts(HildonNote * note, + const gchar * textOk, + const gchar * textCancel) +{ + HildonNotePrivate *priv; + + g_return_if_fail(HILDON_IS_NOTE(note)); + + priv = HILDON_NOTE_GET_PRIVATE(HILDON_NOTE(note)); + if (priv->okButton) { + gtk_button_set_label(GTK_BUTTON(priv->okButton), textOk); + gtk_button_set_label(GTK_BUTTON(priv->cancelButton), + textCancel); + } else { + gtk_button_set_label(GTK_BUTTON(priv->cancelButton), textCancel); + } +} + +/* We play a system sound when the note comes visible */ +static gboolean +sound_handling(GtkWidget * widget, GdkEventExpose *event, gpointer data) +{ + HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE(widget); + g_signal_handler_disconnect(widget, priv->sound_signal_handler); + priv->sound_signal_handler = 0; + + switch (priv->note_n) + { + case HILDON_NOTE_INFORMATION_TYPE: + case HILDON_NOTE_INFORMATION_THEME_TYPE: + hildon_play_system_sound(INFORMATION_SOUND_PATH); + break; + case HILDON_NOTE_CONFIRMATION_TYPE: + case HILDON_NOTE_CONFIRMATION_BUTTON_TYPE: + hildon_play_system_sound(CONFIRMATION_SOUND_PATH); + break; + default: + break; + }; + + return FALSE; +} diff --git a/src/hildon-note.h b/src/hildon-note.h new file mode 100644 index 0000000..359eb23 --- /dev/null +++ b/src/hildon-note.h @@ -0,0 +1,118 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ +#ifndef __HILDON_NOTE_H__ +#define __HILDON_NOTE_H__ + +#include +#include + +G_BEGIN_DECLS +#define HILDON_TYPE_NOTE ( hildon_note_get_type() ) +#define HILDON_NOTE(obj) \ + (GTK_CHECK_CAST (obj, HILDON_TYPE_NOTE, HildonNote)) +#define HILDON_NOTE_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST ((klass), HILDON_TYPE_NOTE, HildonNoteClass)) +#define HILDON_IS_NOTE(obj) (GTK_CHECK_TYPE (obj, HILDON_TYPE_NOTE)) +#define HILDON_IS_NOTE_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_NOTE)) + +typedef struct _HildonNote HildonNote; +typedef struct _HildonNoteClass HildonNoteClass; + +typedef enum /*< skip >*/ +{ + HILDON_NOTE_CONFIRMATION_TYPE = 0, + HILDON_NOTE_CONFIRMATION_BUTTON_TYPE, + HILDON_NOTE_INFORMATION_TYPE, + HILDON_NOTE_INFORMATION_THEME_TYPE, + HILDON_NOTE_PROGRESSBAR_TYPE +} HildonNoteType; + +struct _HildonNote { + GtkDialog parent; +}; + +struct _HildonNoteClass { + GtkDialogClass parent_class; +}; + +GtkWidget *hildon_note_new_confirmation(GtkWindow * parent, + const gchar * description); + +GtkWidget *hildon_note_new_confirmation_add_buttons(GtkWindow * parent, + const gchar * + description, ...); +#ifndef HILDON_DISABLE_DEPRECATED +GtkWidget *hildon_note_new_confirmation_with_icon_stock(GtkWindow * parent, + const gchar * + description, + const gchar * + stock_id); +#endif /* HILDON_DISABLE_DEPRECATED */ + +GtkWidget *hildon_note_new_confirmation_with_icon_name(GtkWindow * parent, + const gchar * + description, + const gchar * + icon_name); + + +GtkWidget *hildon_note_new_cancel_with_progress_bar(GtkWindow * parent, + const gchar * + description, + GtkProgressBar * + progressbar); + +GtkWidget *hildon_note_new_information(GtkWindow * parent, + const gchar * description); + +GtkWidget *hildon_note_new_information_with_icon_name(GtkWindow * parent, + const gchar * + description, + const gchar * + icon_name); +#ifndef HILDON_DISABLE_DEPRECATED +GtkWidget *hildon_note_new_information_with_icon_stock(GtkWindow * parent, + const gchar * + description, + const gchar * + stock_id); + +GtkWidget *hildon_note_new_information_with_icon_theme(GtkWindow * parent, + const gchar * + description, + const gchar * + icon); +#endif /* HILDON_DISABLE_DEPRECATED */ + +void hildon_note_set_button_text(HildonNote * note, const gchar * text); + +void hildon_note_set_button_texts(HildonNote * note, const gchar * textOk, + const gchar * textCancel); + +GType hildon_note_get_type(void) G_GNUC_CONST; +GType hildon_note_type_get_type(void) G_GNUC_CONST; + +G_END_DECLS +#endif /* __HILDON_NOTE_H__ */ diff --git a/src/hildon-number-editor.c b/src/hildon-number-editor.c new file mode 100644 index 0000000..bdca6db --- /dev/null +++ b/src/hildon-number-editor.c @@ -0,0 +1,964 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-number-editor + * @short_description: A widget used to enter a number within a pre-defined range + * + * HildonNumberEditor is used to enter a number from a specific range. + * There are two buttons to scroll the value in number field. + * Manual input is also possible. + */ + +#include +#include + +#include +#include +#include + +#include "hildon-number-editor.h" +#include "hildon-marshalers.h" +#include +#include "hildon-composite-widget.h" +#include +#include +#include "hildon-libs-enum-types.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#define _(String) dgettext(PACKAGE, String) + +/*Pixel spec defines*/ +#define NUMBER_EDITOR_HEIGHT 30 + +/* Size of plus and minus buttons */ +#define BUTTON_HEIGHT 30 +#define BUTTON_WIDTH 30 + +#define HILDON_NUMBER_EDITOR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_NUMBER_EDITOR, \ + HildonNumberEditorPrivate)); + +typedef struct _HildonNumberEditorPrivate HildonNumberEditorPrivate; + +static void +hildon_number_editor_class_init (HildonNumberEditorClass *editor_class); + +static void +hildon_number_editor_init (HildonNumberEditor *editor); + +static gboolean +hildon_number_editor_entry_focusout (GtkWidget *widget, GdkEventFocus *event, + gpointer data); + +static void +hildon_number_editor_entry_changed (GtkWidget *widget, gpointer data); + +static void +hildon_number_editor_size_request (GtkWidget *widget, + GtkRequisition *requisition); + +static void +set_widget_allocation (GtkWidget *widget, GtkAllocation *alloc, + const GtkAllocation *allocation); + +static void +hildon_number_editor_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); + +static gboolean +hildon_number_editor_entry_keypress (GtkWidget *widget, GdkEventKey *event, + gpointer data); + +static gboolean +hildon_number_editor_button_pressed (GtkWidget *widget, GdkEventButton *event, + gpointer data); + +static gboolean +hildon_number_editor_entry_button_released (GtkWidget *widget, + GdkEventButton *event, + gpointer data); +static gboolean +hildon_number_editor_button_released (GtkWidget *widget, + GdkEvent *event, + HildonNumberEditor *editor); +static gboolean +do_mouse_timeout (HildonNumberEditor *editor); + +static void +change_numbers (HildonNumberEditor *editor, gint update); + +static void +hildon_number_editor_forall (GtkContainer *container, gboolean include_internals, + GtkCallback callback, gpointer callback_data); + +static void +hildon_number_editor_destroy (GtkObject *self); + +static gboolean +hildon_number_editor_start_timer (HildonNumberEditor *editor); + +static void +hildon_number_editor_finalize (GObject *self); + +static gboolean +hildon_number_editor_range_error(HildonNumberEditor *editor, + HildonNumberEditorErrorType type); + +static gboolean +hildon_number_editor_select_all (HildonNumberEditorPrivate *priv); + +static void +hildon_number_editor_validate_value(HildonNumberEditor *editor, gboolean allow_intermediate); + +static void hildon_number_editor_set_property(GObject * object, + guint prop_id, + const GValue * value, + GParamSpec * pspec); + +static void hildon_number_editor_get_property(GObject * object, + guint prop_id, + GValue * value, GParamSpec * pspec); + +/* Signal indices */ +enum +{ + RANGE_ERROR, + LAST_SIGNAL +}; + +/* Property indices */ +enum { + PROP_0, + PROP_VALUE +}; + +static GtkContainerClass *parent_class; + +static guint HildonNumberEditor_signal[LAST_SIGNAL] = {0}; + +struct _HildonNumberEditorPrivate +{ + /* Child widgets */ + GtkWidget *num_entry; + GtkWidget *plus; + GtkWidget *minus; + + gint start; /* Minimum */ + gint end; /* Maximum */ + gint default_val; + gint button_type; /* Type of button pressed: 1 = plus, -1 = minus */ + + /* Timer IDs */ + guint button_event_id; /* Repeat change when button is held */ + guint select_all_idle_id; /* Selection repaint hack + see hildon_number_editor_select_all */ +}; + + +GType hildon_number_editor_get_type(void) +{ + static GType editor_type = 0; + + if (!editor_type) + { + static const GTypeInfo editor_info = + { + sizeof(HildonNumberEditorClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_number_editor_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonNumberEditor), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_number_editor_init, + }; + editor_type = g_type_register_static(GTK_TYPE_CONTAINER, + "HildonNumberEditor", + &editor_info, 0); + } + return editor_type; +} + +static void +hildon_number_editor_class_init(HildonNumberEditorClass * editor_class) +{ + GtkContainerClass *container_class = GTK_CONTAINER_CLASS(editor_class); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(editor_class); + GObjectClass *gobject_class = G_OBJECT_CLASS(editor_class); + + g_type_class_add_private(editor_class, + sizeof(HildonNumberEditorPrivate)); + + parent_class = g_type_class_peek_parent(editor_class); + + widget_class->size_request = hildon_number_editor_size_request; + widget_class->size_allocate = hildon_number_editor_size_allocate; + widget_class->focus = hildon_composite_widget_focus; + + editor_class->range_error = hildon_number_editor_range_error; + + /* Because we derived our widget from GtkContainer, we should override + forall method */ + container_class->forall = hildon_number_editor_forall; + GTK_OBJECT_CLASS(editor_class)->destroy = hildon_number_editor_destroy; + gobject_class->finalize = hildon_number_editor_finalize; + gobject_class->set_property = hildon_number_editor_set_property; + gobject_class->get_property = hildon_number_editor_get_property; + + g_object_class_install_property(gobject_class, PROP_VALUE, + g_param_spec_int("value", + "Value", + "The current value of number editor", + G_MININT, + G_MAXINT, + 0, G_PARAM_READWRITE)); + + HildonNumberEditor_signal[RANGE_ERROR] = + g_signal_new("range_error", HILDON_TYPE_NUMBER_EDITOR, + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET + (HildonNumberEditorClass, range_error), + g_signal_accumulator_true_handled, NULL, + _hildon_marshal_BOOLEAN__ENUM, + G_TYPE_BOOLEAN, 1, HILDON_TYPE_NUMBER_EDITOR_ERROR_TYPE); +} + +static void +hildon_number_editor_forall(GtkContainer *container, gboolean include_internals, + GtkCallback callback, gpointer callback_data) +{ + HildonNumberEditorPrivate *priv = + HILDON_NUMBER_EDITOR_GET_PRIVATE(container); + + g_assert(callback != NULL); + + if (!include_internals) + return; + + /* Enumerate child widgets */ + (*callback) (priv->minus, callback_data); + (*callback) (priv->num_entry, callback_data); + (*callback) (priv->plus, callback_data); +} + +static void +hildon_number_editor_destroy(GtkObject *self) +{ + HildonNumberEditorPrivate *priv; + + priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(self); + + /* Free child widgets */ + if (priv->minus) + { + gtk_widget_unparent(priv->minus); + priv->minus = NULL; + } + if (priv->num_entry) + { + gtk_widget_unparent(priv->num_entry); + priv->num_entry = NULL; + } + if (priv->plus) + { + gtk_widget_unparent(priv->plus); + priv->plus = NULL; + } + + if (GTK_OBJECT_CLASS(parent_class)->destroy) + GTK_OBJECT_CLASS(parent_class)->destroy(self); +} + +static void +hildon_number_editor_stop_repeat_timer(HildonNumberEditorPrivate *priv) +{ + if (priv->button_event_id) + { + g_source_remove(priv->button_event_id); + priv->button_event_id = 0; + } +} + +static void +hildon_number_editor_finalize (GObject *self) +{ + HildonNumberEditorPrivate *priv; + + priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(self); + + /* Free timers */ + hildon_number_editor_stop_repeat_timer(priv); + + if (priv->select_all_idle_id) + g_source_remove (priv->select_all_idle_id); + + /* Call parent class finalize, if have one */ + if (G_OBJECT_CLASS (parent_class)->finalize) + G_OBJECT_CLASS (parent_class)->finalize(self); +} + +static void +hildon_number_editor_init (HildonNumberEditor *editor) +{ + HildonNumberEditorPrivate *priv; + + priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); + GTK_WIDGET_SET_FLAGS(GTK_WIDGET(editor), GTK_NO_WINDOW); + + /* Create child widgets */ + priv->num_entry = gtk_entry_new(); + priv->minus = gtk_button_new(); + priv->plus = gtk_button_new(); + + gtk_widget_set_name( priv->minus, "ne-minus-button" ); + gtk_widget_set_name( priv->plus, "ne-plus-button" ); + gtk_widget_set_size_request( priv->minus, BUTTON_WIDTH, BUTTON_HEIGHT ); + gtk_widget_set_size_request( priv->plus, BUTTON_WIDTH, BUTTON_HEIGHT ); + gtk_entry_set_alignment (GTK_ENTRY(priv->num_entry), 1); + + GTK_WIDGET_UNSET_FLAGS( priv->minus, GTK_CAN_FOCUS ); + GTK_WIDGET_UNSET_FLAGS( priv->plus, GTK_CAN_FOCUS ); + + priv->button_event_id = 0; + priv->select_all_idle_id = 0; + + gtk_widget_set_parent(priv->minus, GTK_WIDGET(editor)); + gtk_widget_set_parent(priv->num_entry, GTK_WIDGET(editor)); + gtk_widget_set_parent(priv->plus, GTK_WIDGET(editor)); + + /* Connect child widget signals */ + g_signal_connect(GTK_OBJECT(priv->num_entry), "changed", + G_CALLBACK(hildon_number_editor_entry_changed), + editor); + + g_signal_connect(GTK_OBJECT(priv->num_entry), "focus-out-event", + G_CALLBACK(hildon_number_editor_entry_focusout), + editor); + + g_signal_connect(GTK_OBJECT(priv->num_entry), "key-press-event", + G_CALLBACK(hildon_number_editor_entry_keypress), + editor); + + g_signal_connect(GTK_OBJECT(priv->num_entry), "button-release-event", + G_CALLBACK(hildon_number_editor_entry_button_released), + NULL); + + g_signal_connect(GTK_OBJECT(priv->minus), "button-press-event", + G_CALLBACK(hildon_number_editor_button_pressed), + editor); + + g_signal_connect(GTK_OBJECT(priv->plus), "button-press-event", + G_CALLBACK(hildon_number_editor_button_pressed), + editor); + + g_signal_connect(GTK_OBJECT(priv->minus), "button-release-event", + G_CALLBACK(hildon_number_editor_button_released), + editor); + + g_signal_connect(GTK_OBJECT(priv->plus), "button-release-event", + G_CALLBACK(hildon_number_editor_button_released), + editor); + + g_signal_connect(GTK_OBJECT(priv->minus), "leave-notify-event", + G_CALLBACK(hildon_number_editor_button_released), + editor); + + g_signal_connect(GTK_OBJECT(priv->plus), "leave-notify-event", + G_CALLBACK(hildon_number_editor_button_released), + editor); + + g_object_set( G_OBJECT(priv->num_entry), + "input-mode", HILDON_INPUT_MODE_HINT_NUMERIC, NULL ); + + gtk_widget_show(priv->num_entry); + gtk_widget_show(priv->minus); + gtk_widget_show(priv->plus); + + hildon_number_editor_set_range(editor, G_MININT, G_MAXINT); +} + +static gboolean +hildon_number_editor_entry_button_released (GtkWidget *widget, + GdkEventButton *event, + gpointer data) +{ + gtk_editable_select_region(GTK_EDITABLE(widget), 0, -1); + return FALSE; +} + +static gboolean +hildon_number_editor_button_released (GtkWidget *widget, GdkEvent *event, + HildonNumberEditor *editor) +{ + HildonNumberEditorPrivate *priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); + hildon_number_editor_stop_repeat_timer(priv); + return FALSE; +} + +/* Format given number to editor field, no checks performed, all signals + are sent normally. */ +static void +hildon_number_editor_real_set_value (HildonNumberEditorPrivate *priv, gint value) +{ + gchar buffer[32]; + + /* Update text in entry to new value */ + g_snprintf(buffer, sizeof(buffer), "%d", value); + gtk_entry_set_text(GTK_ENTRY(priv->num_entry), buffer); +} + +static gboolean +hildon_number_editor_button_pressed (GtkWidget *widget, GdkEventButton *event, + gpointer data) +{ + /* FIXME: XXX Why aren't we using hildon_number_editor_start_timer here? XXX */ + /* Need to fetch current value from entry and increment or decrement + it */ + HildonNumberEditor *editor; + HildonNumberEditorPrivate *priv; + GtkSettings *settings; + guint timeout; + + g_assert(HILDON_IS_NUMBER_EDITOR(data)); + + editor = HILDON_NUMBER_EDITOR(data); + priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); + settings = gtk_settings_get_default(); + g_object_get(settings, "gtk-initial-timeout", &timeout, NULL); + + /* Save type of button pressed */ + if (GTK_BUTTON(widget) == GTK_BUTTON(priv->plus)) + priv->button_type = 1; + else + priv->button_type = -1; + + /* Start repetition timer */ + if (!priv->button_event_id) + { + do_mouse_timeout(editor); + priv->button_event_id = g_timeout_add (timeout, + (GSourceFunc) hildon_number_editor_start_timer, + editor); + } + + return FALSE; +} + +static gboolean +hildon_number_editor_start_timer (HildonNumberEditor *editor) +{ + HildonNumberEditorPrivate *priv; + GtkSettings *settings; + guint timeout; + + priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); + settings = gtk_settings_get_default(); + g_object_get(settings, "gtk-update-timeout", &timeout, NULL); + + priv->button_event_id = g_timeout_add(timeout, + (GSourceFunc) do_mouse_timeout, + editor); + return FALSE; +} + +static gboolean +do_mouse_timeout (HildonNumberEditor *editor) +{ + HildonNumberEditorPrivate *priv; + + GDK_THREADS_ENTER (); + + g_assert(HILDON_IS_NUMBER_EDITOR(editor)); + + /* Update value based on button held */ + priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); + change_numbers(editor, priv->button_type); + + GDK_THREADS_LEAVE (); + + return TRUE; +} + +/* Changes the current number value by the amount of update + and verifies the result. */ +static void +change_numbers (HildonNumberEditor *editor, gint update) +{ + HildonNumberEditorPrivate *priv; + gint current_value; + + g_assert(HILDON_IS_NUMBER_EDITOR(editor)); + + priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); + current_value = hildon_number_editor_get_value(editor); + + /* We need to rerun validation by hand, since validation + done in "changed" callback allows intermediate values */ + hildon_number_editor_real_set_value(priv, current_value + update); + hildon_number_editor_validate_value(editor, FALSE); + g_object_notify (G_OBJECT(editor), "value"); +} + +static void +add_select_all_idle (HildonNumberEditorPrivate *priv) +{ + if (!priv->select_all_idle_id) + { + priv->select_all_idle_id = + g_idle_add((GSourceFunc) hildon_number_editor_select_all, priv); + } +} + +static void +hildon_number_editor_validate_value(HildonNumberEditor *editor, gboolean allow_intermediate) +{ + HildonNumberEditorPrivate *priv; + gint error_code, fixup_value; + const gchar *text; + long value; + gchar *tail; + gboolean r; + + g_assert(HILDON_IS_NUMBER_EDITOR(editor)); + + priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); + text = gtk_entry_get_text(GTK_ENTRY(priv->num_entry)); + error_code = -1; + fixup_value = priv->default_val; + + if (text && text[0]) + { + /* Try to convert entry text to number */ + value = strtol(text, &tail, 10); + + /* Check if conversion succeeded */ + if (tail[0] == 0) + { + /* Check if value is in allowed range. This is tricky in those + cases when user is editing a value. + For example: Range = [100, 500] and user have just inputted "4". + This should not lead into error message. Otherwise value is + resetted back to "100" and next "4" press will reset it back + and so on. */ + if (allow_intermediate) + { + /* We now have the following error cases: + * If inputted value as above maximum and + maximum is either positive or then maximum + negative and value is positive. + * If inputted value is below minimum and minimum + is negative or minumum positive and value + negative or zero. + In all other cases situation can be fixed just by + adding new numbers to the string. + */ + if (value > priv->end && (priv->end >= 0 || (priv->end < 0 && value >= 0))) + { + error_code = MAXIMUM_VALUE_EXCEED; + fixup_value = priv->end; + } + else if (value < priv->start && (priv->start < 0 || (priv->start >= 0 && value <= 0))) + { + error_code = MINIMUM_VALUE_EXCEED; + fixup_value = priv->start; + } + } + else + { + if (value > priv->end) { + error_code = MAXIMUM_VALUE_EXCEED; + fixup_value = priv->end; + } + else if (value < priv->start) { + error_code = MINIMUM_VALUE_EXCEED; + fixup_value = priv->start; + } + } + } + /* The only valid case when conversion can fail is when we + have plain '-', intermediate forms are allowed AND + minimum bound is negative */ + else if (!allow_intermediate || strcmp(text, "-") != 0 || priv->start >= 0) + error_code = ERRONEOUS_VALUE; + } + else if (!allow_intermediate) + error_code = ERRONEOUS_VALUE; + + if (error_code != -1) + { + /* If entry is empty and intermediate forms are nor allowed, + emit error signal */ + /* Change to default value */ + hildon_number_editor_set_value(editor, fixup_value); + g_signal_emit(editor, HildonNumberEditor_signal[RANGE_ERROR], + 0, error_code, &r); + add_select_all_idle(priv); + } +} + +static void +hildon_number_editor_entry_changed(GtkWidget *widget, gpointer data) +{ + g_assert(HILDON_IS_NUMBER_EDITOR(data)); + hildon_number_editor_validate_value(HILDON_NUMBER_EDITOR(data), TRUE); + g_object_notify (G_OBJECT(data), "value"); +} + +static void +hildon_number_editor_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + HildonNumberEditor *editor; + HildonNumberEditorPrivate *priv; + GtkRequisition req; + + editor = HILDON_NUMBER_EDITOR(widget); + priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); + + /* Requested size is size of all child widgets plus border space */ + gtk_widget_size_request(priv->minus, &req); + requisition->width = req.width; + + gtk_widget_size_request(priv->num_entry, &req); + requisition->width += req.width; + + gtk_widget_size_request(priv->plus, &req); + requisition->width += req.width; + + requisition->width += HILDON_MARGIN_DEFAULT * 2; + + /* FIXME: XXX Height is fixed */ + requisition->height = NUMBER_EDITOR_HEIGHT; +} + +/* Update @alloc->width so widget fits, update @alloc->x to point to free space */ +static void +set_widget_allocation (GtkWidget *widget, GtkAllocation *alloc, + const GtkAllocation *allocation) +{ + GtkRequisition child_requisition; + + gtk_widget_get_child_requisition(widget, &child_requisition); + + /* Fit to widget width */ + if (allocation->width + allocation->x > + alloc->x + child_requisition.width) + alloc->width = child_requisition.width; + else + { + alloc->width = allocation->width - (alloc->x - allocation->x); + if (alloc->width < 0) + alloc->width = 0; + } + + gtk_widget_size_allocate(widget, alloc); + /* Update x position */ + alloc->x += alloc->width; +} + +static void +hildon_number_editor_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + HildonNumberEditor *editor; + HildonNumberEditorPrivate *priv; + GtkAllocation alloc; + + editor = HILDON_NUMBER_EDITOR(widget); + priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); + + widget->allocation = *allocation; + + /* Add upper border */ + alloc.y = widget->allocation.y + widget->style->ythickness; + + /* Fix height */ + if (widget->allocation.height > NUMBER_EDITOR_HEIGHT) + { + alloc.height = NUMBER_EDITOR_HEIGHT - widget->style->ythickness * 2; + alloc.y += (widget->allocation.height - NUMBER_EDITOR_HEIGHT) / 2; + } + else + alloc.height = widget->allocation.height - widget->style->ythickness * 2; + + if (alloc.height < 0) + alloc.height = 0; + + /* Add left border */ + alloc.x = allocation->x + widget->style->xthickness; + + /* Allocate positions for widgets (left-to-right) */ + set_widget_allocation(priv->minus, &alloc, &widget->allocation); + alloc.x += HILDON_MARGIN_DEFAULT; + + set_widget_allocation(priv->num_entry, &alloc, &widget->allocation); + alloc.x += HILDON_MARGIN_DEFAULT; + + set_widget_allocation(priv->plus, &alloc, &widget->allocation); +} + +static gboolean +hildon_number_editor_entry_focusout (GtkWidget *widget, GdkEventFocus *event, + gpointer data) +{ + g_assert(HILDON_IS_NUMBER_EDITOR(data)); + hildon_number_editor_validate_value(HILDON_NUMBER_EDITOR(data), FALSE); + return FALSE; +} + +static gboolean +hildon_number_editor_entry_keypress (GtkWidget *widget, GdkEventKey *event, + gpointer data) +{ + GtkEditable *editable; + gint cursor_pos; + + g_assert(HILDON_IS_NUMBER_EDITOR(data)); + + editable = GTK_EDITABLE(widget); + cursor_pos = gtk_editable_get_position(editable); + + switch (event->keyval) + { + case GDK_Left: + /* If the cursor is on the left, try to decrement */ + if (cursor_pos == 0) { + change_numbers(HILDON_NUMBER_EDITOR(data), -1); + return TRUE; + } + break; + + case GDK_Right: + /* If the cursor is on the right, try to increment */ + if (cursor_pos >= g_utf8_strlen(gtk_entry_get_text(GTK_ENTRY(widget)), -1)) + { + change_numbers(HILDON_NUMBER_EDITOR(data), 1); + gtk_editable_set_position(editable, cursor_pos); + return TRUE; + } + break; + + default: + break; + }; + + return FALSE; +} + +static gboolean +hildon_number_editor_range_error(HildonNumberEditor *editor, + HildonNumberEditorErrorType type) +{ + + gint min, max; + gchar *err_msg = NULL; + HildonNumberEditorPrivate *priv; + + priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); + min = priv->start; + max = priv->end; + + /* Construct error message */ + switch (type) + { + case MAXIMUM_VALUE_EXCEED: + err_msg = g_strdup_printf(_("ckct_ib_maximum_value"), max, max); + break; + case MINIMUM_VALUE_EXCEED: + err_msg = g_strdup_printf(_("ckct_ib_minimum_value"), min, min); + break; + case ERRONEOUS_VALUE: + err_msg = + g_strdup_printf(_("ckct_ib_set_a_value_within_range"), min, max); + break; + } + + /* Infoprint error */ + if (err_msg) + { + gtk_infoprint(GTK_WINDOW(gtk_widget_get_ancestor(GTK_WIDGET(editor), + GTK_TYPE_WINDOW)), err_msg); + g_free(err_msg); + } + + return TRUE; +} + + +/** + * hildon_number_editor_new: + * @min: minimum accepted value + * @max: maximum accepted value + * + * Creates new number editor + * + * Returns: a new #HildonNumberEditor widget + */ +GtkWidget * +hildon_number_editor_new (gint min, gint max) +{ + HildonNumberEditor *editor = + g_object_new(HILDON_TYPE_NUMBER_EDITOR, NULL); + + /* Set user inputted range to editor */ + hildon_number_editor_set_range(editor, min, max); + + return GTK_WIDGET(editor); +} + +/** + * hildon_number_editor_set_range: + * @editor: a #HildonNumberEditor widget + * @min: minimum accepted value + * @max: maximum accepted value + * + * Sets accepted number range for editor + */ +void +hildon_number_editor_set_range (HildonNumberEditor *editor, gint min, gint max) +{ + HildonNumberEditorPrivate *priv; + gchar buffer_min[32], buffer_max[32]; + gint a, b; + + g_return_if_fail(HILDON_IS_NUMBER_EDITOR(editor)); + + priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); + + /* Set preferences */ + priv->start = MIN(min, max); + priv->end = MAX(min, max); + + /* Find maximum allowed length of value */ + g_snprintf(buffer_min, sizeof(buffer_min), "%d", min); + g_snprintf(buffer_max, sizeof(buffer_max), "%d", max); + a = strlen(buffer_min); + b = strlen(buffer_max); + + /* Set maximum size of entry */ + gtk_entry_set_width_chars(GTK_ENTRY(priv->num_entry), MAX(a, b)); + hildon_number_editor_set_value(editor, priv->start); +} + +/** + * hildon_number_editor_get_value: + * @editor: pointer to #HildonNumberEditor + * + * Returns: current NumberEditor value + */ +gint +hildon_number_editor_get_value (HildonNumberEditor *editor) +{ + HildonNumberEditorPrivate *priv; + + g_return_val_if_fail(HILDON_IS_NUMBER_EDITOR(editor), 0); + + priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); + return atoi(gtk_entry_get_text(GTK_ENTRY(priv->num_entry))); +} + +/** + * hildon_number_editor_set_value: + * @editor: pointer to #HildonNumberEditor + * @value: numeric value for number editor + * + * Sets numeric value for number editor + */ +void +hildon_number_editor_set_value (HildonNumberEditor *editor, gint value) +{ + HildonNumberEditorPrivate *priv; + + g_return_if_fail(HILDON_IS_NUMBER_EDITOR(editor)); + + priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor); + + g_return_if_fail(value <= priv->end); + g_return_if_fail(value >= priv->start); + + priv->default_val = value; + hildon_number_editor_real_set_value(priv, value); + g_object_notify (G_OBJECT(editor), "value"); +} + +/* When calling gtk_entry_set_text, the entry widget does things that can + * cause the whole widget to redraw. This redrawing is delayed and if any + * selections are made right after calling the gtk_entry_set_text the + * setting of the selection might seem to have no effect. + * + * If the selection is delayed with a lower priority than the redrawing, + * the selection should stick. Calling this function with g_idle_add should + * do it. + */ +static gboolean +hildon_number_editor_select_all (HildonNumberEditorPrivate *priv) +{ + GDK_THREADS_ENTER (); + gtk_editable_select_region(GTK_EDITABLE(priv->num_entry), 0, -1); + priv->select_all_idle_id = 0; + GDK_THREADS_LEAVE (); + return FALSE; +} + +static void +hildon_number_editor_set_property(GObject * object, + guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + HildonNumberEditor *editor; + + editor = HILDON_NUMBER_EDITOR(object); + + switch (prop_id) { + case PROP_VALUE: + hildon_number_editor_set_value(editor, g_value_get_int(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +hildon_number_editor_get_property(GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + HildonNumberEditor *editor; + + editor = HILDON_NUMBER_EDITOR(object); + + switch (prop_id) { + case PROP_VALUE: + g_value_set_int(value, hildon_number_editor_get_value(editor)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} diff --git a/src/hildon-number-editor.h b/src/hildon-number-editor.h new file mode 100644 index 0000000..bb1d999 --- /dev/null +++ b/src/hildon-number-editor.h @@ -0,0 +1,81 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_NUMBER_EDITOR_H__ +#define __HILDON_NUMBER_EDITOR_H__ + +#include + +G_BEGIN_DECLS + + + +#define HILDON_TYPE_NUMBER_EDITOR ( hildon_number_editor_get_type() ) + +#define HILDON_NUMBER_EDITOR(obj) (GTK_CHECK_CAST (obj, HILDON_TYPE_NUMBER_EDITOR, HildonNumberEditor)) +#define HILDON_NUMBER_EDITOR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), HILDON_TYPE_NUMBER_EDITOR, HildonNumberEditorClass)) +#define HILDON_IS_NUMBER_EDITOR(obj) (GTK_CHECK_TYPE (obj, HILDON_TYPE_NUMBER_EDITOR)) +#define HILDON_IS_NUMBER_EDITOR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_NUMBER_EDITOR)) + +typedef struct _HildonNumberEditor HildonNumberEditor; +typedef struct _HildonNumberEditorClass HildonNumberEditorClass; + + +struct _HildonNumberEditor +{ + GtkContainer parent; +}; + + +typedef enum +{ + MAXIMUM_VALUE_EXCEED, + MINIMUM_VALUE_EXCEED, + ERRONEOUS_VALUE + +} HildonNumberEditorErrorType; + + +struct _HildonNumberEditorClass +{ + GtkContainerClass parent_class; + + gboolean (*range_error) (HildonNumberEditor *editor, HildonNumberEditorErrorType type); +}; + + +GType hildon_number_editor_get_type (void) G_GNUC_CONST; + +GtkWidget* hildon_number_editor_new (gint min, gint max); + +void hildon_number_editor_set_range (HildonNumberEditor *editor, + gint min, + gint max); + +gint hildon_number_editor_get_value (HildonNumberEditor *editor); +void hildon_number_editor_set_value (HildonNumberEditor *editor, gint value); + + +G_END_DECLS +#endif /* __HILDON_NUMBER_EDITOR_H__ */ diff --git a/src/hildon-plugin-widget.c b/src/hildon-plugin-widget.c new file mode 100644 index 0000000..de061b1 --- /dev/null +++ b/src/hildon-plugin-widget.c @@ -0,0 +1,260 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Author: Kuisma Salonen + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-plugin-widget + * @short_description: A simple interface to load plugin based widgets. Not + * compatible with GObject. + * + * #HildonPluginWidgetInfo is a struct containing information about loaded + * module which contains code for a widget. + */ + + +#include +#include +#include + +#include + + +#include "hildon-plugin-widget.h" + + +#ifndef PLUGIN_DIR +#define PLUGIN_DIR "/usr/lib/hildon-widgets" +#endif + + +struct HildonPluginWidgetInfo_ { + GType base_type; + + gchar *filename; + + GModule *module; + int refcount; + + GType (*get_type) (); +}; + + +static gchar *hildon_plugin_filename(GType base_type, const gchar *name); + + /* WARNING: works properly only with ASCII */ +static gchar *ascii_decapitalize_without_dashes(gchar *source); + +static gchar *hildon_plugin_default_name(gchar *typename); + +/** + * hildon_plugin_info_initialize: + * @base_type: a #GType representing parent type of object that will be + * loaded. + * @name: Name of child. To load default (or #GtkSettings defined), NULL + * should be passed as name. To load specific child type, decapitalized name + * should be passed here. + * + * Creates a new #HildonPluginWidgetInfo structure and opens a module. + * + * The naming of child widgets (or objects) doesn't matter, but for plugins + * the file names should be type + * -.so where the + * decapitalized type name would be for example for #GtkWidget gtk-widget. + * + * The name comes from name argument or from #GtkSettings where the variable + * storing it is with name -plugin, for #GtkWidget this would + * be "GtkWidget-plugin". If nothing is defined in #GtkSettings, name + * "default" is assumed. For this case there should be symlink to some child + * type plugin named -default.so + * + * Returns: a #HildonPluginWidgetInfo struct pointer upon success, NULL if + * failed. + */ +HildonPluginWidgetInfo *hildon_plugin_info_initialize(GType base_type, const gchar *name) +{ + HildonPluginWidgetInfo *ret; + GModule *module; + gchar *filename; + + + if(!base_type) { + return NULL; + } + + + filename = hildon_plugin_filename(base_type, name); + g_return_val_if_fail (filename != NULL, NULL); + + + module = g_module_open(filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); + if(!module) { + g_warning ("Failed to load plugin for '%s' (filename: '%s')", name, filename); + g_free(filename); + return NULL; + } + + + ret = (HildonPluginWidgetInfo *)g_malloc0(sizeof(HildonPluginWidgetInfo) + strlen(filename) + 1); + ret->filename = (gchar *)ret + sizeof(HildonPluginWidgetInfo); + + ret->base_type = base_type; + + ret->module = module; + + g_module_symbol(module, "export_type", (void **)&ret->get_type); + + memcpy(ret->filename, filename, strlen(filename)); + + + g_free(filename); + + + return ret; +} + +/** + * hildon_plugin_info_construct_widget: + * @info: pointer to a #HildonPluginWidgetInfo struct. + * + * Creates instance of loaded type from module stored in + * #HildonPluginWidgetInfo struct. Designed for loading types inherited from + * GtkWidget, but could be basically any GTK+ type. + * + * Returns: a GtkWidget pointer to instance of loaded type. + */ +GtkWidget *hildon_plugin_info_construct_widget(HildonPluginWidgetInfo *info) +{ + g_return_val_if_fail (info != NULL, NULL); + info->refcount++; + + + return GTK_WIDGET(g_type_create_instance(info->get_type())); +} + +/** + * hildon_plugin_info_kill: + * @info: a pointer to a #HildonPluginWidgetInfo struct that should be + * destroyed. + * + * Frees the plugin information structure and unloads the module. + */ +void hildon_plugin_info_kill(HildonPluginWidgetInfo *info) +{ + if(!info) { + return; + } + + + g_module_close(info->module); + + + g_free(info); +} + + +static gchar *hildon_plugin_filename(GType base_type, const gchar *name) +{ + gchar *ret, *name2, *plgbuf; + gchar *typename = (gchar *)g_type_name(base_type); + int retsize; + + + plgbuf = ascii_decapitalize_without_dashes(typename); + + + if(name) { + name2 = g_strdup(name); + } else { + name2 = hildon_plugin_default_name(typename); + } + + + retsize = strlen(PLUGIN_DIR) + strlen(plgbuf) + strlen(name2) + 6; + ret = (gchar *)g_malloc0(retsize); + g_snprintf(ret, retsize, "%s/%s_%s.so", PLUGIN_DIR, plgbuf, name2); + + + g_free(name2); + g_free(plgbuf); + + + return ret; +} + + /* possible speedup: pre-allocate more memory and ditch the first loop */ +static gchar *ascii_decapitalize_without_dashes(gchar *source) +{ + gchar *ptr, *ret = g_strdup (source); + + + for(ptr = ret; *ptr; ptr++) { + if(*ptr >= 'A' && *ptr <= 'Z') { + *ptr += 0x20; + } + } + + + return ret; +} + + +static gchar *hildon_plugin_default_name(gchar *typename) +{ + GtkSettings *settings; + gchar *ret, *val, *tmp; + int tmplen; + + + tmplen = strlen(typename) + strlen("-plugin") + 1; + tmp = (gchar *)g_malloc0(tmplen); + g_snprintf(tmp, tmplen, "%s-plugin", typename); + + + gtk_settings_install_property(g_param_spec_string(tmp, + tmp, + "Plugin for this pecific widget", + NULL, + G_PARAM_READWRITE)); + + settings = gtk_settings_get_default(); + + g_object_get(G_OBJECT(settings), tmp, &val, NULL); + + g_free(tmp); + + + if(val) { + ret = (gchar *)g_malloc0(strlen(val)+1); + memcpy(ret, val, strlen(val)); + g_free(val); + } else { + ret = (gchar *)g_malloc0(strlen("default")+1); + + + g_snprintf(ret, strlen("default")+1, "default"); + } + + + return ret; +} diff --git a/src/hildon-plugin-widget.h b/src/hildon-plugin-widget.h new file mode 100644 index 0000000..a537bf5 --- /dev/null +++ b/src/hildon-plugin-widget.h @@ -0,0 +1,56 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Author: Kuisma Salonen + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + + +#ifndef __HILDON_PLUGIN_WIDGET_H__ +#define __HILDON_PLUGIN_WIDGET_H__ + + +#include + +#include + + +/** + * HildonPluginWidgetInfo: + * + * Contains information about the loaded module which has some widget + * inherited from some non-plugin widget. The struct should be considered + * private and should not be used directly. + */ +typedef struct HildonPluginWidgetInfo_ HildonPluginWidgetInfo; + + +HildonPluginWidgetInfo *hildon_plugin_info_initialize(GType base_type, const gchar *name); + + +GtkWidget *hildon_plugin_info_construct_widget(HildonPluginWidgetInfo *info); + + +void hildon_plugin_info_kill(HildonPluginWidgetInfo *info); + + + +#endif /* __HILDON_PLUGIN_WIDGET_H__ */ diff --git a/src/hildon-private.h b/src/hildon-private.h new file mode 100644 index 0000000..772080b --- /dev/null +++ b/src/hildon-private.h @@ -0,0 +1,38 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + + +#ifndef __HILDON_PRIVATE_H__ +#define __HILDON_PRIVATE_H__ + +#include + +G_BEGIN_DECLS + +void +_hildon_time_editor_get_time_separators(GtkLabel *hm_sep_label, + GtkLabel *ms_sep_label); + +G_END_DECLS +#endif /* __HILDON_PRIVATE_H__ */ diff --git a/src/hildon-program.c b/src/hildon-program.c new file mode 100644 index 0000000..0aae6fc --- /dev/null +++ b/src/hildon-program.c @@ -0,0 +1,630 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/* + * @file hildon-program.c + * + * This file implements the HildonProgram object + * + */ + +#include "hildon-program.h" +#include "hildon-window-private.h" + +/*FIXME*/ +#include + + +#define HILDON_PROGRAM_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_PROGRAM, HildonProgramPriv)); + + +typedef struct _HildonProgramPriv HildonProgramPriv; + +struct _HildonProgramPriv +{ + gboolean killable; + gboolean is_topmost; + GdkWindow *group_leader; + guint window_count; + GtkWidget *common_menu; + GtkWidget *common_toolbar; + GSList *windows; + Window window_group; + gchar *name; +}; + +static void +hildon_program_init (HildonProgram *self); + +static void +hildon_program_finalize (GObject *self); + +static void +hildon_program_class_init (HildonProgramClass *self); + +static void +hildon_program_get_property(GObject * object, guint property_id, + GValue * value, GParamSpec * pspec); +static void +hildon_program_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec); + +enum +{ + PROP_0, + PROP_IS_TOPMOST, + PROP_KILLABLE +}; + + +GType +hildon_program_get_type (void) +{ + static GType program_type = 0; + + if (!program_type) + { + static const GTypeInfo program_info = + { + sizeof(HildonProgramClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_program_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonProgram), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_program_init, + }; + program_type = g_type_register_static(G_TYPE_OBJECT, + "HildonProgram", &program_info, 0); + } + return program_type; +} + +static void +hildon_program_init (HildonProgram *self) +{ + HildonProgramPriv *priv = HILDON_PROGRAM_GET_PRIVATE (self); + + priv->killable = FALSE; + priv->window_count = 0; + priv->is_topmost = FALSE; + priv->window_group = GDK_WINDOW_XID (gdk_display_get_default_group + (gdk_display_get_default())); + priv->common_toolbar = NULL; + priv->name = NULL; +} + +static void +hildon_program_finalize (GObject *self) +{ + HildonProgramPriv *priv = HILDON_PROGRAM_GET_PRIVATE (HILDON_PROGRAM (self)); + + if (priv->common_toolbar) + { + g_object_unref (priv->common_toolbar); + priv->common_toolbar = NULL; + } + + if (priv->common_menu) + { + g_object_unref (priv->common_menu); + priv->common_menu = NULL; + } + + g_free (priv->name); + +} + +static void +hildon_program_class_init (HildonProgramClass *self) +{ + GObjectClass *object_class = G_OBJECT_CLASS(self); + + g_type_class_add_private (self, sizeof(HildonProgramPriv)); + + /* Set up object virtual functions */ + object_class->finalize = hildon_program_finalize; + object_class->set_property = hildon_program_set_property; + object_class->get_property = hildon_program_get_property; + + /* Install properties */ + g_object_class_install_property (object_class, PROP_IS_TOPMOST, + g_param_spec_boolean ("is-topmost", + "Is top-most", + "Whether one of the program's window or dialog currently " + "is activated by window manager", + FALSE, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, PROP_KILLABLE, + g_param_spec_boolean ("can-hibernate", + "Can hibernate", + "Whether the program should be set to hibernate by the Task " + "Navigator in low memory situation", + FALSE, + G_PARAM_READWRITE)); + return; +} + + +static void +hildon_program_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + switch (property_id){ + case PROP_KILLABLE: + hildon_program_set_can_hibernate (HILDON_PROGRAM (object), + g_value_get_boolean (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } + +} + +static void +hildon_program_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + HildonProgramPriv *priv = HILDON_PROGRAM_GET_PRIVATE (object); + + switch (property_id) + { + case PROP_KILLABLE: + g_value_set_boolean (value, priv->killable); + break; + case PROP_IS_TOPMOST: + g_value_set_boolean (value, priv->is_topmost); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } + +} + +/* Utilities */ +static gint +hildon_program_window_list_compare (gconstpointer window_a, + gconstpointer window_b) +{ + g_return_val_if_fail (1, HILDON_IS_WINDOW(window_a) && + HILDON_IS_WINDOW(window_b)); + + return window_a != window_b; +} + +/* + * foreach function, checks if a window is topmost and acts consequently + */ +static void +hildon_program_window_list_is_is_topmost (gpointer data, gpointer window_id_) +{ + if (data && HILDON_IS_WINDOW (data)) + { + HildonWindow *window = HILDON_WINDOW (data); + Window window_id = * (Window*)window_id_; + + hildon_window_update_topmost (window, window_id); + } +} + +/* + * Check the _MB_CURRENT_APP_WINDOW on the root window, and update + * the top_most status accordingly + */ +static void +hildon_program_update_top_most (HildonProgram *program) +{ + XWMHints *wm_hints; + Window active_window; + HildonProgramPriv *priv; + + priv = HILDON_PROGRAM_GET_PRIVATE (program); + + active_window = hildon_window_get_active_window(); + + if (active_window) + { + wm_hints = XGetWMHints (GDK_DISPLAY (), active_window); + + if (wm_hints) + { + + if (wm_hints->window_group == priv->window_group) + { + if (!priv->is_topmost) + { + priv->is_topmost = TRUE; + g_object_notify (G_OBJECT (program), "is-topmost"); + } + } + else if (priv->is_topmost) + { + priv->is_topmost = FALSE; + g_object_notify (G_OBJECT (program), "is-topmost"); + } + } + XFree (wm_hints); + } + + /* Check each window if it was is_topmost */ + g_slist_foreach (priv->windows, + (GFunc)hildon_program_window_list_is_is_topmost, &active_window); +} + + +/* Event filter */ + +/* + * We keep track of the _MB_CURRENT_APP_WINDOW property on the root window, + * to detect when a window belonging to this program was is_topmost. This + * is based on the window group WM hint. + */ +static GdkFilterReturn +hildon_program_root_window_event_filter (GdkXEvent *xevent, + GdkEvent *event, + gpointer data) +{ + XAnyEvent *eventti = xevent; + HildonProgram *program = HILDON_PROGRAM (data); + Atom active_app_atom = + XInternAtom (GDK_DISPLAY (), "_MB_CURRENT_APP_WINDOW", False); + + if (eventti->type == PropertyNotify) + { + XPropertyEvent *pevent = xevent; + + if (pevent->atom == active_app_atom) + { + hildon_program_update_top_most (program); + } + } + + return GDK_FILTER_CONTINUE; +} + + +/** + * hildon_program_common_toolbar_topmost_window: + * @window: A @HildonWindow to be informed about its new common toolbar + * @data: Not used, it is here just to respect the API + * + * Checks if the window is the topmost window of the program and in + * that case forces the window to take the common toolbar. + **/ +static void +hildon_program_common_toolbar_topmost_window (gpointer window, gpointer data) +{ + if (HILDON_IS_WINDOW (window) && + hildon_window_get_is_topmost (HILDON_WINDOW (window))) + { + hildon_window_take_common_toolbar (HILDON_WINDOW (window)); + } +} + +/* Public methods */ + +/** + * hildon_program_get_instance: + * + * Return value: Returns the #HildonProgram for the current process. + * The object is created on the first call. + **/ +HildonProgram * +hildon_program_get_instance () +{ + static HildonProgram *program = NULL; + + if (!program) + { + program = g_object_new (HILDON_TYPE_PROGRAM, NULL); + } + + return program; +} + +/** + * hildon_program_add_window: + * @program: The @HildonProgram to which the window should be registered + * @window: A @HildonWindow to be added + * + * Registers a @HildonWindow as belonging to a given @HildonProgram. This + * allows to apply program-wide settings as all the registered windows, + * such as hildon_program_set_common_menu() and + * hildon_pogram_set_common_toolbar() + **/ +void +hildon_program_add_window (HildonProgram *self, HildonWindow *window) +{ + HildonProgramPriv *priv; + + g_return_if_fail (self && HILDON_IS_PROGRAM (self)); + + priv = HILDON_PROGRAM_GET_PRIVATE (self); + + if (g_slist_find_custom (priv->windows, window, + hildon_program_window_list_compare) ) + { + /* We already have that window */ + return; + } + + if (!priv->window_count) + { + hildon_program_update_top_most (self); + + /* Now that we have a window we should start keeping track of + * the root window */ + gdk_window_set_events (gdk_get_default_root_window (), + gdk_window_get_events (gdk_get_default_root_window ()) | GDK_PROPERTY_CHANGE_MASK); + gdk_window_add_filter (gdk_get_default_root_window (), + hildon_program_root_window_event_filter, self ); + } + + hildon_window_set_can_hibernate_property (window, &priv->killable); + + hildon_window_set_program (window, G_OBJECT (self)); + + priv->windows = g_slist_append (priv->windows, window); + priv->window_count ++; +} + +/** + * hildon_program_remove_window: + * @self: The #HildonProgram to which the window should be unregistered + * @window: The @HildonWindow to unregister + * + * Used to unregister a window from the program. Subsequent calls to + * hildon_program_set_common_menu() and hildon_pogram_set_common_toolbar() + * will not affect the window + **/ +void +hildon_program_remove_window (HildonProgram *self, HildonWindow *window) +{ + HildonProgramPriv *priv; + + g_return_if_fail (self && HILDON_IS_PROGRAM (self)); + + priv = HILDON_PROGRAM_GET_PRIVATE (self); + + hildon_window_unset_program (window); + + priv->windows = g_slist_remove (priv->windows, window); + + priv->window_count --; + + if (!priv->window_count) + { + gdk_window_remove_filter (gdk_get_default_root_window(), + hildon_program_root_window_event_filter, + self); + } +} + +/** + * hildon_program_set_can_hibernate: + * @self: The #HildonProgram which can hibernate or not + * @can_hibernate: whether or not the #HildonProgram can hibernate + * + * Used to set whether or not the Hildon task navigator should + * be able to set the program to hibernation in case of low memory + **/ +void +hildon_program_set_can_hibernate (HildonProgram *self, gboolean killable) +{ + HildonProgramPriv *priv; + + g_return_if_fail (self && HILDON_IS_PROGRAM (self)); + + priv = HILDON_PROGRAM_GET_PRIVATE (self); + + if (priv->killable != killable) + { + g_slist_foreach (priv->windows, + (GFunc)hildon_window_set_can_hibernate_property, &killable); + } + + priv->killable = killable; + +} + +/** + * hildon_program_get_can_hibernate: + * @self: The #HildonProgram which can hibernate or not + * + * Return value: Whether or not this #HildonProgram is set to be + * support hibernation from the Hildon task navigator + **/ +gboolean +hildon_program_get_can_hibernate (HildonProgram *self) +{ + HildonProgramPriv *priv; + + g_return_val_if_fail (self && HILDON_IS_PROGRAM (self), FALSE); + + priv = HILDON_PROGRAM_GET_PRIVATE (self); + + return priv->killable; + +} + +/** + * hildon_program_set_common_menu: + * @self: The #HildonProgram in which the common menu should be used + * @menu: A GtkMenu to use as common menu for the program + * + * Sets a GtkMenu that will appear in all the @HildonWindow registered + * to the #HildonProgram. Only one common GtkMenu can be set, further + * call will detach the previous common GtkMenu. A @HildonWindow + * can use it's own GtkMenu with @hildon_window_set_menu + **/ +void +hildon_program_set_common_menu (HildonProgram *self, GtkMenu *menu) +{ + HildonProgramPriv *priv; + + g_return_if_fail (self && HILDON_IS_PROGRAM (self)); + + priv = HILDON_PROGRAM_GET_PRIVATE (self); + + if (priv->common_menu) + { + if (GTK_WIDGET_VISIBLE (priv->common_menu)) + { + gtk_menu_popdown (GTK_MENU(priv->common_menu)); + gtk_menu_shell_deactivate (GTK_MENU_SHELL (priv->common_menu)); + } + + if (gtk_menu_get_attach_widget (GTK_MENU (priv->common_menu))) + { + gtk_menu_detach (GTK_MENU (priv->common_menu)); + } + else + { + g_object_unref (priv->common_menu); + } + } + + priv->common_menu = GTK_WIDGET (menu); + + if (priv->common_menu) + { + g_object_ref (menu); + gtk_object_sink (GTK_OBJECT (menu)); + gtk_widget_show_all (GTK_WIDGET (menu)); + } +} + +/** + * hildon_program_get_common_menu: + * @self: The #HildonProgram from which to retrieve the common menu + * + * Return value: the GtkMenu that was set as common menu for this + * #HildonProgram, or NULL of no common menu was set. + **/ +GtkMenu * +hildon_program_get_common_menu (HildonProgram *self) +{ + HildonProgramPriv *priv; + + g_return_val_if_fail (self && HILDON_IS_PROGRAM (self), NULL); + + priv = HILDON_PROGRAM_GET_PRIVATE (self); + + return GTK_MENU (priv->common_menu); +} + +/** + * hildon_program_set_common_toolbar: + * @self: The #HildonProgram in which the common toolbar should be used + * @toolbar: A GtkToolbar to use as common toolbar for the program + * + * Sets a GtkToolbar that will appear in all the @HildonWindow registered + * to the #HildonProgram. Only one common GtkToolbar can be set, further + * call will detach the previous common GtkToolbar. A @HildonWindow + * can use its own GtkToolbar with @hildon_window_set_toolbar. Both + * #HildonProgram and @HildonWindow specific toolbars will be shown + **/ +void +hildon_program_set_common_toolbar (HildonProgram *self, GtkToolbar *toolbar) +{ + HildonProgramPriv *priv; + + g_return_if_fail (self && HILDON_IS_PROGRAM (self)); + + priv = HILDON_PROGRAM_GET_PRIVATE (self); + + if (priv->common_toolbar) + { + if (priv->common_toolbar->parent) + { + gtk_container_remove (GTK_CONTAINER (priv->common_toolbar->parent), + priv->common_toolbar); + } + + g_object_unref (priv->common_toolbar); + } + + priv->common_toolbar = GTK_WIDGET (toolbar); + + if (priv->common_toolbar) + { + g_object_ref (priv->common_toolbar); + gtk_object_sink (GTK_OBJECT (priv->common_toolbar) ); + } + + /* if the program is the topmost we have to update the common + toolbar right now for the topmost window */ + if (priv->is_topmost) + { + g_slist_foreach (priv->windows, + (GFunc) hildon_program_common_toolbar_topmost_window, NULL); + } +} + +/** + * hildon_program_get_common_toolbar: + * @self: The #HildonProgram from which to retrieve the common toolbar + * + * Return value: the GtkToolbar that was set as common toolbar for this + * #HildonProgram, or NULL of no common menu was set. + **/ +GtkToolbar * +hildon_program_get_common_toolbar (HildonProgram *self) +{ + HildonProgramPriv *priv; + + g_return_val_if_fail (self && HILDON_IS_PROGRAM (self), NULL); + + priv = HILDON_PROGRAM_GET_PRIVATE (self); + + return priv->common_toolbar ? GTK_TOOLBAR (priv->common_toolbar) : NULL; +} + +/** + * hildon_program_get_is_topmost: + * @self: A #HildonWindow + * + * Return value: Whether or not one of the program's window or dialog is + * currenltly activated by the window manager. + **/ +gboolean +hildon_program_get_is_topmost (HildonProgram *self) +{ + HildonProgramPriv *priv; + + g_return_val_if_fail (self && HILDON_IS_PROGRAM (self), FALSE); + + priv = HILDON_PROGRAM_GET_PRIVATE (self); + + return priv->is_topmost; +} + + diff --git a/src/hildon-program.h b/src/hildon-program.h new file mode 100644 index 0000000..1b021f2 --- /dev/null +++ b/src/hildon-program.h @@ -0,0 +1,100 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_PROGRAM_H__ +#define __HILDON_PROGRAM_H__ + +#include +#include"hildon-window.h" + +G_BEGIN_DECLS +typedef struct _HildonProgram HildonProgram; +typedef struct _HildonProgramClass HildonProgramClass; + +#define HILDON_TYPE_PROGRAM (hildon_program_get_type()) +#define HILDON_PROGRAM(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, \ + HILDON_TYPE_PROGRAM, \ + HildonProgram)) +#define HILDON_IS_PROGRAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, \ + HILDON_TYPE_PROGRAM)) + +/* deprecated */ +#define hildon_program_new hildon_program_get_instance + + + +struct _HildonProgram +{ + GObject parent; +}; + +struct _HildonProgramClass +{ + GObjectClass parent; + + /* Padding for future extension */ + void (*_hildon_reserved1)(void); + void (*_hildon_reserved2)(void); + void (*_hildon_reserved3)(void); + void (*_hildon_reserved4)(void); + +}; + +GType +hildon_program_get_type (void); + +/* Public methods */ + +HildonProgram * +hildon_program_get_instance (void); + +void +hildon_program_add_window (HildonProgram *self, HildonWindow *window); + +void +hildon_program_remove_window (HildonProgram *self, HildonWindow *window); + +void +hildon_program_set_can_hibernate (HildonProgram *self, gboolean killable); + +gboolean +hildon_program_get_can_hibernate (HildonProgram *self); + +void +hildon_program_set_common_menu (HildonProgram *self, GtkMenu *menu); + +GtkMenu * +hildon_program_get_common_menu (HildonProgram *self); + +void +hildon_program_set_common_toolbar (HildonProgram *self, GtkToolbar *toolbar); + +GtkToolbar * +hildon_program_get_common_toolbar (HildonProgram *self); + +gboolean +hildon_program_get_is_topmost (HildonProgram *self); + +G_END_DECLS +#endif /* __HILDON_PROGRAM_H__ */ diff --git a/src/hildon-range-editor.c b/src/hildon-range-editor.c new file mode 100644 index 0000000..253ee5e --- /dev/null +++ b/src/hildon-range-editor.c @@ -0,0 +1,1023 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-range-editor + * @short_description: A widget is used to ask bounds of a range + * + * HidlonRangeEditor allows entering a pair of integers, e.g. the lower + * and higher bounds of a range. A minimum and maximum can also be set + * for the bounds. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hildon-range-editor.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#define _(string) dgettext(PACKAGE, string) + +/* Alignment in entry box ( 0 = left, 1 = right ) */ +#define DEFAULT_ALIGNMENT 1 +/* Amount of padding to add to each side of the separator */ +#define DEFAULT_PADDING 3 + +#define DEFAULT_START -999 +#define DEFAULT_END 999 +#define DEFAULT_LENGTH 4 + +#define HILDON_RANGE_EDITOR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_RANGE_EDITOR, HildonRangeEditorPrivate)); + +typedef struct _HildonRangeEditorPrivate HildonRangeEditorPrivate; + +/* Property indices */ +enum +{ + PROP_LOWER = 1, + PROP_HIGHER, + PROP_MIN, + PROP_MAX, + PROP_SEPARATOR +}; + +static GtkContainerClass *parent_class = NULL; + +/*Init functions*/ +static void +hildon_range_editor_class_init (HildonRangeEditorClass *editor_class); +static void +hildon_range_editor_init (HildonRangeEditor *editor); +static void +hildon_range_editor_forall (GtkContainer *container, + gboolean include_internals, GtkCallback callback, + gpointer callback_data); +static void +hildon_range_editor_destroy (GtkObject *self); + +/*size and font functions */ +static void +hildon_range_editor_size_request (GtkWidget *widget, + GtkRequisition *requisition); +static void +hildon_range_editor_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); +static gboolean +hildon_range_editor_entry_focus_in (GtkEditable *editable, + GdkEventFocus *event, + HildonRangeEditor *editor); +static gboolean +hildon_range_editor_entry_focus_out (GtkEditable *editable, + GdkEventFocus *event, + HildonRangeEditor *editor); +static gboolean +hildon_range_editor_entry_keypress (GtkWidget *widget, GdkEventKey *event, + HildonRangeEditor *editor); +static gboolean +hildon_range_editor_released (GtkEditable *editable, GdkEventButton *event, + HildonRangeEditor *editor); +static gboolean +hildon_range_editor_press (GtkEditable *editable, GdkEventButton *event, + HildonRangeEditor *editor); + +static void hildon_range_editor_set_property( GObject *object, guint param_id, + const GValue *value, GParamSpec *pspec ); +static void hildon_range_editor_get_property( GObject *object, guint param_id, + GValue *value, GParamSpec *pspec ); +static void hildon_range_editor_entry_changed(GtkWidget *widget, + HildonRangeEditor *editor); + +/* Private struct */ +struct _HildonRangeEditorPrivate +{ + GtkWidget *start_entry; /* Entry for lower value */ + GtkWidget *end_entry; /* Entry for higher value */ + + GtkWidget *label; + + gint range_limits_start; /* Minimum value allowed for range start/end */ + gint range_limits_end; /* Maximum value allowed for range start/end */ + + gboolean bp; /* Button pressed, don't overwrite selection */ +}; + +/* Private functions */ +static void +hildon_range_editor_class_init (HildonRangeEditorClass *editor_class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(editor_class); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(editor_class); + GtkContainerClass *container_class = GTK_CONTAINER_CLASS(editor_class); + + parent_class = g_type_class_peek_parent(editor_class); + + g_type_class_add_private(editor_class, + sizeof(HildonRangeEditorPrivate)); + + gobject_class->set_property = hildon_range_editor_set_property; + gobject_class->get_property = hildon_range_editor_get_property; + widget_class->size_request = hildon_range_editor_size_request; + widget_class->size_allocate = hildon_range_editor_size_allocate; + + container_class->forall = hildon_range_editor_forall; + GTK_OBJECT_CLASS(editor_class)->destroy = hildon_range_editor_destroy; + + gtk_widget_class_install_style_property(widget_class, + g_param_spec_int("hildon_range_editor_entry_alignment", + "Hildon RangeEditor entry alignment", + "Hildon RangeEditor entry alignment", 0, 1, + DEFAULT_ALIGNMENT, + G_PARAM_READABLE)); + + gtk_widget_class_install_style_property(widget_class, + g_param_spec_int("hildon_range_editor_separator_padding", + "Hildon RangeEditor separator padding", + "Hildon RangeEditor separaror padding", + G_MININT, G_MAXINT, + DEFAULT_PADDING, + G_PARAM_READABLE)); + + /** + * HildonRangeEditor:min: + * + * Minimum value in a range. + * Default: -999 + */ + g_object_class_install_property( gobject_class, PROP_MIN, + g_param_spec_int("min", + "Minimum value", + "Minimum value in a range", + G_MININT, G_MAXINT, + DEFAULT_START, G_PARAM_CONSTRUCT | + G_PARAM_READABLE | G_PARAM_WRITABLE) ); + + /** + * HildonRangeEditor:max: + * + * Maximum value in a range. + * Default: 999 + */ + g_object_class_install_property( gobject_class, PROP_MAX, + g_param_spec_int("max", + "Maximum value", + "Maximum value in a range", + G_MININT, G_MAXINT, + DEFAULT_END, G_PARAM_CONSTRUCT | + G_PARAM_READABLE | G_PARAM_WRITABLE) ); + + /** + * HildonRangeEditor:lower: + * + * Current value in the entry presenting lower end of selected range. + * Default: -999 + */ + g_object_class_install_property( gobject_class, PROP_LOWER, + g_param_spec_int("lower", + "Current lower value", + "Current value in the entry presenting lower end of selected range", + G_MININT, G_MAXINT, + DEFAULT_START, G_PARAM_CONSTRUCT | + G_PARAM_READABLE | G_PARAM_WRITABLE) ); + + /** + * HildonRangeEditor:higher: + * + * Current value in the entry presenting higher end of selected range. + * Default: 999 + */ + g_object_class_install_property( gobject_class, PROP_HIGHER, + g_param_spec_int("higher", + "Current higher value", + "Current value in the entry presenting higher end of selected range", + G_MININT, G_MAXINT, + DEFAULT_END, G_PARAM_CONSTRUCT | + G_PARAM_READABLE | G_PARAM_WRITABLE) ); + + /** + * HildonRangeEditor:separator: + * + * Separator string to separate range editor entries. + * Default: "-" + */ + g_object_class_install_property( gobject_class, PROP_SEPARATOR, + g_param_spec_string("separator", + "Separator", + "Separator string to separate entries", + _("ckct_wi_range_separator"), + G_PARAM_CONSTRUCT | + G_PARAM_READABLE | G_PARAM_WRITABLE) ); +} + +static void +hildon_range_editor_init (HildonRangeEditor *editor) +{ + HildonRangeEditorPrivate *priv; + + gint range_editor_entry_alignment; + gint range_editor_separator_padding; + + priv = HILDON_RANGE_EDITOR_GET_PRIVATE(editor); + + GTK_WIDGET_SET_FLAGS(editor, GTK_NO_WINDOW); + + gtk_widget_push_composite_child(); + + priv->start_entry = gtk_entry_new(); + priv->end_entry = gtk_entry_new(); + priv->label = gtk_label_new(_("ckct_wi_range_separator")); + priv->bp = FALSE; + + /* Get values from gtkrc (or use defaults) */ + /* FIXME: This is broken, styles are not yet attached */ + gtk_widget_style_get(GTK_WIDGET(editor), + "hildon_range_editor_entry_alignment", + &range_editor_entry_alignment, + "hildon_range_editor_separator_padding", + &range_editor_separator_padding, NULL); + + /* Add padding to separator */ + gtk_misc_set_padding (GTK_MISC(priv->label), + range_editor_separator_padding, 0); + + /* Align the text to right in entry box */ + gtk_entry_set_alignment(GTK_ENTRY(priv->start_entry), + range_editor_entry_alignment); + gtk_entry_set_alignment(GTK_ENTRY(priv->end_entry), + range_editor_entry_alignment); + + gtk_widget_set_composite_name(priv->start_entry, "start_entry"); + gtk_widget_set_composite_name(priv->end_entry, "end_entry"); + gtk_widget_set_composite_name(priv->label, "separator_label"); + gtk_widget_set_parent(priv->start_entry, GTK_WIDGET(editor)); + gtk_widget_set_parent(priv->end_entry, GTK_WIDGET(editor)); + gtk_widget_set_parent(priv->label, GTK_WIDGET(editor)); + + g_signal_connect(G_OBJECT(priv->start_entry), "button-release-event", + G_CALLBACK(hildon_range_editor_released), editor); + g_signal_connect(G_OBJECT(priv->end_entry), "button-release-event", + G_CALLBACK(hildon_range_editor_released), editor); + + g_signal_connect(G_OBJECT(priv->start_entry), "button-press-event", + G_CALLBACK(hildon_range_editor_press), editor); + g_signal_connect(G_OBJECT(priv->end_entry), "button-press-event", + G_CALLBACK(hildon_range_editor_press), editor); + + g_signal_connect(G_OBJECT(priv->start_entry), "key-press-event", + G_CALLBACK(hildon_range_editor_entry_keypress), editor); + g_signal_connect(G_OBJECT(priv->end_entry), "key-press-event", + G_CALLBACK(hildon_range_editor_entry_keypress), editor); + + g_signal_connect(G_OBJECT(priv->start_entry), "focus-in-event", + G_CALLBACK(hildon_range_editor_entry_focus_in), editor); + g_signal_connect(G_OBJECT(priv->end_entry), "focus-in-event", + G_CALLBACK(hildon_range_editor_entry_focus_in), editor); + + g_signal_connect(G_OBJECT(priv->start_entry), "focus-out-event", + G_CALLBACK(hildon_range_editor_entry_focus_out), editor); + g_signal_connect(G_OBJECT(priv->end_entry), "focus-out-event", + G_CALLBACK(hildon_range_editor_entry_focus_out), editor); + g_signal_connect(priv->start_entry, "changed", + G_CALLBACK(hildon_range_editor_entry_changed), editor); + g_signal_connect(priv->end_entry, "changed", + G_CALLBACK(hildon_range_editor_entry_changed), editor); + + g_object_set( G_OBJECT(priv->start_entry), + "input-mode", HILDON_INPUT_MODE_HINT_NUMERIC, NULL ); + g_object_set( G_OBJECT(priv->end_entry), + "input-mode", HILDON_INPUT_MODE_HINT_NUMERIC, NULL ); + + gtk_widget_show(priv->start_entry); + gtk_widget_show(priv->end_entry); + gtk_widget_show(priv->label); + + gtk_widget_pop_composite_child(); +} + +static void hildon_range_editor_set_property (GObject *object, guint param_id, + const GValue *value, GParamSpec *pspec) +{ + HildonRangeEditor *editor = HILDON_RANGE_EDITOR(object); + switch (param_id) + { + case PROP_LOWER: + hildon_range_editor_set_lower (editor, g_value_get_int (value)); + break; + + case PROP_HIGHER: + hildon_range_editor_set_higher (editor, g_value_get_int (value)); + break; + + case PROP_MIN: + hildon_range_editor_set_min (editor, g_value_get_int (value)); + break; + + case PROP_MAX: + hildon_range_editor_set_max (editor, g_value_get_int (value)); + break; + + case PROP_SEPARATOR: + hildon_range_editor_set_separator (editor, + g_value_get_string (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); + break; + } +} + +static void hildon_range_editor_get_property( GObject *object, guint param_id, + GValue *value, GParamSpec *pspec ) +{ + HildonRangeEditor *editor = HILDON_RANGE_EDITOR(object); + switch (param_id) + { + case PROP_LOWER: + g_value_set_int (value, hildon_range_editor_get_lower (editor)); + break; + + case PROP_HIGHER: + g_value_set_int (value, hildon_range_editor_get_higher (editor)); + break; + + case PROP_MIN: + g_value_set_int (value, hildon_range_editor_get_min (editor)); + break; + + case PROP_MAX: + g_value_set_int (value, hildon_range_editor_get_max (editor)); + break; + + case PROP_SEPARATOR: + g_value_set_string (value, hildon_range_editor_get_separator (editor)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); + break; + } +} + +static void +hildon_range_editor_entry_validate(HildonRangeEditor *editor, + GtkWidget *edited_entry, gboolean allow_intermediate) +{ + HildonRangeEditorPrivate *priv; + const gchar *text; + long value; + gint min, max, fixup; + gchar *tail; + gchar buffer[256]; + gboolean error = FALSE; + + g_assert(HILDON_IS_RANGE_EDITOR(editor)); + g_assert(GTK_IS_ENTRY(edited_entry)); + + priv = HILDON_RANGE_EDITOR_GET_PRIVATE(editor); + + /* Find the valid range for the modified component */ + if (edited_entry == priv->start_entry) { + min = hildon_range_editor_get_min(editor); + max = hildon_range_editor_get_higher(editor); + } else { + min = hildon_range_editor_get_lower(editor); + max = hildon_range_editor_get_max(editor); + } + + text = gtk_entry_get_text(edited_entry); + + if (text && text[0]) + { + /* Try to convert entry text to number */ + value = strtol(text, &tail, 10); + + /* Check if conversion succeeded */ + if (tail[0] == 0) + { + /* Check if value is in allowed range. This is tricky in those + cases when user is editing a value. + For example: Range = [100, 500] and user have just inputted "4". + This should not lead into error message. Otherwise value is + resetted back to "100" and next "4" press will reset it back + and so on. */ + if (allow_intermediate) + { + /* We now have the following error cases: + * If inputted value as above maximum and + maximum is either positive or then maximum + negative and value is positive. + * If inputted value is below minimum and minimum + is negative or minumum positive and value + negative. + In all other cases situation can be fixed just by + adding new numbers to the string. + */ + if (value > max && (max >= 0 || (max < 0 && value >= 0))) + { + error = TRUE; + fixup = max; + g_snprintf(buffer, sizeof(buffer), _("ckct_ib_maximum_value"), max); + } + else if (value < min && (min < 0 || (min >= 0 && value < 0))) + { + error = TRUE; + fixup = min; + g_snprintf(buffer, sizeof(buffer), _("ckct_ib_minimum_value"), min); + } + } + else + { + if (value > max) { + error = TRUE; + fixup = max; + g_snprintf(buffer, sizeof(buffer), _("ckct_ib_maximum_value"), max); + } + else if (value < min) { + error = TRUE; + fixup = min; + g_snprintf(buffer, sizeof(buffer), _("ckct_ib_minimum_value"), min); + } + } + + if (error) { + if (edited_entry == priv->start_entry) + hildon_range_editor_set_lower(editor, fixup); + else + hildon_range_editor_set_higher(editor, fixup); + } + } + /* The only valid case when conversion can fail is when we + have plain '-', intermediate forms are allowed AND + minimum bound is negative */ + else if (!allow_intermediate || strcmp(text, "-") != 0 || min >= 0) { + error = TRUE; + g_snprintf(buffer, sizeof(buffer), _("ckct_ib_set_a_value_within_range"), min, max); + } + } + else if (!allow_intermediate) { + error = TRUE; + g_snprintf(buffer, sizeof(buffer), _("ckct_ib_set_a_value_within_range"), min, max); + } + + if (error) + { + hildon_banner_show_information(edited_entry, NULL, buffer); + gtk_widget_grab_focus(edited_entry); + } +} + +static gboolean +hildon_range_editor_entry_focus_in (GtkEditable *editable, + GdkEventFocus *event, + HildonRangeEditor *editor) +{ + HildonRangeEditorPrivate *priv = HILDON_RANGE_EDITOR_GET_PRIVATE(editor); + if(priv->bp) + { + priv->bp = FALSE; + return FALSE; + } + if (GTK_WIDGET(editable) == priv->start_entry) + gtk_editable_select_region(editable, -1, 0); + else + gtk_editable_select_region(editable, 0, -1); + return FALSE; +} + +/* Gets and sets the current range. This has two usefull side effects: + * Values are now sorted to the correct order + * Out of range values are clamped to range */ +static void hildon_range_editor_apply_current_range(HildonRangeEditor *editor) +{ + g_assert(HILDON_IS_RANGE_EDITOR(editor)); + + hildon_range_editor_set_range(editor, + hildon_range_editor_get_lower(editor), + hildon_range_editor_get_higher(editor)); +} + +static void hildon_range_editor_entry_changed(GtkWidget *widget, HildonRangeEditor *editor) +{ + g_assert(HILDON_IS_RANGE_EDITOR(editor)); + hildon_range_editor_entry_validate(editor, widget, TRUE); +} + +static gboolean +hildon_range_editor_entry_focus_out (GtkEditable *editable, + GdkEventFocus *event, + HildonRangeEditor *editor) +{ + g_assert(HILDON_IS_RANGE_EDITOR(editor)); + hildon_range_editor_entry_validate(editor, GTK_WIDGET(editable), FALSE); + return FALSE; +} + +static gboolean +hildon_range_editor_press (GtkEditable *editable, GdkEventButton *event, + HildonRangeEditor *editor) +{ + HildonRangeEditorPrivate *priv = HILDON_RANGE_EDITOR_GET_PRIVATE(editor); + priv->bp = TRUE; + return FALSE; +} + +static void +hildon_range_editor_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, gpointer callback_data) +{ + HildonRangeEditorPrivate *priv; + + g_assert(HILDON_IS_RANGE_EDITOR(container)); + g_assert(callback != NULL); + + priv = HILDON_RANGE_EDITOR_GET_PRIVATE(container); + + if (!include_internals) + return; + + (*callback) (priv->start_entry, callback_data); + (*callback) (priv->end_entry, callback_data); + (*callback) (priv->label, callback_data); +} + +static void +hildon_range_editor_destroy(GtkObject *self) +{ + HildonRangeEditorPrivate *priv = HILDON_RANGE_EDITOR_GET_PRIVATE(self); + + if (priv->start_entry) + { + gtk_widget_unparent(priv->start_entry); + priv->start_entry = NULL; + } + if (priv->end_entry) + { + gtk_widget_unparent(priv->end_entry); + priv->end_entry = NULL; + } + if (priv->label) + { + gtk_widget_unparent(priv->label); + priv->label = NULL; + } + + if (GTK_OBJECT_CLASS(parent_class)->destroy) + GTK_OBJECT_CLASS(parent_class)->destroy(self); +} + + +static void +hildon_range_editor_size_request(GtkWidget *widget, + GtkRequisition *requisition) +{ + HildonRangeEditorPrivate *priv = NULL; + GtkRequisition lab_req, mreq; + + priv = HILDON_RANGE_EDITOR_GET_PRIVATE(widget); + + gtk_entry_get_width_chars(GTK_ENTRY(priv->end_entry)); + + gtk_widget_size_request(priv->start_entry, &mreq); + gtk_widget_size_request(priv->end_entry, &mreq); + gtk_widget_size_request(priv->label, &lab_req); + + /* Width for entries and separator label and border */ + requisition->width = mreq.width * 2 + lab_req.width + + widget->style->xthickness * 2; + /* Add vertical border */ + requisition->height = mreq.height + widget->style->ythickness * 2; + /* Fit label height */ + requisition->height = MAX (requisition->height, lab_req.height); +} + +static void +hildon_range_editor_size_allocate(GtkWidget *widget, + GtkAllocation *allocation) +{ + HildonRangeEditorPrivate *priv; + GtkAllocation child1_allocation, child2_allocation, child3_allocation; + + priv = HILDON_RANGE_EDITOR_GET_PRIVATE(widget); + + widget->allocation = *allocation; + + /* Allocate entries, left-to-right */ + if (priv->start_entry && GTK_WIDGET_VISIBLE(priv->start_entry)) + { + GtkRequisition child_requisition; + + gtk_widget_get_child_requisition(priv->start_entry, + &child_requisition); + + child1_allocation.x = allocation->x; + child1_allocation.y = allocation->y; + + child1_allocation.width = child_requisition.width; + child1_allocation.height = allocation->height; + + gtk_widget_size_allocate(priv->start_entry, &child1_allocation); + } + + if (priv->label && GTK_WIDGET_VISIBLE(priv->label)) + { + GtkRequisition child_requisition; + + gtk_widget_get_child_requisition(priv->label, &child_requisition); + + child2_allocation.x = child1_allocation.x + child1_allocation.width; + child2_allocation.y = allocation->y; + /* Add spacing */ + child2_allocation.width = child_requisition.width + 4; + child2_allocation.height = allocation->height; + + gtk_widget_size_allocate (priv->label, &child2_allocation); + } + + if (priv->end_entry && GTK_WIDGET_VISIBLE(priv->end_entry)) + { + GtkRequisition child_requisition; + + gtk_widget_get_child_requisition (priv->end_entry, &child_requisition); + + child3_allocation.x = child2_allocation.x + child2_allocation.width; + child3_allocation.y = allocation->y; + + child3_allocation.width = child_requisition.width; + child3_allocation.height = allocation->height; + + gtk_widget_size_allocate(priv->end_entry, &child3_allocation); + } +} + +/* Button released inside entries */ +static gboolean +hildon_range_editor_released(GtkEditable *editable, GdkEventButton *event, + HildonRangeEditor *editor) +{ + HildonRangeEditorPrivate *priv = HILDON_RANGE_EDITOR_GET_PRIVATE(editor); + if (GTK_WIDGET(editable) == priv->start_entry) + gtk_editable_select_region(editable, -1, 0); + else + gtk_editable_select_region(editable, 0, -1); + return FALSE; +} + +static gboolean +hildon_range_editor_entry_keypress(GtkWidget *widget, GdkEventKey *event, + HildonRangeEditor *editor) +{ + const gchar *text; + gint cursor_pos; + + g_assert(HILDON_IS_RANGE_EDITOR(editor)); + + text = gtk_entry_get_text(GTK_ENTRY(widget)); + cursor_pos = gtk_editable_get_position(GTK_EDITABLE(widget)); + + switch (event->keyval) + { + case GDK_Left: + /* If we are on the first character and press left, + try to move to previous field */ + if (cursor_pos == 0) { + (void) gtk_widget_child_focus(GTK_WIDGET(editor), GTK_DIR_LEFT); + return TRUE; + } + break; + + case GDK_Right: + /* If the cursor is on the right, try to move to the next field */ + if (cursor_pos >= g_utf8_strlen(text, -1)) { + (void) gtk_widget_child_focus(GTK_WIDGET(editor), GTK_DIR_RIGHT); + return TRUE; + } + break; + + default: + break; + }; + + return FALSE; +} + +static void hildon_range_editor_refresh_widths(HildonRangeEditorPrivate *priv) +{ + gchar start_range[32], end_range[32]; + gint length; + + /* Calculate length of entry so extremes would fit */ + g_snprintf(start_range, sizeof(start_range), "%d", priv->range_limits_start); + g_snprintf(end_range, sizeof(end_range), "%d", priv->range_limits_end); + length = MAX(g_utf8_strlen(start_range, -1), g_utf8_strlen(end_range, -1)); + + gtk_entry_set_width_chars(GTK_ENTRY(priv->start_entry), length); + gtk_entry_set_max_length(GTK_ENTRY(priv->start_entry), length); + gtk_entry_set_width_chars(GTK_ENTRY (priv->end_entry), length); + gtk_entry_set_max_length(GTK_ENTRY (priv->end_entry), length); +} + +/* Public functions */ + +/** + * hildon_range_editor_get_type: + * + * Initializes, and returns the type of a hildon range editor. + * + * @Returns : GType of #HildonRangeEditor + * + */ +GType +hildon_range_editor_get_type (void) +{ + static GType editor_type = 0; + + if (!editor_type) + { + static const GTypeInfo editor_info = + { + sizeof(HildonRangeEditorClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_range_editor_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonRangeEditor), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_range_editor_init, + }; + editor_type = g_type_register_static(GTK_TYPE_CONTAINER, + "HildonRangeEditor", + &editor_info, 0); + } + return editor_type; +} + +/** + * hildon_range_editor_new: + * + * HildonRangeEditor contains two GtkEntrys that accept numbers and minus. + * + * Returns: pointer to a new @HildonRangeEditor widget + */ +GtkWidget * +hildon_range_editor_new (void) +{ + return GTK_WIDGET(g_object_new(HILDON_TYPE_RANGE_EDITOR, NULL)); +} + + +/** + * hildon_range_editor_new_with_separator: + * @separator: a string that is shown between the numbers + * + * HildonRangeEditor contains two Gtk entries that accept numbers. + * A separator is displayed between two entries. + * CHECKME: Use '-' as a separator in the case of null separator? + * + * Returns: pointer to a new @HildonRangeEditor widget + */ +GtkWidget * +hildon_range_editor_new_with_separator (const gchar *separator) +{ + return GTK_WIDGET (g_object_new (HILDON_TYPE_RANGE_EDITOR, + "separator", separator, NULL)); +} + + +/** + * hildon_range_editor_set_range: + * @editor: the #HildonRangeEditor widget + * @start: range's start value + * @end: range's end value + * + * Sets a range to the editor. (The current value) + * + * Sets the range of the @HildonRangeEditor widget. + */ +void +hildon_range_editor_set_range (HildonRangeEditor *editor, gint start, gint end) +{ + g_return_if_fail (HILDON_IS_RANGE_EDITOR (editor)); + + /* Make sure that the start/end appear in the correct order */ + hildon_range_editor_set_lower (editor, MIN(start, end)); + hildon_range_editor_set_higher (editor, MAX(start, end)); +} + + +/** + * hildon_range_editor_get_range: + * @editor: the #HildonRangeEditor widget + * @start: ranges start value + * @end: ranges end value + * + * Gets the range of the @HildonRangeEditor widget. + */ +void +hildon_range_editor_get_range (HildonRangeEditor *editor, gint *start, + gint *end) +{ + HildonRangeEditorPrivate *priv; + + g_return_if_fail (HILDON_IS_RANGE_EDITOR (editor) && start && end); + priv = HILDON_RANGE_EDITOR_GET_PRIVATE (editor); + + *start = hildon_range_editor_get_lower (editor); + *end = hildon_range_editor_get_higher (editor); +} + + +/** + * hildon_range_editor_set_limits: + * @editor: the #HildonRangeEditor widget + * @start: minimum acceptable value (default: no limit) + * @end: maximum acceptable value (default: no limit) + * + * Sets the range of the @HildonRangeEditor widget. + */ +void +hildon_range_editor_set_limits (HildonRangeEditor *editor, gint start, + gint end) +{ + /* FIXME: Setting start/end as separate steps can modify + the inputted range unneedlesly */ + hildon_range_editor_set_min (editor, start); + hildon_range_editor_set_max (editor, end); +} + +void +hildon_range_editor_set_lower (HildonRangeEditor *editor, gint value) +{ + HildonRangeEditorPrivate *priv; + gchar buffer[32]; + + g_return_if_fail (HILDON_IS_RANGE_EDITOR (editor)); + priv = HILDON_RANGE_EDITOR_GET_PRIVATE (editor); + + g_snprintf(buffer, sizeof(buffer), "%d", CLAMP(value, + priv->range_limits_start, priv->range_limits_end)); + + /* Update entry text with new value */ + gtk_entry_set_text (GTK_ENTRY (priv->start_entry), buffer); + g_object_notify (G_OBJECT (editor), "lower"); +} + +void +hildon_range_editor_set_higher (HildonRangeEditor *editor, gint value) +{ + HildonRangeEditorPrivate *priv; + gchar buffer[32]; + + g_return_if_fail (HILDON_IS_RANGE_EDITOR (editor)); + priv = HILDON_RANGE_EDITOR_GET_PRIVATE (editor); + + g_snprintf(buffer, sizeof(buffer), "%d", CLAMP(value, + priv->range_limits_start, priv->range_limits_end)); + + /* Update entry text with new value */ + gtk_entry_set_text (GTK_ENTRY (priv->end_entry), buffer); + g_object_notify (G_OBJECT (editor), "higher"); +} + +gint +hildon_range_editor_get_lower (HildonRangeEditor *editor) +{ + HildonRangeEditorPrivate *priv; + g_return_val_if_fail (HILDON_IS_RANGE_EDITOR (editor), 0); + priv = HILDON_RANGE_EDITOR_GET_PRIVATE (editor); + return atoi(gtk_entry_get_text(GTK_ENTRY(priv->start_entry))); +} + +gint +hildon_range_editor_get_higher (HildonRangeEditor *editor) +{ + HildonRangeEditorPrivate *priv; + g_return_val_if_fail (HILDON_IS_RANGE_EDITOR (editor), 0); + priv = HILDON_RANGE_EDITOR_GET_PRIVATE (editor); + return atoi(gtk_entry_get_text(GTK_ENTRY (priv->end_entry))); +} + +void +hildon_range_editor_set_min (HildonRangeEditor *editor, gint value) +{ + HildonRangeEditorPrivate *priv; + + g_return_if_fail (HILDON_IS_RANGE_EDITOR (editor)); + + /* We can cause many properties to change */ + g_object_freeze_notify(G_OBJECT(editor)); + priv = HILDON_RANGE_EDITOR_GET_PRIVATE (editor); + priv->range_limits_start = value; + + if (priv->range_limits_end < value) + hildon_range_editor_set_max (editor, value); + /* Setting maximum applies widths and range in this case */ + else { + hildon_range_editor_refresh_widths(priv); + hildon_range_editor_apply_current_range(editor); + } + + g_object_notify (G_OBJECT (editor), "min"); + g_object_thaw_notify(G_OBJECT(editor)); +} + +void +hildon_range_editor_set_max (HildonRangeEditor *editor, gint value) +{ + HildonRangeEditorPrivate *priv; + + g_return_if_fail (HILDON_IS_RANGE_EDITOR (editor)); + + /* We can cause many properties to change */ + g_object_freeze_notify(G_OBJECT(editor)); + priv = HILDON_RANGE_EDITOR_GET_PRIVATE (editor); + priv->range_limits_end = value; + + if (priv->range_limits_start > value) + hildon_range_editor_set_min (editor, value); + /* Setting minimum applies widths and range in this case */ + else { + hildon_range_editor_refresh_widths(priv); + hildon_range_editor_apply_current_range(editor); + } + + g_object_notify (G_OBJECT (editor), "max"); + g_object_thaw_notify(G_OBJECT(editor)); +} + +gint +hildon_range_editor_get_min (HildonRangeEditor *editor) +{ + HildonRangeEditorPrivate *priv; + g_return_val_if_fail (HILDON_IS_RANGE_EDITOR (editor), 0); + priv = HILDON_RANGE_EDITOR_GET_PRIVATE (editor); + + return priv->range_limits_start; +} + +gint +hildon_range_editor_get_max (HildonRangeEditor *editor) +{ + HildonRangeEditorPrivate *priv; + g_return_val_if_fail (HILDON_IS_RANGE_EDITOR (editor), 0); + priv = HILDON_RANGE_EDITOR_GET_PRIVATE (editor); + + return priv->range_limits_end; +} + +void +hildon_range_editor_set_separator (HildonRangeEditor *editor, + const gchar *separator) +{ + HildonRangeEditorPrivate *priv; + g_return_if_fail (HILDON_IS_RANGE_EDITOR (editor)); + priv = HILDON_RANGE_EDITOR_GET_PRIVATE (editor); + + gtk_label_set_text (GTK_LABEL (priv->label), separator); + g_object_notify (G_OBJECT(editor), "separator"); +} + +const gchar * +hildon_range_editor_get_separator (HildonRangeEditor *editor) +{ + HildonRangeEditorPrivate *priv; + g_return_val_if_fail (HILDON_IS_RANGE_EDITOR (editor), NULL); + priv = HILDON_RANGE_EDITOR_GET_PRIVATE (editor); + + return gtk_label_get_text (GTK_LABEL (priv->label)); +} diff --git a/src/hildon-range-editor.h b/src/hildon-range-editor.h new file mode 100644 index 0000000..dbbf424 --- /dev/null +++ b/src/hildon-range-editor.h @@ -0,0 +1,96 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_RANGE_EDITOR_H__ +#define __HILDON_RANGE_EDITOR_H__ + +#include + +G_BEGIN_DECLS +/** + * HILDON_TYPE_RANGE_EDITOR + * + * Macro for getting type of range editor. + * Since: 0.12.10 + */ +#define HILDON_TYPE_RANGE_EDITOR (hildon_range_editor_get_type()) + +/** + * HILDON_RANGE_EDITOR_TYPE + * + * Deprecated: use #HILDON_TYPE_RANGE_EDITOR instead + */ +#define HILDON_RANGE_EDITOR_TYPE HILDON_TYPE_RANGE_EDITOR + +#define HILDON_RANGE_EDITOR(obj) \ + (GTK_CHECK_CAST (obj, HILDON_TYPE_RANGE_EDITOR, HildonRangeEditor)) +#define HILDON_RANGE_EDITOR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass),\ + HILDON_TYPE_RANGE_EDITOR, HildonRangeEditorClass)) +#define HILDON_IS_RANGE_EDITOR(obj) \ + (GTK_CHECK_TYPE (obj, HILDON_TYPE_RANGE_EDITOR)) +#define HILDON_IS_RANGE_EDITOR_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_RANGE_EDITOR)) +/** + * HildonRangeEditor: + * + * Internal struct for range editor. + */ +typedef struct _HildonRangeEditor HildonRangeEditor; +typedef struct _HildonRangeEditorClass HildonRangeEditorClass; + + +struct _HildonRangeEditor { + GtkContainer parent; +}; + +struct _HildonRangeEditorClass { + GtkContainerClass parent_class; +}; + +GType hildon_range_editor_get_type(void) G_GNUC_CONST; + +GtkWidget *hildon_range_editor_new_with_separator(const gchar * separator); +GtkWidget *hildon_range_editor_new(void); + +void hildon_range_editor_set_range(HildonRangeEditor * editor, + gint start, gint end); +void hildon_range_editor_get_range(HildonRangeEditor * editor, + gint * start, gint * end); +void hildon_range_editor_set_limits(HildonRangeEditor * editor, + gint start, gint end); + +void hildon_range_editor_set_lower (HildonRangeEditor *editor, gint value); +void hildon_range_editor_set_higher (HildonRangeEditor *editor, gint value); +gint hildon_range_editor_get_lower (HildonRangeEditor *editor); +gint hildon_range_editor_get_higher (HildonRangeEditor *editor); +void hildon_range_editor_set_min (HildonRangeEditor *editor, gint value); +void hildon_range_editor_set_max (HildonRangeEditor *editor, gint value); +gint hildon_range_editor_get_min (HildonRangeEditor *editor); +gint hildon_range_editor_get_max (HildonRangeEditor *editor); +void hildon_range_editor_set_separator (HildonRangeEditor *editor, + const gchar *separator); +const gchar *hildon_range_editor_get_separator (HildonRangeEditor *editor); + +G_END_DECLS +#endif /* __HILDON_RANGE_EDITOR_H__ */ diff --git a/src/hildon-scroll-area.c b/src/hildon-scroll-area.c new file mode 100644 index 0000000..ff484be --- /dev/null +++ b/src/hildon-scroll-area.c @@ -0,0 +1,239 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-scroll-area + * @short_description: A helper to create Maemo specific views, + * which are using scrollable area + * + * #GtkScrollArea combines a large widget that needs scrolling (like a + * text editor or a tree view) and other widgets that wouldn't fit one + * the screen normally without scrolling (like entries, toolbars etc.) + * into one scrollable area. + */ + +#include "hildon-scroll-area.h" +#include +#include +#include +#include +#include + +typedef struct + { + GtkWidget *fixed; + + /* Scrolled windows */ + GtkWidget *swouter; + GtkWidget *swinner; + + /* Widget that's being contained */ + GtkWidget *child; + + /* Vertical adjustment for scrolled windows */ + GtkAdjustment *outadj; + GtkAdjustment *inadj; + + } HildonScrollArea; + + +static void hildon_scroll_area_outer_value_changed (GtkAdjustment *adjustment, + HildonScrollArea *sc); +static void hildon_scroll_area_inner_value_changed (GtkAdjustment *adjustment, + HildonScrollArea *sc); +static void hildon_scroll_area_size_allocate (GtkWidget *widget, + GtkAllocation *allocation, + HildonScrollArea *sc); +static void hildon_scroll_area_child_requisition (GtkWidget *widget, + GtkRequisition *req, + HildonScrollArea *sc); +static void hildon_scroll_area_fixed_allocate (GtkWidget *widget, + GtkAllocation *allocation, + HildonScrollArea *sc); + +static int calculate_size (GtkWidget *widget); + +/** + * hildon_scroll_area_new: + * @sw: #GtkWidget - #GtkScrolledWindow + * @child: #GtkWidget - child to be place inside the sw + * + * This is not a widget. It's a helper function to create + * hildon-specific scrolling methods. + * A common situation where the scroll area should be used + * might be following. A view containing @GtkTreeView based widget, + * (or any similar widget which has built-in @GtkScrolledWindow support) + * and eg. couple buttons. Normaly @GtkScrolledWindow can not handle + * the situation so that the @GtkTreeView built-in support + * would work. The scroll area is connecting this built-in system to + * the scrolled window and also noticing the buttons. To use, one should + * create a box to which pack the buttons and the scroll area. + * The scroll area then contains the problematic widget eg. the @GtkTreeView. + * Then the box should be placed in the @GtkScrolledWindow. + * The function is currently assuming that the newly created scroll area + * hierarchy is not modified in anyway. Or if it is, it may lead to + * unwanted problems. Also assumed, that the @child will be packed + * to the @sw. + * + * Returns: a @GtkFixed + */ +GtkWidget *hildon_scroll_area_new (GtkWidget *sw, GtkWidget *child) +{ + GtkWidget *swi; + GtkWidget *fixed; + HildonScrollArea *sc; + + g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (sw) + && GTK_IS_WIDGET (child), NULL); + + swi = gtk_scrolled_window_new (NULL, NULL); + fixed = gtk_fixed_new (); + sc = g_malloc (sizeof (HildonScrollArea)); + memset (sc, 0, sizeof (HildonScrollArea)); + + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swi), + GTK_POLICY_NEVER, GTK_POLICY_NEVER); + + gtk_container_add (GTK_CONTAINER (swi), child); + gtk_fixed_put (GTK_FIXED (fixed), swi, 0, 0); + + sc->fixed = fixed; + sc->swouter = sw; + sc->swinner = swi; + sc->child = child; + sc->outadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (sw)); + sc->inadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (swi)); + + g_signal_connect_after (G_OBJECT (child), "size-request", + G_CALLBACK (hildon_scroll_area_child_requisition), sc); + + g_signal_connect_after (G_OBJECT (sc->outadj), "value_changed", + G_CALLBACK (hildon_scroll_area_outer_value_changed), sc); + g_signal_connect_after (G_OBJECT (sc->inadj), "value_changed", + G_CALLBACK (hildon_scroll_area_inner_value_changed), sc); + + g_signal_connect_after (G_OBJECT (sw), "size-allocate", + G_CALLBACK (hildon_scroll_area_size_allocate), sc); + g_signal_connect (G_OBJECT (sc->fixed), "size-allocate", + G_CALLBACK (hildon_scroll_area_fixed_allocate), sc); + g_signal_connect_swapped (G_OBJECT (sw), "destroy", + G_CALLBACK (g_free), sc); + + gtk_widget_show_all (sw); + return fixed; +} + +static void hildon_scroll_area_fixed_allocate (GtkWidget *widget, + GtkAllocation *allocation, + HildonScrollArea *sc) +{ + gtk_widget_set_size_request (sc->swinner, -1, + MIN (sc->outadj->page_size, allocation->height)); +} + + +static int calculate_size (GtkWidget *widget) +{ + int size = 0; + + if (GTK_IS_TEXT_VIEW (widget)) + return 0; + + if (GTK_IS_CONTAINER (widget)) { + GList *children = gtk_container_get_children (GTK_CONTAINER (widget)); + while (children != NULL) { + GtkWidget *wid = GTK_WIDGET (children->data); + gint sz = calculate_size (wid); + if ((GTK_WIDGET_VISIBLE (wid))) { + size += sz; + } + + children = g_list_next (children); + } + } else { + size = widget->allocation.height; + } + + return size; +} + +static void hildon_scroll_area_child_requisition (GtkWidget *widget, + GtkRequisition *req, + HildonScrollArea *sc) +{ + /* Limit height to fixed height */ + gint new_req = MAX (req->height, sc->fixed->allocation.height); + gint adjust_factor = calculate_size (sc->swouter) * 0.7; + + adjust_factor = MAX (0, adjust_factor - sc->outadj->value); + new_req = MIN (sc->outadj->page_size - adjust_factor, new_req); + + gtk_widget_set_size_request (sc->fixed, -1, req->height); + /* Request inner scrolled window at most page size */ + gtk_widget_set_size_request (sc->swinner, -1, new_req); +} + +static void hildon_scroll_area_outer_value_changed (GtkAdjustment *adjustment, + HildonScrollArea *sc) +{ + GtkRequisition req; + gtk_widget_size_request (sc->child, &req); + + /* Update inner adjustment position based on outer one, update fixed position */ + if ((sc->outadj->value + sc->outadj->page_size) > sc->fixed->allocation.y + && sc->outadj->value < (sc->fixed->allocation.y + req.height)) + { + gdouble new_pos = 0; + + new_pos = MAX (sc->outadj->value - sc->fixed->allocation.y, 0); + new_pos = MIN (new_pos, req.height - sc->inadj->page_size); + new_pos = MAX (new_pos, 0); + + gtk_fixed_move (GTK_FIXED (sc->fixed), sc->swinner, 0, new_pos); + gtk_adjustment_set_value (sc->inadj, new_pos); + } +} + +static void hildon_scroll_area_inner_value_changed (GtkAdjustment *adjustment, + HildonScrollArea *sc) +{ + /* Update outer adjustment based on inner adjustment position */ + if (sc->outadj->value != sc->fixed->allocation.y + adjustment->value) + gtk_adjustment_set_value (sc->outadj, + sc->fixed->allocation.y + adjustment->value); +} + +__inline__ static gint calculate_width (HildonScrollArea *sc) +{ + GtkScrolledWindow *scwin = GTK_SCROLLED_WINDOW (sc->swouter); + return (scwin->hscrollbar_visible * scwin->hscrollbar->allocation.width); +} + +static void hildon_scroll_area_size_allocate (GtkWidget *widget, + GtkAllocation *allocation, + HildonScrollArea *sc) +{ + gtk_widget_set_size_request (sc->fixed, calculate_width (sc), sc->fixed->allocation.height); + gtk_widget_set_size_request (sc->child, sc->fixed->allocation.width, -1); +} diff --git a/src/hildon-scroll-area.h b/src/hildon-scroll-area.h new file mode 100644 index 0000000..ce1c725 --- /dev/null +++ b/src/hildon-scroll-area.h @@ -0,0 +1,40 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/* + * The reason why this is not made as a widget: + * We can not create a widget which could return the correct child. + * (ie. by gtk_bin_get_child) + */ + +#ifndef __HILDON_SCROLL_AREA_H__ +#define __HILDON_SCROLL_AREA_H__ + +#include + +G_BEGIN_DECLS + GtkWidget * hildon_scroll_area_new(GtkWidget * sw, GtkWidget * child); + +G_END_DECLS +#endif /* __HILDON_SCROLL_AREA_H__ */ diff --git a/src/hildon-seekbar.c b/src/hildon-seekbar.c new file mode 100644 index 0000000..34d3b50 --- /dev/null +++ b/src/hildon-seekbar.c @@ -0,0 +1,601 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-seekbar + * @short_description: A widget used to identify a place from a content + * + * HildonSeekbar allows seeking in media with a range widget. It + * supports for setting or getting the length (total time) of the media, + * the position within it and the fraction (maximum position in a + * stream/the amount currently downloaded). The position is clamped + * between zero and the total time, or zero and the fraction in case of + * a stream. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "hildon-seekbar.h" + +#define HILDON_SEEKBAR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_SEEKBAR, HildonSeekbarPrivate)); + +typedef struct _HildonSeekbarPrivate HildonSeekbarPrivate; + +/* our parent class */ +static GtkScaleClass *parent_class = NULL; + +/* Init functions */ +static void hildon_seekbar_class_init(HildonSeekbarClass * seekbar_class); +static void hildon_seekbar_init(HildonSeekbar * seekbar); + +/* property functions */ +static void hildon_seekbar_set_property(GObject * object, guint prop_id, + const GValue * value, + GParamSpec * pspec); + +static void hildon_seekbar_get_property(GObject * object, guint prop_id, + GValue * value, + GParamSpec * pspec); + +/* virtual functions */ +static void hildon_seekbar_size_request(GtkWidget * widget, + GtkRequisition * event); +static void hildon_seekbar_size_allocate(GtkWidget * widget, + GtkAllocation * allocation); +static gboolean hildon_seekbar_expose(GtkWidget * widget, + GdkEventExpose * event); +static gboolean hildon_seekbar_button_press_event(GtkWidget * widget, + GdkEventButton * event); +static gboolean hildon_seekbar_button_release_event(GtkWidget * widget, + GdkEventButton * event); +static gboolean hildon_seekbar_keypress(GtkWidget * widget, + GdkEventKey * event); + + +#define MINIMUM_WIDTH 115 +#define DEFAULT_HEIGHT 58 + +/* Toolbar width and height defines */ +#define TOOL_MINIMUM_WIDTH 75 +#define TOOL_DEFAULT_HEIGHT 40 + +#define DEFAULT_DISPLAYC_BORDER 10 +#define BUFFER_SIZE 32 +#define EXTRA_SIDE_BORDER 20 +#define TOOL_EXTRA_SIDE_BORDER 0 + +/* the number of steps it takes to move from left to right */ +#define NUM_STEPS 20 + +#define SECONDS_PER_MINUTE 60 + +/* the number of digits precision for the internal range. + * note, this needs to be enough so that the step size for + * small total_times doesn't get rounded off. Currently set to 3 + * this is because for the smallest total time ( i.e 1 ) and the current + * num steps ( 20 ) is: 1/20 = 0.05. 0.05 is 2 digits, and we + * add one for safety */ +#define MAX_ROUND_DIGITS 3 + +/* + * FIXME HildonSeekbar introduced major changes in GtkRange mostly related + * to stream_indicator. These changes should be minimized. + */ + +/* Property indices */ +enum { + PROP_TOTAL_TIME = 1, + PROP_POSITION, + PROP_FRACTION +}; + +/* private variables */ +struct _HildonSeekbarPrivate { + gboolean is_toolbar; /* TRUE if this widget is inside a toolbar */ + guint fraction; /* This is the amount of time that has progressed from + the beginning. It should be an integer between the + minimum and maximum values of the corresponding + adjustment, ie. adjument->lower and ->upper.. */ +}; + +/** + * Initialises, and returns the type of a hildon seekbar. + */ +GType hildon_seekbar_get_type(void) +{ + static GType seekbar_type = 0; + + if (!seekbar_type) { + static const GTypeInfo seekbar_info = { + sizeof(HildonSeekbarClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_seekbar_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonSeekbar), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_seekbar_init, + }; + seekbar_type = g_type_register_static(GTK_TYPE_SCALE, + "HildonSeekbar", + &seekbar_info, 0); + } + return seekbar_type; +} + +/** + * Initialises the seekbar class. + */ +static void hildon_seekbar_class_init(HildonSeekbarClass * seekbar_class) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(seekbar_class); + GObjectClass *object_class = G_OBJECT_CLASS(seekbar_class); + + parent_class = g_type_class_peek_parent(seekbar_class); + + g_type_class_add_private(seekbar_class, sizeof(HildonSeekbarPrivate)); + + widget_class->size_request = hildon_seekbar_size_request; + widget_class->size_allocate = hildon_seekbar_size_allocate; + widget_class->expose_event = hildon_seekbar_expose; + widget_class->button_press_event = hildon_seekbar_button_press_event; + widget_class->button_release_event = + hildon_seekbar_button_release_event; + widget_class->key_press_event = hildon_seekbar_keypress; + + object_class->set_property = hildon_seekbar_set_property; + object_class->get_property = hildon_seekbar_get_property; + + g_object_class_install_property(object_class, PROP_TOTAL_TIME, + g_param_spec_double("total_time", + "total time", + "Total playing time of this media file", + 0, /* min value */ + G_MAXDOUBLE, /* max value */ + 0, /* default */ + G_PARAM_READWRITE)); + + g_object_class_install_property(object_class, PROP_POSITION, + g_param_spec_double("position", + "position", + "Current position in this media file", + 0, /* min value */ + G_MAXDOUBLE, /* max value */ + 0, /* default */ + G_PARAM_READWRITE)); + + g_object_class_install_property(object_class, PROP_FRACTION, + g_param_spec_double("fraction", + "Fraction", + "current fraction related to the" + "progress indicator", + 0, /* min value */ + G_MAXDOUBLE, /* max value */ + 0, /* default */ + G_PARAM_READWRITE)); +} + + +static void hildon_seekbar_init(HildonSeekbar * seekbar) +{ + HildonSeekbarPrivate *priv; + GtkRange *range = GTK_RANGE(seekbar); + + priv = HILDON_SEEKBAR_GET_PRIVATE(seekbar); + + /* Initialize range widget */ + range->orientation = GTK_ORIENTATION_HORIZONTAL; + range->flippable = TRUE; + range->has_stepper_a = TRUE; + range->has_stepper_d = TRUE; + range->round_digits = MAX_ROUND_DIGITS; + + gtk_scale_set_draw_value (GTK_SCALE (seekbar), FALSE); +} + +/* + * Purpose of this function is to prevent Up and Down keys from + * changing the widget's value (like Left and Right). Instead they + * are used for changing focus to other widgtes. + */ +static gboolean hildon_seekbar_keypress(GtkWidget * widget, + GdkEventKey * event) +{ + if (event->keyval == GDK_Up || event->keyval == GDK_Down) + return FALSE; + return ((GTK_WIDGET_CLASS(parent_class)->key_press_event) (widget, + event)); +} + +static void +hildon_seekbar_set_property(GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + HildonSeekbar *seekbar = HILDON_SEEKBAR(object); + + switch (prop_id) { + case PROP_TOTAL_TIME: + hildon_seekbar_set_total_time(seekbar, g_value_get_double(value)); + break; + case PROP_POSITION: + hildon_seekbar_set_position(seekbar, g_value_get_double(value)); + break; + case PROP_FRACTION: + hildon_seekbar_set_fraction(seekbar, g_value_get_double(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/* handle getting of seekbar properties */ +static void +hildon_seekbar_get_property(GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GtkRange *range = GTK_RANGE(object); + + switch (prop_id) { + case PROP_TOTAL_TIME: + g_value_set_double(value, range->adjustment->upper); + break; + case PROP_POSITION: + g_value_set_double(value, range->adjustment->value); + break; + case PROP_FRACTION: + g_value_set_double(value, + hildon_seekbar_get_fraction(HILDON_SEEKBAR(object))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/** + * hildon_seekbar_new: + * + * Create a new #HildonSeekbar widget. + * + * Returns: a #GtkWidget pointer of #HildonSeekbar widget + */ +GtkWidget *hildon_seekbar_new(void) +{ + return g_object_new(HILDON_TYPE_SEEKBAR, NULL); +} + +/** + * hildon_seekbar_get_total_time: + * @seekbar: pointer to #HildonSeekbar widget + * + * Returns: total playing time of media in seconds. + */ +gint hildon_seekbar_get_total_time(HildonSeekbar *seekbar) +{ + GtkWidget *widget; + widget = GTK_WIDGET (seekbar); + g_return_val_if_fail(HILDON_IS_SEEKBAR(seekbar), 0); + g_return_val_if_fail(GTK_RANGE(widget)->adjustment, 0); + return GTK_RANGE(widget)->adjustment->upper; +} + +/** + * hildon_seekbar_set_total_time: + * @seekbar: pointer to #HildonSeekbar widget + * @time: integer greater than zero + * + * Set total playing time of media in seconds. + */ +void hildon_seekbar_set_total_time(HildonSeekbar *seekbar, gint time) +{ + GtkAdjustment *adj; + GtkWidget *widget; + gboolean value_changed = FALSE; + + g_return_if_fail(HILDON_IS_SEEKBAR(seekbar)); + widget = GTK_WIDGET (seekbar); + + if (time <= 0) { + return; + } + + g_return_if_fail(GTK_RANGE(widget)->adjustment); + + adj = GTK_RANGE(widget)->adjustment; + adj->upper = time; + + /* Clamp position to total time */ + if (adj->value > time) { + adj->value = time; + value_changed = TRUE; + } + + /* Calculate new step value */ + adj->step_increment = adj->upper / NUM_STEPS; + adj->page_increment = adj->step_increment; + + gtk_adjustment_changed(adj); + + /* Update range widget position/fraction */ + if (value_changed) { + gtk_adjustment_value_changed(adj); + hildon_seekbar_set_fraction(seekbar, + MIN(hildon_seekbar_get_fraction(seekbar), + time)); + + g_object_freeze_notify (G_OBJECT(seekbar)); + + hildon_seekbar_set_position(seekbar, + MIN(hildon_seekbar_get_position(seekbar), + time)); + + g_object_notify(G_OBJECT (seekbar), "total-time"); + + g_object_thaw_notify (G_OBJECT(seekbar)); + } +} + +/** + * hildon_seekbar_get_fraction: + * @seekbar: pointer to #HildonSeekbar widget + * + * Get current fraction value of the rage. + * + * Returns: current fraction + */ +guint hildon_seekbar_get_fraction( HildonSeekbar *seekbar ) +{ + g_return_val_if_fail( HILDON_IS_SEEKBAR( seekbar ), 0 ); + + return osso_gtk_range_get_stream_position (GTK_RANGE(seekbar)); +} + +/** + * hildon_seekbar_set_fraction: + * @seekbar: pointer to #HildonSeekbar widget + * @fraction: the new position of the progress indicator + * + * Set current fraction value of the range. + * It should be between the minimal and maximal values of the range in seekbar. + */ +void hildon_seekbar_set_fraction( HildonSeekbar *seekbar, guint fraction ) +{ + GtkRange *range = NULL; + g_return_if_fail( HILDON_IS_SEEKBAR( seekbar ) ); + + range = GTK_RANGE(GTK_WIDGET(seekbar)); + + g_return_if_fail(fraction <= range->adjustment->upper && + fraction >= range->adjustment->lower); + + /* Set to show stream indicator. */ + g_object_set (G_OBJECT (seekbar), "stream_indicator", TRUE, NULL); + + fraction = CLAMP(fraction, range->adjustment->lower, + range->adjustment->upper); + + /* Update stream position of range widget */ + osso_gtk_range_set_stream_position( range, fraction ); + + if (fraction < hildon_seekbar_get_position(seekbar)) + hildon_seekbar_set_position(seekbar, fraction); + + g_object_notify (G_OBJECT (seekbar), "fraction"); +} + +/** + * hildon_seekbar_get_position: + * @seekbar: pointer to #HildonSeekbar widget + * + * Get current position in stream in seconds. + * + * Returns: current position in stream in seconds + */ +gint hildon_seekbar_get_position(HildonSeekbar *seekbar) +{ + g_return_val_if_fail(HILDON_IS_SEEKBAR(seekbar), 0); + g_return_val_if_fail(GTK_RANGE(seekbar)->adjustment, 0); + + return GTK_RANGE(seekbar)->adjustment->value; +} + +/** + * hildon_seekbar_set_position: + * @seekbar: pointer to #HildonSeekbar widget + * @time: time within range of >= 0 && < G_MAXINT + * + * Set current position in stream in seconds. + */ +void hildon_seekbar_set_position(HildonSeekbar *seekbar, gint time) +{ + GtkRange *range; + GtkAdjustment *adj; + gint value; + + g_return_if_fail(time >= 0); + g_return_if_fail(HILDON_IS_SEEKBAR(seekbar)); + range = GTK_RANGE(seekbar); + adj = range->adjustment; + g_return_if_fail(adj); + + /* only change value if it is a different int. this allows us to have + smooth scrolls for small total_times */ + value = floor(adj->value); + if (time != value) { + value = (time < adj->upper) ? time : adj->upper; + if (value <= osso_gtk_range_get_stream_position (range)) { + adj->value = value; + gtk_adjustment_value_changed(adj); + + g_object_notify(G_OBJECT(seekbar), "position"); + } + } +} + +static void hildon_seekbar_size_request(GtkWidget * widget, + GtkRequisition * req) +{ + HildonSeekbar *self = NULL; + HildonSeekbarPrivate *priv = NULL; + GtkWidget *parent = NULL; + + self = HILDON_SEEKBAR(widget); + priv = HILDON_SEEKBAR_GET_PRIVATE(self); + + parent = gtk_widget_get_ancestor(GTK_WIDGET(self), GTK_TYPE_TOOLBAR); + + priv->is_toolbar = parent ? TRUE : FALSE; + + if (GTK_WIDGET_CLASS(parent_class)->size_request) + GTK_WIDGET_CLASS(parent_class)->size_request(widget, req); + + /* Request minimum size, depending on whether the widget is in a + * toolbar or not */ + req->width = priv->is_toolbar ? TOOL_MINIMUM_WIDTH : MINIMUM_WIDTH; + req->height = priv->is_toolbar ? TOOL_DEFAULT_HEIGHT : DEFAULT_HEIGHT; +} + +static void hildon_seekbar_size_allocate(GtkWidget * widget, + GtkAllocation * allocation) +{ + HildonSeekbarPrivate *priv; + + priv = HILDON_SEEKBAR_GET_PRIVATE(HILDON_SEEKBAR(widget)); + + if (priv->is_toolbar == TRUE) + { + /* Center vertically */ + if (allocation->height > TOOL_DEFAULT_HEIGHT) + { + allocation->y += + (allocation->height - TOOL_DEFAULT_HEIGHT) / 2; + allocation->height = TOOL_DEFAULT_HEIGHT; + } + /* Add space for border */ + allocation->x += TOOL_EXTRA_SIDE_BORDER; + allocation->width -= 2 * TOOL_EXTRA_SIDE_BORDER; + } + else + { + /* Center vertically */ + if (allocation->height > DEFAULT_HEIGHT) + { + allocation->y += (allocation->height - DEFAULT_HEIGHT) / 2; + allocation->height = DEFAULT_HEIGHT; + } + + /* Add space for border */ + allocation->x += EXTRA_SIDE_BORDER; + allocation->width -= 2 * EXTRA_SIDE_BORDER; + } + + if (GTK_WIDGET_CLASS(parent_class)->size_allocate) + GTK_WIDGET_CLASS(parent_class)->size_allocate(widget, allocation); +} + +static gboolean hildon_seekbar_expose(GtkWidget * widget, + GdkEventExpose * event) +{ + HildonSeekbarPrivate *priv; + gint extra_side_borders = 0; + + priv = HILDON_SEEKBAR_GET_PRIVATE(HILDON_SEEKBAR(widget)); + + extra_side_borders = priv->is_toolbar ? TOOL_EXTRA_SIDE_BORDER : + EXTRA_SIDE_BORDER; + + if (GTK_WIDGET_DRAWABLE(widget)) { + /* Paint border */ + gtk_paint_box(widget->style, widget->window, + GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, + NULL, widget, "seekbar", + widget->allocation.x - extra_side_borders, + widget->allocation.y, + widget->allocation.width + 2 * extra_side_borders, + widget->allocation.height); + + (*GTK_WIDGET_CLASS(parent_class)->expose_event) (widget, event); + } + + return FALSE; +} + +/* + * Event handler for button press. Changes button1 to button2. + */ +static gboolean +hildon_seekbar_button_press_event(GtkWidget * widget, + GdkEventButton * event) +{ + gint result = FALSE; + + /* We change here the button id because we want to use button2 + * functionality for button1: jump to mouse position + * instead of slowly incrementing to it */ + if (event->button == 1) event->button = 2; + + /* call the parent handler */ + if (GTK_WIDGET_CLASS(parent_class)->button_press_event) + result = GTK_WIDGET_CLASS(parent_class)->button_press_event(widget, + event); + + return result; +} +/* + * Event handler for button release. Changes button1 to button2. + */ +static gboolean +hildon_seekbar_button_release_event(GtkWidget * widget, + GdkEventButton * event) +{ + gboolean result = FALSE; + + /* We change here the button id because we want to use button2 + * functionality for button1: jump to mouse position + * instead of slowly incrementing to it */ + event->button = event->button == 1 ? 2 : event->button; + + /* call the parent handler */ + if (GTK_WIDGET_CLASS(parent_class)->button_release_event) + result = GTK_WIDGET_CLASS(parent_class)->button_release_event(widget, + event); + return result; +} diff --git a/src/hildon-seekbar.h b/src/hildon-seekbar.h new file mode 100644 index 0000000..47c7548 --- /dev/null +++ b/src/hildon-seekbar.h @@ -0,0 +1,65 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_SEEKBAR_H__ +#define __HILDON_SEEKBAR_H__ + +#include + +G_BEGIN_DECLS +#define HILDON_TYPE_SEEKBAR ( hildon_seekbar_get_type() ) +#define HILDON_SEEKBAR(obj) (GTK_CHECK_CAST (obj,\ + HILDON_TYPE_SEEKBAR, HildonSeekbar)) +#define HILDON_SEEKBAR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass),\ + HILDON_TYPE_SEEKBAR, HildonSeekbarClass)) +#define HILDON_IS_SEEKBAR(obj) (GTK_CHECK_TYPE (obj, HILDON_TYPE_SEEKBAR)) +#define HILDON_IS_SEEKBAR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass),\ + HILDON_TYPE_SEEKBAR)) +/** + * HildonSeekbar: + * + * Contains only private data. + */ +typedef struct _HildonSeekbar HildonSeekbar; +typedef struct _HildonSeekbarClass HildonSeekbarClass; + +struct _HildonSeekbar { + GtkScale scale; +}; + +struct _HildonSeekbarClass { + GtkScaleClass parent_class; +}; + +GType hildon_seekbar_get_type(void) G_GNUC_CONST; +GtkWidget *hildon_seekbar_new(void); +gint hildon_seekbar_get_total_time(HildonSeekbar *seekbar); +void hildon_seekbar_set_total_time(HildonSeekbar *seekbar, gint time); +gint hildon_seekbar_get_position(HildonSeekbar *seekbar); +void hildon_seekbar_set_position(HildonSeekbar *seekbar, gint time); +void hildon_seekbar_set_fraction(HildonSeekbar *seekbar, guint fraction); +guint hildon_seekbar_get_fraction(HildonSeekbar *seekbar); + +G_END_DECLS +#endif /* __HILDON_SEEKBAR_H__ */ diff --git a/src/hildon-set-password-dialog.c b/src/hildon-set-password-dialog.c new file mode 100644 index 0000000..527fc30 --- /dev/null +++ b/src/hildon-set-password-dialog.c @@ -0,0 +1,666 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-set-password-dialog + * @short_description: A dialog used to set, change or remove a password + * @see_also: #HildonGetPasswordDialog + * + * HildonSetPasswordDialog allows setting and changing a password. + * + * In Change mode: Dialog is used to change or remove an existing + * password. Unselecting the check box dims the password fields below + * it. If the dialog is accepted with 'OK' while the check box is + * unselected, a Confirmation Note is shown. If the Confirmation Note + * Dialog is accepted with 'Remove', the password protection is removed. + * + * In Set mode: Set Password Dialog is used to define a password, or + * change a password that cannot be removed. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#define _(String) dgettext(PACKAGE, String) +#define c_(String) dgettext("hildon-common-strings", String) + +static GtkDialogClass *parent_class; + +#define HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(obj)\ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_SET_PASSWORD_DIALOG, HildonSetPasswordDialogPrivate)); + +typedef struct +_HildonSetPasswordDialogPrivate HildonSetPasswordDialogPrivate; + +static void +hildon_set_password_dialog_class_init(HildonSetPasswordDialogClass * + class); +static void hildon_set_password_dialog_init(HildonSetPasswordDialog * + dialog); +static void hildon_checkbox_toggled(GtkWidget * widget, gpointer dialog); + +static void +hildon_set_password_response_change(GtkDialog * d, gint arg1, gpointer unused); +static void +hildon_set_password_response_set(GtkDialog * d, gint arg1, gpointer unused); + +static void create_contents(HildonSetPasswordDialog *dialog); +static void hildon_set_password_set_property(GObject * object, + guint prop_id, + const GValue * value, + GParamSpec * pspec); +static void hildon_set_password_get_property(GObject * object, + guint prop_id, GValue * value, + GParamSpec * pspec); + +/* Private struct */ +struct _HildonSetPasswordDialogPrivate { + GtkWidget *checkboxCaption; + GtkWidget *checkbox; + + GtkLabel *domainLabel; + + GtkWidget *pwd1stEntry; + GtkWidget *pwd1stCaption; + gchar *pwd1stCaption_string; + + GtkWidget *pwd2ndEntry; + GtkWidget *pwd2ndCaption; + gchar *pwd2ndCaption_string; + + GtkWidget *okButton; + GtkWidget *cancelButton; + + gboolean protection; +}; + +enum { + PROP_NONE = 0, + PROP_DOMAIN, + PROP_PASSWORD, + PROP_HILDON_PASSWORD_DIALOG +}; + +/* Private functions */ +static void +hildon_set_password_set_property(GObject * object, + guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + HildonSetPasswordDialog *dialog = HILDON_SET_PASSWORD_DIALOG(object); + HildonSetPasswordDialogPrivate *priv; + + priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(dialog); + + switch (prop_id) { + case PROP_DOMAIN: + /* Update domain label to display new value */ + gtk_label_set_text(priv->domainLabel, g_value_get_string(value)); + break; + case PROP_PASSWORD: + /* Update password entry to display new value */ + gtk_entry_set_text(GTK_ENTRY(priv->pwd1stEntry), g_value_get_string(value)); + break; + case PROP_HILDON_PASSWORD_DIALOG: + /* Note this is a G_PARAM_CONSTRUCT_ONLY type property */ + priv->protection = g_value_get_boolean(value); + + /* We now have the necessary information to populate the dialog */ + create_contents(dialog); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +hildon_set_password_get_property(GObject * object, + guint prop_id, + GValue * value, + GParamSpec * pspec) +{ + HildonSetPasswordDialogPrivate *priv = NULL; + + priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_DOMAIN: + g_value_set_string(value, gtk_label_get_text(priv->domainLabel)); + break; + case PROP_PASSWORD: + g_value_set_string(value, + gtk_entry_get_text(GTK_ENTRY(priv->pwd1stEntry))); + break; + case PROP_HILDON_PASSWORD_DIALOG: + g_value_set_boolean(value, priv->protection); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + + +static void +create_contents(HildonSetPasswordDialog *dialog) +{ + HildonSetPasswordDialogPrivate *priv = NULL; + + GtkSizeGroup *group; + + priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(dialog); + priv->checkbox = NULL; + + /* Size group for labels */ + group = GTK_SIZE_GROUP(gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL)); + + gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); + + /* Setup and pack domain label */ + priv->domainLabel = GTK_LABEL(gtk_label_new(NULL)); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), + GTK_WIDGET(priv->domainLabel), FALSE, FALSE, 0); + gtk_widget_show(GTK_WIDGET(priv->domainLabel)); + + if (priv->protection == TRUE) { + /* Use Change Password Dialog strings */ + priv->pwd1stCaption_string = _(HILDON_SET_MODIFY_PASSWORD_DIALOG_PASSWORD); + priv->pwd2ndCaption_string = _(HILDON_SET_MODIFY_PASSWORD_DIALOG_VERIFY_PASSWORD); + + /* Setup checkbox to enable/disable password protection */ + priv->checkbox = gtk_check_button_new(); + gtk_widget_show(priv->checkbox); + priv->checkboxCaption = hildon_caption_new + (group, + _(HILDON_SET_MODIFY_PASSWORD_DIALOG_LABEL), + priv->checkbox, + NULL, HILDON_CAPTION_OPTIONAL); + hildon_caption_set_separator(HILDON_CAPTION(priv->checkboxCaption), ""); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), + priv->checkboxCaption, TRUE, TRUE, 0); + gtk_widget_show(priv->checkboxCaption); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbox), + TRUE); + gtk_signal_connect(GTK_OBJECT(priv->checkbox), "toggled", + G_CALLBACK(hildon_checkbox_toggled), dialog); + + /* Setup appropriate response handler */ + g_signal_connect(G_OBJECT(dialog), "response", + G_CALLBACK(hildon_set_password_response_change), + NULL); + } else { + /* Use Set Password Dialog strings */ + priv->pwd1stCaption_string = _(HILDON_SET_PASSWORD_DIALOG_PASSWORD); + priv->pwd2ndCaption_string = _(HILDON_SET_PASSWORD_DIALOG_VERIFY_PASSWORD); + + /* Setup appropriate response handler */ + g_signal_connect(G_OBJECT(dialog), "response", + G_CALLBACK(hildon_set_password_response_set), + NULL); + } + + /* Create the password field */ + priv->pwd1stEntry = gtk_entry_new(); + g_object_set (priv->pwd1stEntry, "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL); + gtk_entry_set_visibility(GTK_ENTRY(priv->pwd1stEntry), FALSE); + gtk_widget_show(priv->pwd1stEntry); + priv->pwd1stCaption = hildon_caption_new(group, + priv->pwd1stCaption_string, + priv->pwd1stEntry, + NULL, HILDON_CAPTION_OPTIONAL); + hildon_caption_set_separator(HILDON_CAPTION(priv->pwd1stCaption), ""); + gtk_entry_set_visibility(GTK_ENTRY(priv->pwd1stEntry), FALSE); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), + priv->pwd1stCaption, TRUE, TRUE, 0); + gtk_widget_show(priv->pwd1stCaption); + + /* Create the password verify field */ + priv->pwd2ndEntry = gtk_entry_new(); + g_object_set (priv->pwd2ndEntry, "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL); + gtk_widget_show(priv->pwd2ndEntry); + priv->pwd2ndCaption = hildon_caption_new(group, + priv->pwd2ndCaption_string, + priv->pwd2ndEntry, + NULL, HILDON_CAPTION_OPTIONAL); + hildon_caption_set_separator(HILDON_CAPTION(priv->pwd2ndCaption), ""); + gtk_entry_set_visibility(GTK_ENTRY(priv->pwd2ndEntry), FALSE); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), + priv->pwd2ndCaption, TRUE, TRUE, 0); + gtk_widget_show(priv->pwd2ndCaption); + + /* Set dialog title */ + gtk_window_set_title(GTK_WINDOW(dialog), + _(priv->protection + ? HILDON_SET_MODIFY_PASSWORD_DIALOG_TITLE + : HILDON_SET_PASSWORD_DIALOG_TITLE)); + + /* Create the OK/CANCEL buttons */ + priv->okButton = gtk_dialog_add_button + (GTK_DIALOG(dialog), _(priv->protection + ? HILDON_SET_MODIFY_PASSWORD_DIALOG_OK + : HILDON_SET_PASSWORD_DIALOG_OK), + GTK_RESPONSE_OK); + priv->cancelButton = gtk_dialog_add_button + (GTK_DIALOG(dialog), _(priv->protection + ? HILDON_SET_MODIFY_PASSWORD_DIALOG_CANCEL + : HILDON_SET_PASSWORD_DIALOG_CANCEL), + GTK_RESPONSE_CANCEL); + + gtk_widget_show(priv->okButton); + gtk_widget_show(priv->cancelButton); + + /* Ensure group is freed when all its contents have been removed */ + g_object_unref(group); +} + +static void +hildon_set_password_dialog_class_init(HildonSetPasswordDialogClass * class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(class); + + parent_class = g_type_class_peek_parent(class); + + /* Override virtual methods */ + object_class->set_property = hildon_set_password_set_property; + object_class->get_property = hildon_set_password_get_property; + + /* Install new properties */ + g_object_class_install_property(object_class, + PROP_DOMAIN, + g_param_spec_string ("domain", + "Domain", + "Set Domain (content) for domain label.", + NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property(object_class, + PROP_HILDON_PASSWORD_DIALOG, + g_param_spec_boolean ("modify_protection", + "Password type", + "Set type to dialog", + TRUE, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE)); + + g_object_class_install_property(object_class, + PROP_PASSWORD, + g_param_spec_string ("password", + "Password content", + "Set content to dialog", + "DEFAULT", + G_PARAM_READWRITE)); + + /* Install private structure */ + g_type_class_add_private(class, + sizeof(HildonSetPasswordDialogPrivate)); +} + +static void +hildon_set_password_dialog_init(HildonSetPasswordDialog * dialog) +{ + /* Most of the initializations are done in create_contents() + after the 'modify_protection' property has been set */ + + gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); +} + + +/* We come here when response button is clicked and dialog + is used to change existing password. */ +static void +hildon_set_password_response_change(GtkDialog * dialog, gint arg1, + gpointer unused) +{ + GtkEntry *pwd1stEntry; + GtkEntry *pwd2ndEntry; + gchar *text1; + gchar *text2; + HildonNote *note; + gint i; + HildonSetPasswordDialogPrivate *priv; + + priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(dialog); + + /* Password and verification */ + pwd1stEntry = GTK_ENTRY(gtk_bin_get_child + (GTK_BIN(priv->pwd1stCaption))); + pwd2ndEntry = GTK_ENTRY(gtk_bin_get_child + (GTK_BIN(priv->pwd2ndCaption))); + text1 = GTK_ENTRY(pwd1stEntry)->text; + text2 = GTK_ENTRY(pwd2ndEntry)->text; + + /* User accepted the dialog */ + if (arg1 == GTK_RESPONSE_OK){ + /* Is the checkbox marked, so password protection is still in use? */ + if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->checkbox))){ + /* Yes, Something is given as password as well? */ + if (text1[0] != '\0') { + if (strcmp (text1, text2) == 0) { + /* Passwords match, so accept change password */ + priv->protection = TRUE; + } else if (text2[0] == '\0') { + /* Second field is empty, so show error, but don't clear fields */ + g_signal_stop_emission_by_name(G_OBJECT(dialog), + "response"); + gtk_infoprint (NULL, + c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH)); + gtk_widget_grab_focus(GTK_WIDGET(pwd2ndEntry)); + } else { + /* Error: Passwords don't match, so start over */ + g_signal_stop_emission_by_name(G_OBJECT(dialog), + "response"); + gtk_entry_set_text(pwd1stEntry, ""); + gtk_entry_set_text(pwd2ndEntry, ""); + gtk_infoprint (NULL, + c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH)); + gtk_widget_grab_focus(GTK_WIDGET(pwd1stEntry)); + } + } else { + /* No, the password is empty */ + g_signal_stop_emission_by_name(G_OBJECT(dialog), "response"); + if (text2[0] == '\0') { + /* Error: Both fields are empty */ + gtk_infoprint (NULL, c_(HILDON_SET_PASSWORD_DIALOG_EMPTY)); + } else { + /* Error: Second field doesn't match + the empty first field, so start over */ + gtk_infoprint (NULL, c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH)); + gtk_entry_set_text(pwd2ndEntry, ""); + } + gtk_widget_grab_focus(GTK_WIDGET(pwd1stEntry)); + } + } else { + /* No, user wants to remove password protection. + Confirm remove password protection */ + note = HILDON_NOTE(hildon_note_new_confirmation + (GTK_WINDOW(dialog), + c_(HILDON_SET_PASSWORD_DIALOG_REMOVE_PROTECTION + ))); + + hildon_note_set_button_texts + (HILDON_NOTE(note), + c_(HILDON_REMOVE_PROTECTION_CONFIRMATION_REMOVE), + c_(HILDON_REMOVE_PROTECTION_CONFIRMATION_CANCEL)); + + /* Display confirmation note */ + i = gtk_dialog_run(GTK_DIALOG(note)); + + gtk_widget_destroy(GTK_WIDGET(note)); + + if (i == GTK_RESPONSE_OK) + /* Remove password protection */ + priv->protection = FALSE; + else { + /* Remove password protection cancelled */ + priv->protection = TRUE; + g_signal_stop_emission_by_name(G_OBJECT(dialog), "response"); + } + } + + } else { + /* Watch out for fading boolean values */ + priv->protection = TRUE; + } +} + +/* We come here when response button is clicked and dialog + is used to set new password. */ +static void +hildon_set_password_response_set(GtkDialog * dialog, gint arg1, + gpointer unused) +{ + GtkEntry *pwd1stEntry; + GtkEntry *pwd2ndEntry; + gchar *text1; + gchar *text2; + + HildonSetPasswordDialogPrivate *priv; + + priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(dialog); + + /* Password and confirmation */ + pwd1stEntry = GTK_ENTRY(gtk_bin_get_child + (GTK_BIN(priv->pwd1stCaption))); + pwd2ndEntry = GTK_ENTRY(gtk_bin_get_child + (GTK_BIN(priv->pwd2ndCaption))); + text1 = GTK_ENTRY(pwd1stEntry)->text; + text2 = GTK_ENTRY(pwd2ndEntry)->text; + + if (arg1 == GTK_RESPONSE_OK) { + /* User provided something for password? */ + if (text1[0] != '\0') { + if (strcmp (text1, text2) == 0) { + /* Passwords match, so accept set password */ + priv->protection = TRUE; + } else if (text2[0] == '\0') { + /* Second field is empty, so show error, + but don't clear the fields */ + g_signal_stop_emission_by_name(G_OBJECT(dialog), "response"); + gtk_infoprint (NULL, c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH)); + gtk_widget_grab_focus (GTK_WIDGET (priv->pwd2ndEntry)); + } else { + /* Error: Passwords don't match, so start over */ + g_signal_stop_emission_by_name(G_OBJECT(dialog), "response"); + gtk_entry_set_text(pwd1stEntry, ""); + gtk_entry_set_text(pwd2ndEntry, ""); + gtk_infoprint (NULL, c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH)); + gtk_widget_grab_focus(GTK_WIDGET(priv->pwd1stEntry)); + } + } else { + /* First field is empty */ + g_signal_stop_emission_by_name(G_OBJECT(dialog), "response"); + if (text2[0] == '\0') { + /* Error: Both fields are empty */ + gtk_infoprint (NULL, c_(HILDON_SET_PASSWORD_DIALOG_EMPTY)); + } else { + /* Error: Second field doesn't match + the empty first field, so start over */ + gtk_infoprint (NULL, c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH)); + gtk_entry_set_text(pwd2ndEntry, ""); + } + gtk_widget_grab_focus(GTK_WIDGET(pwd1stEntry)); + } + } else { + /* Watch out for fading boolean values */ + priv->protection = FALSE; + } +} + +static void hildon_checkbox_toggled(GtkWidget * widget, gpointer dialog) +{ + HildonSetPasswordDialogPrivate *priv = + HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(dialog); + gboolean active; + + /* If the user enabled/disabled the password protection feature + we enable/disable password entries accordingly */ + active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); + gtk_widget_set_sensitive(GTK_WIDGET(priv->pwd1stEntry), active); + gtk_widget_set_sensitive(GTK_WIDGET(priv->pwd2ndEntry), active); +} + +/* Public functions */ + +/** + * hildon_set_password_dialog_get_type: + * + * Returns GType for HildonPasswordDialog as produced by + * g_type_register_static(). + * + * Returns: HildonSetPasswordDialog type + */ +GType hildon_set_password_dialog_get_type(void) +{ + static GType dialog_type = 0; + + if (!dialog_type) { + static const GTypeInfo dialog_info = { + sizeof(HildonSetPasswordDialogClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_set_password_dialog_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonSetPasswordDialog), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_set_password_dialog_init + }; + + dialog_type = g_type_register_static(GTK_TYPE_DIALOG, + "HildonSetPasswordDialog", + &dialog_info, 0); + } + return dialog_type; +} + +/** + * hildon_set_password_dialog_new: + * @parent: parent window; can be NULL + * @modify_protection: TRUE creates a new change password dialog and FALSE + * creates a new set password dialog + * + * Constructs a new HildonSetPasswordDialog. + * + * Returns: a new #GtkWidget of type HildonSetPasswordDialog + */ + +GtkWidget *hildon_set_password_dialog_new(GtkWindow * parent, + gboolean modify_protection) +{ + return hildon_set_password_dialog_new_with_default(parent, "", + modify_protection); +} + +/** + * hildon_set_password_dialog_new_with_default: + * @parent: parent window; can be NULL + * @password: a default password to be shown in password field + * @modify_protection: TRUE creates a new change password dialog and FALSE + * creates a new set password dialog + * + * Same as #hildon_set_password_dialog_new, but with a default password + * in password field. + * + * Returns: a new #GtkWidget of type HildonSetPasswordDialog + */ + +GtkWidget *hildon_set_password_dialog_new_with_default + (GtkWindow *parent, + const gchar *password, + gboolean modify_protection) +{ + GtkWidget *dialog = g_object_new(HILDON_TYPE_SET_PASSWORD_DIALOG, + "modify_protection", modify_protection, + "password", password, NULL); + + if (parent != NULL) { + gtk_window_set_transient_for(GTK_WINDOW(dialog), parent); + } + + return dialog; +} + +/** + * hildon_set_password_dialog_get_password: + * @dialog: pointer to HildonSetPasswordDialog + * + * Returns current password. + * + * Returns: changed password ( if the dialog is successfully + * accepted with 'OK' ( and when the check box is 'ON' ( in Change Password + * Dialog )) + */ +const gchar + *hildon_set_password_dialog_get_password(HildonSetPasswordDialog * + dialog) +{ + HildonSetPasswordDialogPrivate *priv; + + g_return_val_if_fail(HILDON_IS_SET_PASSWORD_DIALOG(dialog), NULL); + + priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(dialog); + + return GTK_ENTRY(priv->pwd1stEntry)->text; +} + +/** + * hildon_set_password_dialog_get_protected: + * @dialog: pointer to HildonSetPasswordDialog + * + * Returns the protection mode. + * + * Returns: password protection mode ( TRUE when the protection is + * 'ON' and FALSE when the protection is 'OFF' ) + */ +gboolean +hildon_set_password_dialog_get_protected(HildonSetPasswordDialog * dialog) +{ + HildonSetPasswordDialogPrivate *priv; + + g_return_val_if_fail(HILDON_IS_SET_PASSWORD_DIALOG(dialog), FALSE); + + priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(dialog); + + return priv->protection; +} + +/** + * hildon_set_password_dialog_set_domain(GtkWidget *dialog, + * @dialog: the dialog + * @domain: the domain or some other descriptive text to be set + * + * Sets the optional descriptive text. + */ + +void hildon_set_password_dialog_set_domain(HildonSetPasswordDialog *dialog, + const gchar *domain) +{ + HildonSetPasswordDialogPrivate *priv = NULL; + + g_return_if_fail(HILDON_IS_SET_PASSWORD_DIALOG(dialog)); + + priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(dialog); + gtk_label_set_text(priv->domainLabel, domain); +} diff --git a/src/hildon-set-password-dialog.h b/src/hildon-set-password-dialog.h new file mode 100644 index 0000000..3e019f6 --- /dev/null +++ b/src/hildon-set-password-dialog.h @@ -0,0 +1,102 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_SET_PASSWORD_DIALOG_H__ +#define __HILDON_SET_PASSWORD_DIALOG_H__ + +#include + +G_BEGIN_DECLS + + +#define HILDON_TYPE_SET_PASSWORD_DIALOG \ + ( hildon_set_password_dialog_get_type() ) +#define HILDON_SET_PASSWORD_DIALOG(obj) \ + (GTK_CHECK_CAST (obj, HILDON_TYPE_SET_PASSWORD_DIALOG,\ + HildonSetPasswordDialog)) +#define HILDON_SET_PASSWORD_DIALOG_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST ((klass), HILDON_TYPE_SET_PASSWORD_DIALOG, \ + HildonSetPasswordDialogClass)) +#define HILDON_IS_SET_PASSWORD_DIALOG(obj) \ + (GTK_CHECK_TYPE (obj, HILDON_TYPE_SET_PASSWORD_DIALOG)) +#define HILDON_IS_SET_PASSWORD_DIALOG_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_SET_PASSWORD_DIALOG)) + + + +#define HILDON_SET_PASSWORD_DIALOG_TITLE "ecdg_ti_set_password" +#define HILDON_SET_PASSWORD_DIALOG_PASSWORD "ecdg_fi_set_passwd_enter_pwd" +#define HILDON_SET_PASSWORD_DIALOG_VERIFY_PASSWORD "ecdg_fi_set_passwd_confirm" +#define HILDON_SET_PASSWORD_DIALOG_OK "ecdg_bd_set_password_dialog_ok" +#define HILDON_SET_PASSWORD_DIALOG_CANCEL "ecdg_bd_set_password_dialog_cancel" + +#define HILDON_SET_MODIFY_PASSWORD_DIALOG_TITLE "ckdg_ti_dialog_c_passwd_change_password" +#define HILDON_SET_MODIFY_PASSWORD_DIALOG_LABEL "ckdg_fi_dialog_c_passwd_pwd_protect" +#define HILDON_SET_MODIFY_PASSWORD_DIALOG_PASSWORD "ckdg_fi_dialog_c_passwd_new_pwd" +#define HILDON_SET_MODIFY_PASSWORD_DIALOG_VERIFY_PASSWORD "ckdg_fi_dialog_c_passwd_ver_pwd" +#define HILDON_SET_MODIFY_PASSWORD_DIALOG_OK "ckdg_bd_change_password_dialog_ok" +#define HILDON_SET_MODIFY_PASSWORD_DIALOG_CANCEL "ckdg_bd_change_password_dialog_cancel" + +#define HILDON_SET_PASSWORD_DIALOG_MISMATCH "ecdg_ib_passwords_do_not_match" +#define HILDON_SET_PASSWORD_DIALOG_EMPTY "ecdg_ib_password_is_empty" +#define HILDON_SET_PASSWORD_DIALOG_REMOVE_PROTECTION "ckdg_nc_dialog_c_passwd_remove_pwd" + +#define HILDON_REMOVE_PROTECTION_CONFIRMATION_REMOVE "ckdg_bd_dialog_c_passwd_remove_button" +#define HILDON_REMOVE_PROTECTION_CONFIRMATION_CANCEL "ckdg_bd_dialog_c_passwd_cancel_button" + + + +typedef struct _HildonSetPasswordDialog HildonSetPasswordDialog; +typedef struct _HildonSetPasswordDialogClass HildonSetPasswordDialogClass; + +struct _HildonSetPasswordDialog { + GtkDialog parent; +}; + +struct _HildonSetPasswordDialogClass { + GtkDialogClass parent_class; +}; + + + +GtkWidget * hildon_set_password_dialog_new (GtkWindow *parent, + gboolean modify_protection); + +GtkWidget * hildon_set_password_dialog_new_with_default (GtkWindow *parent, + const gchar *password, + gboolean modify_protection); + +GType hildon_set_password_dialog_get_type (void) G_GNUC_CONST; + +const gchar *hildon_set_password_dialog_get_password (HildonSetPasswordDialog *dialog); + +gboolean hildon_set_password_dialog_get_protected (HildonSetPasswordDialog *dialog); + +void hildon_set_password_dialog_set_domain (HildonSetPasswordDialog *dialog, + const gchar *domain); + + +G_END_DECLS + +#endif /* __HILDON_SET_PASSWORD_DIALOG_H__ */ diff --git a/src/hildon-sort-dialog.c b/src/hildon-sort-dialog.c new file mode 100644 index 0000000..2c28552 --- /dev/null +++ b/src/hildon-sort-dialog.c @@ -0,0 +1,495 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-sort-dialog + * @short_description: A widget for defining the sorting order of items + * + * HildonSortDialog is used to define an order (ascending/descending) + * and a field by which items are sorted in a list. The combo boxes + * display the current value when the dialog is opened. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include "hildon-sort-dialog.h" + + +#define _(String) dgettext(PACKAGE, String) + +static GtkDialogClass *parent_class; + +#define HILDON_SORT_DIALOG_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), HILDON_TYPE_SORT_DIALOG, HildonSortDialogPrivate)); + +typedef struct _HildonSortDialogPrivate HildonSortDialogPrivate; + +static void hildon_sort_dialog_class_init(HildonSortDialogClass * class); +static void hildon_sort_dialog_init(HildonSortDialog * widget); +static void hildon_sort_dialog_set_property(GObject * object, + guint prop_id, + const GValue * value, + GParamSpec * pspec); +static void hildon_sort_dialog_get_property(GObject * object, + guint prop_id, + GValue * value, GParamSpec * pspec); +static void reconstruct_combo (HildonSortDialog * dialog, + gboolean remove, + gboolean reversed); +static gint hildon_sort_dialog_add_sort_key_with_sorting(HildonSortDialog * dialog, + const gchar * sort_key, + gboolean sorting); +static void sort_key_changed(GtkWidget * widget, + HildonSortDialog * dialog); +static void hildon_sort_dialog_finalize(GObject * object); + +enum { + PROP_0, + PROP_SORT_KEY, + PROP_SORT_ORDER +}; + +/* private data */ +struct _HildonSortDialogPrivate { + /* Sort category widgets */ + GtkWidget *combo_key; + GtkWidget *caption_key; + + /* Sort order widgets */ + GtkWidget *combo_order; + GtkWidget *caption_order; + + /* Index value counter */ + gint index_counter; + + /* If the current order displayed is reversed */ + gboolean reversed; + + /* An array for each key representing if a key should be reverse-sorted */ + gboolean *key_reversed; +}; + +/* Private functions */ + +static void sort_key_changed(GtkWidget * widget, HildonSortDialog * dialog) +{ + g_return_if_fail(HILDON_IS_SORT_DIALOG(dialog)); + + HildonSortDialogPrivate *priv = HILDON_SORT_DIALOG_GET_PRIVATE(dialog); + + gint index = gtk_combo_box_get_active(GTK_COMBO_BOX(widget)); + + if (priv->key_reversed [index] != priv->reversed) { + reconstruct_combo (dialog, TRUE, priv->key_reversed [index]); + gtk_combo_box_set_active(GTK_COMBO_BOX(priv->combo_order), 0); + } + + priv->reversed = priv->key_reversed [index]; +} + +/* + * Initialises the sort dialog class. + */ +static void hildon_sort_dialog_class_init(HildonSortDialogClass * class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(class); + parent_class = g_type_class_peek_parent(class); + g_type_class_add_private(class, sizeof(HildonSortDialogPrivate)); + + gobject_class->set_property = hildon_sort_dialog_set_property; + gobject_class->get_property = hildon_sort_dialog_get_property; + gobject_class->finalize = (gpointer) hildon_sort_dialog_finalize; + + g_object_class_install_property(gobject_class, PROP_SORT_KEY, + g_param_spec_int("sort-key", + "Sort Key", + "The currently active sort key", + G_MININT, + G_MAXINT, + 0, G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, PROP_SORT_ORDER, + g_param_spec_enum("sort-order", + "Sort Order", + "The current sorting order", + GTK_TYPE_SORT_TYPE, + GTK_SORT_ASCENDING, + G_PARAM_READWRITE)); +} + +static gint hildon_sort_dialog_add_sort_key_with_sorting(HildonSortDialog * dialog, const gchar * sort_key, gboolean sorting) +{ + HildonSortDialogPrivate *priv; + + g_return_val_if_fail(HILDON_IS_SORT_DIALOG(dialog), -1); + + priv = HILDON_SORT_DIALOG_GET_PRIVATE(dialog); + gboolean *new_array = g_malloc (sizeof (gboolean) * (priv->index_counter + 1)); + + /* Rewrite the old values */ + int i = 0; + for (i = 0; i < priv->index_counter; i++) + new_array [i] = priv->key_reversed [i]; + + new_array [priv->index_counter] = sorting; + gtk_combo_box_append_text(GTK_COMBO_BOX(priv->combo_key), sort_key); + + /* Free the old one and reassign */ + if (priv->key_reversed != NULL) + g_free (priv->key_reversed); + priv->key_reversed = new_array; + + return priv->index_counter++; +} + +static void reconstruct_combo (HildonSortDialog * dialog, gboolean remove, gboolean reversed) +{ + HildonSortDialogPrivate *priv; + priv = HILDON_SORT_DIALOG_GET_PRIVATE(dialog); + + if (remove) { + gtk_combo_box_remove_text(GTK_COMBO_BOX(priv->combo_order), 1); + gtk_combo_box_remove_text(GTK_COMBO_BOX(priv->combo_order), 0); + } + + if (reversed) { + gtk_combo_box_append_text(GTK_COMBO_BOX(priv->combo_order), _("ckdg_va_sort_descending")); + gtk_combo_box_append_text(GTK_COMBO_BOX(priv->combo_order), _("ckdg_va_sort_ascending")); + } else { + gtk_combo_box_append_text(GTK_COMBO_BOX(priv->combo_order), _("ckdg_va_sort_ascending")); + gtk_combo_box_append_text(GTK_COMBO_BOX(priv->combo_order), _("ckdg_va_sort_descending")); + } +} + +static void hildon_sort_dialog_init(HildonSortDialog * dialog) +{ + HildonSortDialogPrivate *priv; + GtkSizeGroup *group; + + g_assert(HILDON_IS_SORT_DIALOG(dialog)); + + priv = HILDON_SORT_DIALOG_GET_PRIVATE(dialog); + + priv->index_counter = 0; + priv->reversed = FALSE; + priv->key_reversed = NULL; + + group = GTK_SIZE_GROUP(gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL)); + + gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); + gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); + gtk_window_set_title(GTK_WINDOW(dialog), _("ckdg_ti_sort")); + + /* Tab one */ + priv->combo_key = gtk_combo_box_new_text(); + priv->caption_key = hildon_caption_new(group, _("ckdg_fi_sort_field"), priv->combo_key, + NULL, HILDON_CAPTION_OPTIONAL); + hildon_caption_set_separator(HILDON_CAPTION(priv->caption_key), ""); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), + priv->caption_key, FALSE, FALSE, 0); + + /* Tab two */ + priv->combo_order = gtk_combo_box_new_text(); + reconstruct_combo (dialog, FALSE, FALSE); + + priv->caption_order = hildon_caption_new(group, _("ckdg_fi_sort_order"), + priv->combo_order, + NULL, HILDON_CAPTION_OPTIONAL); + hildon_caption_set_separator(HILDON_CAPTION(priv->caption_order), ""); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), + priv->caption_order, FALSE, FALSE, 0); + + gtk_combo_box_set_active(GTK_COMBO_BOX(priv->combo_key), 0); + gtk_combo_box_set_active(GTK_COMBO_BOX(priv->combo_order), 0); + g_signal_connect (G_OBJECT (priv->combo_key), "changed", (gpointer) sort_key_changed, dialog); + + /* Create the OK/CANCEL buttons */ + (void) gtk_dialog_add_button(GTK_DIALOG(dialog), + _("ckdg_bd_sort_dialog_ok"), + GTK_RESPONSE_OK); + (void) gtk_dialog_add_button(GTK_DIALOG(dialog), + _("ckdg_bd_sort_dialog_cancel"), + GTK_RESPONSE_CANCEL); + /* FIXME: Hardcoded sizes are bad */ + gtk_window_resize(GTK_WINDOW(dialog), 370, 100); + gtk_widget_show_all(GTK_DIALOG(dialog)->vbox); + + g_object_unref(group); /* Captions now own their references to sizegroup */ +} + +/* Public functions */ + +/** + * hildon_sort_dialog_get_type: + * + * Returns GType for HildonSortDialog as produced by + * g_type_register_static(). + * + * Returns: HildonSortDialog type + */ +GType hildon_sort_dialog_get_type() +{ + static GType dialog_type = 0; + + if (!dialog_type) { + static const GTypeInfo dialog_info = { + sizeof(HildonSortDialogClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_sort_dialog_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonSortDialog), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_sort_dialog_init + }; + + dialog_type = g_type_register_static(GTK_TYPE_DIALOG, + "HildonSortDialog", + &dialog_info, 0); + } + return dialog_type; +} + +/** + * hildon_sort_dialog_new: + * @parent: widget to be transient for, or NULL if none + * + * HildonSortDialog contains two HildonCaptions with combo boxes. + * + * Returns: pointer to a new @HildonSortDialog widget + */ +GtkWidget *hildon_sort_dialog_new(GtkWindow * parent) +{ + GtkWidget *sort_dialog = g_object_new(HILDON_TYPE_SORT_DIALOG, NULL); + + if (parent) + gtk_window_set_transient_for(GTK_WINDOW(sort_dialog), parent); + + return sort_dialog; +} + +/** + * hildon_sort_dialog_get_sort_key: + * @dialog: the #HildonSortDialog widget + * + * Gets index to currently active sort key. + * + * Returns: an integer which is the index value of the "Sort by" + * field + */ +gint hildon_sort_dialog_get_sort_key(HildonSortDialog * dialog) +{ + GtkWidget *combo_key; + HildonSortDialogPrivate *priv; + + g_return_val_if_fail(HILDON_IS_SORT_DIALOG(dialog), -1); + + priv = HILDON_SORT_DIALOG_GET_PRIVATE(dialog); + + combo_key = gtk_bin_get_child(GTK_BIN(priv->caption_key)); + + return gtk_combo_box_get_active(GTK_COMBO_BOX(combo_key)); +} + +/** + * hildon_sort_dialog_get_sort_order: + * @dialog: the #HildonSortDialog widget + * + * Gets current sorting order from "Sort order" field. + * + * Returns: current sorting order as #GtkSortType + */ +GtkSortType hildon_sort_dialog_get_sort_order(HildonSortDialog * dialog) +{ + GtkWidget *combo_order; + HildonSortDialogPrivate *priv; + + g_return_val_if_fail(HILDON_IS_SORT_DIALOG(dialog), 0); + + priv = HILDON_SORT_DIALOG_GET_PRIVATE(dialog); + combo_order = gtk_bin_get_child(GTK_BIN(priv->caption_order)); + + gint sort_order = gtk_combo_box_get_active(GTK_COMBO_BOX(combo_order)); + + if (priv->reversed) + return (sort_order == 0) ? 1 : 0; + else + return sort_order; +} + +/** + * hildon_sort_dialog_set_sort_key: + * @dialog: the #HildonSortDialog widget + * @key: combo box's index value + * + * Sets the index value of the #HildonSortDialog widget. + */ +void hildon_sort_dialog_set_sort_key(HildonSortDialog * dialog, gint key) +{ + GtkWidget *combo_key; + HildonSortDialogPrivate *priv; + + g_return_if_fail(HILDON_IS_SORT_DIALOG(dialog)); + + priv = HILDON_SORT_DIALOG_GET_PRIVATE(dialog); + combo_key = gtk_bin_get_child(GTK_BIN(priv->caption_key)); + gtk_combo_box_set_active(GTK_COMBO_BOX(combo_key), key); + + g_object_notify (G_OBJECT (dialog), "sort-key"); +} + +/** + * hildon_sort_dialog_set_sort_order: + * @dialog: the #HildonSortDialog widget + * @order: combo box's index value + * + * Sets the index value of the #HildonSortDialog widget. + */ +void +hildon_sort_dialog_set_sort_order(HildonSortDialog * dialog, + GtkSortType order) +{ + GtkWidget *combo_order; + HildonSortDialogPrivate *priv; + + g_return_if_fail(HILDON_IS_SORT_DIALOG(dialog)); + + priv = HILDON_SORT_DIALOG_GET_PRIVATE(dialog); + combo_order = gtk_bin_get_child(GTK_BIN(priv->caption_order)); + + if (priv->reversed) + order = (order == 0) ? 1 : 0; + + gtk_combo_box_set_active(GTK_COMBO_BOX(combo_order), order); + + g_object_notify (G_OBJECT (dialog), "sort-order"); +} + +/** + * hildon_sort_dialog_add_sort_key: + * @dialog: the #HildonSortDialog widget + * @sort_key: combo box's index value + * + * Adds a new sort key and returns the respective index in + * sort key combobox. + * + * Returns: an integer which is the index of the added combo box's + * item + */ +gint +hildon_sort_dialog_add_sort_key(HildonSortDialog * dialog, + const gchar * sort_key) +{ + return hildon_sort_dialog_add_sort_key_with_sorting (dialog, sort_key, FALSE); +} + +/** + * hildon_sort_dialog_add_sort_key_reversed: + * @dialog: the #HildonSortDialog widget + * @sort_key: combo box's index value + * + * Adds a new sort key and returns the respective index in + * sort key combobox. The default sort order for this key is reversed (Descending first). + * + * Returns: an integer which is the index of the added combo box's + * item + * + * Since: 0.14.1 + */ +gint +hildon_sort_dialog_add_sort_key_reversed(HildonSortDialog * dialog, + const gchar * sort_key) +{ + return hildon_sort_dialog_add_sort_key_with_sorting (dialog, sort_key, TRUE); +} + +static void +hildon_sort_dialog_set_property(GObject * object, + guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + HildonSortDialog *dialog; + + dialog = HILDON_SORT_DIALOG(object); + + switch (prop_id) { + case PROP_SORT_KEY: + hildon_sort_dialog_set_sort_key(dialog, g_value_get_int(value)); + break; + case PROP_SORT_ORDER: + hildon_sort_dialog_set_sort_order(dialog, g_value_get_enum(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +hildon_sort_dialog_get_property(GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + HildonSortDialog *dialog; + + dialog = HILDON_SORT_DIALOG(object); + + switch (prop_id) { + case PROP_SORT_KEY: + g_value_set_int(value, hildon_sort_dialog_get_sort_key(dialog)); + break; + case PROP_SORT_ORDER: + g_value_set_enum(value, hildon_sort_dialog_get_sort_order(dialog)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +hildon_sort_dialog_finalize(GObject * object) +{ + HildonSortDialogPrivate *priv; + HildonSortDialog *dialog; + + g_return_if_fail (HILDON_IS_SORT_DIALOG (object)); + dialog = HILDON_SORT_DIALOG(object); + + priv = HILDON_SORT_DIALOG_GET_PRIVATE(dialog); + if (priv != NULL && priv->key_reversed != NULL) + g_free(priv->key_reversed); + + if (G_OBJECT_CLASS(parent_class)->finalize) + G_OBJECT_CLASS(parent_class)->finalize(object); +} + + diff --git a/src/hildon-sort-dialog.h b/src/hildon-sort-dialog.h new file mode 100644 index 0000000..5ef6bcf --- /dev/null +++ b/src/hildon-sort-dialog.h @@ -0,0 +1,68 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_SORT_DIALOG_H__ +#define __HILDON_SORT_DIALOG_H__ + +#include + +G_BEGIN_DECLS +#define HILDON_TYPE_SORT_DIALOG \ + ( hildon_sort_dialog_get_type() ) +#define HILDON_SORT_DIALOG(obj) \ + (GTK_CHECK_CAST (obj, HILDON_TYPE_SORT_DIALOG, HildonSortDialog)) +#define HILDON_SORT_DIALOG_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST ((klass), HILDON_TYPE_SORT_DIALOG, \ + HildonSortDialogClass)) +#define HILDON_IS_SORT_DIALOG(obj) \ + (GTK_CHECK_TYPE (obj, HILDON_TYPE_SORT_DIALOG)) +#define HILDON_IS_SORT_DIALOG_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_SORT_DIALOG)) +typedef struct _HildonSortDialog HildonSortDialog; +typedef struct _HildonSortDialogClass HildonSortDialogClass; + + + +struct _HildonSortDialog { + GtkDialog parent; +}; + +struct _HildonSortDialogClass { + GtkDialogClass parent_class; +}; + +GType hildon_sort_dialog_get_type(void) G_GNUC_CONST; + + +GtkWidget *hildon_sort_dialog_new(GtkWindow * parent); +gint hildon_sort_dialog_get_sort_key(HildonSortDialog * dialog); +GtkSortType hildon_sort_dialog_get_sort_order(HildonSortDialog * dialog); +void hildon_sort_dialog_set_sort_key(HildonSortDialog * dialog, gint key); +void hildon_sort_dialog_set_sort_order(HildonSortDialog * dialog, + GtkSortType order); +gint hildon_sort_dialog_add_sort_key(HildonSortDialog * dialog, + const gchar * sort_key); + +G_END_DECLS +#endif /* __HILDON_SORT_DIALOG_H__ */ diff --git a/src/hildon-system-sound.c b/src/hildon-system-sound.c new file mode 100644 index 0000000..38d29fd --- /dev/null +++ b/src/hildon-system-sound.c @@ -0,0 +1,93 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-system-sound + * @short_description: An esd-based utility function for playing a sound + * + * HildonSystemSound is an esd-based utility function for playing a sound + * from the system sounds directory with volume taken from GConf. + */ + +#include +#include +#include "hildon-system-sound.h" + +#define ALARM_GCONF_PATH "/apps/osso/sound/system_alert_volume" + +/** + * hildon_play_system_sound: + * @sample: sound file to play + * + * Plays the given sample using esd sound daemon. + * Volume level is received from gconf. + */ +void hildon_play_system_sound(const gchar *sample) +{ + GConfClient *client; + GConfValue *value; + gint volume, scale, sock, sample_id; + + client = gconf_client_get_default(); + value = gconf_client_get(client, ALARM_GCONF_PATH, NULL); + + /* We want error cases to match full volume, not silence, so + we do not want to use gconf_client_get_int */ + if (!value || value->type != GCONF_VALUE_INT) + volume = 2; + else + volume = gconf_value_get_int(value); + + if (value) + gconf_value_free(value); + g_object_unref(client); + + switch (volume) + { + case 0: + return; + case 1: + scale = 0x80; + break; + case 2: + default: + scale = 0xff; + break; + }; + + sock = esd_open_sound(NULL); + if (sock <= 0) + return; + + sample_id = esd_file_cache(sock, g_get_prgname(), sample); + if (sample_id < 0) { + close(sock); + return; + } + + esd_set_default_sample_pan(sock, sample_id, scale, scale); + esd_sample_play(sock, sample_id); + esd_sample_free(sock, sample_id); + close(sock); +} diff --git a/src/hildon-system-sound.h b/src/hildon-system-sound.h new file mode 100644 index 0000000..666a8bb --- /dev/null +++ b/src/hildon-system-sound.h @@ -0,0 +1,32 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ +#ifndef __HILDON_SYSTEM_SOUND_H__ +#define __HILDON_SYSTEM_SOUND_H__ + +G_BEGIN_DECLS + +void hildon_play_system_sound(const gchar *sample); + +G_END_DECLS +#endif /* __HILDON_SYSTEM_SOUND_H__ */ diff --git a/src/hildon-telephone-editor.c b/src/hildon-telephone-editor.c new file mode 100644 index 0000000..a18acad --- /dev/null +++ b/src/hildon-telephone-editor.c @@ -0,0 +1,1436 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-telephone-editor.c + * @short_description: A widget which allows users to enter telephone numbers + * + * A single-line editor which allows user to enter a telephone number. + * There are two modes to choose from (coerce/free format). + * Coerce format has three fields which are placed horizontally. + * The fields are: country code, area code and number. When nothing is + * entered in the fields, assisting text is displayed. Tapping on the + * field highlights the field and allows users to input numbers. + * + * The widget is used where a user should enter a phone number. Free format + * should be used wherever possible as it enables the user to enter the + * phone number in the format she likes. Free format also supports DTMF + * strings as a part of the phone number. The format can not be changed + * at runtime. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include "hildon-telephone-editor.h" +#include "hildon-composite-widget.h" + +#define _(String) gettext (String) +#define HILDON_TELEPHONE_EDITOR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TELEPHONE_EDITOR_TYPE, HildonTelephoneEditorPriv)); + +#define AREA_LEN 4 +#define COUNTRY_LEN 7 +#define NUMBER_LEN 10 + +#define AREA_STR "Area" +#define COUNTRY_STR "Country" +#define NUMBER_STR "Number" + +typedef struct _HildonTelephoneEditorPriv HildonTelephoneEditorPriv; + +enum { + PROP_0, + PROP_COUNTRY_STR, + PROP_AREA_STR, + PROP_NUMBER_STR, + PROP_SHOW_BORDER, + PROP_SHOW_PLUS, + PROP_FORMAT +}; + +/*< private >*/ +struct _HildonTelephoneEditorPriv { + HildonTelephoneEditorFormat format; /* format of the editor */ + + gboolean edited_country; /* is the country edited */ + gboolean edited_area; /* is the area edited */ + gboolean edited_number; /* is the number edited */ + + gboolean editable_country; /* is the country editable */ + gboolean editable_area; /* is the area editable */ + gboolean editable_number; /* is the number editable */ + + gboolean show_plus; /* show '+' sign in country */ + gboolean show_border; /* show border around the widget */ + + GtkWidget *frame; /* frame for border lines */ + GtkWidget *plus; /* + in front of country code */ + GtkWidget *plus_event; /* event box for the + -label */ + GtkWidget *country; /* country code */ + GtkWidget *area; /* area code */ + GtkWidget *number; /* telephone number */ + + gint j; +}; + + +static GtkContainerClass *parent_class; + +static void +hildon_telephone_editor_class_init(HildonTelephoneEditorClass * + editor_class); + +static void +hildon_telephone_editor_init(HildonTelephoneEditor * editor); + +static void +hildon_telephone_editor_forall(GtkContainer * container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data); +static void +hildon_telephone_editor_destroy(GtkObject * self); + +static void +hildon_telephone_editor_size_allocate(GtkWidget * widget, + GtkAllocation * allocation); + +static void +hildon_telephone_editor_size_request(GtkWidget * widget, + GtkRequisition * requisition); + +static gboolean +hildon_telephone_editor_button_release(GtkWidget * widget, + GdkEventButton * event, + gpointer data); +static void +hildon_telephone_editor_focus_dest_entry(GtkWidget * widget, + gboolean edited, + gboolean move_left); +static gboolean +hildon_telephone_editor_entry_keypress(GtkWidget * widget, + GdkEventKey * event, gpointer data); + +static gboolean +hildon_telephone_editor_mnemonic_activate( GtkWidget *widget, + gboolean group_cycling); + +static void +hildon_telephone_editor_set_property(GObject * object, + guint prop_id, + const GValue * value, + GParamSpec * pspec); +static void +hildon_telephone_editor_get_property(GObject * object, + guint prop_id, + GValue * value, GParamSpec * pspec); + +GType hildon_telephone_editor_get_type(void) +{ + static GType editor_type = 0; + + if (!editor_type) { + static const GTypeInfo editor_info = { + sizeof(HildonTelephoneEditorClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_telephone_editor_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonTelephoneEditor), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_telephone_editor_init, + }; + editor_type = g_type_register_static(GTK_TYPE_CONTAINER, + "HildonTelephoneEditor", + &editor_info, 0); + } + return editor_type; +} + +static void +hildon_telephone_editor_class_init(HildonTelephoneEditorClass * + editor_class) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(editor_class); + GtkContainerClass *container_class = GTK_CONTAINER_CLASS(editor_class); + GObjectClass *object_class = G_OBJECT_CLASS(editor_class); + + parent_class = g_type_class_peek_parent(editor_class); + + g_type_class_add_private(editor_class, sizeof(HildonTelephoneEditorPriv)); + + widget_class->size_request = hildon_telephone_editor_size_request; + widget_class->size_allocate = hildon_telephone_editor_size_allocate; + container_class->forall = hildon_telephone_editor_forall; + widget_class->mnemonic_activate = hildon_telephone_editor_mnemonic_activate; + widget_class->focus = hildon_composite_widget_focus; + object_class->set_property = hildon_telephone_editor_set_property; + object_class->get_property = hildon_telephone_editor_get_property; + + GTK_OBJECT_CLASS(editor_class)->destroy = hildon_telephone_editor_destroy; + + /* Install properties */ + g_object_class_install_property(object_class, PROP_COUNTRY_STR, + g_param_spec_string("country", + ("Country string"), + ("Country string"), + COUNTRY_STR, G_PARAM_READWRITE)); + + g_object_class_install_property(object_class, PROP_AREA_STR, + g_param_spec_string("area", + ("Area string"), + ("Area string"), + AREA_STR, G_PARAM_READWRITE)); + + g_object_class_install_property(object_class, PROP_NUMBER_STR, + g_param_spec_string("number", + ("Number string"), + ("Number string"), + NUMBER_STR, G_PARAM_READWRITE)); + + g_object_class_install_property(object_class, PROP_SHOW_BORDER, + g_param_spec_boolean ("show-border", + "Show Border", + "Wether to show the border around the widget", + TRUE, G_PARAM_READWRITE)); + + g_object_class_install_property(object_class, PROP_SHOW_PLUS, + g_param_spec_boolean ("show-plus", + "Show Plus", + "Wether to show the plus sign in front of" + " coerce format's country field", + TRUE, G_PARAM_READWRITE)); + + g_object_class_install_property(object_class, PROP_FORMAT, + g_param_spec_int("set-format", + ("Format"), + ("Sets telephoneditor format"), + HILDON_TELEPHONE_EDITOR_FORMAT_FREE, + HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA, + 0, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); +} + +static void +hildon_telephone_editor_init(HildonTelephoneEditor * editor) +{ + HildonTelephoneEditorPriv *priv; + gboolean use_frames = FALSE; /* in entries, for debug purposes */ + + priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); + + priv->frame = gtk_frame_new(NULL); + priv->plus = gtk_label_new("+"); + priv->plus_event = gtk_event_box_new(); + priv->country = gtk_entry_new(); + priv->area = gtk_entry_new(); + priv->number = gtk_entry_new(); + priv->edited_country = FALSE; + priv->edited_area = FALSE; + priv->edited_number = FALSE; + priv->show_plus = TRUE; + priv->show_border = TRUE; + priv->editable_country = TRUE; + priv->editable_area = TRUE; + priv->editable_number = TRUE; + + gtk_container_add(GTK_CONTAINER(priv->plus_event), priv->plus); + + gtk_entry_set_has_frame(GTK_ENTRY(priv->country), use_frames); + gtk_entry_set_has_frame(GTK_ENTRY(priv->area), use_frames); + gtk_entry_set_has_frame(GTK_ENTRY(priv->number), use_frames); + + gtk_widget_set_parent(priv->frame, GTK_WIDGET(editor)); + gtk_widget_set_parent(priv->plus_event, GTK_WIDGET(editor)); + + hildon_telephone_editor_set_widths(editor, COUNTRY_LEN, AREA_LEN, + NUMBER_LEN); + + /* set signals for country entry */ + gtk_signal_connect(GTK_OBJECT(priv->country), "button_release_event", + G_CALLBACK(hildon_telephone_editor_button_release), + editor); + + gtk_signal_connect(GTK_OBJECT(priv->country), "key-press-event", + G_CALLBACK(hildon_telephone_editor_entry_keypress), + editor); + + /* set signals for plus label */ + gtk_signal_connect(GTK_OBJECT(priv->plus_event), "button_press_event", + G_CALLBACK(hildon_telephone_editor_button_release), + editor); + + /* set signals for area entry */ + gtk_signal_connect(GTK_OBJECT(priv->area), "button_release_event", + G_CALLBACK(hildon_telephone_editor_button_release), + editor); + + gtk_signal_connect(GTK_OBJECT(priv->area), "key-press-event", + G_CALLBACK(hildon_telephone_editor_entry_keypress), + editor); + + /* set signals for number entry */ + gtk_signal_connect(GTK_OBJECT(priv->number), "button_release_event", + G_CALLBACK(hildon_telephone_editor_button_release), + editor); + + gtk_signal_connect(GTK_OBJECT(priv->number), "key-press-event", + G_CALLBACK(hildon_telephone_editor_entry_keypress), + editor); + + GTK_WIDGET_SET_FLAGS(editor, GTK_NO_WINDOW); + + gtk_widget_show(priv->number); + gtk_widget_show(priv->area); + gtk_widget_show(priv->country); + gtk_widget_show_all(priv->frame); + gtk_widget_show_all(priv->plus_event); +} + +/** + * hildon_telephone_editor_new: + * @format: format of the editor + * + * Creates a new #HildonTelephoneEditor. The editor can be in a free + * format where the user can type in country code, area code and the + * phone number and can type in other characters than just digits. In + * coerse format the editor has fields where the user can input only + * digits. See #HildonTelephoneEditorFormat for the different coerse + * formats. + * + * Returns: new #HildonTelephoneEditor + */ +GtkWidget * +hildon_telephone_editor_new(HildonTelephoneEditorFormat format) +{ + + HildonTelephoneEditor *editor; + + editor = + g_object_new(HILDON_TELEPHONE_EDITOR_TYPE, "set-format", format, + "set-country", _(COUNTRY_STR), "set-area", + _(AREA_STR), "set-number", _(NUMBER_STR), NULL); + + return GTK_WIDGET(editor); +} + +/** + * hildon_telephone_editor_new_with_strings: + * @format: format of the editor + * @country: default text for the country field + * @area: default text for the area field + * @number: default text for the number field + * + * Creates a new #HildonTelephoneEditor. See hildon_telephone_editor_new + * for details. + * + * Returns: new #HildonTelephoneEditor + */ +GtkWidget * +hildon_telephone_editor_new_with_strings(HildonTelephoneEditorFormat + format, + const gchar * country, + const gchar * area, + const gchar * number) +{ + HildonTelephoneEditor *editor; + + editor = + g_object_new(HILDON_TELEPHONE_EDITOR_TYPE, "set-format", format, + "set-country", country, "set-area", area, + "set-number", number, NULL); + + return GTK_WIDGET(editor); +} + +static void +hildon_telephone_editor_get_property(GObject * object, + guint prop_id, + GValue * value, + GParamSpec * pspec) +{ + HildonTelephoneEditor *editor; + HildonTelephoneEditorPriv *priv; + + editor = HILDON_TELEPHONE_EDITOR (object); + priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_COUNTRY_STR: + g_value_set_string(value, + hildon_telephone_editor_get_country(editor)); + break; + case PROP_AREA_STR: + g_value_set_string(value, + hildon_telephone_editor_get_area(editor)); + break; + case PROP_NUMBER_STR: + g_value_set_string(value, + hildon_telephone_editor_get_number(editor)); + break; + case PROP_SHOW_BORDER: + g_value_set_boolean(value, + hildon_telephone_editor_get_show_border(editor)); + break; + case PROP_SHOW_PLUS: + g_value_set_boolean(value, + hildon_telephone_editor_get_show_plus(editor)); + break; + case PROP_FORMAT: + g_value_set_int(value, priv->format); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +hildon_telephone_editor_set_property(GObject * object, + guint prop_id, + const GValue * value, + GParamSpec * pspec) +{ + HildonTelephoneEditor *editor; + HildonTelephoneEditorPriv *priv; + + editor = HILDON_TELEPHONE_EDITOR (object); + priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_COUNTRY_STR: + hildon_telephone_editor_set_country(editor, + _(g_value_get_string(value))); + break; + case PROP_AREA_STR: + hildon_telephone_editor_set_area(editor, + _(g_value_get_string(value))); + break; + case PROP_NUMBER_STR: + hildon_telephone_editor_set_number(editor, + _(g_value_get_string(value))); + break; + case PROP_SHOW_BORDER: + hildon_telephone_editor_set_show_border( + editor, g_value_get_boolean(value)); + break; + case PROP_SHOW_PLUS: + hildon_telephone_editor_set_show_plus( + editor, g_value_get_boolean(value)); + break; + case PROP_FORMAT: + priv->format = g_value_get_int(value); + if (priv->format != HILDON_TELEPHONE_EDITOR_FORMAT_FREE) + gtk_entry_set_text(GTK_ENTRY(priv->number), _(NUMBER_STR)); + + /* set proper fields according to selected format */ + switch (priv->format) { + case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE: + gtk_widget_set_parent(priv->number, GTK_WIDGET(object)); + case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA: + gtk_widget_set_parent(priv->area, GTK_WIDGET(object)); + case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY: + gtk_widget_set_parent(priv->country, GTK_WIDGET(object)); + break; + case HILDON_TELEPHONE_EDITOR_FORMAT_FREE: + gtk_widget_set_parent(priv->number, GTK_WIDGET(object)); + break; + default: + g_assert_not_reached(); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static gboolean +hildon_telephone_editor_mnemonic_activate( GtkWidget *widget, + gboolean group_cycling) +{ + HildonTelephoneEditorPriv *priv; + priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(widget); + + if (!GTK_CONTAINER(widget)->focus_child) + { + if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE) + { + gtk_widget_grab_focus(priv->number); + + if (priv->editable_number && !priv->edited_number) + gtk_editable_select_region(GTK_EDITABLE(priv->number), 0, -1); + } + else + { + if (priv->editable_country) + { + gtk_widget_grab_focus(priv->country); + if (!priv->edited_country) + gtk_editable_select_region(GTK_EDITABLE(priv->country), 0, -1); + } + else if ((priv->editable_area) && (priv->format != + HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY)) + { + gtk_widget_grab_focus(priv->area); + if (!priv->edited_area) + gtk_editable_select_region(GTK_EDITABLE(priv->area), 0, -1); + } + else if ((priv->editable_number) && (priv->format == + HILDON_TELEPHONE_EDITOR_FORMAT_COERCE)) + { + gtk_widget_grab_focus(priv->number); + if (!priv->edited_number) + gtk_editable_select_region(GTK_EDITABLE(priv->number), 0, -1); + } + else + gtk_widget_grab_focus(priv->country); + } + } + return TRUE; +} + +static void +hildon_telephone_editor_forall(GtkContainer * container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) +{ + HildonTelephoneEditor *editor; + HildonTelephoneEditorPriv *priv; + + editor = HILDON_TELEPHONE_EDITOR(container); + priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); + + g_return_if_fail(container); + g_return_if_fail(callback); + + if (!include_internals) + return; + + switch (priv->format) { + case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE: + (*callback) (priv->number, callback_data); + case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA: + (*callback) (priv->area, callback_data); + case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY: + (*callback) (priv->country, callback_data); + break; + case HILDON_TELEPHONE_EDITOR_FORMAT_FREE: + (*callback) (priv->number, callback_data); + break; + default: + g_return_if_reached(); + } + + if (priv->show_plus) + (*callback) (priv->plus_event, callback_data); + + if (priv->show_border) + (*callback) (priv->frame, callback_data); + +} + +static void +hildon_telephone_editor_destroy(GtkObject * self) +{ + HildonTelephoneEditorPriv *priv; + + priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(self); + + switch (priv->format) { + case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE: + if (priv->number) { + gtk_widget_unparent(priv->number); + priv->number = NULL; + } + case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA: + if (priv->area) { + gtk_widget_unparent(priv->area); + priv->area = NULL; + } + case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY: + if (priv->country) { + gtk_widget_unparent(priv->country); + priv->country = NULL; + } + break; + case HILDON_TELEPHONE_EDITOR_FORMAT_FREE: + if (priv->number) { + gtk_widget_unparent(priv->number); + priv->number = NULL; + } + break; + default: + g_return_if_reached(); + } + + if (priv->plus_event) { + gtk_widget_unparent(priv->plus_event); + priv->plus_event = NULL; + } + if (priv->frame) { + gtk_widget_unparent(priv->frame); + priv->frame = NULL; + } + if (GTK_OBJECT_CLASS(parent_class)->destroy) + GTK_OBJECT_CLASS(parent_class)->destroy(self); +} + +static void +hildon_telephone_editor_size_request(GtkWidget *widget, + GtkRequisition *requisition) +{ + HildonTelephoneEditor *editor; + HildonTelephoneEditorPriv *priv; + GtkRequisition req; + + g_return_if_fail(requisition); + + editor = HILDON_TELEPHONE_EDITOR(widget); + priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); + + if (priv->show_border) + gtk_widget_size_request(priv->frame, requisition); + + requisition->width = 0; + requisition->height = 0; + + switch (priv->format) + { + case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE: + gtk_widget_size_request(priv->number, &req); + requisition->width += req.width; + if (requisition->height < req.height) + requisition->height = req.height; + + case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA: + gtk_widget_size_request(priv->area, &req); + requisition->width += req.width; + if (requisition->height < req.height) + requisition->height = req.height; + + case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY: + gtk_widget_size_request(priv->country, &req); + requisition->width += req.width; + if (requisition->height < req.height) + requisition->height = req.height; + + break; + case HILDON_TELEPHONE_EDITOR_FORMAT_FREE: + gtk_widget_size_request(priv->number, &req); + requisition->width += req.width; + if (requisition->height < req.height) + requisition->height = req.height; + + break; + default: + g_return_if_reached(); + } + + if (priv->show_plus) + { + gtk_widget_size_request(priv->plus_event, &req); + requisition->width += req.width; + if (requisition->height < req.height) + requisition->height = req.height; + } + + requisition->width += GTK_CONTAINER(priv->frame)->border_width * 2; + requisition->height += GTK_CONTAINER(priv->frame)->border_width * 2; +} + +static void +hildon_telephone_editor_size_allocate(GtkWidget *widget, + GtkAllocation *allocation) +{ + HildonTelephoneEditor *editor; + HildonTelephoneEditorPriv *priv; + gint header_x = 6, frame_w = 12; + GtkAllocation alloc, country_alloc, area_alloc, number_alloc; + GtkRequisition requisition, country_requisition, area_requisition, + number_requisition; + + g_return_if_fail(widget); + g_return_if_fail(allocation); + + if (allocation->height < 0 ) + allocation->height = 0; + + widget->allocation = *allocation; + + header_x += allocation->x; + editor = HILDON_TELEPHONE_EDITOR(widget); + priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); + + + if (priv->show_plus && + priv->format != HILDON_TELEPHONE_EDITOR_FORMAT_FREE) { + gtk_widget_get_child_requisition(priv->plus_event, &requisition); + + alloc.x = header_x; + alloc.y = allocation->y + 1; + alloc.width = requisition.width; + alloc.height = requisition.height; + + header_x += alloc.width; + gtk_widget_size_allocate(priv->plus_event, &alloc); + frame_w += alloc.width; + } + + gtk_widget_get_child_requisition(priv->number, &number_requisition); + + number_alloc.width = number_requisition.width; + + number_alloc.height = allocation->height - 4 - + GTK_CONTAINER(priv->frame)->border_width * 2; + + /* get sizes */ + switch (priv->format) { + case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE: + case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA: + gtk_widget_get_child_requisition(priv->area, &area_requisition); + + area_alloc.width = area_requisition.width; + area_alloc.height = number_alloc.height; + case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY: + gtk_widget_get_child_requisition(priv->country, &country_requisition); + + country_alloc.width = country_requisition.width; + country_alloc.height = number_alloc.height; + break; + case HILDON_TELEPHONE_EDITOR_FORMAT_FREE: + break; + default: + g_return_if_reached(); + } + + + /* allocate in coerce formats */ + switch (priv->format) { + case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE: + number_alloc.x = header_x + country_alloc.width + area_alloc.width; + number_alloc.y = allocation->y + 1; + + gtk_widget_size_allocate(priv->number, &number_alloc); + frame_w += number_alloc.width; + case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA: + area_alloc.x = header_x + country_alloc.width; + area_alloc.y = allocation->y + 1; + + gtk_widget_size_allocate(priv->area, &area_alloc); + frame_w += area_alloc.width; + case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY: + country_alloc.x = header_x; + country_alloc.y = allocation->y + 1; + + gtk_widget_size_allocate(priv->country, &country_alloc); + frame_w += country_alloc.width; + break; + case HILDON_TELEPHONE_EDITOR_FORMAT_FREE: + number_alloc.x = header_x; + number_alloc.y = allocation->y + 1; + + gtk_widget_size_allocate(priv->number, &number_alloc); + frame_w += number_alloc.width; + break; + default: + g_return_if_reached(); + } + + if (priv->show_border) + { + alloc.x = allocation->x; + alloc.y = allocation->y; + + alloc.width = frame_w - 4; + + alloc.height = allocation->height; + gtk_widget_size_allocate( GTK_WIDGET(priv->frame), &alloc ); + } +} + +static gboolean +hildon_telephone_editor_button_release(GtkWidget * widget, + GdkEventButton * event, gpointer data) +{ + gtk_editable_select_region(GTK_EDITABLE(widget), 0, -1); + return FALSE; +} + +static void +hildon_telephone_editor_focus_dest_entry(GtkWidget * widget, + gboolean edited, + gboolean move_left) +{ + /* full coerse mode, wrap to field */ + gtk_widget_grab_focus(widget); + + if (move_left) + gtk_editable_set_position(GTK_EDITABLE(widget), -1); + else + gtk_editable_set_position(GTK_EDITABLE(widget), 0); + /* new field not yet edited, select all */ + if (!edited) + gtk_editable_select_region(GTK_EDITABLE(widget), 0, -1); +} + +static gboolean +hildon_telephone_editor_entry_keypress(GtkWidget * widget, + GdkEventKey * event, gpointer data) +{ + HildonTelephoneEditor *editor; + HildonTelephoneEditorPriv *priv; + gint pos, width; + gint cpos, start, end; + + g_return_val_if_fail(widget, FALSE); + g_return_val_if_fail(event, FALSE); + g_return_val_if_fail(data, FALSE); + + editor = HILDON_TELEPHONE_EDITOR(data); + priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); + cpos = gtk_editable_get_position(GTK_EDITABLE(widget)); + gtk_editable_get_selection_bounds(GTK_EDITABLE(widget), &start, &end); + + if( event->keyval == GDK_Up || event->keyval == GDK_KP_Up || + event->keyval == GDK_Down || event->keyval == GDK_KP_Down ) + return FALSE; + + /* Wrap around should not happen; that's why following code */ + switch (priv->format) { + case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE: + if (((event->keyval == GDK_Left || event->keyval == GDK_KP_Left) && + (widget == priv->country) && ((cpos == 0) || + ((start == 0 && end == strlen(GTK_ENTRY(priv->country)->text))))) + || + ((event->keyval == GDK_Right || event->keyval == GDK_KP_Right) + && (widget == priv->number) + && (cpos >= strlen(GTK_ENTRY(priv->number)->text)))) + return TRUE; + break; + case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA: + if (((event->keyval == GDK_Left || event->keyval == GDK_KP_Left) && + (widget == priv->country) && ((cpos == 0) || + ((start == 0 + && end == + strlen(GTK_ENTRY + (priv->country)-> + text))))) + || + ((event->keyval == GDK_Right || event->keyval == GDK_KP_Right) + && (widget == priv->area) + && (cpos >= strlen(GTK_ENTRY(priv->area)->text)))) + return TRUE; + break; + case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY: + break; + case HILDON_TELEPHONE_EDITOR_FORMAT_FREE: + break; + } + + /* valid key pressed */ + if (event->keyval == GDK_Left || event->keyval == GDK_KP_Left || + event->keyval == GDK_Right || event->keyval == GDK_KP_Right || + event->keyval == GDK_BackSpace || event->keyval == GDK_Delete || + event->keyval == GDK_KP_Delete || + (event->keyval >= GDK_0 && event->keyval <= GDK_9) || + (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE && + (event->keyval == GDK_slash || event->keyval == GDK_space || + event->keyval == GDK_parenleft || event->keyval == GDK_parenright + || event->keyval == GDK_period || event->keyval == GDK_hyphen + || event->keyval == GDK_plus || event->keyval == GDK_asterisk + || event->keyval == GDK_KP_Multiply + || event->keyval == GDK_KP_Add || event->keyval == GDK_numbersign + || event->keyval == GDK_question || event->keyval == GDK_KP_Subtract + || event->keyval == GDK_minus))) + { + if ((event->keyval >= GDK_0 && event->keyval <= GDK_9) || + (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE && + (event->keyval == GDK_slash || event->keyval == GDK_space || + event->keyval == GDK_parenleft || + event->keyval == GDK_parenright || + event->keyval == GDK_period || event->keyval == GDK_hyphen || + event->keyval == GDK_plus || event->keyval == GDK_asterisk || + event->keyval == GDK_KP_Add || + event->keyval == GDK_KP_Multiply || + event->keyval == GDK_numbersign || + event->keyval == GDK_question || + event->keyval == GDK_KP_Subtract || + event->keyval == GDK_minus))) + { + if (widget == priv->country) + priv->edited_country = TRUE; + if (widget == priv->area) + priv->edited_area = TRUE; + if (widget == priv->number) + priv->edited_number = TRUE; + } + + pos = gtk_editable_get_position(GTK_EDITABLE(widget)); + + /* going left */ + if (event->keyval == GDK_Left || event->keyval == GDK_KP_Left) { + /* not yet on the left edge and the widget is edited */ + if (pos != 0 && + ((widget == priv->country && priv->edited_country == TRUE) + || (widget == priv->area && priv->edited_area == TRUE) + || (widget == priv->number + && priv->edited_number == TRUE))) + return FALSE; + + /* left edge of number field */ + if (widget == priv->number) { + /* Stop signal handler, if only number field exists */ + if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE) + return TRUE; + else { + /* Grab the focus to the area field, if it is editable + */ + if (priv->editable_area) { + hildon_telephone_editor_focus_dest_entry + (priv->area, priv->edited_area, TRUE); + } + /* Grab the focus to the country field, if it is + editable */ + else if (priv->editable_country) { + hildon_telephone_editor_focus_dest_entry + (priv->country, priv->edited_country, TRUE); + } else + return TRUE; + } + } + + /* left edge of area field */ + if (widget == priv->area) { /* grab the focus to the country + field, if it is editable */ + if (priv->editable_country) { + hildon_telephone_editor_focus_dest_entry + (priv->country, priv->edited_country, TRUE); + } else + return TRUE; + } + + /* left edge of country field, let's wrap */ + if (widget == priv->country) { + /* Stop the signal handler, if only country field exists */ + if (priv->format == + HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY) + return TRUE; + /* wrap to area, if in AREA mode */ + else if (priv->format == + HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA) { + hildon_telephone_editor_focus_dest_entry + (priv->area, priv->edited_area, TRUE); + } + + else { + hildon_telephone_editor_focus_dest_entry + (priv->number, priv->edited_number, TRUE); + } + } + } + /* going right */ + else if (event->keyval == GDK_Right || event->keyval == GDK_KP_Right) { + width = g_utf8_strlen(gtk_entry_get_text(GTK_ENTRY(widget)), -1); + + /* not yet on the rigth edge and the widget is edited */ + if (pos != width && + ((widget == priv->country && priv->edited_country == TRUE) + || (widget == priv->area && priv->edited_area == TRUE) + || (widget == priv->number + && priv->edited_number == TRUE))) + return FALSE; + + /* rigth edge of number field */ + if (widget == priv->number) { + /* Stop signal handler, if only number field exists */ + if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE) + return TRUE; + else { + hildon_telephone_editor_focus_dest_entry + (priv->country, priv->edited_country, FALSE); + } + } + + /* rigth edge of area field */ + if (widget == priv->area) { + /* area mode, wrap to country field */ + if (priv->format == + HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA) { + hildon_telephone_editor_focus_dest_entry + (priv->country, priv->edited_country, FALSE); + } + /* grab the focus to the number field, if it is editable */ + else if (priv->editable_number) { + hildon_telephone_editor_focus_dest_entry + (priv->number, priv->edited_number, FALSE); + } else + return TRUE; + } + + /* rigth edge of country field */ + if (widget == priv->country) { + /* wrap around, if only country field exists */ + if (priv->format == + HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY) + return TRUE; + + /* area mode, move to area field */ + else if (priv->format == + HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA || + priv->format == + HILDON_TELEPHONE_EDITOR_FORMAT_COERCE) { + /* grab the focus to the area field, if it is editable + */ + if (priv->editable_area) { + hildon_telephone_editor_focus_dest_entry + (priv->area, priv->edited_area, FALSE); + } + /* grab the focus to the area field, if it is editable + */ + else if ((priv->format == + HILDON_TELEPHONE_EDITOR_FORMAT_COERCE) && + priv->editable_number) { + hildon_telephone_editor_focus_dest_entry + (priv->number, priv->edited_number, FALSE); + } else + return TRUE; + } + + else { + hildon_telephone_editor_focus_dest_entry + (priv->number, priv->edited_number, FALSE); + } + } + } + return FALSE; + } + return TRUE; +} + +/** + * hildon_telephone_editor_set_editable: + * @hte: #HildonTelephoneEditor + * @country: set the editable status of the country field in coarce format + * @area: set the editable status of the area field in coarce format + * @number: set the editable status of the number field in coarce format + * + * Specify wheter the fields in coerse format are editable or + * not. This function is ignored if the editor is in free mode. The + * number or area and number parameters are ignored if the editor is + * in HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA or + * HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY formats, + * respectively. + */ +void +hildon_telephone_editor_set_editable(HildonTelephoneEditor * editor, + gboolean country, + gboolean area, gboolean number) +{ + HildonTelephoneEditorPriv *priv; + + g_return_if_fail(editor); + + priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); + + priv->editable_country = country; + priv->editable_area = area; + priv->editable_number = number; + + if (priv->country) + { + gtk_editable_set_editable(GTK_EDITABLE(priv->country), country); + gtk_widget_set_sensitive(GTK_WIDGET(priv->plus), country); + } + + if (priv->area) + gtk_editable_set_editable(GTK_EDITABLE(priv->area), area); + + if (priv->number) + gtk_editable_set_editable(GTK_EDITABLE(priv->number), number); +} + +/** + * hildon_telephone_editor_set_widths: + * @hte: #HildonTelephoneEditor + * @country: width (characters) of the country field in coarce mode + * @area: width (characters) of the area field in coarce mode + * @number: width (characters) of the number field in coarce mode + * + * Set widths of the fields in coecse format. Country and area parameters + * are ignored, if the editor is in free mode. The number or area and number + * parameters are ignored if the editor is in + * HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA or + * HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY mode, respectively. + */ +void +hildon_telephone_editor_set_widths(HildonTelephoneEditor * editor, + guint country, + guint area, guint number) +{ + HildonTelephoneEditorPriv *priv; + + g_return_if_fail(editor); + + priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); + + if (priv->country) { + /*gtk_entry_set_max_length(GTK_ENTRY(priv->country), country);*/ + gtk_entry_set_width_chars(GTK_ENTRY(priv->country), country); + } + + if (priv->area) { + /*gtk_entry_set_max_length(GTK_ENTRY(priv->area), area);*/ + gtk_entry_set_width_chars(GTK_ENTRY(priv->area), area); + } + + if (priv->number) { + /*gtk_entry_set_max_length(GTK_ENTRY(priv->number), number);*/ + gtk_entry_set_width_chars(GTK_ENTRY(priv->number), number); + } + +} + +/** + * hildon_telephone_editor_set_show_plus: + * @hte: #HildonTelephoneEditor + * @show: show the plus sign + * + * Show or hide the plus sign in front of coerce format's country field. + */ +void +hildon_telephone_editor_set_show_plus(HildonTelephoneEditor * editor, + gboolean show) +{ + HildonTelephoneEditorPriv *priv; + + g_return_if_fail(editor); + + priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); + + /* do nothing in FREE format */ + if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE) + return; + + if (show && !priv->show_plus) { + priv->show_plus = TRUE; + gtk_widget_set_parent(priv->plus_event, GTK_WIDGET(editor)); + gtk_widget_show(priv->plus_event); + } else if (!show && priv->show_plus) { + gtk_widget_hide(priv->plus_event); + gtk_widget_unparent(priv->plus_event); + priv->show_plus = FALSE; + } +} + +/** + * hildon_telephone_editor_get_show_plus: + * @hte: #HildonTelephoneEditor + * + * Get the visibility status of the plus sign in + * front of coerce format's country field. + * + * Returns: gboolean + */ +gboolean +hildon_telephone_editor_get_show_plus(HildonTelephoneEditor * + editor) +{ + HildonTelephoneEditorPriv *priv; + g_return_val_if_fail(editor, FALSE); + priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); + + /* no plus in FREE format */ + if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE) + return FALSE; + return priv->show_plus; +} + +/** + * hildon_telephone_editor_set_show_border: + * @hte: #HildonTelephoneEditor + * @show: show the border + * + * Show or hide the border around the widget + */ +void +hildon_telephone_editor_set_show_border(HildonTelephoneEditor * + editor, gboolean show) +{ + HildonTelephoneEditorPriv *priv; + g_return_if_fail(editor); + priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); + + if (show && !priv->show_border) { + priv->show_border = TRUE; + gtk_widget_set_parent(priv->frame, GTK_WIDGET(editor)); + gtk_widget_show(priv->frame); + } else if (!show && priv->show_border) { + gtk_widget_hide(priv->frame); + gtk_widget_unparent(priv->frame); + priv->show_border = FALSE; + } +} + +/** + * hildon_telephone_editor_get_show_border: + * @hte: #HildonTelephoneEditor + * + * Get the visibility status of the border around the widget. + * + * Returns: gboolean + */ +gboolean +hildon_telephone_editor_get_show_border(HildonTelephoneEditor * editor) +{ + HildonTelephoneEditorPriv *priv; + g_return_val_if_fail(editor, FALSE); + priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); + + return priv->show_border; +} + +/** + * hildon_telephone_editor_get_country: + * @hte: #HildonTelephoneEditor + * + * Get text in the country field in coarse format. This function must + * not be called if in free mode. + * + * Returns: pointer to the text in the country field. It must not + * be changed or freed. + */ +const gchar * +hildon_telephone_editor_get_country(HildonTelephoneEditor * + editor) +{ + HildonTelephoneEditorPriv *priv; + g_return_val_if_fail(editor, NULL); + priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); + + /* return NULL if in FREE format */ + if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE) + return NULL; + + return gtk_entry_get_text(GTK_ENTRY(priv->country)); +} + +/** + * hildon_telephone_editor_set_country: + * @hte: #HildonTelephoneEditor + * @country: text to be set in country field + * + * Set text in the country field in coarse format. This function must + * not be called if in free mode. + */ +void +hildon_telephone_editor_set_country(HildonTelephoneEditor * editor, + const gchar * country) +{ + HildonTelephoneEditorPriv *priv; + const gchar *p; + gunichar u; + + g_return_if_fail(editor); + g_return_if_fail(country); + + priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); + + /* do nothing in FREE format */ + if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE) + return; + + if (!priv->country) + return; + + p = country; + g_return_if_fail(g_utf8_validate(p, -1, NULL)); + + /* allow only digits */ + do { + u = g_utf8_get_char(p); + if (!g_unichar_isdigit(*p)) + return; + + p = g_utf8_next_char(p); + } while (*p); + + gtk_entry_set_text(GTK_ENTRY(priv->country), country); +} + +/** + * hildon_telephone_editor_get_area: + * @hte: #HildonTelephoneEditor + * + * Get text in the area field in coarse format. This function must not + * be called if in free mode or in + * HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY mode. + * + * Returns: pointer to the text in the area field. It must not be + * changed or freed. + */ +const gchar * +hildon_telephone_editor_get_area(HildonTelephoneEditor * + editor) +{ + HildonTelephoneEditorPriv *priv; + g_return_val_if_fail(editor, NULL); + priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); + + /* return NULL if in FREE format or if in COERCE_COUNTRY format */ + if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE) + return NULL; + if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY) + return NULL; + + return gtk_entry_get_text(GTK_ENTRY(priv->area)); +} + +/** + * hildon_telephone_editor_set_area: + * @hte: #HildonTelephoneEditor + * @area: text to be set in area field + * + * Set text in the area field in coarse format. This function must not + * be called if in free mode or in + * HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY mode. + */ +void +hildon_telephone_editor_set_area(HildonTelephoneEditor * editor, + const gchar * area) +{ + HildonTelephoneEditorPriv *priv; + const gchar *p; + gunichar u; + + g_return_if_fail(editor); + g_return_if_fail(area); + + priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); + + /* do nothing in FREE format */ + if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE) + return; + + if (!priv->area) + return; + + p = area; + g_return_if_fail(g_utf8_validate(p, -1, NULL)); + + /* allow only digits */ + do { + u = g_utf8_get_char(p); + if (!g_unichar_isdigit(u)) + return; + + p = g_utf8_next_char(p); + } while (*p); + + gtk_entry_set_text(GTK_ENTRY(priv->area), area); +} + +/** + * hildon_telephone_editor_get_number: + * @hte: #HildonTelephoneEditor + * + * Get text in the number field in all formats. In free mode, this + * functions returns the whole phone number. In coarce mode, it returns + * only the number field. This function must not be called if + * the editor is in HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA or + * HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY modes. + * + * Returns: pointer to text in the number field. It must not be + * changed or freed. + */ +const gchar * +hildon_telephone_editor_get_number(HildonTelephoneEditor * + editor) +{ + HildonTelephoneEditorPriv *priv; + g_return_val_if_fail(editor, NULL); + priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); + + return gtk_entry_get_text(GTK_ENTRY(priv->number)); +} + +/** + * hildon_telephone_editor_set_number: + * @hte: #HildonTelephoneEditor + * @number: text to be set to number field + * + * Set text in the number field in all formats. In free mode this + * functions sets the whole phone number. In coerce mode, it sets + * only the number field. This function must not be called if + * the editor is in HILDON_TELEPHONE_EDITOR_FORMAT_COERSE_AREA or + * HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY modes. + */ +void +hildon_telephone_editor_set_number(HildonTelephoneEditor * editor, + const gchar * number) +{ + HildonTelephoneEditorPriv *priv; + const gchar *p; + gunichar u; + + g_return_if_fail(editor); + g_return_if_fail(number); + + priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor); + + if (!priv->number) + return; + + p = number; + g_return_if_fail(g_utf8_validate(p, -1, NULL)); + + /* allow only digits in coerce format or some other in free format */ + do { + u = g_utf8_get_char(p); + if (g_unichar_isdigit(u) || + (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE && + (u == '+' || + u == 'p' || + u == 'w' || + u == '(' || + u == ')' || + u == '/' || + u == ' ' || + u == '.' || u == '-' || u == '*' || u == '#' || u == '?'))) + p = g_utf8_next_char(p); + else + return; + + } while (*p); + + gtk_entry_set_text(GTK_ENTRY(priv->number), number); +} diff --git a/src/hildon-telephone-editor.h b/src/hildon-telephone-editor.h new file mode 100644 index 0000000..7cba96b --- /dev/null +++ b/src/hildon-telephone-editor.h @@ -0,0 +1,133 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_TELEPHONE_EDITOR_H__ +#define __HILDON_TELEPHONE_EDITOR_H__ + +#include + +G_BEGIN_DECLS +/** + * HILDON_TELEPHONE_EDITOR_TYPE: + * + * Macro for getting type of telephone editor. + */ +#define HILDON_TELEPHONE_EDITOR_TYPE \ + ( hildon_telephone_editor_get_type() ) +#define HILDON_TELEPHONE_EDITOR(obj) \ + (GTK_CHECK_CAST (obj, HILDON_TELEPHONE_EDITOR_TYPE, \ + HildonTelephoneEditor)) +#define HILDON_TELEPHONE_EDITOR_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST ((klass), HILDON_TELEPHONE_EDITOR_TYPE, \ + HildonTelephoneEditorClass)) +#define HILDON_IS_TELEPHONE_EDITOR(obj) \ + (GTK_CHECK_TYPE (obj, HILDON_TELEPHONE_EDITOR_TYPE)) +#define HILDON_IS_TELEPHONE_EDITOR_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TELEPHONE_EDITOR_TYPE)) +/** + * HildonTelephoneEditorFormat: + * @HILDON_TELEPHONE_EDITOR_FORMAT_FREE: Free format. + * @HILDON_TELEPHONE_EDITOR_FORMAT_COERCE: Coerce format, three fields. + * @HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY: Coerce format, only + * country field. + * @HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA: Coerce format, country + * and area fields. + * + * Define all possible format modes for the HildonTelephoneEditor. + * + */ + typedef enum { + HILDON_TELEPHONE_EDITOR_FORMAT_FREE = 0, + HILDON_TELEPHONE_EDITOR_FORMAT_COERCE, + HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY, + HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA +} HildonTelephoneEditorFormat; + + +/** + * HildonTelephoneEditor: + * + * Internal struct for telephone editor. + */ +typedef struct _HildonTelephoneEditor HildonTelephoneEditor; +typedef struct _HildonTelephoneEditorClass HildonTelephoneEditorClass; + +/*< private >*/ +struct _HildonTelephoneEditor { + GtkContainer parent; +}; + +struct _HildonTelephoneEditorClass { + GtkContainerClass parent_class; +}; + +GType hildon_telephone_editor_get_type(void); + +GtkWidget *hildon_telephone_editor_new(HildonTelephoneEditorFormat format); +GtkWidget + *hildon_telephone_editor_new_with_strings(HildonTelephoneEditorFormat + format, + const gchar * country, + const gchar * area, + const gchar * number); +void hildon_telephone_editor_set_editable(HildonTelephoneEditor * hte, + gboolean country, gboolean area, + gboolean number); + +void hildon_telephone_editor_set_show_plus(HildonTelephoneEditor * hte, + gboolean show); + +gboolean hildon_telephone_editor_get_show_plus(HildonTelephoneEditor * + hte); + +void hildon_telephone_editor_set_show_border(HildonTelephoneEditor * hte, + gboolean show); + +gboolean hildon_telephone_editor_get_show_border(HildonTelephoneEditor * + hte); + + +void hildon_telephone_editor_set_widths(HildonTelephoneEditor * hte, + guint country, + guint area, guint number); + +const gchar *hildon_telephone_editor_get_country(HildonTelephoneEditor * + hte); + +void hildon_telephone_editor_set_country(HildonTelephoneEditor * hte, + const gchar * country); + +const gchar *hildon_telephone_editor_get_area(HildonTelephoneEditor * hte); + +void hildon_telephone_editor_set_area(HildonTelephoneEditor * hte, + const gchar * area); + +const gchar *hildon_telephone_editor_get_number(HildonTelephoneEditor * + hte); + +void hildon_telephone_editor_set_number(HildonTelephoneEditor * hte, + const gchar * number); + +G_END_DECLS +#endif /* __HILDON_TELEPHONE_EDITOR_H__ */ diff --git a/src/hildon-time-editor.c b/src/hildon-time-editor.c new file mode 100644 index 0000000..31bada1 --- /dev/null +++ b/src/hildon-time-editor.c @@ -0,0 +1,1902 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-time-editor + * @short_description: A widget used to enter time or duration in hours, minutes, + * and optional seconds + * @see_also: #HildonTimePicker + * + * HildonTimeEditor is used to edit time or duration. Time mode is + * restricted to normal 24 hour cycle, but Duration mode can select any + * amount of time up to 99 hours. It consists of entries for hours, + * minutes and seconds, and pm/am indicator as well as a button which + * popups a #HildonTimePicker dialog. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "hildon-composite-widget.h" +#include "hildon-marshalers.h" +#include "hildon-libs-enum-types.h" + +#define _(String) dgettext(PACKAGE, String) + +#define HILDON_TIME_EDITOR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_TIME_EDITOR, HildonTimeEditorPrivate)); + +#define TICKS(h,m,s) ((h) * 3600 + (m) * 60 + (s)) + +#define TIME_EDITOR_HEIGHT 30 +#define ICON_PRESSED 4 +#define ICON_NAME "qgn_widg_timedit" +#define ICON_SIZE "timepicker-size" +#define MIN_DURATION 0 +#define MAX_DURATION TICKS(99, 59, 59) + +/* Default values for properties */ +#define HILDON_TIME_EDITOR_TICKS_VALUE 0 +#define HILDON_TIME_EDITOR_DURATION_MODE FALSE +#define HILDON_TIME_EDITOR_DURATION_LOWER_VALUE 0 +#define HILDON_TIME_EDITOR_DURATION_UPPER_VALUE TICKS(99, 59, 59) + +#define HOURS_MAX_24 23 +#define HOURS_MAX_12 12 +#define HOURS_MIN_24 0 +#define HOURS_MIN_12 1 +#define MINUTES_MAX 59 +#define SECONDS_MAX 59 +#define MINUTES_MIN 0 +#define SECONDS_MIN 0 + +static GtkContainerClass *parent_class; + +typedef struct _HildonTimeEditorPrivate HildonTimeEditorPrivate; + +enum +{ + PROP_TICKS = 1, + PROP_DURATION_MODE, + PROP_DURATION_MIN, + PROP_DURATION_MAX, + PROP_SHOW_SECONDS, + PROP_SHOW_HOURS +}; + +/* Indices for h/m/s entries in priv->entries */ +enum { + ENTRY_HOURS, + ENTRY_MINS, + ENTRY_SECS, + + ENTRY_COUNT +}; + +/* Signals */ +enum { + TIME_ERROR, + LAST_SIGNAL +}; + +/* Error codes categories */ +enum { + MAX_VALUE, + MIN_VALUE, + WITHIN_RANGE, + NUM_ERROR_CODES +}; + +static guint time_editor_signals[LAST_SIGNAL] = { 0 }; +static guint hour_errors[NUM_ERROR_CODES] = { MAX_HOURS, MIN_HOURS, EMPTY_HOURS }; +static guint min_errors[NUM_ERROR_CODES] = { MAX_MINS, MIN_MINS, EMPTY_MINS }; +static guint sec_errors[NUM_ERROR_CODES] = { MAX_SECS, MIN_SECS, EMPTY_SECS }; + +struct _HildonTimeEditorPrivate { + guint ticks; /* Current duration in seconds */ + + gchar *am_symbol; + gchar *pm_symbol; + + GtkWidget *iconbutton; /* button for icon */ + + GtkWidget *frame; /* frame around the entries */ + GtkWidget *entries[ENTRY_COUNT]; /* h, m, s entries */ + GtkWidget *hm_label; /* between hour and minute */ + GtkWidget *sec_label; /* between minute and second */ + GtkWidget *ampm_label; /* label for showing am or pm */ + + GtkWidget *error_widget; /* field to highlight in idle */ + GtkWidget *ampm_button; /* am/pm change button */ + + + gboolean duration_mode; /* In HildonDurationEditor mode */ + gboolean show_seconds; /* show seconds */ + gboolean show_hours; /* show hours */ + + gboolean ampm_pos_after; /* is am/pm shown after others */ + gboolean clock_24h; /* whether to show a 24h clock */ + gboolean am; /* TRUE == am, FALSE == pm */ + + guint duration_min; /* duration editor ranges */ + guint duration_max; /* duration editor ranges */ + + guint highlight_idle; + gboolean skipper; /* FIXME (MDK): To prevent us from looping inside the validation events. + When set to TRUE further validations (that can happen from-inside other validations) + are being skipped. Nasty hack to cope with a bad design. */ +}; + +/*** + * Widget functions + */ + +static void hildon_time_editor_class_init (HildonTimeEditorClass *editor_class); +static void hildon_time_editor_init (HildonTimeEditor *editor); + +static void hildon_time_editor_finalize (GObject *obj_self); + +static void hildon_time_editor_set_property(GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec); + +static void hildon_time_editor_get_property(GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec); + +static void hildon_time_editor_forall(GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data); + +static void hildon_time_editor_destroy(GtkObject * self); + +/*** + * Signal handlers + */ + +static gboolean hildon_time_editor_entry_focusout(GtkWidget *widget, + GdkEventFocus *event, + gpointer data); + +static gboolean hildon_time_editor_entry_focusin(GtkWidget *widget, + GdkEventFocus *event, + gpointer data); + +static gboolean hildon_time_editor_time_error(HildonTimeEditor *editor, + HildonTimeEditorErrorType type); + +static gboolean hildon_time_editor_ampm_clicked(GtkWidget *widget, + gpointer data); + +static gboolean hildon_time_editor_icon_clicked(GtkWidget *widget, + gpointer data); + +static void hildon_time_editor_size_request(GtkWidget *widget, + GtkRequisition *requisition); + +static void hildon_time_editor_size_allocate(GtkWidget *widget, + GtkAllocation *allocation); + +static gboolean hildon_time_editor_entry_keypress(GtkWidget *widget, + GdkEventKey *event, + gpointer data); + +/*** + * Internal functions + */ + +static gboolean hildon_time_editor_check_locale(HildonTimeEditor * editor); + +static +void hildon_time_editor_tap_and_hold_setup(GtkWidget * widget, + GtkWidget * menu, + GtkCallback func, + GtkWidgetTapAndHoldFlags flags); +static void +hildon_time_editor_validate (HildonTimeEditor *editor, gboolean allow_intermediate); + +static void hildon_time_editor_set_to_current_time (HildonTimeEditor * editor); + +static gboolean +_hildon_time_editor_entry_select_all(GtkWidget *widget); + + +/*** + * Utility functions + */ + +static void convert_to_12h (guint *h, gboolean *am); +static void convert_to_24h (guint *h, gboolean am); + +static void ticks_to_time (guint ticks, + guint *hours, + guint *minutes, + guint *seconds); + +static void +hildon_time_editor_inserted_text (GtkEditable * editable, + gchar * new_text, + gint new_text_length, + gint * position, + gpointer user_data); + +GType hildon_time_editor_get_type(void) +{ + static GType editor_type = 0; + + if (!editor_type) { + static const GTypeInfo editor_info = { + sizeof(HildonTimeEditorClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_time_editor_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonTimeEditor), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_time_editor_init, + }; + editor_type = g_type_register_static(GTK_TYPE_CONTAINER, + "HildonTimeEditor", + &editor_info, 0); + } + return editor_type; +} + +static void hildon_time_editor_forall(GtkContainer * container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) +{ + HildonTimeEditor *editor; + HildonTimeEditorPrivate *priv; + + g_assert(HILDON_IS_TIME_EDITOR(container)); + g_assert(callback != NULL); + + editor = HILDON_TIME_EDITOR(container); + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + + if (!include_internals) + return; + + /* widget that are always shown */ + (*callback) (priv->iconbutton, callback_data); + (*callback) (priv->frame, callback_data); +} + +static void hildon_time_editor_destroy(GtkObject * self) +{ + HildonTimeEditorPrivate *priv; + + priv = HILDON_TIME_EDITOR_GET_PRIVATE(self); + + if (priv->iconbutton) { + gtk_widget_unparent(priv->iconbutton); + priv->iconbutton = NULL; + } + if (priv->frame) { + gtk_widget_unparent(priv->frame); + priv->frame = NULL; + } + + if (GTK_OBJECT_CLASS(parent_class)->destroy) + GTK_OBJECT_CLASS(parent_class)->destroy(self); + +} + +static void +hildon_time_editor_class_init(HildonTimeEditorClass * editor_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(editor_class); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(editor_class); + GtkContainerClass *container_class = GTK_CONTAINER_CLASS(editor_class); + + parent_class = g_type_class_peek_parent(editor_class); + + g_type_class_add_private(editor_class, + sizeof(HildonTimeEditorPrivate)); + + object_class->get_property = hildon_time_editor_get_property; + object_class->set_property = hildon_time_editor_set_property; + widget_class->size_request = hildon_time_editor_size_request; + widget_class->size_allocate = hildon_time_editor_size_allocate; + widget_class->tap_and_hold_setup = + hildon_time_editor_tap_and_hold_setup; + widget_class->focus = hildon_composite_widget_focus; + + container_class->forall = hildon_time_editor_forall; + GTK_OBJECT_CLASS(editor_class)->destroy = hildon_time_editor_destroy; + + object_class->finalize = hildon_time_editor_finalize; + + editor_class->time_error = hildon_time_editor_time_error; + + time_editor_signals[TIME_ERROR] = + g_signal_new("time-error", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(HildonTimeEditorClass, time_error), + g_signal_accumulator_true_handled, NULL, + _hildon_marshal_BOOLEAN__ENUM, + G_TYPE_BOOLEAN, 1, HILDON_TYPE_TIME_EDITOR_ERROR_TYPE); + + /** + * HildonTimeEditor:ticks: + * + * If editor is in duration mode, contains the duration seconds. + * If not, contains seconds since midnight. + */ + g_object_class_install_property( object_class, PROP_TICKS, + g_param_spec_uint("ticks", + "Duration value", + "Current value of duration", + 0, G_MAXUINT, + HILDON_TIME_EDITOR_TICKS_VALUE, + G_PARAM_READABLE | G_PARAM_WRITABLE) ); + + /** + * HildonTimeEditor:show_seconds: + * + * Controls whether seconds are shown in the editor + */ + g_object_class_install_property( object_class, PROP_SHOW_SECONDS, + g_param_spec_boolean("show_seconds", + "Show seconds property", + "Controls whether the seconds are shown in the editor", + FALSE, + G_PARAM_READABLE | G_PARAM_WRITABLE) ); + + /** + * HildonTimeEditor:show_hours: + * + * Controls whether hours are shown in the editor + */ + g_object_class_install_property( object_class, PROP_SHOW_HOURS, + g_param_spec_boolean("show_hours", + "Show hours field", + "Controls whether the hours field is shown in the editor", + TRUE, + G_PARAM_READABLE | G_PARAM_WRITABLE) ); + + /** + * HildonTimeEditor:duration_mode: + * + * Controls whether the TimeEditor is in duration mode + */ + g_object_class_install_property( object_class, PROP_DURATION_MODE, + g_param_spec_boolean("duration_mode", + "Duration mode", + "Controls whether the TimeEditor is in duration mode", + HILDON_TIME_EDITOR_DURATION_MODE, + G_PARAM_READABLE | G_PARAM_WRITABLE) ); + + /** + * HildonTimeEditor:duration_min: + * + * Minimum allowed duration value. + */ + g_object_class_install_property( object_class, PROP_DURATION_MIN, + g_param_spec_uint("duration_min", + "Minumum duration value", + "Smallest possible duration value", + MIN_DURATION, MAX_DURATION, + HILDON_TIME_EDITOR_DURATION_LOWER_VALUE, + G_PARAM_READABLE | G_PARAM_WRITABLE) ); + + /** + * HildonTimeEditor:duration_max: + * + * Maximum allowed duration value. + */ + g_object_class_install_property( object_class, PROP_DURATION_MAX, + g_param_spec_uint("duration_max", + "Maximum duration value", + "Largest possible duration value", + 0, G_MAXUINT, + HILDON_TIME_EDITOR_DURATION_UPPER_VALUE, + G_PARAM_READABLE | G_PARAM_WRITABLE) ); +} + +static +void hildon_time_editor_tap_and_hold_setup(GtkWidget * widget, + GtkWidget * menu, + GtkCallback func, + GtkWidgetTapAndHoldFlags flags) +{ + HildonTimeEditorPrivate *priv = HILDON_TIME_EDITOR_GET_PRIVATE(widget); + gint i; + + /* Forward this tap_and_hold_setup signal to all our child widgets */ + for (i = 0; i < ENTRY_COUNT; i++) + { + gtk_widget_tap_and_hold_setup(priv->entries[i], menu, func, + GTK_TAP_AND_HOLD_NO_SIGNALS); + } + gtk_widget_tap_and_hold_setup(priv->ampm_button, menu, func, + GTK_TAP_AND_HOLD_NO_SIGNALS); + gtk_widget_tap_and_hold_setup(priv->iconbutton, menu, func, + GTK_TAP_AND_HOLD_NONE); +} + +static void hildon_time_editor_entry_changed(GtkWidget *widget, gpointer data) +{ + g_assert(HILDON_IS_TIME_EDITOR(data)); + hildon_time_editor_validate(HILDON_TIME_EDITOR(data), TRUE); +} + +static void hildon_time_editor_init(HildonTimeEditor * editor) +{ + HildonTimeEditorPrivate *priv; + GtkWidget *hbox, *icon; + gint i; + + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + + gtk_widget_push_composite_child(); + + /* Setup defaults and create widgets */ + priv->ticks = 0; + priv->show_seconds = FALSE; + priv->show_hours = TRUE; + priv->ampm_pos_after = TRUE; + priv->clock_24h = TRUE; + priv->duration_mode = FALSE; + priv->iconbutton = gtk_button_new(); + priv->ampm_label = gtk_label_new(NULL); + priv->hm_label = gtk_label_new(NULL); + priv->sec_label = gtk_label_new(NULL); + priv->frame = gtk_frame_new(NULL); + priv->ampm_button = gtk_button_new(); + priv->skipper = FALSE; + + icon = gtk_image_new_from_icon_name(ICON_NAME, HILDON_ICON_SIZE_WIDG); + hbox = gtk_hbox_new(FALSE, 0); + + GTK_WIDGET_SET_FLAGS(editor, GTK_NO_WINDOW); + GTK_WIDGET_UNSET_FLAGS(priv->iconbutton, GTK_CAN_FOCUS | GTK_CAN_DEFAULT); + + gtk_container_set_border_width(GTK_CONTAINER(priv->frame), 0); + + gtk_container_add(GTK_CONTAINER(priv->iconbutton), icon); + gtk_container_add(GTK_CONTAINER(priv->ampm_button), priv->ampm_label); + gtk_button_set_relief(GTK_BUTTON(priv->ampm_button), GTK_RELIEF_NONE); + gtk_button_set_focus_on_click(GTK_BUTTON(priv->ampm_button), FALSE); + + /* Create hour, minute and second entries */ + for (i = 0; i < ENTRY_COUNT; i++) + { + priv->entries[i] = gtk_entry_new(); + + /* No frames for entries, so that they all appear to be inside one long entry */ + gtk_entry_set_has_frame(GTK_ENTRY(priv->entries[i]), FALSE); + + /* Set the entries to accept only numeric characters */ + g_object_set (priv->entries[i], "input-mode", + HILDON_INPUT_MODE_HINT_NUMERIC, NULL); + + /* The entry fields all take exactly two characters */ + gtk_entry_set_max_length (GTK_ENTRY(priv->entries[i]), 2); + gtk_entry_set_width_chars (GTK_ENTRY(priv->entries[i]), 2); + + g_signal_connect(priv->entries[i], "focus-in-event", + G_CALLBACK(hildon_time_editor_entry_focusin), editor); + g_signal_connect(priv->entries[i], "focus-out-event", + G_CALLBACK(hildon_time_editor_entry_focusout), editor); + g_signal_connect(priv->entries[i], "key-press-event", + G_CALLBACK(hildon_time_editor_entry_keypress), editor); + g_signal_connect(priv->entries[i], "changed", + G_CALLBACK(hildon_time_editor_entry_changed), editor); + + /* inserted signal sets time */ + g_signal_connect_after (G_OBJECT(priv->entries[i]), "insert_text", + G_CALLBACK (hildon_time_editor_inserted_text), + editor); + } + + /* clicked signal for am/pm label */ + g_signal_connect(G_OBJECT(priv->ampm_button), "clicked", + G_CALLBACK(hildon_time_editor_ampm_clicked), editor); + + /* clicked signal for icon */ + g_signal_connect(G_OBJECT(priv->iconbutton), "clicked", + G_CALLBACK(hildon_time_editor_icon_clicked), editor); + + /* Set ourself as the parent of all the widgets we created */ + gtk_widget_set_parent(priv->iconbutton, GTK_WIDGET(editor)); + gtk_box_pack_start(GTK_BOX(hbox), priv->entries[ENTRY_HOURS], FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), priv->hm_label, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), priv->entries[ENTRY_MINS], FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), priv->sec_label, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), priv->entries[ENTRY_SECS], FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), priv->ampm_button, FALSE, FALSE, 0); + gtk_misc_set_padding(GTK_MISC(priv->ampm_label), 0, 0); + + gtk_container_add(GTK_CONTAINER(priv->frame), hbox); + + /* Show created widgets */ + gtk_widget_set_parent(priv->frame, GTK_WIDGET(editor)); + gtk_widget_show_all(priv->frame); + gtk_widget_show_all(priv->iconbutton); + + /* Update AM/PM and time separators settings from locale */ + if (!hildon_time_editor_check_locale(editor)) { + /* Using 12h clock */ + priv->clock_24h = FALSE; + } else { + gtk_widget_hide(priv->ampm_button); + } + + if (!priv->show_seconds) { + gtk_widget_hide(priv->sec_label); + gtk_widget_hide(priv->entries[ENTRY_SECS]); + } + + /* set the default time to current time. */ + hildon_time_editor_set_to_current_time (editor); + + gtk_widget_pop_composite_child(); +} + +static void hildon_time_editor_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + HildonTimeEditor *time_editor = HILDON_TIME_EDITOR(object); + switch (param_id) + { + case PROP_TICKS: + hildon_time_editor_set_ticks (time_editor, g_value_get_uint(value)); + break; + + case PROP_SHOW_SECONDS: + hildon_time_editor_set_show_seconds (time_editor, g_value_get_boolean(value)); + break; + + case PROP_SHOW_HOURS: + hildon_time_editor_set_show_hours (time_editor, g_value_get_boolean(value)); + break; + + case PROP_DURATION_MODE: + hildon_time_editor_set_duration_mode (time_editor, g_value_get_boolean(value)); + break; + + case PROP_DURATION_MIN: + hildon_time_editor_set_duration_min (time_editor, g_value_get_uint(value)); + break; + + case PROP_DURATION_MAX: + hildon_time_editor_set_duration_max (time_editor, g_value_get_uint(value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); + break; + } +} + +static void hildon_time_editor_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + HildonTimeEditor *time_editor = HILDON_TIME_EDITOR(object); + switch (param_id) + { + + case PROP_TICKS: + g_value_set_uint (value, hildon_time_editor_get_ticks (time_editor)); + break; + + case PROP_SHOW_SECONDS: + g_value_set_boolean (value, hildon_time_editor_get_show_seconds (time_editor)); + break; + + case PROP_SHOW_HOURS: + g_value_set_boolean (value, hildon_time_editor_get_show_hours (time_editor)); + break; + + case PROP_DURATION_MODE: + g_value_set_boolean (value, hildon_time_editor_get_duration_mode (time_editor)); + break; + + case PROP_DURATION_MIN: + g_value_set_uint (value, hildon_time_editor_get_duration_min (time_editor)); + break; + + case PROP_DURATION_MAX: + g_value_set_uint (value, hildon_time_editor_get_duration_max (time_editor)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); + break; + } +} + +/** + * hildon_time_editor_new: + * + * This function creates a new time editor. + * + * Returns: pointer to a new #HildonTimeEditor widget + */ + +GtkWidget *hildon_time_editor_new(void) +{ + return GTK_WIDGET(g_object_new(HILDON_TYPE_TIME_EDITOR, NULL)); +} + +static void hildon_time_editor_finalize(GObject * obj_self) +{ + HildonTimeEditorPrivate *priv = HILDON_TIME_EDITOR_GET_PRIVATE(obj_self); + + g_free(priv->am_symbol); + g_free(priv->pm_symbol); + + if (priv->highlight_idle) + g_source_remove(priv->highlight_idle); + + if (G_OBJECT_CLASS(parent_class)->finalize) + G_OBJECT_CLASS(parent_class)->finalize(obj_self); +} + +/** + * _hildon_time_editor_get_time_separators: + * @editor: the #HildonTimeEditor + * @hm_sep_label: the label that will show the hour:minutes separator + * @ms_sep_label: the label that will show the minutes:seconds separator + * + * Gets hour-minute separator and minute-second separator from current + * locale and sets then to the labels we set as parameters. Both + * parameters can be NULL if you just want to assing one separator. + * + */ +void +_hildon_time_editor_get_time_separators(GtkLabel *hm_sep_label, + GtkLabel *ms_sep_label) +{ + gchar buffer[256]; + gchar *separator; + GDate locale_test_date; + gchar *iter, *endp = NULL; + + /* Get localized time string */ + g_date_set_dmy(&locale_test_date, 1, 2, 1970); + (void) g_date_strftime(buffer, sizeof(buffer), "%X", &locale_test_date); + + if (hm_sep_label != NULL) + { + /* Find h-m separator */ + iter = buffer; + while (*iter && g_ascii_isdigit(*iter)) iter++; + + /* Extract h-m separator*/ + endp = iter; + while (*endp && !g_ascii_isdigit(*endp)) endp++; + separator = g_strndup(iter, endp - iter); + gtk_label_set_label(hm_sep_label, separator); + g_free(separator); + } + + if (ms_sep_label != NULL) + { + /* Find m-s separator */ + iter = endp; + while (*iter && g_ascii_isdigit(*iter)) iter++; + + /* Extract m-s separator*/ + endp = iter; + while (*endp && !g_ascii_isdigit(*endp)) endp++; + separator = g_strndup(iter, endp - iter); + gtk_label_set_label(ms_sep_label, separator); + g_free(separator); + } + +} + +/* Convert ticks to H:M:S. Ticks = seconds since 00:00:00. */ +static void ticks_to_time (guint ticks, + guint *hours, + guint *minutes, + guint *seconds) +{ + guint left; + + *hours = ticks / 3600; + left = ticks % 3600; + *minutes = left / 60; + *seconds = left % 60; +} + +/** + * hildon_time_editor_set_ticks: + * @editor: the #HildonTimeEditor widget + * @ticks: the duration to set, in seconds + * + * Sets the current duration in seconds. This means seconds from + * midnight, if not in duration mode. In case of any errors, it tries + * to fix it. + */ + +void hildon_time_editor_set_ticks (HildonTimeEditor * editor, + guint ticks) +{ + HildonTimeEditorPrivate *priv; + guint i, h, m, s; + gchar str[3]; + + g_assert(HILDON_IS_TIME_EDITOR(editor)); + + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + + /* Validate ticks. If it's too low or too high, set it to + min/max value for the current mode. */ + if (priv->duration_mode) + priv->ticks = CLAMP(ticks, priv->duration_min, priv->duration_max); + else { + /* Check that ticks value is valid. We only need to check that hours + don't exceed 23. */ + ticks_to_time (ticks, &h, &m, &s); + if (h > HOURS_MAX_24) + ticks = TICKS(HOURS_MAX_24, m, s); + + priv->ticks = ticks; + } + + /* Get the time in H:M:S. */ + ticks_to_time (priv->ticks, &h, &m, &s); + + if (!priv->clock_24h && !priv->duration_mode) + { + /* Convert 24h H:M:S values to 12h mode, and update AM/PM state */ + convert_to_12h (&h, &priv->am); + } + + /* Set H:M:S values to entries. We do not want to invoke validation + callbacks (since they can cause new call to this function), so we + block signals while setting values. */ + for (i = 0; i < ENTRY_COUNT; i++) + { + g_signal_handlers_block_by_func(priv->entries[i], + (gpointer) hildon_time_editor_entry_changed, editor); + + g_signal_handlers_block_by_func(priv->entries[i], + (gpointer) hildon_time_editor_inserted_text, editor); + + g_signal_handlers_block_by_func(priv->entries[i], + (gpointer) hildon_time_editor_entry_focusout, editor); + + } + + g_snprintf(str, sizeof(str), "%02u", h); + gtk_entry_set_text(GTK_ENTRY(priv->entries[ENTRY_HOURS]), str); + + g_snprintf(str, sizeof(str), "%02u", m); + gtk_entry_set_text(GTK_ENTRY(priv->entries[ENTRY_MINS]), str); + + g_snprintf(str, sizeof(str), "%02u", s); + gtk_entry_set_text(GTK_ENTRY(priv->entries[ENTRY_SECS]), str); + + for (i = 0; i < ENTRY_COUNT; i++) + { + g_signal_handlers_unblock_by_func(priv->entries[i], + (gpointer) hildon_time_editor_entry_changed, editor); + + g_signal_handlers_unblock_by_func(priv->entries[i], + (gpointer) hildon_time_editor_inserted_text, editor); + + g_signal_handlers_unblock_by_func(priv->entries[i], + (gpointer) hildon_time_editor_entry_focusout, editor); + + } + + /* Update AM/PM label in case we're in 12h mode */ + gtk_label_set_label(GTK_LABEL(priv->ampm_label), + priv->am ? priv->am_symbol : priv->pm_symbol); + + g_object_notify (G_OBJECT (editor), "ticks"); +} + +static void +hildon_time_editor_set_to_current_time (HildonTimeEditor * editor) +{ + time_t now; + const struct tm *tm; + + now = time(NULL); + tm = localtime(&now); + + if (tm != NULL) + hildon_time_editor_set_time(editor, tm->tm_hour, tm->tm_min, tm->tm_sec); +} + +/** + * hildon_time_editor_get_ticks: + * @editor: the #HildonTimeEditor widget + * + * This function returns the current duration, in seconds. + * This means seconds from midnight, if not in duration mode. + * + * Returns: current duration in seconds + */ + +guint hildon_time_editor_get_ticks (HildonTimeEditor * editor) +{ + HildonTimeEditorPrivate *priv; + + g_return_val_if_fail(editor, 0); + g_return_val_if_fail(HILDON_IS_TIME_EDITOR(editor), 0); + + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + + return (priv->ticks); +} + +/** + * hildon_time_editor_set_show_seconds: + * @editor: the #HildonTimeEditor + * @show_seconds: enable or disable showing of seconds + * + * This function shows or hides the seconds field. + */ + +void hildon_time_editor_set_show_seconds (HildonTimeEditor * editor, + gboolean show_seconds) +{ + HildonTimeEditorPrivate *priv; + + g_return_if_fail(HILDON_IS_TIME_EDITOR(editor)); + + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + + if (show_seconds != priv->show_seconds) { + priv->show_seconds = show_seconds; + + /* show/hide seconds field and its ':' label if the value changed. */ + if (show_seconds) { + gtk_widget_show(priv->entries[ENTRY_SECS]); + gtk_widget_show(priv->sec_label); + } else { + gtk_widget_hide(priv->entries[ENTRY_SECS]); + gtk_widget_hide(priv->sec_label); + } + + g_object_notify (G_OBJECT (editor), "show_seconds"); + } +} + +/** + * hildon_time_editor_get_show_seconds: + * @editor: the #HildonTimeEditor widget + * + * This function returns a boolean indicating the visibility of + * seconds in the #HildonTimeEditor + * + * Returns: TRUE if the seconds are visible + */ + +gboolean hildon_time_editor_get_show_seconds (HildonTimeEditor * editor) +{ + HildonTimeEditorPrivate *priv; + + g_return_val_if_fail (HILDON_IS_TIME_EDITOR (editor), FALSE); + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + + return (priv->show_seconds); +} + +/** + * hildon_time_editor_set_duration_mode: + * @editor: the #HildonTimeEditor + * @duration_mode: enable or disable duration editor mode + * + * This function sets the duration editor mode in which the maximum hours + * is 99. + */ + +void hildon_time_editor_set_duration_mode (HildonTimeEditor * editor, + gboolean duration_mode) +{ + HildonTimeEditorPrivate *priv; + + g_return_if_fail(HILDON_IS_TIME_EDITOR(editor)); + + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + + if (duration_mode != priv->duration_mode) { + priv->duration_mode = duration_mode; + + if (duration_mode) { + /* FIXME: Why do we reset the duration range here? + Would change API, so won't touch this for now. */ + hildon_time_editor_set_duration_range(editor, MIN_DURATION, + MAX_DURATION); + /* There's no AM/PM label or time picker icon in duration mode. + Make sure they're hidden. */ + gtk_widget_hide(GTK_WIDGET(priv->ampm_label)); + gtk_widget_hide(GTK_WIDGET(priv->ampm_button)); + gtk_widget_hide(GTK_WIDGET(priv->iconbutton)); + /* Duration mode has seconds by default. */ + hildon_time_editor_set_show_seconds(editor, TRUE); + } else { + /* Make sure AM/PM label and time picker icons are visible if needed */ + if (!priv->clock_24h) + gtk_widget_show(GTK_WIDGET(priv->ampm_label)); + + gtk_widget_show(GTK_WIDGET(priv->ampm_button)); + gtk_widget_show(GTK_WIDGET(priv->iconbutton)); + + /* Reset the ticks to current time. Anything set in duration mode + * is bound to be invalid or useless in time mode. + */ + hildon_time_editor_set_to_current_time (editor); + } + + g_object_notify (G_OBJECT (editor), "duration_mode"); + } +} + +/** + * hildon_time_editor_get_duration_mode: + * @editor: the #HildonTimeEditor widget + * + * This function returns a boolean indicating whether the #HildonTimeEditor + * is in the duration mode. + * + * Returns: TRUE if the #HildonTimeEditor is in duration mode + */ + +gboolean hildon_time_editor_get_duration_mode (HildonTimeEditor * editor) +{ + HildonTimeEditorPrivate *priv; + + g_return_val_if_fail (HILDON_IS_TIME_EDITOR (editor), FALSE); + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + + return (priv->duration_mode); +} + +/** + * hildon_time_editor_set_duration_min: + * @editor: the #HildonTimeEditor widget + * @duration_min: mimimum allowed duration + * + * Sets the minimum allowed duration for the duration mode. + * Note: Has no effect in time mode + */ + +void hildon_time_editor_set_duration_min (HildonTimeEditor * editor, + guint duration_min) +{ + HildonTimeEditorPrivate *priv; + + g_return_if_fail(HILDON_IS_TIME_EDITOR(editor)); + g_return_if_fail(duration_min >= MIN_DURATION); + + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + + if( !priv->duration_mode ) + return; + + priv->duration_min = duration_min; + + /* Clamp the current value to the minimum if necessary */ + if (priv->ticks < duration_min) + { + hildon_time_editor_set_ticks (editor, duration_min); + } + + g_object_notify (G_OBJECT (editor), "duration_min"); +} + +/** + * hildon_time_editor_get_duration_min: + * @editor: the #HildonTimeEditor widget + * + * This function returns the smallest duration the #HildonTimeEditor + * allows in the duration mode. + * + * Returns: minimum allowed duration in seconds + */ + +guint hildon_time_editor_get_duration_min (HildonTimeEditor * editor) +{ + HildonTimeEditorPrivate *priv; + + g_return_val_if_fail(HILDON_IS_TIME_EDITOR(editor), 0); + + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + + if( !priv->duration_mode ) + return (0); + + return (priv->duration_min); +} + +/** + * hildon_time_editor_set_duration_max: + * @editor: the #HildonTimeEditor widget + * @duration_max: maximum allowed duration in seconds + * + * Sets the maximum allowed duration in seconds for the duration mode. + * Note: Has no effect in time mode + */ + +void hildon_time_editor_set_duration_max (HildonTimeEditor * editor, + guint duration_max) +{ + HildonTimeEditorPrivate *priv; + + g_return_if_fail(HILDON_IS_TIME_EDITOR(editor)); + g_return_if_fail(duration_max <= MAX_DURATION); + + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + + if( !priv->duration_mode ) + return; + + priv->duration_max = duration_max; + + /* Clamp the current value to the maximum if necessary */ + if (priv->ticks > duration_max) + { + hildon_time_editor_set_ticks (editor, duration_max); + } + + g_object_notify (G_OBJECT (editor), "duration_max"); +} + +/** + * hildon_time_editor_get_duration_max: + * @editor: the #HildonTimeEditor widget + * + * This function returns the longest duration the #HildonTimeEditor + * allows in the duration mode. + * + * Returns: maximum allowed duration in seconds + */ + +guint hildon_time_editor_get_duration_max (HildonTimeEditor * editor) +{ + HildonTimeEditorPrivate *priv; + + g_return_val_if_fail(HILDON_IS_TIME_EDITOR(editor), 0); + + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + + if( !priv->duration_mode ) + return (0); + + return (priv->duration_max); +} + + +/** + * hildon_time_editor_set_time: + * @editor: the #HildonTimeEditor widget + * @hours: hours + * @minutes: minutes + * @seconds: seconds + * + * This function sets the time on an existing time editor. If the + * time specified by the arguments is invalid, it's fixed. + * The time is assumed to be in 24h format. + */ + +void hildon_time_editor_set_time(HildonTimeEditor * editor, guint hours, + guint minutes, guint seconds) +{ + g_return_if_fail(HILDON_IS_TIME_EDITOR(editor)); + + hildon_time_editor_set_ticks (editor, TICKS(hours, minutes, seconds)); +} + +/** + * hildon_time_editor_get_time: + * @editor: the #HildonTimeEditor widget + * @hours: hours + * @minutes: minutes + * @seconds: seconds + * + * Gets the time of the #HildonTimeEditor widget. The time returned is + * always in 24h format. + */ + +void hildon_time_editor_get_time(HildonTimeEditor * editor, + guint * hours, + guint * minutes, guint * seconds) +{ + HildonTimeEditorPrivate *priv; + + g_return_if_fail(HILDON_IS_TIME_EDITOR(editor)); + + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + + ticks_to_time (hildon_time_editor_get_ticks (editor), + hours, minutes, seconds); +} + +/** + * hildon_time_editor_set_duration_range: + * @editor: the #HildonTimeEditor widget + * @min_seconds: minimum allowed time in seconds + * @max_seconds: maximum allowed time in seconds + * + * Sets the duration editor time range of the #HildonTimeEditor widget. + */ + +void hildon_time_editor_set_duration_range(HildonTimeEditor * editor, + guint min_seconds, + guint max_seconds) +{ + HildonTimeEditorPrivate *priv; + guint tmp; + + g_return_if_fail(HILDON_IS_TIME_EDITOR(editor)); + + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + /* Swap values if reversed */ + if (min_seconds > max_seconds) + { + tmp = max_seconds; + max_seconds = min_seconds; + min_seconds = tmp; + } + + hildon_time_editor_set_duration_max (editor, max_seconds); + hildon_time_editor_set_duration_min (editor, min_seconds); + + if (priv->duration_mode) { + /* Set minimum allowed value for duration editor. + FIXME: Shouldn't it be changed only if it's not in range? + Would change API, so won't touch this for now. */ + hildon_time_editor_set_ticks(editor, min_seconds); + } +} + +/** + * hildon_time_editor_get_duration_range: + * @editor: the #HildonTimeEditor widget + * @min_seconds: pointer to guint + * @max_seconds: pointer to guint + * + * Gets the duration editor time range of the #HildonTimeEditor widget. + */ + +void hildon_time_editor_get_duration_range(HildonTimeEditor * editor, + guint * min_seconds, + guint * max_seconds) +{ + HildonTimeEditorPrivate *priv; + + g_return_if_fail(HILDON_IS_TIME_EDITOR(editor)); + + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + + *min_seconds = priv->duration_min; + *max_seconds = priv->duration_max; +} + +static gboolean hildon_time_editor_check_locale(HildonTimeEditor * editor) +{ + HildonTimeEditorPrivate *priv; + + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + + /* Update time separator symbols */ + _hildon_time_editor_get_time_separators(GTK_LABEL(priv->hm_label), GTK_LABEL(priv->sec_label)); + + /* Get AM/PM symbols. */ + priv->am_symbol = g_strdup(nl_langinfo(AM_STR)); + priv->pm_symbol = g_strdup(nl_langinfo(PM_STR)); + + if (priv->am_symbol[0] == '\0') + return TRUE; + else { + /* 12h clock mode. Check if AM/PM should be before or after time. + %p is the AM/PM string, so we assume that if the format string + begins with %p it's in the beginning, and in any other case it's + in the end (although that's not necessarily the case). */ + if (strncmp(nl_langinfo(T_FMT_AMPM), "%p", 2) == 0) + priv->ampm_pos_after = FALSE; + return FALSE; + } +} + +static gboolean hildon_time_editor_entry_focusin(GtkWidget * widget, + GdkEventFocus * event, + gpointer data) +{ + g_idle_add((GSourceFunc) _hildon_time_editor_entry_select_all, + GTK_ENTRY(widget)); + + return FALSE; +} + +static gboolean +hildon_time_editor_time_error(HildonTimeEditor *editor, + HildonTimeEditorErrorType type) +{ + return TRUE; +} + +/* Returns negative if we didn't get value, + * and should stop further validation + */ +static gint validated_conversion(HildonTimeEditorPrivate *priv, + GtkWidget *field, + gint min, + gint max, + gint def_value, + gboolean allow_intermediate, + guint *error_code, + GString *error_string) +{ + const gchar *text; + gchar *tail; + long value; + + text = gtk_entry_get_text(GTK_ENTRY(field)); + + if (text && text[0]) + { + /* Try to convert entry text to number */ + value = strtol(text, &tail, 10); + + /* Check if conversion succeeded */ + if ((tail[0] == 0) && !(text[0] == '-')) + { + if (value > max) { + g_string_printf(error_string, _("ckct_ib_maximum_value"), max); + priv->error_widget = field; + *error_code = MAX_VALUE; + return max; + } + if (value < min && !allow_intermediate) { + g_string_printf(error_string, _("ckct_ib_minimum_value"), min); + priv->error_widget = field; + *error_code = MIN_VALUE; + return min; + } + + return value; + } + /* We'll handle failed conversions soon */ + else + { + if ((tail[0] == '-') || (text[0] == '-')) + { + g_string_printf(error_string, _("ckct_ib_minimum_value"), min); + priv->error_widget = field; + *error_code = MIN_VALUE; + return min; + } + } + } + else if (allow_intermediate) + return -1; /* Empty field while user is still editing. No error, but + cannot validate either... */ + else /* Empty field: show error and set value to minimum allowed */ + { + g_string_printf(error_string, _("ckct_ib_set_a_value_within_range"), min, max); + priv->error_widget = field; + *error_code = WITHIN_RANGE; + return def_value; + } + + /* Empty field and not allowed intermediated OR failed conversion */ + g_string_printf(error_string, _("ckct_ib_set_a_value_within_range"), min, max); + priv->error_widget = field; + *error_code = WITHIN_RANGE; + return -1; +} + +static void +hildon_time_editor_real_validate(HildonTimeEditor *editor, + gboolean allow_intermediate, GString *error_string) +{ + HildonTimeEditorPrivate *priv; + guint h, m, s, ticks; + guint error_code; + guint max_hours, min_hours, def_hours; + guint max_minutes, min_minutes, def_minutes; + guint max_seconds, min_seconds, def_seconds; + gboolean r; + + g_assert(HILDON_IS_TIME_EDITOR(editor)); + + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + + /* Find limits for field based validation. */ + if (priv->duration_mode) + { + ticks_to_time(priv->duration_min, &min_hours, &min_minutes, &min_seconds); + ticks_to_time(priv->duration_max, &max_hours, &max_minutes, &max_seconds); + } else { + if (priv->clock_24h) { + max_hours = HOURS_MAX_24; + min_hours = HOURS_MIN_24; + } else { + max_hours = HOURS_MAX_12; + min_hours = HOURS_MIN_12; + } + } + + hildon_time_editor_get_time(editor, &def_hours, &def_minutes, &def_seconds); + + /* Get time components from fields and validate them... */ + if (priv->show_hours) { + h = validated_conversion(priv, priv->entries[ENTRY_HOURS], min_hours, max_hours, def_hours, + allow_intermediate, &error_code, error_string); + if (priv->error_widget == priv->entries[ENTRY_HOURS]) + g_signal_emit (editor, time_editor_signals [TIME_ERROR], 0, hour_errors[error_code], &r); + if ((gint) h < 0) return; + } + else h = 0; + m = validated_conversion(priv, priv->entries[ENTRY_MINS], MINUTES_MIN, MINUTES_MAX, def_minutes, + allow_intermediate, &error_code, error_string); + if (priv->error_widget == priv->entries[ENTRY_MINS]) + g_signal_emit (editor, time_editor_signals [TIME_ERROR], 0, min_errors[error_code], &r); + if ((gint) m < 0) return; + if (priv->show_seconds) { + s = validated_conversion(priv, priv->entries[ENTRY_SECS], SECONDS_MIN, SECONDS_MAX, def_seconds, + allow_intermediate, &error_code, error_string); + if (priv->error_widget == priv->entries[ENTRY_SECS]) + g_signal_emit (editor, time_editor_signals [TIME_ERROR], 0, sec_errors[error_code], &r); + if ((gint) s < 0) return; + } + else s = 0; + + /* Ok, we now do separate check that tick count is valid for duration mode */ + if (priv->duration_mode) + { + ticks = TICKS(h, m, s); + + if (ticks < priv->duration_min && !allow_intermediate) + { + g_string_printf(error_string, + _("ckct_ib_min_allowed_duration_hts"), + min_hours, min_minutes, min_seconds); + hildon_time_editor_set_ticks (editor, priv->duration_min); + priv->error_widget = priv->show_hours ? priv->entries[ENTRY_HOURS] : priv->entries[ENTRY_MINS]; + g_signal_emit (editor, time_editor_signals[TIME_ERROR], 0, MIN_DUR, &r); + return; + } + else if (ticks > priv->duration_max) + { + g_string_printf(error_string, + _("ckct_ib_max_allowed_duration_hts"), + max_hours, max_minutes, max_seconds); + hildon_time_editor_set_ticks (editor, priv->duration_max); + priv->error_widget = priv->show_hours ? priv->entries[ENTRY_HOURS] : priv->entries[ENTRY_MINS]; + g_signal_emit (editor, time_editor_signals[TIME_ERROR], 0, MAX_DUR, &r); + return; + } + } + else if (!priv->clock_24h) + convert_to_24h (&h, priv->am); + + /* The only case when we do not want to refresh the + time display, is when the user is editing a value + (unless the value was out of bounds and we have to fix it) */ + if (!allow_intermediate || priv->error_widget) + hildon_time_editor_set_time (editor, h, m, s); +} + +/* Setting text to entries causes entry to recompute itself + in idle callback, which remove selection. Because of this + we need to do selection in idle as well. */ +static gboolean highlight_callback(gpointer data) +{ + HildonTimeEditorPrivate *priv; + GtkWidget *widget; + gint i; + + g_assert(HILDON_IS_TIME_EDITOR(data)); + priv = HILDON_TIME_EDITOR_GET_PRIVATE(data); + + GDK_THREADS_ENTER (); + + widget = priv->error_widget; + priv->error_widget = NULL; + + if (GTK_IS_WIDGET(widget) == FALSE) + goto Done; + + /* Avoid revalidation because it will issue the date_error signal + twice when there is an empty field. We must block the signal + for all the entries because we do not know where the focus + comes from */ + for (i = 0; i < ENTRY_COUNT; i++) + g_signal_handlers_block_by_func(priv->entries[i], + (gpointer) hildon_time_editor_entry_focusout, data); + gtk_editable_select_region(GTK_EDITABLE(widget), 0, -1); + gtk_widget_grab_focus(widget); + for (i = 0; i < ENTRY_COUNT; i++) + g_signal_handlers_unblock_by_func(priv->entries[i], + (gpointer) hildon_time_editor_entry_focusout, data); + +Done: + priv->highlight_idle = 0; + GDK_THREADS_LEAVE (); + + return FALSE; +} + +/* Update ticks from current H:M:S entries. If they're invalid, show an + infoprint and update the fields unless they're empty. */ +static void +hildon_time_editor_validate (HildonTimeEditor *editor, gboolean allow_intermediate) +{ + HildonTimeEditorPrivate *priv; + GString *error_message; + + g_assert(HILDON_IS_TIME_EDITOR(editor)); + + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + + /* if there is already an error we do nothing until it will be managed by the idle */ + if (priv->highlight_idle == 0 && priv->skipper == FALSE) + { + priv->skipper = TRUE; + error_message = g_string_new(NULL); + hildon_time_editor_real_validate(editor, + allow_intermediate, error_message); + + if (priv->error_widget) + { + hildon_banner_show_information(priv->error_widget, NULL, + error_message->str); + + priv->highlight_idle = g_idle_add(highlight_callback, editor); + } + + priv->skipper = FALSE; + g_string_free(error_message, TRUE); + } +} + +/* on inserted text, if entry has two digits, jumps to the next field. */ +static void +hildon_time_editor_inserted_text (GtkEditable * editable, + gchar * new_text, + gint new_text_length, + gint * position, + gpointer user_data) +{ + HildonTimeEditor *editor; + GtkEntry *entry; + gchar *value; + HildonTimeEditorPrivate *priv; + + entry = GTK_ENTRY(editable); + editor = HILDON_TIME_EDITOR(user_data); + + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + + /* if there is already an error we don't have to do anything */ + if (!priv->error_widget) + { + + value = (gchar *) gtk_entry_get_text(entry); + + if (strlen(value) == 2) + { + if (GTK_WIDGET(editable) == priv->entries[ENTRY_HOURS]) + { + /* We already checked the input in changed signal, but + * now we will re-check it again in focus-out we + * intermediate flag set to FALSE */ + gtk_widget_grab_focus(priv->entries[ENTRY_MINS]); + *position = -1; + } + else if (GTK_WIDGET(editable) == priv->entries[ENTRY_MINS] && + GTK_WIDGET_VISIBLE (priv->entries[ENTRY_SECS])) + { + /* See above */ + gtk_widget_grab_focus(priv->entries[ENTRY_SECS]); + *position = -1; + } + } + } +} + +static gboolean hildon_time_editor_entry_focusout(GtkWidget * widget, + GdkEventFocus * event, + gpointer data) +{ + g_assert(HILDON_IS_TIME_EDITOR(data)); + + /* Validate the given time and update ticks. */ + hildon_time_editor_validate(HILDON_TIME_EDITOR(data), FALSE); + + return FALSE; +} + +static gboolean +hildon_time_editor_ampm_clicked(GtkWidget * widget, + gpointer data) +{ + HildonTimeEditor *editor; + HildonTimeEditorPrivate *priv; + + g_assert(GTK_IS_WIDGET(widget)); + g_assert(HILDON_IS_TIME_EDITOR(data)); + + editor = HILDON_TIME_EDITOR(data); + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + + /* First validate the given time and update ticks. */ + hildon_time_editor_validate (editor, FALSE); + + /* Apply the AM/PM change by moving the current time by 12 hours */ + if (priv->am) { + /* 00:00 .. 11:59 -> 12:00 .. 23:59 */ + hildon_time_editor_set_ticks (editor, priv->ticks + 12*3600); + } else { + /* 12:00 .. 23:59 -> 00:00 .. 11:59 */ + hildon_time_editor_set_ticks (editor, priv->ticks - 12*3600); + } + return FALSE; +} + +static gboolean +hildon_time_editor_icon_clicked(GtkWidget * widget, gpointer data) +{ + HildonTimeEditor *editor; + GtkWidget *picker; + GtkWidget *parent; + guint h, m, s, result; + HildonTimeEditorPrivate *priv; + + g_assert(HILDON_IS_TIME_EDITOR(data)); + + editor = HILDON_TIME_EDITOR(data); + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + + /* icon is passive in duration editor mode */ + if (hildon_time_editor_get_duration_mode(editor)) + return FALSE; + + /* Validate and do not launch if broken */ + hildon_time_editor_validate(HILDON_TIME_EDITOR(data), FALSE); + if (priv->error_widget != NULL) + return FALSE; + + /* Launch HildonTimePicker dialog */ + parent = gtk_widget_get_ancestor(GTK_WIDGET(editor), GTK_TYPE_WINDOW); + picker = hildon_time_picker_new(GTK_WINDOW(parent)); + + hildon_time_editor_get_time(editor, &h, &m, &s); + hildon_time_picker_set_time(HILDON_TIME_PICKER(picker), h, m); + + result = gtk_dialog_run(GTK_DIALOG(picker)); + switch (result) { + case GTK_RESPONSE_OK: + case GTK_RESPONSE_ACCEPT: + /* Use the selected time */ + hildon_time_picker_get_time(HILDON_TIME_PICKER(picker), &h, &m); + hildon_time_editor_set_time(editor, h, m, 0); + break; + default: + break; + } + + gtk_widget_destroy(picker); + return FALSE; +} + +static void hildon_time_editor_size_request(GtkWidget * widget, + GtkRequisition * requisition) +{ + HildonTimeEditor *editor; + HildonTimeEditorPrivate *priv; + GtkRequisition req; + + editor = HILDON_TIME_EDITOR(widget); + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + + /* Get frame's size */ + gtk_widget_size_request(priv->frame, requisition); + + if (GTK_WIDGET_VISIBLE(priv->iconbutton)) + { + gtk_widget_size_request(priv->iconbutton, &req); + /* Reserve space for icon */ + requisition->width += req.width + ICON_PRESSED + + HILDON_MARGIN_DEFAULT; + } + + /* FIXME: It's evil to use hardcoded TIME_EDITOR_HEIGHT. For now we'll + want to force this since themes might have varying thickness values + which cause the height to change. */ + requisition->height = TIME_EDITOR_HEIGHT; +} + +static void hildon_time_editor_size_allocate(GtkWidget * widget, + GtkAllocation * allocation) +{ + HildonTimeEditorPrivate *priv = HILDON_TIME_EDITOR_GET_PRIVATE(widget); + GtkAllocation alloc; + GtkRequisition req, max_req; + + widget->allocation = *allocation; + gtk_widget_get_child_requisition(widget, &max_req); + + /* Center horizontally */ + alloc.x = allocation->x + MAX(allocation->width - max_req.width, 0) / 2; + /* Center vertically */ + alloc.y = allocation->y + MAX(allocation->height - max_req.height, 0) / 2; + + /* allocate frame */ + gtk_widget_get_child_requisition(priv->frame, &req); + + alloc.width = req.width; + alloc.height = max_req.height; + gtk_widget_size_allocate(priv->frame, &alloc); + + /* allocate icon */ + if (GTK_WIDGET_VISIBLE(priv->iconbutton)) { + gtk_widget_get_child_requisition(priv->iconbutton, &req); + + alloc.x += alloc.width + HILDON_MARGIN_DEFAULT; + alloc.width = req.width; + gtk_widget_size_allocate(priv->iconbutton, &alloc); + } + + /* FIXME: ugly way to move labels up. They just don't seem move up + otherwise. This is likely because we force the editor to be + smaller than it otherwise would be. */ + alloc = priv->ampm_label->allocation; + alloc.y = allocation->y - 2; + alloc.height = max_req.height + 2; + gtk_widget_size_allocate(priv->ampm_label, &alloc); + + alloc = priv->hm_label->allocation; + alloc.y = allocation->y - 2; + alloc.height = max_req.height + 2; + gtk_widget_size_allocate(priv->hm_label, &alloc); + + alloc = priv->sec_label->allocation; + alloc.y = allocation->y - 2; + alloc.height = max_req.height + 2; + gtk_widget_size_allocate(priv->sec_label, &alloc); +} + +static gboolean hildon_time_editor_entry_keypress(GtkWidget * widget, + GdkEventKey * event, + gpointer data) +{ + HildonTimeEditor *editor; + HildonTimeEditorPrivate *priv; + gint cursor_pos; + gboolean r; + + g_assert(GTK_IS_ENTRY(widget)); + g_assert(event != NULL); + g_assert(HILDON_IS_TIME_EDITOR(data)); + + editor = HILDON_TIME_EDITOR(data); + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + cursor_pos = gtk_editable_get_position(GTK_EDITABLE(widget)); + + /* Show error message in case the key pressed is not allowed + (only digits and control characters are allowed )*/ + if (!g_unichar_isdigit(event->keyval) && !(event->keyval & 0xF000)) { + g_signal_emit(editor, time_editor_signals[TIME_ERROR], 0, INVALID_CHAR, &r); + hildon_banner_show_information(widget, NULL, _("ckct_ib_illegal_character")); + return TRUE; + } + + switch (event->keyval) + { + case GDK_Return: + /* Return key popups up time picker dialog. Visually it looks as if + the time picker icon was clicked. Before opening the time picker + the fields are first validated and fixed. */ + hildon_time_editor_validate (editor, FALSE); + hildon_gtk_button_set_depressed(GTK_BUTTON(priv->iconbutton), TRUE); + hildon_time_editor_icon_clicked(widget, data); + hildon_gtk_button_set_depressed(GTK_BUTTON(priv->iconbutton), FALSE); + return TRUE; + + case GDK_Left: + /* left arrow pressed in the entry. If we are on first position, try to + move to the previous field. */ + if (cursor_pos == 0) { + (void) gtk_widget_child_focus(GTK_WIDGET(editor), GTK_DIR_LEFT); + return TRUE; + } + break; + + case GDK_Right: + /* right arrow pressed in the entry. If we are on last position, try to + move to the next field. */ + if (cursor_pos >= g_utf8_strlen(gtk_entry_get_text(GTK_ENTRY(widget)), -1)) { + (void) gtk_widget_child_focus(GTK_WIDGET(editor), GTK_DIR_RIGHT); + return TRUE; + } + break; + + default: + break; + }; + + return FALSE; +} + +/*** + * Utility functions + */ + +static void +convert_to_12h (guint *h, gboolean *am) +{ + g_assert(0 <= *h && *h < 24); + + /* 00:00 to 00:59 add 12 hours */ + /* 01:00 to 11:59 straight to am */ + /* 12:00 to 12:59 straight to pm */ + /* 13:00 to 23:59 subtract 12 hours */ + + if ( *h == 0 ) { *am = TRUE; *h += 12;} + else if ( 1 <= *h && *h < 12 ) { *am = TRUE; } + else if ( 12 <= *h && *h < 13 ) { *am = FALSE; } + else { *am = FALSE; *h -= 12;} +} + +static void +convert_to_24h (guint *h, gboolean am) +{ + if (*h == 12 && am) /* 12 midnight - 12:59 AM subtract 12 hours */ + { + *h -= 12; + } + else if (!am && 1 <= *h && *h < 12) /* 1:00 PM - 11:59 AM add 12 hours */ + { + *h += 12; + } +} + +/** + * hildon_time_editor_set_show_hours: + * @editor: The #HildonTimeEditor. + * @enable: Enable or disable showing of hours. + * + * This function shows or hides the hours field. + * + * Since: 0.12.4 + **/ +void hildon_time_editor_set_show_hours(HildonTimeEditor * editor, + gboolean show_hours) +{ + HildonTimeEditorPrivate *priv; + + g_return_if_fail(HILDON_IS_TIME_EDITOR(editor)); + + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + + if (show_hours != priv->show_hours) { + priv->show_hours = show_hours; + + /* show/hide hours field and its ':' label if the value changed. */ + if (show_hours) { + gtk_widget_show(priv->entries[ENTRY_HOURS]); + gtk_widget_show(priv->hm_label); + } else { + gtk_widget_hide(priv->entries[ENTRY_HOURS]); + gtk_widget_hide(priv->hm_label); + } + + g_object_notify (G_OBJECT (editor), "show_hours"); + } +} + +/** + * hildon_time_editor_get_show_hours: + * @self: the @HildonTimeEditor widget. + * + * This function returns a boolean indicating the visibility of + * hours in the @HildonTimeEditor + * + * Return value: TRUE if hours are visible. + * + * Since: 0.12.4-1 + **/ +gboolean hildon_time_editor_get_show_hours(HildonTimeEditor *editor) +{ + HildonTimeEditorPrivate *priv; + + g_return_val_if_fail (HILDON_IS_TIME_EDITOR (editor), FALSE); + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + + return priv->show_hours; +} + +/*** + * Deprecated functions + */ + +/** + * hildon_time_editor_show_seconds: + * @editor: the #HildonTimeEditor + * @enable: enable or disable showing of seconds + * + * This function is deprecated, + * use #hildon_time_editor_set_show_seconds instead. + */ +void hildon_time_editor_show_seconds(HildonTimeEditor * editor, + gboolean enable) +{ + hildon_time_editor_set_show_seconds (editor, enable); +} +/** + * hildon_time_editor_enable_duration_mode: + * @editor: the #HildonTimeEditor + * @enable: enable or disable duration editor mode + * + * This function is deprecated, + * use #hildon_time_editor_set_duration_mode instead. + */ +void hildon_time_editor_enable_duration_mode(HildonTimeEditor * editor, + gboolean enable) +{ + hildon_time_editor_set_duration_mode (editor, enable); +} + +/* Idle callback */ +static gboolean +_hildon_time_editor_entry_select_all (GtkWidget *widget) +{ + GDK_THREADS_ENTER (); + gtk_editable_select_region(GTK_EDITABLE(widget), 0, -1); + GDK_THREADS_LEAVE (); + return FALSE; +} diff --git a/src/hildon-time-editor.h b/src/hildon-time-editor.h new file mode 100644 index 0000000..7169fa0 --- /dev/null +++ b/src/hildon-time-editor.h @@ -0,0 +1,121 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_TIME_EDITOR_H__ +#define __HILDON_TIME_EDITOR_H__ + +#include + +G_BEGIN_DECLS + +#define HILDON_TYPE_TIME_EDITOR (hildon_time_editor_get_type()) + +#define HILDON_TIME_EDITOR(obj) (GTK_CHECK_CAST (obj, HILDON_TYPE_TIME_EDITOR, HildonTimeEditor)) +#define HILDON_TIME_EDITOR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), HILDON_TYPE_TIME_EDITOR, HildonTimeEditorClass)) + +#define HILDON_IS_TIME_EDITOR(obj) (GTK_CHECK_TYPE (obj, HILDON_TYPE_TIME_EDITOR)) +#define HILDON_IS_TIME_EDITOR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_TIME_EDITOR)) + + +typedef enum +{ + NO_TIME_ERROR = -1, + MAX_HOURS, + MAX_MINS, + MAX_SECS, + MIN_HOURS, + MIN_MINS, + MIN_SECS, + EMPTY_HOURS, + EMPTY_MINS, + EMPTY_SECS, + MIN_DUR, + MAX_DUR, + INVALID_TIME, + INVALID_CHAR +} HildonTimeEditorErrorType; + +typedef struct _HildonTimeEditor HildonTimeEditor; +typedef struct _HildonTimeEditorClass HildonTimeEditorClass; + +struct _HildonTimeEditor { + GtkContainer parent; +}; + +struct _HildonTimeEditorClass { + GtkContainerClass parent_class; + + gboolean (*time_error) (HildonTimeEditor *editor, + HildonTimeEditorErrorType type); +}; + +GType hildon_time_editor_get_type(void) G_GNUC_CONST; +GtkWidget *hildon_time_editor_new(void); + + +void hildon_time_editor_set_time (HildonTimeEditor * editor, + guint hours, + guint minutes, + guint seconds); + +void hildon_time_editor_get_time (HildonTimeEditor * editor, + guint * hours, + guint * minutes, + guint * seconds); + +#ifndef HILDON_DISABLE_DEPRECATED +void hildon_time_editor_show_seconds (HildonTimeEditor * editor, gboolean enable); +void hildon_time_editor_enable_duration_mode (HildonTimeEditor * editor, gboolean enable); +#endif /* HILDON_DISABLE_DEPRECATED */ + + +void hildon_time_editor_set_duration_range (HildonTimeEditor * editor, + guint min_seconds, + guint max_seconds); + +void hildon_time_editor_get_duration_range (HildonTimeEditor * editor, + guint * min_seconds, + guint * max_seconds); + +void hildon_time_editor_set_ticks (HildonTimeEditor * editor, guint ticks); +guint hildon_time_editor_get_ticks (HildonTimeEditor * editor); + +void hildon_time_editor_set_show_seconds (HildonTimeEditor * editor, gboolean show_seconds); +gboolean hildon_time_editor_get_show_seconds (HildonTimeEditor * editor); + +void hildon_time_editor_set_show_hours (HildonTimeEditor * editor, gboolean show_hours); +gboolean hildon_time_editor_get_show_hours (HildonTimeEditor * editor); + +void hildon_time_editor_set_duration_mode (HildonTimeEditor * editor, gboolean duration_mode); +gboolean hildon_time_editor_get_duration_mode (HildonTimeEditor * editor); + +void hildon_time_editor_set_duration_min (HildonTimeEditor * editor, guint duration_min); +guint hildon_time_editor_get_duration_min (HildonTimeEditor * editor); + +void hildon_time_editor_set_duration_max (HildonTimeEditor * editor, guint duration_max); +guint hildon_time_editor_get_duration_max (HildonTimeEditor * editor); + + +G_END_DECLS +#endif /* __HILDON_TIME_EDITOR_H__ */ diff --git a/src/hildon-time-picker.c b/src/hildon-time-picker.c new file mode 100644 index 0000000..bdf6fba --- /dev/null +++ b/src/hildon-time-picker.c @@ -0,0 +1,933 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-time-picker + * @short_description: A dialog popup widget which lets the user set the time + * @see_also: #HildonTimeEditor + * + * #HildonTimePicker is a dialog popup widget which lets the user set the time, + * using up/down arrows on hours and minutes. There are two arrows for minutes, + * so that minutes can be added also in 10 min increments.This widget is mainly + * used as a part of #HildonTimeEditor implementation. + */ + +#include "hildon-time-picker.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#define _(String) dgettext(PACKAGE, String) + +#define HILDON_TIME_PICKER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_TIME_PICKER, HildonTimePickerPrivate)) + +#define DEFAULT_HOURS 1 +#define DEFAULT_MINUTES 1 +#define DEFAULT_ARROW_WIDTH 26 +#define DEFAULT_ARROW_HEIGHT 26 + +#define MINS_IN_1H (60) +#define MINS_IN_24H (MINS_IN_1H * 24) +#define MINS_IN_12H (MINS_IN_1H * 12) + +#define HILDON_TIME_PICKER_LABEL_X_PADDING 0 +#define HILDON_TIME_PICKER_LABEL_Y_PADDING 1 + + +/* Indices for grouped labels in priv->widgets */ +enum +{ + WIDGET_GROUP_HOURS, + WIDGET_GROUP_10_MINUTES, + WIDGET_GROUP_1_MINUTES, + WIDGET_GROUP_AMPM, + + WIDGET_GROUP_COUNT +}; + +/* Indices for up/down buttons in group->buttons */ +enum +{ + BUTTON_UP, + BUTTON_DOWN, + + BUTTON_COUNT +}; + +typedef struct +{ + GtkWidget *frame; + GtkWidget *eventbox; + GtkLabel *label; + + /* buttons are used for hours and minutes, but not for am/pm */ + GtkWidget *buttons[BUTTON_COUNT]; + +} HildonTimePickerWidgetGroup; + +static GtkDialogClass *parent_class; + +struct _HildonTimePickerPrivate +{ + HildonTimePickerWidgetGroup widgets[WIDGET_GROUP_COUNT]; + + gchar *am_symbol; + gchar *pm_symbol; + + guint key_repeat; + guint minutes; /* time in minutes since midnight */ + gint mul; /* for key repeat handling */ + guint timer_id; + + guint show_ampm : 1; /* 12 hour clock, show AM/PM */ + guint ampm_left : 1; + guint button_press : 1; + guint start_key_repeat : 1; +}; + +enum +{ + PROP_MINUTES = 1 +}; + + +static const gint button_multipliers[WIDGET_GROUP_COUNT][2] = +{ + { MINS_IN_1H, -MINS_IN_1H }, + { 10, -10 }, + { 1, -1 }, + { 0, 0 } +}; + +static void +hildon_time_picker_class_init( HildonTimePickerClass *klass ); + +static void +hildon_time_picker_init( HildonTimePicker *picker ); + +static gboolean +hildon_time_picker_key_repeat_timeout( gpointer tpicker ); + +static void +hildon_time_picker_change_time( HildonTimePicker *picker, guint minutes ); + +static gboolean +hildon_time_picker_ampm_release( GtkWidget *widget, GdkEvent *event, + HildonTimePicker *picker ); + +static gboolean +hildon_time_picker_arrow_press( GtkWidget *widget, GdkEvent *event, + HildonTimePicker *picker ); +static gboolean +hildon_time_picker_arrow_release( GtkWidget *widget, GdkEvent *event, + HildonTimePicker *picker ); + +static void +hildon_time_picker_finalize( GObject *object ); + +static void +hildon_time_picker_get_property( GObject *object, guint param_id, + GValue *value, GParamSpec *pspec ); + +static void +hildon_time_picker_set_property( GObject *object, guint param_id, + const GValue *value, GParamSpec *pspec ); + +static gboolean +hildon_time_picker_event_box_focus_in( GtkWidget *widget, GdkEvent *event, + gpointer unused ); + +static gboolean +hildon_time_picker_event_box_focus_out( GtkWidget *widget, GdkEvent *event, + gpointer unused ); + +static gboolean +hildon_time_picker_event_box_key_press( GtkWidget *widget, GdkEventKey *event, + HildonTimePicker *picker ); + +static gboolean +hildon_time_picker_event_box_key_release( GtkWidget *widget, GdkEventKey *event, + HildonTimePicker *picker ); + +static gboolean +hildon_time_picker_event_box_button_press( GtkWidget *widget, GdkEventKey *event, + gpointer unused ); + +static void +hildon_time_picker_map( GtkWidget *widget ); + +static void +frame_size_request (GtkWidget *widget, GtkRequisition *requistion); + +GType hildon_time_picker_get_type( void ) +{ + static GType picker_type = 0; + + if( !picker_type ) + { + static const GTypeInfo picker_info = + { + sizeof(HildonTimePickerClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)hildon_time_picker_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonTimePicker), + 0, /* n_preallocs */ + (GInstanceInitFunc)hildon_time_picker_init, + }; + picker_type = g_type_register_static( GTK_TYPE_DIALOG, "HildonTimePicker", + &picker_info, 0 ); + } + return picker_type; +} + + +static void +hildon_time_picker_class_init( HildonTimePickerClass *klass ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); + parent_class = g_type_class_peek_parent( klass ); + + gobject_class->finalize = hildon_time_picker_finalize; + gobject_class->get_property = hildon_time_picker_get_property; + gobject_class->set_property = hildon_time_picker_set_property; + widget_class->map = hildon_time_picker_map; + + /** + * HildonTimePicker:minutes: + * + * Currently selected time in minutes since midnight. + */ + g_object_class_install_property( gobject_class, PROP_MINUTES, + g_param_spec_uint("minutes", + "Current minutes", + "The selected time in minutes " + "since midnight", + 0, MINS_IN_24H, 0, + G_PARAM_READABLE | G_PARAM_WRITABLE) ); + + gtk_widget_class_install_style_property( widget_class, + g_param_spec_uint("arrow-width", + "Arrow width", + "Increase/decrease arrows width.", + 0, G_MAXUINT, + DEFAULT_ARROW_WIDTH, + G_PARAM_READABLE) ); + + gtk_widget_class_install_style_property( widget_class, + g_param_spec_uint("arrow-height", + "Arrow height", + "Increase/decrease arrows height.", + 0, G_MAXUINT, + DEFAULT_ARROW_HEIGHT, + G_PARAM_READABLE) ); + + g_type_class_add_private( klass, sizeof(HildonTimePickerPrivate) ); +} + +/* Okay, this is really bad. We make the requisition of the frames a bit larger + * so that it doesn't "change" when digits are changed (see #37489). It's a + * really bad solution to a problem, but the whole layout of the time picker is + * on crack anyways */ +static void frame_size_request (GtkWidget *widget, GtkRequisition *requistion) +{ + int framed = requistion->width / 10; + requistion->width = (framed + 1) * 10; +} + +static void hildon_time_picker_init( HildonTimePicker *picker ) +{ + HildonTimePickerPrivate *priv = HILDON_TIME_PICKER_GET_PRIVATE(picker); + gint widget_group_table_column_pos[WIDGET_GROUP_COUNT]; + GtkSettings *settings = NULL; + GtkDialog *dialog = GTK_DIALOG(picker); + GtkTable *table = NULL; + GtkWidget *maintocenter, *colon_label; + const struct tm *local = NULL; + time_t stamp; + gint i = 0; + GtkSizeGroup *size_group; + + picker->priv = priv; + + widget_group_table_column_pos[WIDGET_GROUP_HOURS] = 1; + widget_group_table_column_pos[WIDGET_GROUP_10_MINUTES] = 3; + widget_group_table_column_pos[WIDGET_GROUP_1_MINUTES] = 4; + widget_group_table_column_pos[WIDGET_GROUP_AMPM] = 5; + + /* Get AM/PM strings from locale. If they're set, the time is wanted + in 12 hour mode. */ + priv->am_symbol = g_strdup(nl_langinfo(AM_STR)); + priv->pm_symbol = g_strdup(nl_langinfo(PM_STR)); + + priv->show_ampm = priv->am_symbol[0] != '\0'; + if (priv->show_ampm) + { + /* Check if AM/PM should be before or after time. + %p is the AM/PM string, so we assume that if the format string + begins with %p it's in the beginning, and in any other case it's + in the end (although that's not necessarily the case). */ + if (strncmp(nl_langinfo(T_FMT_AMPM), "%p", 2) == 0) + { + /* Before time. Update column position. */ + priv->ampm_left = TRUE; + widget_group_table_column_pos[WIDGET_GROUP_AMPM] = 0; + } + } + + gtk_widget_push_composite_child(); + + /* Pack all our internal widgets into a table */ + table = GTK_TABLE(gtk_table_new(3, 6, FALSE)); + + /* Put everything centered into window */ + maintocenter = gtk_alignment_new( 0.5, 0, 0, 0 ); + + /* Create our internal widgets */ + for (i = 0; i < WIDGET_GROUP_COUNT; i++) + { + HildonTimePickerWidgetGroup *group = &priv->widgets[i]; + gint table_column = widget_group_table_column_pos[i]; + + /* Create frame and attach to table. With AM/PM label we're attaching + it later. */ + group->frame = gtk_frame_new(NULL); + if (i != WIDGET_GROUP_AMPM) + { + gtk_table_attach(table, group->frame, table_column, table_column + 1, + 1, 2, GTK_EXPAND, GTK_EXPAND, 0, 0); + + + } + /* FIXME: is it needed to force it to 0 here? */ + gtk_container_set_border_width(GTK_CONTAINER(group->frame), 0); + + /* Create eventbox inside frame */ + group->eventbox = gtk_event_box_new(); + gtk_container_add(GTK_CONTAINER(group->frame), group->eventbox); + + g_object_set(group->eventbox, "can-focus", TRUE, NULL); + gtk_widget_set_events(group->eventbox, + GDK_FOCUS_CHANGE_MASK | GDK_BUTTON_PRESS_MASK ); + + /* Connect signals to eventbox */ + g_signal_connect(group->eventbox, "key-release-event", + G_CALLBACK(hildon_time_picker_event_box_key_release), + picker); + g_signal_connect(group->eventbox, "key-press-event", + G_CALLBACK(hildon_time_picker_event_box_key_press), + picker); + g_signal_connect(group->eventbox, "focus-in-event", + G_CALLBACK(hildon_time_picker_event_box_focus_in), + picker); + g_signal_connect(group->eventbox, "focus-out-event", + G_CALLBACK(hildon_time_picker_event_box_focus_out), + picker); + g_signal_connect(group->eventbox, "button-press-event", + G_CALLBACK(hildon_time_picker_event_box_button_press), + picker); + + /* Create label inside eventbox */ + group->label = GTK_LABEL(gtk_label_new(NULL)); + g_signal_connect(group->frame, "size-request", + G_CALLBACK(frame_size_request), + NULL); + gtk_misc_set_alignment (GTK_MISC (group->label), 0.5, 0.5); + gtk_container_add(GTK_CONTAINER(group->eventbox), GTK_WIDGET(group->label)); + + if (i != WIDGET_GROUP_AMPM) + { + gint button; + + /* Add some padding to hour and minute labels, and make them bigger */ + gtk_misc_set_padding(GTK_MISC(group->label), + HILDON_TIME_PICKER_LABEL_X_PADDING, + HILDON_TIME_PICKER_LABEL_Y_PADDING); + gtk_widget_set_name(GTK_WIDGET(group->label), "osso-LargeFont"); + + /* Create up and down buttons for hours and mins */ + for (button = 0; button < BUTTON_COUNT; button++) + { + gint table_row = button == BUTTON_UP ? 0 : 2; + + group->buttons[button] = gtk_button_new(); + gtk_table_attach(table, group->buttons[button], + table_column, table_column + 1, + table_row, table_row + 1, + GTK_SHRINK, GTK_SHRINK, 0, 0); + g_object_set(group->buttons[button], "can-focus", FALSE, NULL); + + /* Connect signals */ + g_signal_connect(group->buttons[button], "button-press-event", + G_CALLBACK(hildon_time_picker_arrow_press), picker); + g_signal_connect(group->buttons[button], "button-release-event", + G_CALLBACK(hildon_time_picker_arrow_release), picker); + } + + gtk_widget_set_name(group->buttons[BUTTON_UP], + "hildon-time-picker-up"); + gtk_widget_set_name(group->buttons[BUTTON_DOWN], + "hildon-time-picker-down"); + } + } + + /* Label between hour and minutes */ + colon_label = gtk_label_new(NULL); + _hildon_time_editor_get_time_separators(GTK_LABEL(colon_label), NULL); + + gtk_table_attach(table, colon_label, 2, 3, 1, 2, + GTK_SHRINK, GTK_SHRINK, 6, 0); /* FIXME: magic */ + gtk_widget_set_name(colon_label, "osso-LargeFont" ); + + priv->minutes = 0; + priv->mul = 0; + priv->key_repeat = 0; + priv->start_key_repeat = FALSE; + priv->timer_id = 0; + priv->button_press = FALSE; + + gtk_table_set_row_spacing( table, 0, 6 ); + gtk_table_set_row_spacing( table, 1, 6 ); + + if (priv->show_ampm) + { + gint table_column = widget_group_table_column_pos[WIDGET_GROUP_AMPM]; + GtkWidget *ampmtotop = NULL; + + /* Show the AM/PM label centered vertically */ + ampmtotop = gtk_alignment_new( 0, 0.5, 0, 0 ); + gtk_table_attach(table, ampmtotop, table_column, table_column + 1, + 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); + gtk_container_add(GTK_CONTAINER(ampmtotop), + priv->widgets[WIDGET_GROUP_AMPM].frame); + + if (table_column != 0) + gtk_table_set_col_spacing(table, table_column - 1, 9); + + /* Connect AM/PM signal handlers */ + g_signal_connect(priv->widgets[WIDGET_GROUP_AMPM].eventbox, + "button-release-event", + G_CALLBACK(hildon_time_picker_ampm_release), picker); + } + + gtk_widget_pop_composite_child(); + + /* Get button press repeater timeout from settings (in milliseconds) */ + settings = gtk_settings_get_default(); + g_object_get( settings, "gtk-update-timeout", &priv->key_repeat, NULL ); + + /* This dialog isn't modal */ + gtk_window_set_modal( GTK_WINDOW(dialog), FALSE ); + /* And final dialog packing */ + gtk_dialog_set_has_separator( dialog, FALSE ); + gtk_dialog_add_button( dialog, _("ecdg_bd_time_picker_close"), + GTK_RESPONSE_OK ); + + gtk_container_add( GTK_CONTAINER(maintocenter), GTK_WIDGET(table) ); + gtk_box_pack_start( GTK_BOX(dialog->vbox), maintocenter, TRUE, FALSE, 0 ); + + /* Set default time to current time */ + stamp = time( NULL ); + local = localtime( &stamp ); + hildon_time_picker_set_time( picker, local->tm_hour, local->tm_min ); + + gtk_widget_show_all( maintocenter ); +} + +static void +hildon_time_picker_set_property( GObject *object, guint param_id, + const GValue *value, GParamSpec *pspec ) +{ + HildonTimePicker *picker = HILDON_TIME_PICKER(object); + + switch( param_id ) + { + case PROP_MINUTES: + hildon_time_picker_change_time( picker, g_value_get_uint(value) ); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); + break; + } +} + +static void +hildon_time_picker_finalize( GObject *object ) +{ + HildonTimePicker *picker = HILDON_TIME_PICKER(object); + + /* Make sure the timer is stopped */ + if (picker->priv->timer_id) + g_source_remove(picker->priv->timer_id); + + g_free(picker->priv->am_symbol); + g_free(picker->priv->pm_symbol); + + if (G_OBJECT_CLASS(parent_class)->finalize) + G_OBJECT_CLASS(parent_class)->finalize(object); +} + +static void +hildon_time_picker_get_property( GObject *object, guint param_id, + GValue *value, GParamSpec *pspec ) +{ + HildonTimePickerPrivate *priv = HILDON_TIME_PICKER(object)->priv; + + switch( param_id ) + { + case PROP_MINUTES: + g_value_set_uint( value, priv->minutes ); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); + break; + } +} + +static void +hildon_time_picker_map( GtkWidget *widget ) +{ + guint width, height; + gint i, button; + HildonTimePickerPrivate *priv = HILDON_TIME_PICKER(widget)->priv; + + /* Widget is now mapped. Set border for the dialog. */ + gdk_window_set_decorations( widget->window, GDK_DECOR_BORDER ); + + /* Update hour/minute up/down buttons sizes from style properties */ + gtk_widget_style_get( widget, + "arrow-width", &width, + "arrow-height", &height, NULL ); + for (i = 0; i < WIDGET_GROUP_COUNT; i++) + { + if (priv->widgets[i].buttons[0] != NULL) + { + for (button = 0; button < BUTTON_COUNT; button++) + { + gtk_widget_set_size_request(priv->widgets[i].buttons[button], + width, height); + } + } + } + + GTK_WIDGET_CLASS(parent_class)->map( widget ); +} + + +static gboolean +hildon_time_picker_event_box_button_press( GtkWidget *widget, + GdkEventKey *event, gpointer unused ) +{ + /* Clicked hour/minute field. Move focus to it. */ + gtk_widget_grab_focus( widget ); + return FALSE; +} + +static gboolean +hildon_time_picker_ampm_release( GtkWidget *widget, GdkEvent *event, + HildonTimePicker *picker ) +{ + /* Clicked AM/PM label. Move focus to it and move the time by 12 hours. */ + gtk_widget_grab_focus( widget ); + hildon_time_picker_change_time( picker, picker->priv->minutes > MINS_IN_12H ? + picker->priv->minutes - MINS_IN_12H : + picker->priv->minutes + MINS_IN_12H ); + return FALSE; +} + +static gboolean +hildon_time_picker_arrow_press( GtkWidget *widget, GdkEvent *event, + HildonTimePicker *picker ) +{ + HildonTimePickerPrivate *priv = picker->priv; + gint i, button; + gint newval = 0; + + /* Make sure we don't add repeat timer twice. Normally it shouldn't + happen but WM can cause button release to be lost. */ + if( priv->button_press ) + return FALSE; + + priv->start_key_repeat = priv->button_press = TRUE; + + /* Find the widget which was clicked */ + priv->mul = 0; + for (i = 0; i < WIDGET_GROUP_COUNT; i++) + { + for (button = 0; button < BUTTON_COUNT; button++) + { + if (priv->widgets[i].buttons[button] == widget) + { + /* Update multiplier and move the focus to the clicked field */ + priv->mul = button_multipliers[i][button]; + gtk_widget_grab_focus(priv->widgets[i].eventbox); + break; + } + } + } + g_assert(priv->mul != 0); + + /* Change the time now, wrapping if needed. */ + newval = priv->minutes + priv->mul; + if( newval < 0 ) + newval += MINS_IN_24H; + + hildon_time_picker_change_time( picker, newval ); + + /* Keep changing the time as long as button is being pressed. + The first repeat takes 3 times longer to start than the rest. */ + priv->timer_id = g_timeout_add(priv->key_repeat * 3, + hildon_time_picker_key_repeat_timeout, + picker); + return FALSE; +} + +static gboolean +hildon_time_picker_arrow_release( GtkWidget *widget, GdkEvent *event, + HildonTimePicker *picker ) +{ + HildonTimePickerPrivate *priv = picker->priv; + if( priv->timer_id ) + { + /* Stop repeat timer */ + g_source_remove( priv->timer_id ); + priv->timer_id = 0; + } + priv->button_press = FALSE; + return FALSE; +} + +static gboolean +hildon_time_picker_event_box_focus_in( GtkWidget *widget, GdkEvent *event, + gpointer unused ) +{ + /* Draw the widget in selected state so focus shows clearly. */ + gtk_widget_set_state( widget, GTK_STATE_SELECTED ); + return FALSE; +} + +static gboolean +hildon_time_picker_event_box_focus_out( GtkWidget *widget, GdkEvent *event, + gpointer unused ) +{ + /* Draw the widget in normal state */ + gtk_widget_set_state( widget, GTK_STATE_NORMAL ); + return FALSE; +} + +static gint +hildon_time_picker_lookup_eventbox_group(HildonTimePicker *picker, + GtkWidget *widget) +{ + gint i; + + for (i = 0; i < WIDGET_GROUP_COUNT; i++) + { + if (picker->priv->widgets[i].eventbox == widget) + return i; + } + return -1; +} + +static gboolean +hildon_time_picker_event_box_key_press( GtkWidget *widget, GdkEventKey *event, + HildonTimePicker *picker ) +{ + HildonTimePickerPrivate *priv = picker->priv; + HildonTimePickerWidgetGroup *group; + gint group_idx; + + /* If mouse button is already being pressed, ignore this keypress */ + if( priv->timer_id ) + return TRUE; + + group_idx = hildon_time_picker_lookup_eventbox_group(picker, widget); + group = group_idx < 0 ? NULL : &picker->priv->widgets[group_idx]; + + /* Handle keypresses in hour/minute/AMPM fields */ + switch( event->keyval ) + { + case GDK_Up: + case GDK_Down: + if (group != NULL) + { + gint button = event->keyval == GDK_Up ? BUTTON_UP : BUTTON_DOWN; + + if (group->buttons[button] != NULL) + { + /* Fake a button up/down press */ + hildon_time_picker_arrow_press(group->buttons[button], NULL, picker); + gtk_widget_set_state(group->buttons[button], GTK_STATE_SELECTED); + } + else + { + /* Fake a AM/PM button release */ + g_assert(group_idx == WIDGET_GROUP_AMPM); + hildon_time_picker_ampm_release(group->eventbox, NULL, picker); + } + } + return TRUE; + + case GDK_Left: + /* If we're in leftmost field, stop this keypress signal. + Otherwise let the default key handler move focus to field in left. */ + if (priv->show_ampm && priv->ampm_left) + { + /* AM/PM is the leftmost field */ + if (group_idx == WIDGET_GROUP_AMPM) + return TRUE; + } + else + { + /* Hours is the leftmost field */ + if (group_idx == WIDGET_GROUP_HOURS) + return TRUE; + } + break; + + case GDK_Right: + /* If we're in rightmost field, stop this keypress signal. + Otherwise let the default key handler move focus to field in right. */ + if (priv->show_ampm && !priv->ampm_left) + { + /* AM/PM is the rightmost field */ + if (group_idx == WIDGET_GROUP_AMPM) + return TRUE; + } + else + { + /* 1-minutes is the leftmost field */ + if (group_idx == WIDGET_GROUP_1_MINUTES) + return TRUE; + } + break; + + case GDK_Escape: + gtk_dialog_response (GTK_DIALOG (picker), GTK_RESPONSE_CANCEL); + return TRUE; + + case GDK_Return: + gtk_dialog_response (GTK_DIALOG (picker), GTK_RESPONSE_OK); + return TRUE; + } + + return FALSE; +} + +static gboolean +hildon_time_picker_event_box_key_release( GtkWidget *widget, GdkEventKey *event, + HildonTimePicker *picker ) +{ + HildonTimePickerWidgetGroup *group; + gint group_idx; + + /* Fake a button release if in key-press handler we faked a button press. */ + switch( event->keyval ) + { + case GDK_Up: + case GDK_Down: + group_idx = hildon_time_picker_lookup_eventbox_group(picker, widget); + if (group_idx >= 0) + { + gint button = event->keyval == GDK_Up ? BUTTON_UP : BUTTON_DOWN; + + group = &picker->priv->widgets[group_idx]; + if (group->buttons[button] != NULL) + { + /* Fake a button up/down press */ + gtk_widget_set_state(group->buttons[button], GTK_STATE_NORMAL); + hildon_time_picker_arrow_release(group->buttons[button], + NULL, picker); + } + } + break; + } + return FALSE; +} + +/* Button up/down is being pressed. Update the time. */ +static gboolean +hildon_time_picker_key_repeat_timeout( gpointer tpicker ) +{ + HildonTimePicker *picker; + HildonTimePickerPrivate *priv = NULL; + gint newval = 0; + + GDK_THREADS_ENTER (); + + picker = HILDON_TIME_PICKER(tpicker); + g_assert(picker != NULL); + + priv = picker->priv; + + /* Change the time, wrapping if needed */ + newval = priv->minutes + priv->mul; + if( newval < 0 ) + newval += MINS_IN_24H; + + hildon_time_picker_change_time( picker, newval ); + + if( priv->start_key_repeat ) + { + /* This is the first repeat. Shorten the timeout to key_repeat + (instead of the first time's 3*key_repeat) */ + priv->timer_id = g_timeout_add(priv->key_repeat, + hildon_time_picker_key_repeat_timeout, + picker); + priv->start_key_repeat = FALSE; + + GDK_THREADS_LEAVE (); + return FALSE; + } + + GDK_THREADS_LEAVE (); + return TRUE; +} + + + +static void +hildon_time_picker_change_time( HildonTimePicker *picker, guint minutes ) +{ + HildonTimePickerPrivate *priv = picker->priv; + gchar str[3] = "00"; + guint hours = 0; + gboolean ampm = TRUE; + + /* If the minutes isn't in valid range, wrap them. */ + minutes %= MINS_IN_24H; + + if( priv->minutes == minutes ) + return; + + /* Minutes changed. Update widgets to show the new time. */ + priv->minutes = minutes; + + if (priv->show_ampm) + { + /* am < 12:00 <= pm */ + ampm = !((guint)(minutes / MINS_IN_12H)); + /* 12:00 - 23:59 -> 00:00 - 11:59 */ + minutes %= MINS_IN_12H; + if( minutes < MINS_IN_1H ) + /* 00:mm is always shown as 12:mm */ + minutes += MINS_IN_12H; + + /* Update the AM/PM label */ + gtk_label_set_text(priv->widgets[WIDGET_GROUP_AMPM].label, + ampm ? priv->am_symbol : priv->pm_symbol); + } + + /* Update hour and minute fields */ + hours = minutes / MINS_IN_1H; + minutes %= MINS_IN_1H; + + snprintf(str, sizeof(str), "%02d", hours); + gtk_label_set_text(priv->widgets[WIDGET_GROUP_HOURS].label, str); + + snprintf(str, sizeof(str), "%d", minutes / 10); + gtk_label_set_text(priv->widgets[WIDGET_GROUP_10_MINUTES].label, str); + + snprintf(str, sizeof(str), "%d", minutes % 10); + gtk_label_set_text(priv->widgets[WIDGET_GROUP_1_MINUTES].label, str); + + g_object_notify( G_OBJECT(picker), "minutes" ); +} + +/** + * hildon_time_picker_new: + * @parent: parent window + * + * #HildonTimePicker shows time picker dialog. The close button is placed + * in the dialog's action area and time picker is placed in dialogs vbox. + * The actual time picker consists of two #GtkLabel fields - one for hours + * and one for minutes - and an AM/PM button. A colon (:) is placed + * between hour and minute fields. + * + * Returns: pointer to a new #HildonTimePicker widget. + */ +GtkWidget *hildon_time_picker_new( GtkWindow *parent ) +{ + GtkWidget *widget = g_object_new( HILDON_TYPE_TIME_PICKER, + "minutes", 360, NULL ); + + if( parent ) + gtk_window_set_transient_for( GTK_WINDOW(widget), parent ); + + return GTK_WIDGET(widget); +} + +/** + * hildon_time_picker_set_time: + * @picker: the #HildonTimePicker widget + * @hours: hours + * @minutes: minutes + * + * Sets the time of the #HildonTimePicker widget. + */ +void hildon_time_picker_set_time( HildonTimePicker *picker, + guint hours, guint minutes ) +{ + g_return_if_fail( HILDON_IS_TIME_PICKER(picker) ); + hildon_time_picker_change_time( picker, hours * MINS_IN_1H + minutes ); +} + +/** + * hildon_time_picker_get_time: + * @picker: the #HildonTimePicker widget + * @hours: hours + * @minutes: minutes + * + * Gets the time of the #HildonTimePicker widget. + */ +void hildon_time_picker_get_time( HildonTimePicker *picker, + guint *hours, guint *minutes ) +{ + guint current; + g_return_if_fail( HILDON_IS_TIME_PICKER(picker) ); + + current = picker->priv->minutes; + *hours = current / MINS_IN_1H; + *minutes = current % MINS_IN_1H; +} diff --git a/src/hildon-time-picker.h b/src/hildon-time-picker.h new file mode 100644 index 0000000..dcf79cf --- /dev/null +++ b/src/hildon-time-picker.h @@ -0,0 +1,74 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ +#ifndef __HILDON_TIME_PICKER_H__ +#define __HILDON_TIME_PICKER_H__ + +#include + +G_BEGIN_DECLS + + +#define HILDON_TYPE_TIME_PICKER (hildon_time_picker_get_type()) +#define HILDON_TIME_PICKER(obj) (GTK_CHECK_CAST (obj, \ + HILDON_TYPE_TIME_PICKER, \ + HildonTimePicker)) +#define HILDON_TIME_PICKER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), \ + HILDON_TYPE_TIME_PICKER,\ + HildonTimePickerClass)) +#define HILDON_IS_TIME_PICKER(obj) (GTK_CHECK_TYPE (obj, \ + HILDON_TYPE_TIME_PICKER)) +#define HILDON_IS_TIME_PICKER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass),\ + HILDON_TYPE_TIME_PICKER)) + + +typedef struct _HildonTimePicker HildonTimePicker; +typedef struct _HildonTimePickerClass HildonTimePickerClass; +typedef struct _HildonTimePickerPrivate HildonTimePickerPrivate; + + +struct _HildonTimePicker +{ + GtkDialog parent; + HildonTimePickerPrivate *priv; +}; + +struct _HildonTimePickerClass +{ + GtkDialogClass parent_class; +}; + + +GType hildon_time_picker_get_type( void ) G_GNUC_CONST; + +GtkWidget *hildon_time_picker_new( GtkWindow *parent ); + +void hildon_time_picker_set_time( HildonTimePicker *picker, + guint hours, guint minutes ); + +void hildon_time_picker_get_time( HildonTimePicker *picker, + guint *hours, guint *minutes ); + + +G_END_DECLS +#endif /* __HILDON_TIME_PICKER_H__ */ diff --git a/src/hildon-volumebar-private.h b/src/hildon-volumebar-private.h new file mode 100644 index 0000000..d93700f --- /dev/null +++ b/src/hildon-volumebar-private.h @@ -0,0 +1,47 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ +#ifndef __HILDON_VOLUMEBAR_PRIVATE__ +#define __HILDON_VOLUMEBAR_PRIVATE__ + +#include +#include + +G_BEGIN_DECLS +#define HILDON_VOLUMEBAR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_VOLUMEBAR, HildonVolumebarPrivate)); + +typedef struct _HildonVolumebarPrivate HildonVolumebarPrivate; + +struct _HildonVolumebarPrivate { + HildonVolumebarRange *volumebar; + GtkToggleButton *tbutton; + gboolean is_toolbar; /* is inside toolbar (for horizontal volumebar) */ + GdkWindow *event_window; /* input-only window to catch insensitive presses */ +}; + +void _hildon_volumebar_mute_toggled(HildonVolumebar * self); + +G_END_DECLS +#endif /* __HILDON_VOLUMEBAR_PRIVATE__ */ diff --git a/src/hildon-volumebar-range.c b/src/hildon-volumebar-range.c new file mode 100644 index 0000000..ef4b152 --- /dev/null +++ b/src/hildon-volumebar-range.c @@ -0,0 +1,293 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/* + * @file hildon-volumebar-range.c + * + * This file contains the implementation of the HildonVolumebarRange. + * This widget is an "workhorse" for #HildonVolumebar widget. + * It is not designed to be used as a standalone widget. + * + * Purpose of this widget is to act as an "container" for GtkScale + * widget. #HildonVolumebarRange changes some event parameters so + * that #HildonVolumebar can meet its specifications. + * + * Currently #HildonVolumebarRange models range of [0..100]. + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include "hildon-volumebar-range.h" + +#define VOLUMEBAR_RANGE_INITIAL_VALUE 50.0 +#define VOLUMEBAR_RANGE_MINIMUM_VALUE 0.0 +#define VOLUMEBAR_RANGE_MAXIMUM_VALUE 100.0 +#define VOLUMEBAR_RANGE_STEP_INCREMENT_VALUE 5.0 +#define VOLUMEBAR_RANGE_PAGE_INCREMENT_VALUE 5.0 +#define VOLUMEBAR_RANGE_PAGE_SIZE_VALUE 0.0 + +#define CHANGE_THRESHOLD 0.001 + +static GtkScaleClass *parent_class; + +static void hildon_volumebar_range_class_init(HildonVolumebarRangeClass * + volumerange_class); +static void hildon_volumebar_range_init(HildonVolumebarRange * + volumerange); +static void hildon_volumebar_range_set_property(GObject * object, + guint prop_id, + const GValue * value, + GParamSpec * pspec); +static void hildon_volumebar_range_get_property(GObject * object, + guint prop_id, + GValue * value, + GParamSpec * pspec); +static gint hildon_volumebar_range_button_press_event(GtkWidget * widget, + GdkEventButton * + event); +static gint hildon_volumebar_range_button_release_event(GtkWidget * widget, + GdkEventButton * + event); +static gboolean hildon_volumebar_range_keypress(GtkWidget * widget, + GdkEventKey * event); + +enum { + PROP_NONE = 0, + PROP_LEVEL +}; + +GType +hildon_volumebar_range_get_type(void) +{ + static GType volumerange_type = 0; + + if (!volumerange_type) { + static const GTypeInfo volumerange_info = { + sizeof(HildonVolumebarRangeClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_volumebar_range_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonVolumebarRange), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_volumebar_range_init, + }; + volumerange_type = g_type_register_static(GTK_TYPE_SCALE, + "HildonVolumebarRange", + &volumerange_info, 0); + } + return volumerange_type; +} + +static void +hildon_volumebar_range_class_init(HildonVolumebarRangeClass * + volumerange_class) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(volumerange_class); + GObjectClass *object_class = G_OBJECT_CLASS(volumerange_class); + + parent_class = g_type_class_peek_parent(volumerange_class); + + widget_class->button_press_event = + hildon_volumebar_range_button_press_event; + widget_class->button_release_event = + hildon_volumebar_range_button_release_event; + widget_class->key_press_event = hildon_volumebar_range_keypress; + + object_class->set_property = hildon_volumebar_range_set_property; + object_class->get_property = hildon_volumebar_range_get_property; + + g_object_class_install_property(object_class, + PROP_LEVEL, + g_param_spec_double("level", + "Level", + "Current volume level", + VOLUMEBAR_RANGE_MINIMUM_VALUE, + VOLUMEBAR_RANGE_MAXIMUM_VALUE, + VOLUMEBAR_RANGE_INITIAL_VALUE, + G_PARAM_READWRITE)); + return; +} + +static void +hildon_volumebar_range_init(HildonVolumebarRange * volumerange) +{ + /* stepper_a = "less", stepper_d = "more" */ + GTK_RANGE(volumerange)->has_stepper_a = TRUE; + GTK_RANGE(volumerange)->has_stepper_d = TRUE; +} + +static void +hildon_volumebar_range_set_property(GObject * object, + guint prop_id, + const GValue * value, + GParamSpec * pspec) +{ + HildonVolumebarRange *range = HILDON_VOLUMEBAR_RANGE(object); + + switch (prop_id) { + case PROP_LEVEL: + hildon_volumebar_range_set_level(range, g_value_get_double(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static void +hildon_volumebar_range_get_property(GObject * object, + guint prop_id, + GValue * value, + GParamSpec * pspec) +{ + HildonVolumebarRange *range = HILDON_VOLUMEBAR_RANGE(object); + + switch (prop_id) { + case PROP_LEVEL: + g_value_set_double(value, hildon_volumebar_range_get_level(range)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +static +gboolean hildon_volumebar_range_keypress(GtkWidget * widget, + GdkEventKey * event) +{ + /* Accept arrow keys only if they match the orientation of the widget */ + if (GTK_RANGE (widget)->orientation == GTK_ORIENTATION_HORIZONTAL) + { + if (event->keyval == GDK_Up || event->keyval == GDK_Down) { + return FALSE; + } + } + else + { + if (event->keyval == GDK_Left || event->keyval == GDK_Right) { + return FALSE; + } + } + + return ((GTK_WIDGET_CLASS(parent_class)->key_press_event) (widget, + event)); +} + +GtkWidget * +hildon_volumebar_range_new(GtkOrientation orientation) +{ + GtkAdjustment * adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (VOLUMEBAR_RANGE_INITIAL_VALUE, + VOLUMEBAR_RANGE_MINIMUM_VALUE, + VOLUMEBAR_RANGE_MAXIMUM_VALUE, + VOLUMEBAR_RANGE_STEP_INCREMENT_VALUE, + VOLUMEBAR_RANGE_PAGE_INCREMENT_VALUE, + VOLUMEBAR_RANGE_PAGE_SIZE_VALUE)); + HildonVolumebarRange *self = + g_object_new(HILDON_TYPE_VOLUMEBAR_RANGE, + "adjustment", adjustment, + NULL); + + GTK_RANGE(self)->orientation = orientation; + + /* Default vertical range is upside down for purposes of this widget */ + gtk_range_set_inverted(GTK_RANGE(self), + (orientation == GTK_ORIENTATION_VERTICAL)); + + return GTK_WIDGET(self); +} + +gdouble +hildon_volumebar_range_get_level(HildonVolumebarRange * self) +{ + g_return_val_if_fail(HILDON_IS_VOLUMEBAR_RANGE(self), -1.0); + + return gtk_adjustment_get_value(gtk_range_get_adjustment(GTK_RANGE(self))); +} + +void +hildon_volumebar_range_set_level(HildonVolumebarRange * self, + gdouble level) +{ + GtkAdjustment *adjustment; + + g_return_if_fail(HILDON_IS_VOLUMEBAR_RANGE(self)); + + adjustment = gtk_range_get_adjustment(GTK_RANGE(self)); + + /* Check that value has actually changed. Note that it's not safe to + * just compare if floats are equivalent or not */ + if (ABS(gtk_adjustment_get_value(adjustment) - level) > CHANGE_THRESHOLD) { + gtk_adjustment_set_value(adjustment, level); + } +} + +static gint +hildon_volumebar_range_button_press_event(GtkWidget * widget, + GdkEventButton * + event) +{ + gboolean result = FALSE; + + /* FIXME: By default, clicking left mouse button on GtkRange moves the + slider by one step towards the click location. However, we want stylus + taps to move the slider to the position of the tap, which by default + is the middle button behaviour. To avoid breaking default GtkRange + behaviour, this has been implemented by faking a middle button press. */ + event->button = (event->button == 1) ? 2 : event->button; + if (GTK_WIDGET_CLASS(parent_class)->button_press_event) { + result = + GTK_WIDGET_CLASS(parent_class)->button_press_event(widget, + event); + } + return result; +} + +static gint +hildon_volumebar_range_button_release_event(GtkWidget * widget, + GdkEventButton * + event) +{ + gboolean result = FALSE; + + /* FIXME: By default, clicking left mouse button on GtkRange moves the + slider by one step towards the click location. However, we want stylus + taps to move the slider to the position of the tap, which by default + is the middle button behaviour. To avoid breaking default GtkRange + behaviour, this has been implemented by faking a middle button press. */ + event->button = event->button == 1 ? 2 : event->button; + if (GTK_WIDGET_CLASS(parent_class)->button_release_event) { + result = + GTK_WIDGET_CLASS(parent_class)->button_release_event(widget, + event); + } + return result; +} diff --git a/src/hildon-volumebar-range.h b/src/hildon-volumebar-range.h new file mode 100644 index 0000000..545ff9d --- /dev/null +++ b/src/hildon-volumebar-range.h @@ -0,0 +1,78 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_VOLUMEBAR_RANGE_H__ +#define __HILDON_VOLUMEBAR_RANGE_H__ + +#include + +G_BEGIN_DECLS + +/** + * HILDON_VOLUMEBAR_RANGE_TYPE + * + * Macro for getting type of volumebar range. + * Since: 0.12.10 + */ +#define HILDON_TYPE_VOLUMEBAR_RANGE ( hildon_volumebar_range_get_type() ) + +/** + * HILDON_VOLUMEBAR_RANGE_TYPE + * + * Deprecated: use #HILDON_VOLUMEBAR_RANGE_TYPE instead + */ +#define HILDON_VOLUMEBAR_RANGE_TYPE HILDON_TYPE_VOLUMEBAR_RANGE + + +#define HILDON_VOLUMEBAR_RANGE(obj) (GTK_CHECK_CAST (obj,\ + HILDON_TYPE_VOLUMEBAR_RANGE, HildonVolumebarRange)) +#define HILDON_VOLUMEBAR_RANGE_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST ((klass),\ + HILDON_TYPE_VOLUMEBAR_RANGE, HildonVolumebarRangeClass)) +#define HILDON_IS_VOLUMEBAR_RANGE(obj) (GTK_CHECK_TYPE (obj,\ + HILDON_TYPE_VOLUMEBAR_RANGE)) +#define HILDON_IS_VOLUMEBAR_RANGE_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_VOLUMEBAR_RANGE)) + +typedef struct _HildonVolumebarRange HildonVolumebarRange; +typedef struct _HildonVolumebarRangeClass HildonVolumebarRangeClass; + +struct _HildonVolumebarRange { + GtkScale scale; +}; + +struct _HildonVolumebarRangeClass { + GtkScaleClass parent_class; +}; + +GType hildon_volumebar_range_get_type (void) G_GNUC_CONST; +GtkWidget * hildon_volumebar_range_new (GtkOrientation orientation); +gdouble hildon_volumebar_range_get_level (HildonVolumebarRange *self); +void hildon_volumebar_range_set_level (HildonVolumebarRange *self, + gdouble level); + + +G_END_DECLS + +#endif /* __HILDON_VOLUMEBAR_RANGE_H__ */ diff --git a/src/hildon-volumebar.c b/src/hildon-volumebar.c new file mode 100644 index 0000000..8f6f635 --- /dev/null +++ b/src/hildon-volumebar.c @@ -0,0 +1,622 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-volumebar + * @short_description: Base class for widgets that display a volume bar + * @see_also: #HildonHVolumebar, #HildonVVolumebar + * + * #HildonVolumebar is a base class for widgets that display a volume bar that + * allows increasing or decreasing volume within a predefined range, and muting + * the volume when users click the mute icon. + */ + +#include +#include +#include + +#include "hildon-volumebar.h" +#include "hildon-volumebar-range.h" +#include "hildon-volumebar-private.h" + +static GtkContainerClass *parent_class; + +static void +hildon_volumebar_class_init(HildonVolumebarClass * volumebar_class); +static void +hildon_volumebar_init(HildonVolumebar * volumebar); + +static void +hildon_child_forall(GtkContainer * container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data); +static void +hildon_volumebar_destroy(GtkObject * self); + +static void hildon_volumebar_set_property(GObject * object, + guint prop_id, + const GValue * value, + GParamSpec * pspec); +static void hildon_volumebar_get_property(GObject * object, + guint prop_id, + GValue * value, + GParamSpec * pspec); + +static void mute_toggled (HildonVolumebar *self); + +static gboolean +hildon_volumebar_key_press(GtkWidget * widget, + GdkEventKey * event); + +static void hildon_volumebar_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); +static void hildon_volumebar_realize (GtkWidget *widget); +static void hildon_volumebar_unrealize (GtkWidget *widget); +static void hildon_volumebar_map (GtkWidget *widget); +static void hildon_volumebar_unmap (GtkWidget *widget); +static void hildon_volumebar_notify (GObject *self, GParamSpec *param); + + +enum +{ + MUTE_TOGGLED_SIGNAL, + LEVEL_CHANGED_SIGNAL, + LAST_SIGNAL +}; + +enum { + PROP_NONE = 0, + PROP_HILDON_HAS_MUTE, + PROP_HILDON_FOCUSABLE, + PROP_HILDON_LEVEL, + PROP_HILDON_MUTE +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +GType +hildon_volumebar_get_type(void) +{ + static GType volumebar_type = 0; + + if (!volumebar_type) { + static const GTypeInfo volumebar_info = { + sizeof(HildonVolumebarClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_volumebar_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonVolumebar), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_volumebar_init, + }; + volumebar_type = g_type_register_static(GTK_TYPE_CONTAINER, + "HildonVolumebar", + &volumebar_info, 0); + } + return volumebar_type; +} + +static void +hildon_volumebar_class_init(HildonVolumebarClass *volumebar_class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (volumebar_class); + GtkObjectClass *object_class = GTK_OBJECT_CLASS(volumebar_class); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(volumebar_class); + GtkContainerClass *container_class = GTK_CONTAINER_CLASS(volumebar_class); + + parent_class = g_type_class_peek_parent(volumebar_class); + + g_type_class_add_private(volumebar_class, + sizeof(HildonVolumebarPrivate)); + + /* Because we derived our widget from GtkContainer, we should also + override forall method */ + volumebar_class->mute_toggled = mute_toggled; + container_class->forall = hildon_child_forall; + widget_class->size_allocate = hildon_volumebar_size_allocate; + widget_class->realize = hildon_volumebar_realize; + widget_class->unrealize = hildon_volumebar_unrealize; + widget_class->map = hildon_volumebar_map; + widget_class->unmap = hildon_volumebar_unmap; + widget_class->key_press_event = hildon_volumebar_key_press; + object_class->destroy = hildon_volumebar_destroy; + + signals[MUTE_TOGGLED_SIGNAL] = g_signal_new("mute_toggled", + G_OBJECT_CLASS_TYPE + (object_class), + G_SIGNAL_RUN_LAST | + G_SIGNAL_ACTION, + G_STRUCT_OFFSET + (HildonVolumebarClass, + mute_toggled), NULL, NULL, + gtk_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[LEVEL_CHANGED_SIGNAL] = g_signal_new("level_changed", + G_OBJECT_CLASS_TYPE + (object_class), + G_SIGNAL_RUN_LAST | + G_SIGNAL_ACTION, + G_STRUCT_OFFSET + (HildonVolumebarClass, + level_changed), NULL, + NULL, + gtk_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + gobject_class->notify = hildon_volumebar_notify; + gobject_class->set_property = hildon_volumebar_set_property; + gobject_class->get_property = hildon_volumebar_get_property; + + /*This kind of property could be usefull in the gtkcontainer*/ + g_object_class_install_property(gobject_class, + PROP_HILDON_FOCUSABLE, + g_param_spec_boolean("can-focus", + "The widget focusablility", + "The widget focusablility. TRUE is focusable", + TRUE, + G_PARAM_CONSTRUCT | G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, + PROP_HILDON_HAS_MUTE, + g_param_spec_boolean("has_mute", + "Show/Hide the mute button", + "Whether the mute button is visible. Default value: TRUE", + TRUE, + G_PARAM_CONSTRUCT | G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, + PROP_HILDON_LEVEL, + g_param_spec_double("level", + "Level", + "Current volume level", + 0.0, + 100.0, + 50.0, + G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, + PROP_HILDON_MUTE, + g_param_spec_boolean("mute", + "Mute", + "Whether volume is muted", + FALSE, + G_PARAM_READWRITE)); +} + +static void +hildon_volumebar_init(HildonVolumebar * volumebar) +{ + HildonVolumebarPrivate *priv; + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(volumebar); + + /* Should set GTK_NO_WINDOW flag, because widget is derived from + GtkContainer */ + GTK_WIDGET_SET_FLAGS(GTK_WIDGET(volumebar), GTK_NO_WINDOW); + GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(volumebar), GTK_CAN_FOCUS); + + /* Initialize mute button */ + priv->tbutton = GTK_TOGGLE_BUTTON(gtk_toggle_button_new()); + g_object_set (G_OBJECT (priv->tbutton), "can-focus", FALSE, NULL); +} + +static void +hildon_volumebar_size_allocate (GtkWidget *widget, GtkAllocation *allocation) +{ + HildonVolumebarPrivate *priv; + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget); + + if (GTK_WIDGET_CLASS (parent_class)->size_allocate) + GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation); + + if (GTK_WIDGET_REALIZED (widget)) + gdk_window_move_resize (priv->event_window, + allocation->x, allocation->y, + allocation->width, allocation->height); +} + +static void +hildon_volumebar_realize (GtkWidget *widget) +{ + HildonVolumebarPrivate *priv; + GdkWindowAttr attributes; + gint attributes_mask; + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget); + + GTK_WIDGET_CLASS(parent_class)->realize(widget); + + 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_ONLY; + attributes.event_mask = GDK_BUTTON_PRESS_MASK; + + attributes_mask = GDK_WA_X | GDK_WA_Y; + + priv->event_window = gdk_window_new (widget->window, + &attributes, attributes_mask); + gdk_window_set_user_data (priv->event_window, widget); +} + +static void +hildon_volumebar_unrealize (GtkWidget *widget) +{ + HildonVolumebarPrivate *priv; + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget); + + if (priv->event_window) { + gdk_window_set_user_data (priv->event_window, NULL); + gdk_window_destroy (priv->event_window); + priv->event_window = NULL; + } + + GTK_WIDGET_CLASS(parent_class)->unrealize(widget); +} + +static void +hildon_volumebar_map (GtkWidget *widget) +{ + HildonVolumebarPrivate *priv; + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget); + + GTK_WIDGET_CLASS(parent_class)->map(widget); + + /* the event window must be on top of all other widget windows, so show it + * last */ + if (!GTK_WIDGET_SENSITIVE (widget)) + gdk_window_show (priv->event_window); +} + +static void hildon_volumebar_unmap (GtkWidget *widget) +{ + HildonVolumebarPrivate *priv; + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget); + + gdk_window_hide (priv->event_window); + + GTK_WIDGET_CLASS(parent_class)->unmap(widget); +} + +static void +hildon_child_forall(GtkContainer * container, + gboolean include_internals, + GtkCallback callback, gpointer callback_data) +{ + HildonVolumebarPrivate *priv; + + g_assert(HILDON_IS_VOLUMEBAR(container)); + g_assert(callback != NULL); + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(container); + + /* No external children */ + if (!include_internals) + return; + + /* Execute callback for both internals */ + (*callback) (GTK_WIDGET(priv->tbutton), callback_data); + (*callback) (GTK_WIDGET(priv->volumebar), callback_data); +} + +static void +hildon_volumebar_notify (GObject *self, GParamSpec *param) +{ + HildonVolumebarPrivate *priv; + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(self); + + if (GTK_WIDGET_MAPPED (self)) { + /* show/hide the event window on sensitivity change */ + if (g_str_equal (param->name, "sensitive")) { + if (GTK_WIDGET_SENSITIVE (self)) + gdk_window_hide (priv->event_window); + else + gdk_window_show (priv->event_window); + } + } + + if (G_OBJECT_CLASS(parent_class)->notify) + G_OBJECT_CLASS(parent_class)->notify (self, param); +} + +static void +hildon_volumebar_destroy(GtkObject * self) +{ + HildonVolumebarPrivate *priv; + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(self); + + if (priv->tbutton) { + gtk_widget_unparent(GTK_WIDGET(priv->tbutton)); + priv->tbutton = NULL; + } + if (priv->volumebar) { + gtk_widget_unparent(GTK_WIDGET(priv->volumebar)); + priv->volumebar = NULL; + } + + if (GTK_OBJECT_CLASS(parent_class)->destroy) + GTK_OBJECT_CLASS(parent_class)->destroy(self); +} + +static void +hildon_volumebar_set_property(GObject * object, + guint prop_id, + const GValue * value, + GParamSpec * pspec) +{ + HildonVolumebarPrivate *priv; + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_HILDON_HAS_MUTE: + /* Mute button always exists, but might be hidden */ + if (g_value_get_boolean(value)) + gtk_widget_show(GTK_WIDGET(priv->tbutton)); + else + gtk_widget_hide(GTK_WIDGET(priv->tbutton)); + break; + case PROP_HILDON_FOCUSABLE: + g_object_set( G_OBJECT(priv->volumebar), "can-focus", + g_value_get_boolean(value), NULL ); + break; + case PROP_HILDON_LEVEL: + hildon_volumebar_set_level(HILDON_VOLUMEBAR(priv->volumebar), + g_value_get_double(value)); + break; + case PROP_HILDON_MUTE: + hildon_volumebar_set_mute(HILDON_VOLUMEBAR(priv->volumebar), + g_value_get_boolean(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + + break; + } +} + +static void +hildon_volumebar_get_property(GObject * object, + guint prop_id, GValue * value, + GParamSpec * pspec) +{ + HildonVolumebar *vb = HILDON_VOLUMEBAR(object); + HildonVolumebarPrivate *priv = HILDON_VOLUMEBAR_GET_PRIVATE(vb); + + switch (prop_id) { + case PROP_HILDON_HAS_MUTE: + g_value_set_boolean(value, GTK_WIDGET_VISIBLE(priv->tbutton)); + break; + case PROP_HILDON_FOCUSABLE: + g_value_set_boolean(value, GTK_WIDGET_CAN_FOCUS(priv->volumebar)); + break; + case PROP_HILDON_LEVEL: + g_value_set_double(value, hildon_volumebar_get_level(vb)); + break; + case PROP_HILDON_MUTE: + g_value_set_boolean(value, hildon_volumebar_get_mute(vb)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } +} + +/** + * hildon_volumebar_level_change: + * @self: a #HildonVolumebar widget + * + * Emits "level_changed" signal to the given volume bar. This function + * is mainly used by derived classes. + */ +void +hildon_volumebar_level_change(HildonVolumebar * self) +{ + g_return_if_fail(HILDON_IS_VOLUMEBAR(self)); + g_signal_emit_by_name(GTK_WIDGET(self), "level_changed"); +} + +/** + * hildon_volumebar_set_level: + * @self: volume bar to change level on + * @level: new level + * + * Sets new volume level for this #HildonVolumebar. + */ +void +hildon_volumebar_set_level(HildonVolumebar * self, gdouble level) +{ + HildonVolumebarPrivate *priv; + + g_return_if_fail(HILDON_IS_VOLUMEBAR(self)); + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(self); + + hildon_volumebar_range_set_level(priv->volumebar, level); +} + +/** + * hildon_volumebar_get_level: + * @self: volume bar to query level on + * + * Gets the volume level of this #HildonVolumebar. + * + * Returns: volume level or -1 on error + */ +gdouble +hildon_volumebar_get_level(HildonVolumebar * self) +{ + HildonVolumebarPrivate *priv; + + g_return_val_if_fail(HILDON_IS_VOLUMEBAR(self), -1); + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(self); + + return hildon_volumebar_range_get_level(priv->volumebar); +} + +/** + * hildon_volumebar_set_mute: + * @self: volume bar to work on + * @mute: mute ON/OFF + * + * Sets mute status for this #HildonVolumebar. + */ +void +hildon_volumebar_set_mute(HildonVolumebar * self, gboolean mute) +{ + HildonVolumebarPrivate *priv; + gboolean focusable = TRUE; + + g_return_if_fail(HILDON_IS_VOLUMEBAR(self)); + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(self); + + /* Slider should be insensitive when mute is on */ + gtk_widget_set_sensitive(GTK_WIDGET(priv->volumebar), !mute); + + focusable = GTK_WIDGET_CAN_FOCUS (GTK_WIDGET (priv->volumebar)); + + if (mute){ + if (focusable){ + /* Make mute button focusable since the slider isn't anymore */ + g_object_set (G_OBJECT (priv->tbutton), "can-focus", TRUE, NULL); + gtk_widget_grab_focus (GTK_WIDGET(priv->tbutton)); + } + } + else + { + g_object_set (G_OBJECT (priv->tbutton), "can-focus", FALSE, NULL); + + /* Mute off grabs focus */ + if (focusable){ + gtk_widget_grab_focus (GTK_WIDGET (self)); + } + else{ + /* If volumebar is not focusable, focus the parent window instead */ + GtkWidget *win = gtk_widget_get_ancestor (GTK_WIDGET (self), + GTK_TYPE_WINDOW); + gtk_window_set_focus (GTK_WINDOW (win), NULL); + } + } + + /* Update mute button state and redraw */ + gtk_toggle_button_set_active(priv->tbutton, mute); + + gtk_widget_queue_draw (GTK_WIDGET (self)); +} + +/** + * hildon_volumebar_get_mute: + * @self: volume bar to query mute status + * + * Gets mute status of this #HildonVolumebar (ON/OFF). + * + * Returns: Mute status as #gboolean value. + */ +gboolean +hildon_volumebar_get_mute(HildonVolumebar * self) +{ + HildonVolumebarPrivate *priv; + + g_return_val_if_fail(HILDON_IS_VOLUMEBAR(self), TRUE); + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(self); + + return gtk_toggle_button_get_active(priv->tbutton); +} + +/** + * hildon_volumebar_get_adjustment + * @self : a #HildonVolumebar + * + * Gets the GtkAdjustment used in volume bar. This can be handy + * to give to hildon_appview_set_connected_adjustment which + * will allow changing the volume with increase / decrease + * hardware buttons. + * + * This is a temporary solution until volume bar is restructured to + * be a child class of GtkRange. + * + * Returns: a #GtkAdjustment used by volume bar. + */ +GtkAdjustment * +hildon_volumebar_get_adjustment (HildonVolumebar * self) +{ + HildonVolumebarPrivate *priv; + + g_return_val_if_fail(HILDON_IS_VOLUMEBAR(self), NULL); + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(self); + + return gtk_range_get_adjustment (GTK_RANGE (priv->volumebar)); +} + +static void +mute_toggled (HildonVolumebar *self) +{ + /* This looks like no-op, but it still does something meaningfull! + set_mute also updates the ui to match new state that + is already reported by get_mute */ + hildon_volumebar_set_mute (self, hildon_volumebar_get_mute(self)); +} + +static gboolean +hildon_volumebar_key_press (GtkWidget * widget, + GdkEventKey * event) +{ + HildonVolumebarPrivate *priv; + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget); + + /* Enter key toggles mute button (unless it is hidden) */ + if (event->keyval == GDK_Return && GTK_WIDGET_VISIBLE(priv->tbutton)) { + gtk_toggle_button_set_active(priv->tbutton, + !hildon_volumebar_get_mute(HILDON_VOLUMEBAR(widget))); + return TRUE; + } + + return GTK_WIDGET_CLASS(parent_class)->key_press_event(widget, event); +} + +/* Sends mute-toggled signal to widget, used as a callback in derived classes + Just keep this "protected" in order to avoid introducing new API. */ +void +_hildon_volumebar_mute_toggled(HildonVolumebar * self) +{ + g_return_if_fail(HILDON_IS_VOLUMEBAR(self)); + g_signal_emit_by_name(self, "mute_toggled"); +} diff --git a/src/hildon-volumebar.h b/src/hildon-volumebar.h new file mode 100644 index 0000000..10e0694 --- /dev/null +++ b/src/hildon-volumebar.h @@ -0,0 +1,74 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ +#ifndef __HILDON_VOLUMEBAR_H__ +#define __HILDON_VOLUMEBAR_H__ + +#include +#include + +G_BEGIN_DECLS + +#define HILDON_TYPE_VOLUMEBAR ( hildon_volumebar_get_type() ) +#define HILDON_VOLUMEBAR(obj) (GTK_CHECK_CAST (obj,\ + HILDON_TYPE_VOLUMEBAR, HildonVolumebar)) +#define HILDON_VOLUMEBAR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass),\ + HILDON_TYPE_VOLUMEBAR, HildonVolumebarClass)) +#define HILDON_IS_VOLUMEBAR(obj) (GTK_CHECK_TYPE (obj,\ + HILDON_TYPE_VOLUMEBAR)) +#define HILDON_IS_VOLUMEBAR_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_VOLUMEBAR)) + +typedef struct _HildonVolumebar HildonVolumebar; +typedef struct _HildonVolumebarClass HildonVolumebarClass; + +struct _HildonVolumebar { + GtkContainer par; +}; + +struct _HildonVolumebarClass { + GtkContainerClass parent_class; + + /* signals */ + void (*mute_toggled) (HildonVolumebar * self); + void (*level_changed) (HildonVolumebar * self); +}; + + +GType hildon_volumebar_get_type (void) G_GNUC_CONST; + +double hildon_volumebar_get_level (HildonVolumebar *self); +void hildon_volumebar_set_level (HildonVolumebar *self, + gdouble level); + +gboolean hildon_volumebar_get_mute (HildonVolumebar *self); +void hildon_volumebar_set_mute (HildonVolumebar *self, + gboolean mute); + +void hildon_volumebar_level_change (HildonVolumebar *self); + +GtkAdjustment * hildon_volumebar_get_adjustment (HildonVolumebar *self); + + +G_END_DECLS +#endif /* __HILDON_VOLUMEBAR_H__ */ diff --git a/src/hildon-vvolumebar.c b/src/hildon-vvolumebar.c new file mode 100644 index 0000000..17fde14 --- /dev/null +++ b/src/hildon-vvolumebar.c @@ -0,0 +1,233 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/* + * SECTION:hildon-vvolumebar + * @short_description: A widget that displays a vertical volume bar + * @see_also: #HildonVolumebar, #HildonHVolumebar + * + * #HildonVVolumebar is a subclass of #HildonVolumebar. It displays a + * vertical volume bar that allows increasing or decreasing volume + * within a predefined range, and muting when users click the mute icon. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include "hildon-vvolumebar.h" +#include "hildon-volumebar-range.h" +#include "hildon-volumebar-private.h" + +/* Volume bar */ +#define DEFAULT_BAR_WIDTH 58 +#define MINIMUM_BAR_HEIGHT 165 +/* Toggle button */ +#define DEFAULT_VERTICAL_TBUTTON_WIDTH 26 +#define DEFAULT_VERTICAL_TBUTTON_HEIGHT 26 +#define DEFAULT_ENDING_SIZE 20 +/* Gap to leave for mute button */ +#define HORIZONTAL_MUTE_GAP 16 +#define VERTICAL_MUTE_GAP 6 + +static HildonVolumebarClass *parent_class; +static void hildon_vvolumebar_class_init(HildonVVolumebarClass * klass); +static void hildon_vvolumebar_init(HildonVVolumebar * vvolumebar); +static gboolean hildon_vvolumebar_expose(GtkWidget * widget, + GdkEventExpose * event); +static void hildon_vvolumebar_size_request(GtkWidget * widget, + GtkRequisition * requisition); +static void hildon_vvolumebar_size_allocate(GtkWidget * widget, + GtkAllocation * allocation); + +GType hildon_vvolumebar_get_type(void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo info = { + sizeof(HildonVVolumebarClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_vvolumebar_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonVVolumebar), + 0, + (GInstanceInitFunc) hildon_vvolumebar_init, + }; + type = + g_type_register_static(HILDON_TYPE_VOLUMEBAR, + "HildonVVolumebar", &info, 0); + } + return type; +} + +static void hildon_vvolumebar_class_init(HildonVVolumebarClass * klass) +{ + GtkWidgetClass *volumebar_class = GTK_WIDGET_CLASS(klass); + + parent_class = g_type_class_peek_parent(klass); + + volumebar_class->size_request = hildon_vvolumebar_size_request; + volumebar_class->size_allocate = hildon_vvolumebar_size_allocate; + volumebar_class->expose_event = hildon_vvolumebar_expose; +} + +static void hildon_vvolumebar_init(HildonVVolumebar * vvolumebar) +{ + HildonVolumebarPrivate *priv; + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(vvolumebar); + + priv->volumebar = + HILDON_VOLUMEBAR_RANGE(hildon_volumebar_range_new + (GTK_ORIENTATION_VERTICAL)); + + GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(vvolumebar), GTK_CAN_FOCUS); + + gtk_widget_set_parent(GTK_WIDGET(priv->tbutton), GTK_WIDGET(vvolumebar)); + gtk_widget_set_parent(GTK_WIDGET(priv->volumebar), GTK_WIDGET(vvolumebar)); + + gtk_scale_set_draw_value(GTK_SCALE(priv->volumebar), FALSE); + + /* Signals */ + g_signal_connect_swapped(G_OBJECT(priv->volumebar), "value-changed", + G_CALLBACK(hildon_volumebar_level_change), + vvolumebar); + g_signal_connect_swapped(priv->tbutton, "toggled", + G_CALLBACK(_hildon_volumebar_mute_toggled), vvolumebar); + + gtk_widget_show(GTK_WIDGET(priv->volumebar)); +} + +/** + * hildon_vvolumebar_new: + * + * Creates a new #HildonVVolumebar widget. + * + * Returns: a new #HildonVVolumebar + */ +GtkWidget *hildon_vvolumebar_new(void) +{ + return GTK_WIDGET(g_object_new(HILDON_TYPE_VVOLUMEBAR, NULL)); +} + +static gboolean hildon_vvolumebar_expose(GtkWidget * widget, + GdkEventExpose * event) +{ + HildonVolumebarPrivate *priv; + + g_assert(HILDON_IS_VVOLUMEBAR(widget)); + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(HILDON_VOLUMEBAR(widget)); + + if (GTK_WIDGET_DRAWABLE(widget)) { + /* Paint background */ + gtk_paint_box(widget->style, widget->window, + GTK_WIDGET_STATE(priv->volumebar), GTK_SHADOW_OUT, + NULL, widget, "background", + widget->allocation.x, + widget->allocation.y, + widget->allocation.width, + widget->allocation.height); + + /* The contents of the widget can paint themselves */ + (*GTK_WIDGET_CLASS(parent_class)->expose_event) (widget, event); + } + + return FALSE; +} + +static void +hildon_vvolumebar_size_request(GtkWidget * widget, + GtkRequisition * requisition) +{ + g_assert(HILDON_IS_VVOLUMEBAR(widget)); + + requisition->height = MINIMUM_BAR_HEIGHT; + requisition->width = DEFAULT_BAR_WIDTH; +} + +static void +hildon_vvolumebar_size_allocate(GtkWidget * widget, + GtkAllocation * allocation) +{ + HildonVolumebarPrivate *priv; + + GtkAllocation range_allocation, button_allocation; + + g_assert(HILDON_IS_VVOLUMEBAR(widget)); + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget); + + /* Center the widget horizontally */ + if (allocation->width > DEFAULT_BAR_WIDTH) { + allocation->x += + (allocation->width - DEFAULT_BAR_WIDTH) / 2; + allocation->width = DEFAULT_BAR_WIDTH; + } + + GTK_WIDGET_CLASS(parent_class)->size_allocate(widget, allocation); + + if (priv->volumebar && GTK_WIDGET_VISIBLE(priv->volumebar)) { + /* Allocate space for the slider */ + range_allocation.x = allocation->x; + range_allocation.y = allocation->y + DEFAULT_ENDING_SIZE; + + range_allocation.width = DEFAULT_BAR_WIDTH; + + if (priv->tbutton && GTK_WIDGET_VISIBLE(priv->tbutton)) + { + /* Leave room for the mute button */ + range_allocation.height = MAX(0, + allocation->height + - 2 * DEFAULT_ENDING_SIZE + - DEFAULT_VERTICAL_TBUTTON_HEIGHT + - VERTICAL_MUTE_GAP); + } + + else + { + range_allocation.height = MAX(0, + allocation->height + - 2 * DEFAULT_ENDING_SIZE); + } + + gtk_widget_size_allocate(GTK_WIDGET(priv->volumebar), + &range_allocation); + } + + if (priv->tbutton && GTK_WIDGET_VISIBLE(priv->tbutton)) { + /* Allocate space for the mute button */ + button_allocation.x = allocation->x + HORIZONTAL_MUTE_GAP; + button_allocation.y = allocation->y + allocation->height - + VERTICAL_MUTE_GAP - 2 * DEFAULT_ENDING_SIZE; + button_allocation.width = DEFAULT_VERTICAL_TBUTTON_WIDTH; + button_allocation.height = DEFAULT_VERTICAL_TBUTTON_HEIGHT; + gtk_widget_size_allocate(GTK_WIDGET(priv->tbutton), + &button_allocation); + } +} diff --git a/src/hildon-vvolumebar.h b/src/hildon-vvolumebar.h new file mode 100644 index 0000000..5807aee --- /dev/null +++ b/src/hildon-vvolumebar.h @@ -0,0 +1,60 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_VVOLUMEBAR_H__ +#define __HILDON_VVOLUMEBAR_H__ + +#include + +G_BEGIN_DECLS + +#define HILDON_TYPE_VVOLUMEBAR ( hildon_vvolumebar_get_type() ) + +#define HILDON_VVOLUMEBAR(obj) (GTK_CHECK_CAST (obj, HILDON_TYPE_VVOLUMEBAR, HildonVVolumebar)) + +#define HILDON_VVOLUMEBAR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass),\ + HILDON_TYPE_VVOLUMEBAR, HildonVVolumebarClass)) + +#define HILDON_IS_VVOLUMEBAR(obj) (GTK_CHECK_TYPE (obj, HILDON_TYPE_VVOLUMEBAR)) + +#define HILDON_IS_VVOLUMEBAR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_VVOLUMEBAR)) + + +typedef struct _HildonVVolumebar HildonVVolumebar; +typedef struct _HildonVVolumebarClass HildonVVolumebarClass; + +struct _HildonVVolumebar { + HildonVolumebar volumebar; /* this is our parent class */ +}; + +struct _HildonVVolumebarClass { + HildonVolumebarClass parent_class; +}; + +GType hildon_vvolumebar_get_type (void) G_GNUC_CONST; +GtkWidget * hildon_vvolumebar_new (void); + + +G_END_DECLS +#endif /* __HILDON_VVOLUMEBAR_H__ */ diff --git a/src/hildon-weekday-picker.c b/src/hildon-weekday-picker.c new file mode 100644 index 0000000..5f25fd1 --- /dev/null +++ b/src/hildon-weekday-picker.c @@ -0,0 +1,502 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-weekday-picker + * @short_description: A widget for picking days on which a certain event + * should take place + * @see_also: #HildonWeekdayPicker + * + * #HildonWeekdayPicker supports non-mutually exclusive selection of days of + * the week. Selected days of the week are shown with a pushed-in effect. + * + * #HildonWeekdayPicker is used where users are required to pick days on which + * a certain event should take place, for example, which days a Calendar event + * should be repeated on. It is used in Calendar in the Repeat dialog, in Tasks + * in the Repeat dialog and in the Email set-up wizard. + */ + + /* GDate numbers days from 1 to 7 and G_DATE_MONDAY is 1st day. However + according to locale settings first day is sunday. To get around this + problem, we addjust GDate days numbering to be same as locale + numbering */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hildon-weekday-picker.h" +#include "hildon-composite-widget.h" + +#define HILDON_WEEKDAY_PICKER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_WEEKDAY_PICKER, HildonWeekdayPickerPrivate)); + +static GtkContainerClass *parent_class; + +typedef struct _HildonWeekdayPickerPrivate HildonWeekdayPickerPrivate; + +static void +hildon_weekday_picker_class_init(HildonWeekdayPickerClass * picker_class); +static void +hildon_weekday_picker_init(HildonWeekdayPicker * picker); +static void +hildon_weekday_picker_size_allocate(GtkWidget * widget, + GtkAllocation * allocation); +static void +hildon_weekday_picker_size_request(GtkWidget * widget, + GtkRequisition * requisition); +static void +hildon_weekday_picker_forall(GtkContainer * container, + gboolean include_internals, + GtkCallback callback, gpointer callback_data); +static void +hildon_weekday_picker_destroy(GtkObject * self); + +static void +button_toggle(GtkToggleButton * togglebutton, gpointer wpicker); + +struct _HildonWeekdayPickerPrivate { + GtkWidget *buttons[8]; /* weekday buttons in show order */ + GtkWidget *day_order_buttons[8]; /* weekday buttons in glib day order */ +}; + +enum { + SELECTION_CHANGED_SIGNAL, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +GType hildon_weekday_picker_get_type(void) +{ + static GType picker_type = 0; + + if (!picker_type) { + static const GTypeInfo picker_info = { + sizeof(HildonWeekdayPickerClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_weekday_picker_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonWeekdayPicker), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_weekday_picker_init, + }; + picker_type = g_type_register_static(GTK_TYPE_CONTAINER, + "HildonWeekdayPicker", + &picker_info, 0); + } + return picker_type; +} + +static void +hildon_weekday_picker_class_init(HildonWeekdayPickerClass * picker_class) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(picker_class); + GtkContainerClass *container_class = GTK_CONTAINER_CLASS(picker_class); + GObjectClass *object_class = G_OBJECT_CLASS(picker_class); + + parent_class = g_type_class_peek_parent(picker_class); + + g_type_class_add_private(picker_class, + sizeof(HildonWeekdayPickerPrivate)); + + /* Override virtual methods */ + widget_class->size_request = hildon_weekday_picker_size_request; + widget_class->size_allocate = hildon_weekday_picker_size_allocate; + widget_class->focus = hildon_composite_widget_focus; + container_class->forall = hildon_weekday_picker_forall; + GTK_OBJECT_CLASS(picker_class)->destroy = + hildon_weekday_picker_destroy; + + /* Create a signal for reporting user actions */ + signals[SELECTION_CHANGED_SIGNAL] = g_signal_new("selection_changed", + G_OBJECT_CLASS_TYPE + (object_class), + G_SIGNAL_RUN_LAST | + G_SIGNAL_ACTION, + G_STRUCT_OFFSET + (HildonWeekdayPickerClass, + selection_changed), NULL, NULL, + gtk_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); +} + +static void +hildon_weekday_picker_init(HildonWeekdayPicker * picker) +{ + HildonWeekdayPickerPrivate *priv; + gint i, day; + /* weekday indexes to be used with nl_langinfo. These are shifted + * by one for glib compability */ + int wdays[] = { + -1, /* 0 = invalid date */ + ABDAY_2, /* 1 = monday in glib */ + ABDAY_3, /* 2 = tuesday in glib */ + ABDAY_4, /* 3 = wednesday in glib */ + ABDAY_5, /* 4 = thursday in glib */ + ABDAY_6, /* 5 = friday in glib */ + ABDAY_7, /* 6 = saturday in glib */ + ABDAY_1 }; /* 7 = sunday in glib */ + GtkSizeGroup *sgroup; + + sgroup = gtk_size_group_new(GTK_SIZE_GROUP_BOTH); + + /* Check our first weekday */ + day = *nl_langinfo(_NL_TIME_FIRST_WEEKDAY); + + priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker); + + /* Shift the days by one. This is done because GDateWeekday + * starts with Monday(1) and langinfo's first day is Sunday */ + day--; + if (day < 1) + day = 7; + + /* Initialize and pack day buttons */ + for (i = 1; i <= 7; i++) { + priv->buttons[i] = + gtk_toggle_button_new_with_label(nl_langinfo(wdays[day])); + priv->day_order_buttons[day] = priv->buttons[i]; + day++; + + if (day > 7) + day = 1; + + g_signal_connect(GTK_WIDGET(priv->buttons[i]), + "toggled", G_CALLBACK(button_toggle), picker); + + gtk_size_group_add_widget(sgroup, priv->buttons[i]); + + gtk_widget_set_parent(priv->buttons[i], GTK_WIDGET(picker)); + gtk_widget_show(priv->buttons[i]); + } + + GTK_WIDGET_SET_FLAGS(picker, GTK_NO_WINDOW); + + g_object_unref( sgroup ); +} + +/** + * hildon_weekday_picker_new: + * + * Creates a new #HildonWeekdayPicker. + * + * Returns: pointer to a new #HildonWeekdayPicker widget. + */ +GtkWidget *hildon_weekday_picker_new(void) +{ + return g_object_new(HILDON_TYPE_WEEKDAY_PICKER, NULL); +} + +static void +hildon_weekday_picker_forall(GtkContainer * container, + gboolean include_internals, GtkCallback callback, + gpointer callback_data) +{ + HildonWeekdayPicker *picker; + HildonWeekdayPickerPrivate *priv; + gint i; + + g_assert(container); + g_assert(callback); + + picker = HILDON_WEEKDAY_PICKER(container); + priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker); + + /* We only have internal children */ + if (!include_internals) + return; + + /* Activate callback for each day button */ + for (i = 1; i <= 7; ++i) { + (*callback) (priv->buttons[i], callback_data); + } + +} + +static void +hildon_weekday_picker_destroy(GtkObject * self) +{ + HildonWeekdayPickerPrivate *priv; + gint i; + + priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(self); + + /* Destroy internal children... */ + for (i = 1; i <= 7; ++i) { + if (priv->buttons[i]) + { + gtk_widget_unparent(priv->buttons[i]); + priv->buttons[i] = NULL; + } + } + + /* ... and chain to parent. */ + if (GTK_OBJECT_CLASS(parent_class)->destroy) + GTK_OBJECT_CLASS(parent_class)->destroy(self); + +} + +static void +hildon_weekday_picker_size_request(GtkWidget * widget, + GtkRequisition *requisition) +{ + HildonWeekdayPicker *picker; + HildonWeekdayPickerPrivate *priv; + gint i; + GtkRequisition req; + + picker = HILDON_WEEKDAY_PICKER(widget); + priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker); + requisition->width = 0; + requisition->height = 0; + + /* Request an area that is as wide as all of the buttons + together and tall enough to hold heightest button */ + for (i = 1; i <= 7; ++i) { + gtk_widget_size_request(priv->buttons[i], &req); + requisition->width += req.width; + if (req.height > requisition->height) + requisition->height = req.height; + + } +} + +static void +hildon_weekday_picker_size_allocate(GtkWidget * widget, + GtkAllocation * allocation) +{ + HildonWeekdayPicker *picker; + HildonWeekdayPickerPrivate *priv; + gint i; + GtkAllocation alloc; + GtkRequisition child_requisition; + gint header_x; + guint sval; + GtkTextDirection direction; + + g_assert(widget); + g_assert(allocation); + + /* Check orientation */ + direction = gtk_widget_get_direction(widget); + + picker = HILDON_WEEKDAY_PICKER(widget); + priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker); + header_x = allocation->x; + widget->allocation = *allocation; + + if (direction == GTK_TEXT_DIR_LTR || direction == GTK_TEXT_DIR_NONE) + sval = 1; + else + sval = 7; + + /* Allocate day buttons side by side honouring the text direction */ + for (i = 1; i <= 7; ++i) { + gtk_widget_get_child_requisition(priv->buttons[sval], + &child_requisition); + + alloc.x = header_x; + alloc.y = allocation->y; + alloc.width = child_requisition.width; + alloc.height = child_requisition.height; + header_x += alloc.width; + gtk_widget_size_allocate(priv->buttons[sval], &alloc); + if (direction == GTK_TEXT_DIR_RTL) + sval--; + else + sval++; + } +} + +static void +button_toggle(GtkToggleButton * button, gpointer wpicker) +{ + HildonWeekdayPicker *picker; + HildonWeekdayPickerPrivate *priv; + gint i; + + g_assert(button); + g_assert(wpicker); + + picker = HILDON_WEEKDAY_PICKER(wpicker); + priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker); + + for (i = 1; i <= 7; ++i) { + if (GTK_WIDGET(button) == priv->day_order_buttons[i]) { + g_signal_emit (GTK_WIDGET(picker), + signals[SELECTION_CHANGED_SIGNAL], 0, i); + break; + } + } +} + +/** + * hildon_weekday_picker_set_day: + * @picker: the #HildonWeekdayPicker widget + * @day: day to be set active + * + * Sets specified weekday active. + */ +void +hildon_weekday_picker_set_day(HildonWeekdayPicker * picker, + GDateWeekday day) +{ + HildonWeekdayPickerPrivate *priv; + + g_return_if_fail(picker); + g_return_if_fail(g_date_valid_weekday(day)); + + priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON + (priv->day_order_buttons[day]), TRUE); +} + +/** + * hildon_weekday_picker_unset_day: + * @picker: the #HildonWeekdayPicker widget + * @day: day to be set inactive + * + * Sets specified weekday inactive. + */ +void +hildon_weekday_picker_unset_day(HildonWeekdayPicker * picker, + GDateWeekday day) +{ + HildonWeekdayPickerPrivate *priv; + + g_return_if_fail(picker); + g_return_if_fail(g_date_valid_weekday(day)); + + priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON + (priv->day_order_buttons[day]), FALSE); +} + +/** + * hildon_weekday_picker_toggle_day: + * @picker: the #HildonWeekdayPicker widget + * @day: day to be toggled + * + * Toggles current status of the specified weekday. + */ +void +hildon_weekday_picker_toggle_day(HildonWeekdayPicker * picker, + GDateWeekday day) +{ + HildonWeekdayPickerPrivate *priv; + + g_return_if_fail(picker); + g_return_if_fail(g_date_valid_weekday(day)); + + priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker); + + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON(priv->day_order_buttons[day]), + !gtk_toggle_button_get_active( + GTK_TOGGLE_BUTTON(priv->day_order_buttons[day]))); +} + +/** + * hildon_weekday_picker_set_all: + * @picker: the #HildonWeekdayPicker widget + * + * Sets all weekdays active. + */ +void +hildon_weekday_picker_set_all(HildonWeekdayPicker * picker) +{ + HildonWeekdayPickerPrivate *priv; + gint i; + + g_return_if_fail(picker); + + priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker); + + for (i = 1; i <= 7; i++) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->buttons[i]), + TRUE); +} + +/** + * hildon_weekday_picker_unset_all: + * @picker: the #HildonWeekdayPicker widget + * + * Sets all weekdays inactive. + */ +void +hildon_weekday_picker_unset_all(HildonWeekdayPicker * picker) +{ + HildonWeekdayPickerPrivate *priv; + gint i; + + g_return_if_fail(picker); + + priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker); + + for (i = 1; i <= 7; i++) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->buttons[i]), + FALSE); +} + +/** + * hildon_weekday_picker_isset_day: + * @picker: the #HildonWeekdayPicker widget + * @day: day to be checked. + * + * Checks if the specified weekday is set active. + * + * Returns: TRUE if the day is set, FALSE if the day is not set + */ +gboolean +hildon_weekday_picker_isset_day(HildonWeekdayPicker * picker, + GDateWeekday day) +{ + HildonWeekdayPickerPrivate *priv; + + g_return_val_if_fail(picker, FALSE); + g_return_val_if_fail(g_date_valid_weekday(day), FALSE); + + priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE(picker); + + return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON( + priv->day_order_buttons[day])); +} diff --git a/src/hildon-weekday-picker.h b/src/hildon-weekday-picker.h new file mode 100644 index 0000000..feb0db6 --- /dev/null +++ b/src/hildon-weekday-picker.h @@ -0,0 +1,149 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_WEEKDAY_PICKER_H__ +#define __HILDON_WEEKDAY_PICKER_H__ + +#include + +G_BEGIN_DECLS +/** + * HILDON_TYPE_WEEKDAY_PICKER: + * + * Macro for getting type of weekday picker. + * Since: 0.12.10 + */ +#define HILDON_TYPE_WEEKDAY_PICKER ( hildon_weekday_picker_get_type() ) + +/** + * HILDON_WEEKDAY_PICKER_TYPE: + * + * Deprecated: use #HILDON_TYPE_WEEKDAY_PICKER instead. + */ +#define HILDON_WEEKDAY_PICKER_TYPE HILDON_TYPE_WEEKDAY_PICKER + +#define HILDON_WEEKDAY_PICKER(obj) \ + (GTK_CHECK_CAST (obj, HILDON_TYPE_WEEKDAY_PICKER, \ + HildonWeekdayPicker)) +#define HILDON_WEEKDAY_PICKER_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST ((klass), \ + HILDON_TYPE_WEEKDAY_PICKER, HildonWeekdayPickerClass)) +#define HILDON_IS_WEEKDAY_PICKER(obj) \ + (GTK_CHECK_TYPE (obj, HILDON_TYPE_WEEKDAY_PICKER)) +#define HILDON_IS_WEEKDAY_PICKER_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_WEEKDAY_PICKER)) +/** + * HildonWeekdayPicker: + * + * Internal struct for weekday picker. + */ +typedef struct _HildonWeekdayPicker HildonWeekdayPicker; +typedef struct _HildonWeekdayPickerClass HildonWeekdayPickerClass; + +struct _HildonWeekdayPicker { + GtkContainer parent; +}; + +struct _HildonWeekdayPickerClass { + GtkContainerClass parent_class; + + void (*selection_changed) (HildonWeekdayPicker * self); +}; + +GType hildon_weekday_picker_get_type(void) G_GNUC_CONST; + +/** + * hildon_weekday_picker_new: + * + * Creates a new #HildonWeekdayPicker. + * + * Return value: New #HildonWeekdayPicker. + **/ +GtkWidget *hildon_weekday_picker_new(void); + +/** + * hildon_weekday_picker_set_day: + * @picker: #HildonWeekdayPicker. + * @day: #GDateWeekday. + * + * Select specified weekday. + * + **/ +void hildon_weekday_picker_set_day(HildonWeekdayPicker * picker, + GDateWeekday day); + +/** + * hildon_weekday_picker_unset_day: + * @picker: #HildonWeekdayPicker. + * @day: #GDateWeekday. + * + * Unselect specified weekday. + * + **/ +void hildon_weekday_picker_unset_day(HildonWeekdayPicker * picker, + GDateWeekday day); + +/** + * hildon_weekday_picker_toggle_day: + * @picker: #HildonWeekdayPicker. + * @day: #GDateWeekday. + * + * Toggle current status of the specified weekday. + * + **/ +void hildon_weekday_picker_toggle_day(HildonWeekdayPicker * picker, + GDateWeekday day); + +/** + * hildon_weekday_picker_set_all: + * @picker: #HildonWeekdayPicker. + * + * Select all weekdays. + * + **/ +void hildon_weekday_picker_set_all(HildonWeekdayPicker * picker); + +/** + * hildon_weekday_picker_unset_all: + * @picker: #HildonWeekdayPicker. + * + * Unselect all weekdays. + * + **/ +void hildon_weekday_picker_unset_all(HildonWeekdayPicker * picker); + +/** + * hildon_weekday_picker_isset_day: + * @picker: #HildonWeekdayPicker. + * @day: #GDateWeekday. + * + * Check if the specified weekday is set. + * + * Return value: Set/not set. + **/ +gboolean hildon_weekday_picker_isset_day(HildonWeekdayPicker * picker, + GDateWeekday day); + +G_END_DECLS +#endif /* __HILDON_WEEKDAY_PICKER_H__ */ diff --git a/src/hildon-window-private.h b/src/hildon-window-private.h new file mode 100644 index 0000000..92ea85e --- /dev/null +++ b/src/hildon-window-private.h @@ -0,0 +1,54 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + + +#ifndef __HILDON_WINDOW_PRIVATE_H__ +#define __HILDON_WINDOW_PRIVATE_H__ + +G_BEGIN_DECLS + +void +hildon_window_set_program (HildonWindow *self, GObject *program); + +void +hildon_window_unset_program (HildonWindow *self); + +void +hildon_window_set_can_hibernate_property (HildonWindow *self, + gpointer can_hibernate); + +void +hildon_window_take_common_toolbar (HildonWindow *self); + +void +hildon_window_update_topmost (HildonWindow *self, Window window_id); + +Window +hildon_window_get_active_window (void); + +void +hildon_window_update_title (HildonWindow *window); + +G_END_DECLS +#endif /* __HILDON_WINDOW_PRIVATE_H__ */ diff --git a/src/hildon-window.c b/src/hildon-window.c new file mode 100644 index 0000000..faf9e0e --- /dev/null +++ b/src/hildon-window.c @@ -0,0 +1,1707 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + + +#include +#include +#include +#include +#include "hildon-app.h" +#include +#include "hildon-program.h" +#include "hildon-window-private.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + + +#include +#define _(String) gettext(String) + +/*The size of screen*/ +#define WINDOW_HEIGHT 480 +#define WINDOW_WIDTH 800 + +#define NAVIGATOR_HEIGHT WINDOW_HEIGHT + +#define APPVIEW_HEIGHT 396 +#define APPVIEW_WIDTH 672 + +#define TOOLBAR_HEIGHT 40 +#define TOOLBAR_MIDDLE 10 +#define TOOLBAR_WIDTH APPVIEW_WIDTH + +/*FIXME*/ +#define CAN_HIBERNATE "CANKILL" +#define CAN_HIBERNATE_LENGTH 7 + +#define CAN_HIBERNATE_PROPERTY "_HILDON_ABLE_TO_HIBERNATE" + +#define TITLE_SEPARATOR " - " + + +#define HILDON_WINDOW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ + HILDON_TYPE_WINDOW, HildonWindowPrivate)) + +static GtkWindowClass *parent_class; + +static void +hildon_window_init (HildonWindow * self); + +static void +hildon_window_class_init (HildonWindowClass * window_class); + +static void +hildon_window_menupopupfunc (GtkMenu *menu, gint *x, gint *y, + gboolean *push_in, + GtkWidget *widget); +static void +hildon_window_menupopupfuncfull (GtkMenu *menu, gint *x, gint *y, + gboolean *push_in, + GtkWidget *widget); +static gboolean +hildon_window_expose (GtkWidget * widget, GdkEventExpose * event); +static void +hildon_window_forall (GtkContainer * container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data); +static void +hildon_window_show_all (GtkWidget *widget); + +static void +hildon_window_size_allocate (GtkWidget * widget, + GtkAllocation * allocation); +static void +hildon_window_size_request (GtkWidget * widget, + GtkRequisition * requisition); +static void +hildon_window_finalize (GObject * obj_self); +static void +hildon_window_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec); +static void +hildon_window_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec); +static void +hildon_window_destroy (GtkObject *obj); +static void +hildon_window_realize (GtkWidget *widget); +static void +hildon_window_unrealize (GtkWidget *widget); +static gboolean +hildon_window_key_press_event (GtkWidget *widget, + GdkEventKey *event); +static gboolean +hildon_window_key_release_event (GtkWidget *widget, + GdkEventKey *event); +static gboolean +hildon_window_window_state_event (GtkWidget *widget, + GdkEventWindowState *event); + + +static void +hildon_window_notify (GObject *gobject, GParamSpec *param); + +static void +hildon_window_is_topmost_notify (HildonWindow *window); + +static gboolean +hildon_window_toggle_menu (HildonWindow * self); + +static gboolean +hildon_window_escape_timeout (gpointer data); + +static GdkFilterReturn +hildon_window_event_filter (GdkXEvent *xevent, GdkEvent *event, gpointer data ); + +static GdkFilterReturn +hildon_window_root_window_event_filter (GdkXEvent *xevent, + GdkEvent *event, + gpointer data ); + +static void +hildon_window_get_borders (HildonWindow *window); + +static void +visible_toolbar (gpointer data, gpointer user_data); +static void +paint_toolbar (GtkWidget *widget, GtkBox *box, + GdkEventExpose * event, + gboolean fullscreen); + +typedef void (*HildonWindowSignal) (HildonWindow *, gint, gpointer); + + + +enum +{ + PROP_0, + PROP_IS_TOPMOST +}; + +enum +{ + WIN_TYPE = 0, + WIN_TYPE_MESSAGE, + MAX_WIN_MESSAGES +}; + +struct _HildonWindowPrivate +{ + GtkWidget *menu; + GtkWidget *vbox; + + GtkBorder *borders; + GtkBorder *toolbar_borders; + + GtkAllocation allocation; + + guint fullscreen; + guint is_topmost; + guint escape_timeout; + gint visible_toolbars; + gint previous_vbox_y; + + HildonProgram *program; +}; + +GType +hildon_window_get_type (void) +{ + static GType window_type = 0; + + if (!window_type) { + static const GTypeInfo window_info = { + sizeof(HildonWindowClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_window_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonWindow), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_window_init, + }; + window_type = g_type_register_static(GTK_TYPE_WINDOW, + "HildonWindow", + &window_info, 0); + } + return window_type; +} + +/* Virtual methods */ + +static void +hildon_window_class_init (HildonWindowClass * window_class) +{ + /* Get convenience variables */ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (window_class); + GObjectClass *object_class = G_OBJECT_CLASS (window_class); + GtkContainerClass *container_class = GTK_CONTAINER_CLASS (window_class); + + /* Set the global parent_class here */ + parent_class = g_type_class_peek_parent (window_class); + + object_class->set_property = hildon_window_set_property; + object_class->get_property = hildon_window_get_property; + object_class->notify = hildon_window_notify; + + /* Set the widgets virtual functions */ + widget_class->size_allocate = hildon_window_size_allocate; + widget_class->size_request = hildon_window_size_request; + widget_class->expose_event = hildon_window_expose; + widget_class->show_all = hildon_window_show_all; + widget_class->realize = hildon_window_realize; + widget_class->unrealize = hildon_window_unrealize; + widget_class->key_press_event = hildon_window_key_press_event; + widget_class->key_release_event = hildon_window_key_release_event; + widget_class->window_state_event = hildon_window_window_state_event; + + /* now the object stuff */ + object_class->finalize = hildon_window_finalize; + + /* To the container */ + container_class->forall = hildon_window_forall; + + /* gtkobject stuff*/ + GTK_OBJECT_CLASS (window_class)->destroy = hildon_window_destroy; + + g_type_class_add_private (window_class, + sizeof (struct _HildonWindowPrivate)); + + /* Install properties */ + g_object_class_install_property (object_class, PROP_IS_TOPMOST, + g_param_spec_boolean ("is-topmost", + "Is top-most", + "Whether the window is currently activated by the window " + "manager", + FALSE, + G_PARAM_READABLE)); + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_boxed ("borders", + "Graphical borders", + "Size of graphical window borders", + GTK_TYPE_BORDER, + G_PARAM_READABLE)); + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_boxed ("toolbar-borders", + "Graphical toolbar borders", + "Size of graphical toolbar borders", + GTK_TYPE_BORDER, + G_PARAM_READABLE)); + + /* opera hack, install clip operation signal */ + g_signal_new ("clipboard_operation", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (HildonWindowClass, clipboard_operation), + NULL, NULL, + g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, + GTK_TYPE_INT); +} + +static void +hildon_window_init (HildonWindow * self) +{ + HildonWindowPrivate *priv = self->priv = HILDON_WINDOW_GET_PRIVATE(self); + + self->priv->vbox = gtk_vbox_new (TRUE, TOOLBAR_MIDDLE); + gtk_widget_set_parent (self->priv->vbox, GTK_WIDGET(self)); + priv->menu = NULL; + priv->visible_toolbars = 0; + priv->is_topmost = FALSE; + priv->borders = NULL; + priv->toolbar_borders = NULL; + priv->escape_timeout = 0; + + priv->fullscreen = FALSE; + + priv->program = NULL; + + /* We need to track the root window _MB_CURRENT_APP_WINDOW property */ + gdk_window_set_events (gdk_get_default_root_window (), + gdk_window_get_events (gdk_get_default_root_window ()) | GDK_PROPERTY_CHANGE_MASK); + + gdk_window_add_filter (gdk_get_default_root_window (), + hildon_window_root_window_event_filter, self); +} + +static void +hildon_window_finalize (GObject * obj_self) +{ + HildonWindow *self; + g_return_if_fail (HILDON_WINDOW (obj_self)); + self = HILDON_WINDOW (obj_self); + + g_free (self->priv->borders); + g_free (self->priv->toolbar_borders); + + if (G_OBJECT_CLASS (parent_class)->finalize) + G_OBJECT_CLASS (parent_class)->finalize (obj_self); + +} + +static void +hildon_window_realize (GtkWidget *widget) +{ + Atom *old_atoms, *new_atoms; + Display *disp; + Window window; + gint atom_count; + Window active_window; + + GTK_WIDGET_CLASS (parent_class)->realize (widget); + + gtk_widget_realize (GTK_WIDGET (HILDON_WINDOW (widget)->priv->vbox)); + + + /* catch the custom button signal from mb to display the menu */ + gdk_window_add_filter (widget->window, hildon_window_event_filter, widget ); + + window = GDK_WINDOW_XID ( widget->window ); + disp = GDK_WINDOW_XDISPLAY ( widget->window ); + + /* Enable custom button that is used for menu */ + XGetWMProtocols (disp, window, &old_atoms, &atom_count); + new_atoms = g_new (Atom, atom_count + 1); + + memcpy (new_atoms, old_atoms, sizeof(Atom) * atom_count); + + new_atoms[atom_count++] = + XInternAtom (disp, "_NET_WM_CONTEXT_CUSTOM", False); + + XSetWMProtocols (disp, window, new_atoms, atom_count); + + XFree(old_atoms); + g_free(new_atoms); + + /* rely on GDK to set the window group to its default */ + gdk_window_set_group (widget->window, NULL); + + if (HILDON_WINDOW (widget)->priv->program) + { + gboolean can_hibernate = hildon_program_get_can_hibernate ( + HILDON_WINDOW (widget)->priv->program); + + hildon_window_set_can_hibernate_property (HILDON_WINDOW (widget), + &can_hibernate); + } + + /* Update the topmost status */ + active_window = hildon_window_get_active_window(); + hildon_window_update_topmost (HILDON_WINDOW (widget), active_window); + + /* Update the window title */ + hildon_window_update_title(HILDON_WINDOW (widget)); + +} + +static void +hildon_window_unrealize (GtkWidget *widget) +{ + + gdk_window_remove_filter (widget->window, hildon_window_event_filter, + widget); + + gtk_widget_unrealize (GTK_WIDGET (HILDON_WINDOW (widget)->priv->vbox)); + GTK_WIDGET_CLASS(parent_class)->unrealize(widget); +} + +static void +hildon_window_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + /*HildonWindow *window = HILDON_WINDOW (object);*/ + + switch (property_id) { + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +hildon_window_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (object); + + switch (property_id) { + + case PROP_IS_TOPMOST: + g_value_set_boolean (value, priv->is_topmost); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +/* + * Retrieve the graphical borders size used by the themes + */ +static void +hildon_window_get_borders (HildonWindow *window) +{ + + g_free (window->priv->borders); + g_free (window->priv->toolbar_borders); + + gtk_widget_style_get (GTK_WIDGET (window), "borders",&window->priv->borders, + "toolbar-borders", &window->priv->toolbar_borders, + NULL); + + if (!window->priv->borders) + { + window->priv->borders = (GtkBorder *)g_malloc0 (sizeof (GtkBorder)); + } + + if (!window->priv->toolbar_borders) + { + window->priv->toolbar_borders = + (GtkBorder *)g_malloc0 (sizeof (GtkBorder)); + } +} + +static void +visible_toolbars (gpointer data, gpointer user_data) +{ + if (GTK_WIDGET_VISIBLE (GTK_WIDGET (((GtkBoxChild *)data)->widget))) + (*((gint *)user_data)) ++; +} + +static gboolean +hildon_window_expose (GtkWidget * widget, GdkEventExpose * event) +{ + HildonWindowPrivate *priv = HILDON_WINDOW (widget)->priv; + GtkWidget *bx = HILDON_WINDOW(widget)->priv->vbox; + GtkBox *box = GTK_BOX(bx); + GtkBorder *b = HILDON_WINDOW(widget)->priv->borders; + GtkBorder *tb = HILDON_WINDOW(widget)->priv->toolbar_borders; + gint tb_height = 0; + gint currently_visible_toolbars = 0; + + if (!priv->borders) + { + hildon_window_get_borders (HILDON_WINDOW (widget)); + b = HILDON_WINDOW(widget)->priv->borders; + tb = HILDON_WINDOW(widget)->priv->toolbar_borders; + } + + tb_height = bx->allocation.height + tb->top + tb->bottom; + + g_list_foreach (box->children, visible_toolbars, + ¤tly_visible_toolbars); + + paint_toolbar (widget, box, + event, priv->fullscreen); + + if (!HILDON_WINDOW (widget)->priv->fullscreen) + { + + /* Draw the left and right window border */ + gint side_borders_height = widget->allocation.height - b->top; + + if (currently_visible_toolbars) + side_borders_height -= tb_height; + else + side_borders_height -= b->bottom; + + if (b->left > 0) + { + gtk_paint_box (widget->style, widget->window, + GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, + &event->area, widget, "left-border", + widget->allocation.x, widget->allocation.y + + b->top, b->left, side_borders_height); + } + + if (b->right > 0) + { + gtk_paint_box (widget->style, widget->window, + GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, + &event->area, widget, "right-border", + widget->allocation.x + widget->allocation.width - + b->right, widget->allocation.y + b->top, + b->right, side_borders_height); + } + + /* If no toolbar, draw the bottom window border */ + if (!currently_visible_toolbars && b->bottom > 0) + { + gtk_paint_box (widget->style, widget->window, + GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, + &event->area, widget, "bottom-border", + widget->allocation.x, widget->allocation.y + + (widget->allocation.height - b->bottom), + widget->allocation.width, b->bottom); + } + + /* Draw the top border */ + if (b->top > 0) + { + gtk_paint_box (widget->style, widget->window, + GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, + &event->area, widget, "top-border", + widget->allocation.x, widget->allocation.y, + widget->allocation.width, b->top); + } + + + } + + /* don't draw the window stuff as it overwrites our borders with a blank + * rectangle. Instead start with the drawing of the GtkBin */ + GTK_WIDGET_CLASS (g_type_class_peek_parent (parent_class))-> + expose_event (widget, event); + /*GTK_WIDGET_CLASS (parent_class))-> + expose_event (widget, event);*/ + + return FALSE; + +} + +static void +hildon_window_size_request (GtkWidget * widget, GtkRequisition * requisition) +{ + HildonWindowPrivate *priv = HILDON_WINDOW (widget)->priv; + GtkWidget *child = GTK_BIN (widget)->child; + GtkRequisition req2; + gint border_width = GTK_CONTAINER(widget)->border_width; + + if (!priv->borders) + { + hildon_window_get_borders (HILDON_WINDOW (widget)); + } + + if (child) + gtk_widget_size_request (child, requisition); + + if (HILDON_WINDOW (widget)->priv->vbox != NULL) + gtk_widget_size_request (HILDON_WINDOW (widget)->priv->vbox, + &req2); + + requisition->height += req2.height; + requisition->width = (requisition->width < req2.width) ? + req2.width : requisition->width; + + + requisition->width += 2 * border_width; + requisition->height += 2 * border_width; + + if (!priv->fullscreen) + { + requisition->height += priv->borders->top; + if (req2.height == 0) + requisition->height += priv->borders->bottom; + requisition->width += priv->borders->left + priv->borders->right; + } +} + +static void +hildon_window_size_allocate (GtkWidget * widget, GtkAllocation * allocation) +{ + HildonWindowPrivate *priv = HILDON_WINDOW (widget)->priv; + GtkAllocation box_alloc; + GtkAllocation alloc = *allocation; + GtkRequisition req; + gint border_width = GTK_CONTAINER(widget)->border_width; + + GtkWidget *box = HILDON_WINDOW(widget)->priv->vbox; + GtkBin *bin = GTK_BIN(widget); + GtkBorder *b = HILDON_WINDOW (widget)->priv->borders; + GtkBorder *tb = HILDON_WINDOW (widget)->priv->toolbar_borders; + + if (!priv->borders) + { + hildon_window_get_borders (HILDON_WINDOW (widget)); + b = HILDON_WINDOW (widget)->priv->borders; + tb = HILDON_WINDOW (widget)->priv->toolbar_borders; + } + + widget->allocation = *allocation; + + gtk_widget_get_child_requisition (box, &req); + + box_alloc.width = allocation->width - tb->left - tb->right; + box_alloc.height = ( (req.height < allocation->height) ? + req.height : allocation->height ); + box_alloc.x = allocation->x + tb->left; + box_alloc.y = allocation->y + allocation->height - box_alloc.height - tb->bottom; + + if (bin->child != NULL && GTK_IS_WIDGET (bin->child) + && GTK_WIDGET_VISIBLE (bin->child)) + { + alloc.x += border_width; + alloc.y += border_width; + alloc.width -= (border_width * 2); + alloc.height -= (border_width * 2) + box_alloc.height; + + if (!(HILDON_WINDOW (widget)->priv->fullscreen)) + { + alloc.x += b->left; + alloc.width -= (b->left + b->right); + alloc.y += b->top; + + alloc.height -= b->top; + + if (box_alloc.height <= 0) + alloc.height -= b->bottom; + else + alloc.height -= (tb->top + tb->bottom); + } + else + { + if (!(box_alloc.height <= 0)) + alloc.height -= (tb->top + tb->bottom); + } + + gtk_widget_size_allocate (bin->child, &alloc); + } + + + gtk_widget_size_allocate (box, &box_alloc); + + if (priv->previous_vbox_y != box_alloc.y) + { + /* The size of the VBox has changed, we need to redraw part + * of the window borders */ + gint draw_from_y = priv->previous_vbox_y < box_alloc.y? + priv->previous_vbox_y - tb->top: + box_alloc.y - tb->top; + + gtk_widget_queue_draw_area (widget, 0, draw_from_y, + widget->allocation.width, + widget->allocation.height - draw_from_y); + + priv->previous_vbox_y = box_alloc.y; + } + +} + +static void +hildon_window_forall (GtkContainer * container, gboolean include_internals, + GtkCallback callback, gpointer callback_data) +{ + HildonWindow *self = HILDON_WINDOW (container); + + g_return_if_fail (callback != NULL); + + GTK_CONTAINER_CLASS (parent_class)->forall (container, include_internals, + callback, callback_data); + if (include_internals && self->priv->vbox != NULL) + (* callback)(GTK_WIDGET (self->priv->vbox), callback_data); +} + +static void +hildon_window_show_all (GtkWidget *widget) +{ + HildonWindow *self = HILDON_WINDOW (widget); + + GTK_WIDGET_CLASS (parent_class)->show_all (widget); + gtk_widget_show_all (self->priv->vbox); + +} + +static void +hildon_window_destroy (GtkObject *obj) +{ + HildonWindow *self = HILDON_WINDOW (obj); + GList *menu_list; + + if (self->priv->vbox != NULL) + { + if (self->priv->program) + { + GtkWidget * common_toolbar = GTK_WIDGET ( + hildon_program_get_common_toolbar (self->priv->program)); + if (common_toolbar && common_toolbar->parent == self->priv->vbox) + { + gtk_container_remove (GTK_CONTAINER (self->priv->vbox), + common_toolbar); + } + } + + gtk_widget_unparent (self->priv->vbox); + self->priv->vbox = NULL; + + } + + menu_list = g_list_copy (gtk_menu_get_for_attach_widget (GTK_WIDGET (obj))); + + while (menu_list) + { + if (GTK_IS_MENU(menu_list->data)) + { + if (GTK_WIDGET_VISIBLE (GTK_WIDGET (menu_list->data))) + { + gtk_menu_popdown (GTK_MENU (menu_list->data)); + gtk_menu_shell_deactivate (GTK_MENU_SHELL (menu_list->data)); + } + gtk_menu_detach (GTK_MENU (menu_list->data)); + } + menu_list = menu_list->next; + } + + g_list_free (menu_list); + + if (self->priv->program) + { + hildon_program_remove_window (self->priv->program, self); + } + + gdk_window_remove_filter (gdk_get_default_root_window(), + hildon_window_root_window_event_filter, + obj); + + gtk_widget_set_events (GTK_WIDGET(obj), 0); + + GTK_OBJECT_CLASS (parent_class)->destroy (obj); +} + + +static void +hildon_window_notify (GObject *gobject, GParamSpec *param) +{ + HildonWindow *window = HILDON_WINDOW (gobject); + + if (strcmp (param->name, "title") == 0) + { + + hildon_window_update_title (window); + } + else if (strcmp (param->name, "is-topmost")) + { + hildon_window_is_topmost_notify (window); + } + + if (G_OBJECT_CLASS(parent_class)->notify) + G_OBJECT_CLASS(parent_class)->notify (gobject, param); +} + +/* Utilities */ + +static void +visible_toolbar (gpointer data, gpointer user_data) +{ + if (GTK_WIDGET_VISIBLE (((GtkBoxChild *)data)->widget)) + (*((gint *)user_data))++; +} + +static void +find_findtoolbar_index (gpointer data, gpointer user_data) +{ + gint *pass_bundle = (gint *)user_data; + + if(((GtkBoxChild *)data)->widget->allocation.y < pass_bundle[0] + && GTK_WIDGET_VISIBLE (((GtkBoxChild *)data)->widget)) + pass_bundle[1]++; +} + +static void +find_findtoolbar (gpointer data, gpointer user_data) +{ + if(HILDON_IS_FIND_TOOLBAR (((GtkBoxChild *)data)->widget) + && GTK_WIDGET_VISIBLE (((GtkBoxChild *)data)->widget)) + (*((GtkWidget **)user_data)) = ((GtkBoxChild *)data)->widget; +} + +static void +paint_toolbar (GtkWidget *widget, GtkBox *box, + GdkEventExpose * event, + gboolean fullscreen) +{ + gint toolbar_num = 0; + gint ftb_index = 0; + gint count; + GtkWidget *findtoolbar = NULL; + gchar toolbar_mode[40]; + GtkBorder *tb = HILDON_WINDOW (widget)->priv->toolbar_borders; + + /* collect info to help on painting the boxes */ + g_list_foreach (box->children, visible_toolbar, + (gpointer) &toolbar_num); + + if(toolbar_num <= 0) + return; + + g_list_foreach (box->children, find_findtoolbar, (gpointer) &findtoolbar); + + if (findtoolbar != NULL) + { + gint pass_bundle[2];/* an array for convient data passing + the first member contains the y allocation + of the find toolbar, and the second allocation + contains the index(how many toolbars are above + find toolbar) */ + pass_bundle[0] = findtoolbar->allocation.y; + pass_bundle[1] = ftb_index; + g_list_foreach(box->children, find_findtoolbar_index, + (gpointer) pass_bundle); + ftb_index = pass_bundle[1]; + } + + /*upper border*/ + sprintf (toolbar_mode, "toolbar%sframe-top", + fullscreen ? "-fullscreen-" : "-"); + gtk_paint_box (widget->style, widget->window, + GTK_WIDGET_STATE (widget), GTK_SHADOW_OUT, + &event->area, widget, toolbar_mode, + widget->allocation.x, + GTK_WIDGET (box)->allocation.y - tb->top, + widget->allocation.width, tb->top); + + /*top most toolbar painting*/ + if (findtoolbar != NULL && ftb_index == 0 ) + { + sprintf (toolbar_mode, "findtoolbar%s", + fullscreen ? "-fullscreen" : ""); + + gtk_paint_box (widget->style, widget->window, + GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, + &event->area, widget, toolbar_mode, + widget->allocation.x, + GTK_WIDGET(box)->allocation.y, + widget->allocation.width, + TOOLBAR_HEIGHT); + } + else + { + sprintf (toolbar_mode, "toolbar%s", + fullscreen ? "-fullscreen" : ""); + + gtk_paint_box (widget->style, widget->window, + GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, + &event->area, widget, toolbar_mode, + widget->allocation.x, + GTK_WIDGET(box)->allocation.y, + widget->allocation.width, + TOOLBAR_HEIGHT); + } + /*multi toolbar painting*/ + for (count = 0; count < toolbar_num - 1; count++) + { + sprintf (toolbar_mode, "toolbar%sframe-middle", + fullscreen ? "-fullscreen-" : "-"); + + gtk_paint_box (widget->style, widget->window, + GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, + &event->area, widget, toolbar_mode, + widget->allocation.x, + GTK_WIDGET(box)->allocation.y + + (1 + count) * TOOLBAR_HEIGHT + + count * TOOLBAR_MIDDLE, + widget->allocation.width, + TOOLBAR_MIDDLE); + + if (findtoolbar != NULL && count + 1 == ftb_index) + { + + sprintf (toolbar_mode, "findtoolbar%s", + fullscreen ? "-fullscreen" : ""); + + gtk_paint_box (widget->style, widget->window, + GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, + &event->area, widget, toolbar_mode, + widget->allocation.x, + GTK_WIDGET(box)->allocation.y + + (1 + count) * (TOOLBAR_HEIGHT + TOOLBAR_MIDDLE), + widget->allocation.width, + TOOLBAR_HEIGHT); + } + else + { + sprintf (toolbar_mode, "toolbar%s", + fullscreen ? "-fullscreen" : ""); + + gtk_paint_box (widget->style, widget->window, + GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, + &event->area, widget, toolbar_mode, + widget->allocation.x, + GTK_WIDGET(box)->allocation.y + + (1 + count) * (TOOLBAR_HEIGHT + TOOLBAR_MIDDLE), + widget->allocation.width, + TOOLBAR_HEIGHT); + } + } + sprintf (toolbar_mode, "toolbar%sframe-bottom", + fullscreen ? "-fullscreen-" : "-"); + + gtk_paint_box (widget->style, widget->window, + GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, + &event->area, widget, toolbar_mode, + widget->allocation.x, + GTK_WIDGET(box)->allocation.y + + GTK_WIDGET(box)->allocation.height, + widget->allocation.width, tb->bottom); + +} + +/* + * Checks the root window to know which is the topped window + */ +Window +hildon_window_get_active_window (void) +{ + Atom realtype; + int format; + int status; + Window ret; + unsigned long n; + unsigned long extra; + union + { + Window *win; + unsigned char *char_pointer; + } win; + Atom active_app_atom = + XInternAtom (GDK_DISPLAY (), "_MB_CURRENT_APP_WINDOW", False); + + win.win = NULL; + + status = XGetWindowProperty (GDK_DISPLAY(), GDK_ROOT_WINDOW(), + active_app_atom, 0L, 16L, + 0, XA_WINDOW, &realtype, &format, + &n, &extra, &win.char_pointer); + if (!(status == Success && realtype == XA_WINDOW && format == 32 + && n == 1 && win.win != NULL)) + { + if (win.win != NULL) + XFree (win.char_pointer); + return None; + } + + ret = win.win[0]; + + if (win.win != NULL) + XFree(win.char_pointer); + + return ret; +} + +static int +xclient_message_type_check (XClientMessageEvent *cm, const gchar *name) +{ + return cm->message_type == XInternAtom(GDK_DISPLAY(), name, FALSE); +} + +/*****************/ +/* Event filters */ +/*****************/ + +/* + * Handle the window border custom button, which toggles the menu, + * and the Hildon input method copy paste messages + */ +static GdkFilterReturn +hildon_window_event_filter (GdkXEvent *xevent, GdkEvent *event, gpointer data) +{ + XAnyEvent *eventti = xevent; + + if (eventti->type == ClientMessage) + { + XClientMessageEvent *cm = xevent; + + if (xclient_message_type_check (cm, "_MB_GRAB_TRANSFER")) + { + hildon_window_toggle_menu (HILDON_WINDOW ( data )); + return GDK_FILTER_REMOVE; + } + /* opera hack clipboard client message */ + else if (xclient_message_type_check (cm, "_HILDON_IM_CLIPBOARD_COPY")) + { + g_signal_emit_by_name(G_OBJECT(data), "clipboard_operation", + HILDON_WINDOW_CO_COPY); + return GDK_FILTER_REMOVE; + } + else if (xclient_message_type_check(cm, "_HILDON_IM_CLIPBOARD_CUT")) + { + g_signal_emit_by_name(G_OBJECT(data), "clipboard_operation", + HILDON_WINDOW_CO_CUT); + return GDK_FILTER_REMOVE; + } + else if (xclient_message_type_check(cm, "_HILDON_IM_CLIPBOARD_PASTE")) + { + g_signal_emit_by_name(G_OBJECT(data), "clipboard_operation", + HILDON_WINDOW_CO_PASTE); + return GDK_FILTER_REMOVE; + } + } + + return GDK_FILTER_CONTINUE; +} + +/* + * Here we keep track of changes in the _MB_CURRENT_APP_WINDOW, + * to know when we acquire/lose topmost status + */ +static GdkFilterReturn +hildon_window_root_window_event_filter (GdkXEvent *xevent, + GdkEvent *event, + gpointer data) +{ + XAnyEvent *eventti = xevent; + HildonWindow *hwindow = HILDON_WINDOW (data); + + + if (eventti->type == PropertyNotify) + { + XPropertyEvent *pevent = xevent; + Atom active_app_atom = + XInternAtom (GDK_DISPLAY (), "_MB_CURRENT_APP_WINDOW", False); + + if (pevent->atom == active_app_atom) + { + Window active_window = hildon_window_get_active_window(); + + hildon_window_update_topmost (hwindow, active_window); + } + } + + return GDK_FILTER_CONTINUE; +} + +/***************************/ +/* Signal handlers */ +/***************************/ + +/* + * Handle the menu hardware key here + */ +static gboolean +hildon_window_key_press_event (GtkWidget *widget, GdkEventKey *event) +{ + HildonWindowPrivate *priv; + + g_return_val_if_fail (HILDON_IS_WINDOW (widget),FALSE); + + priv = HILDON_WINDOW (widget)->priv; + + switch (event->keyval) + { + case HILDON_HARDKEY_MENU: + if (hildon_window_toggle_menu (HILDON_WINDOW (widget))) + return TRUE; + break; + case HILDON_HARDKEY_ESC: + if (!priv->escape_timeout) + { + priv->escape_timeout = g_timeout_add + (HILDON_WINDOW_LONG_PRESS_TIME, + hildon_window_escape_timeout, widget); + } + break; + } + + return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event); + +} + +static gboolean +hildon_window_key_release_event (GtkWidget *widget, GdkEventKey *event) +{ + HildonWindowPrivate *priv; + + g_return_val_if_fail (HILDON_IS_WINDOW (widget),FALSE); + + priv = HILDON_WINDOW (widget)->priv; + + switch (event->keyval) + { + case HILDON_HARDKEY_ESC: + if (priv->escape_timeout) + { + g_source_remove (priv->escape_timeout); + priv->escape_timeout = 0; + } + break; + } + + return GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event); + +} + +/* + * We keep track of the window state changes, because the drawing + * (borders) differs whether we are in fullscreen mode or not + */ +static gboolean +hildon_window_window_state_event (GtkWidget *widget, + GdkEventWindowState *event) +{ + if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) + { + HILDON_WINDOW (widget)->priv->fullscreen = + event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN; + } + + if (GTK_WIDGET_CLASS (parent_class)->window_state_event) + { + return GTK_WIDGET_CLASS (parent_class)->window_state_event ( + widget, + event); + } + else + { + return FALSE; + } +} + +static void +hildon_window_title_notify (GObject *gobject, + GParamSpec *arg1, + gpointer user_data) +{ + HildonWindow *window = HILDON_WINDOW (gobject); + + hildon_window_update_title (window); + +} + +/*******************/ +/* General */ +/*******************/ + +/*The menu popuping needs a menu popup-function*/ +static void +hildon_window_menupopupfunc (GtkMenu *menu, gint *x, gint *y, + gboolean *push_in, GtkWidget *widget) +{ + gint window_x = 0; + gint window_y = 0; + GdkWindow *window = GTK_WIDGET(widget)->window; + + if (window) + { + gdk_window_get_origin (window, &window_x, &window_y); + } + + gtk_widget_style_get (GTK_WIDGET (menu), "horizontal-offset", x, + "vertical-offset", y, NULL); + + *x += window_x; + *y += window_y; + +} + +static void +hildon_window_menupopupfuncfull ( GtkMenu *menu, gint *x, gint *y, + gboolean *push_in, + GtkWidget *widget ) +{ + gtk_widget_style_get (GTK_WIDGET (menu), "horizontal-offset", x, + "vertical-offset", y, NULL); + + *x = MAX (0, *x); + *y = MAX (0, *y); +} + + +/********************/ +/* Private methods */ +/********************/ + + +/* + * Takes the common toolbar when we acquire the top-most status + */ +static void +hildon_window_is_topmost_notify (HildonWindow *window) +{ + if (window->priv->is_topmost) + { + hildon_window_take_common_toolbar (window); + } + + else + { + /* If the window lost focus while the user started to press + * the ESC key, we won't get the release event. We need to + * stop the timeout*/ + if (window->priv->escape_timeout) + { + g_source_remove (window->priv->escape_timeout); + window->priv->escape_timeout = 0; + } + } +} + +/* + * Sets the program to which the window belongs. This should only be called + * by hildon_program_add_window + */ +void +hildon_window_set_program (HildonWindow *self, GObject *program) +{ + if (self->priv->program) + { + g_object_unref (self->priv->program); + } + + /* Now that we are bound to a program, we can rely on it to track the + * root window */ + gdk_window_remove_filter (gdk_get_default_root_window(), + hildon_window_root_window_event_filter, + self); + + self->priv->program = HILDON_PROGRAM (program); + g_object_ref (program); +} + +/* + * Unsets the program to which the window belongs. This should only be called + * by hildon_program_add_window + */ +void +hildon_window_unset_program (HildonWindow *self) +{ + g_return_if_fail(self && HILDON_IS_WINDOW (self)); + + if (self->priv->program) + { + g_object_unref (self->priv->program); + self->priv->program = NULL; + + /* We need to start tacking the root window again */ + gdk_window_set_events (gdk_get_default_root_window (), + gdk_window_get_events (gdk_get_default_root_window ()) + | GDK_PROPERTY_CHANGE_MASK); + + gdk_window_add_filter (gdk_get_default_root_window (), + hildon_window_root_window_event_filter, self ); + } + + self->priv->program = NULL; +} + +/* + * Sets whether or not the program to which this window belongs is + * killable. This is used by the HildonProgram to signify to the + * Task Navigator whether or not it can hibernate in memory-low situations + **/ +void +hildon_window_set_can_hibernate_property (HildonWindow *self, + gpointer _can_hibernate) +{ + GdkAtom killable_atom; + gboolean can_hibernate; + + g_return_if_fail(self && HILDON_IS_WINDOW (self)); + + if (!GTK_WIDGET_REALIZED ((GTK_WIDGET (self)))) + { + return; + } + + can_hibernate = * ((gboolean *)_can_hibernate); + + killable_atom = gdk_atom_intern (CAN_HIBERNATE_PROPERTY, FALSE); + + if (can_hibernate) + { + gdk_property_change (GTK_WIDGET (self)->window, killable_atom, + (GdkAtom)31/* XA_STRING */, 8, + GDK_PROP_MODE_REPLACE, (const guchar *)CAN_HIBERNATE, + CAN_HIBERNATE_LENGTH); + } + else + { + gdk_property_delete (GTK_WIDGET (self)->window, killable_atom); + } + +} + +/* + * If a common toolbar was set to the program, reparent it to + * us + */ +void +hildon_window_take_common_toolbar (HildonWindow *self) +{ + g_return_if_fail(self && HILDON_IS_WINDOW (self)); + + if (self->priv->program) + { + GtkWidget *common_toolbar = + GTK_WIDGET (hildon_program_get_common_toolbar (self->priv->program)); + + if (common_toolbar && common_toolbar->parent != self->priv->vbox) + { + g_object_ref (common_toolbar); + if (common_toolbar->parent) + { + gtk_container_remove (GTK_CONTAINER (common_toolbar->parent), + common_toolbar); + } + + gtk_box_pack_end (GTK_BOX(self->priv->vbox), common_toolbar, + TRUE, TRUE, 0); + g_object_unref (common_toolbar); + + gtk_widget_set_size_request (common_toolbar, -1, TOOLBAR_HEIGHT); + + gtk_widget_show (self->priv->vbox); + + } + } +} + +/* + * Compare the window that was last topped, and act consequently + */ +void +hildon_window_update_topmost (HildonWindow *self, Window window_id) +{ + Window my_window; + + my_window = GDK_WINDOW_XID (GTK_WIDGET (self)->window); + + if (window_id == my_window) + { + if (!self->priv->is_topmost) + { + self->priv->is_topmost = TRUE; + hildon_window_is_topmost_notify (self); + g_object_notify (G_OBJECT (self), "is-topmost"); + } + } + else if (self->priv->is_topmost) + { + /* Should this go in the signal handler? */ + GtkWidget *focus = gtk_window_get_focus (GTK_WINDOW (self)); + + if (GTK_IS_ENTRY (focus)) + gtk_im_context_focus_out (GTK_ENTRY (focus)->im_context); + if (GTK_IS_TEXT_VIEW (focus)) + gtk_im_context_focus_out (GTK_TEXT_VIEW (focus)->im_context); + + self->priv->is_topmost = FALSE; + hildon_window_is_topmost_notify (self); + g_object_notify (G_OBJECT (self), "is-topmost"); + + } +} + +/* + * If the application + * was given a name (with g_set_application_name(), set + * "ProgramName - WindowTitle" as the displayed + * title + */ +void +hildon_window_update_title (HildonWindow *window) +{ + const gchar * application_name; + g_return_if_fail (window && HILDON_IS_WINDOW (window)); + + if (!GTK_WIDGET_REALIZED (window)) + { + return; + } + + application_name = g_get_application_name (); + + if (application_name && application_name[0]) + { + const gchar *old_title = gtk_window_get_title (GTK_WINDOW (window)); + + if (old_title && old_title[0]) + { + gchar *title = NULL; + + title = g_strjoin (TITLE_SEPARATOR, application_name, + old_title, NULL); + + gdk_window_set_title (GTK_WIDGET (window)->window, title); + + g_free (title); + } + + } +} + +static void +detach_menu_func (GtkWidget *attach_widget, GtkMenu *menu) +{ +} +/* + * Toggles the display of the HildonWindow menu. + * Returns whether or not something was done (whether or not we had a menu + * to toggle) + */ +static gboolean +hildon_window_toggle_menu (HildonWindow * self) +{ + GtkMenu *menu_to_use = NULL; + GList *menu_children = NULL; + + g_return_val_if_fail (self && HILDON_IS_WINDOW (self), FALSE); + + /* Select which menu to use, Window specific has highest priority, + * then program specific */ + if (self->priv->menu) + { + menu_to_use = GTK_MENU (self->priv->menu); + } + else if (self->priv->program) + { + menu_to_use = hildon_program_get_common_menu (self->priv->program); + if (menu_to_use && gtk_menu_get_attach_widget (menu_to_use) != + GTK_WIDGET (self)) + { + g_object_ref (menu_to_use); + if (gtk_menu_get_attach_widget (menu_to_use)) + { + gtk_menu_detach (menu_to_use); + } + + gtk_menu_attach_to_widget (menu_to_use, GTK_WIDGET (self), + &detach_menu_func); + g_object_unref (menu_to_use); + } + } + + if (!menu_to_use) + { + return FALSE; + } + + + if (GTK_WIDGET_MAPPED (GTK_WIDGET (menu_to_use))) + { + gtk_menu_popdown (menu_to_use); + gtk_menu_shell_deactivate (GTK_MENU_SHELL (menu_to_use)); + return TRUE; + } + + /* Check if the menu has items */ + menu_children = gtk_container_get_children (GTK_CONTAINER (menu_to_use)); + + if (menu_children) + { + g_list_free (menu_children); + + /* Apply right theming */ + gtk_widget_set_name (GTK_WIDGET (menu_to_use), + "menu_force_with_corners"); + + if (self->priv->fullscreen) + { + gtk_menu_popup (menu_to_use, NULL, NULL, + (GtkMenuPositionFunc) + hildon_window_menupopupfuncfull, + self, 0, + gtk_get_current_event_time ()); + } + else + { + gtk_menu_popup (menu_to_use, NULL, NULL, + (GtkMenuPositionFunc) + hildon_window_menupopupfunc, + self, 0, + gtk_get_current_event_time ()); + } + gtk_menu_shell_select_first (GTK_MENU_SHELL (menu_to_use), TRUE); + return TRUE; + } + + return FALSE; + +} + +/* + * If the ESC key was not released when the timeout expires, + * close the window + */ +static gboolean +hildon_window_escape_timeout (gpointer data) +{ + HildonWindowPrivate *priv; + GdkEvent *event; + + GDK_THREADS_ENTER (); + + priv = HILDON_WINDOW(data)->priv; + + /* Send fake event, simulation a situation that user + pressed 'x' from the corner */ + event = gdk_event_new(GDK_DELETE); + ((GdkEventAny *)event)->window = GDK_WINDOW (g_object_ref (GTK_WIDGET(data)->window)); + gtk_main_do_event(event); + + /* That unrefs the window, so we're reffing it above */ + gdk_event_free(event); + + priv->escape_timeout = 0; + + GDK_THREADS_LEAVE (); + + return FALSE; +} + + +/******************/ +/* public methods */ +/******************/ + + +/** + * hildon_window_new: + * + * Use this function to create a new HildonWindow. + * + * Return value: A @HildonWindow. + **/ +GtkWidget * +hildon_window_new (void) +{ + HildonWindow *newwindow = g_object_new (HILDON_TYPE_WINDOW, NULL); + + return GTK_WIDGET (newwindow); +} + +/** + * hildon_window_add_with_scrollbar + * @self : A @HildonWindow + * @child : A @GtkWidget + * + * Adds the @child to the HildonWindow and creates a scrollbar + * to it. Similar as adding first a @GtkScrolledWindow and then the + * @child to it. + */ +void +hildon_window_add_with_scrollbar (HildonWindow * self, + GtkWidget * child) +{ + GtkScrolledWindow *scrolledw; + + g_return_if_fail (HILDON_IS_WINDOW (self)); + g_return_if_fail (GTK_IS_WIDGET (child)); + g_return_if_fail (child->parent == NULL); + + scrolledw = GTK_SCROLLED_WINDOW (gtk_scrolled_window_new (NULL, NULL)); + gtk_scrolled_window_set_policy (scrolledw, GTK_POLICY_NEVER, + GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type (scrolledw, GTK_SHADOW_NONE); + + if (GTK_IS_VIEWPORT (child)) + gtk_container_add (GTK_CONTAINER (scrolledw), child); + else + { + if (GTK_IS_CONTAINER (child) ) + gtk_container_set_focus_vadjustment (GTK_CONTAINER(child), + gtk_scrolled_window_get_vadjustment (scrolledw) ); + gtk_scrolled_window_add_with_viewport (scrolledw, child); + } + + gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (scrolledw)); +} + +/** + * hildon_window_add_toolbar: + * @self: A @HildonWindow + * @toolbar: A #GtkToolbar to add to the HildonWindow + * + * Adds a toolbar to the window. + **/ +void +hildon_window_add_toolbar (HildonWindow *self, GtkToolbar *toolbar) +{ + GtkBox *vbox; + + g_return_if_fail (self && HILDON_IS_WINDOW (self)); + g_return_if_fail (toolbar && GTK_IS_TOOLBAR (toolbar)); + + vbox = GTK_BOX (self->priv->vbox); + + gtk_box_pack_start (vbox, GTK_WIDGET(toolbar), TRUE, TRUE, 0); + gtk_box_reorder_child (vbox, GTK_WIDGET(toolbar), 0); + gtk_widget_set_size_request (GTK_WIDGET (toolbar), -1, TOOLBAR_HEIGHT); + + gtk_widget_queue_resize (GTK_WIDGET(self)); +} + +/** + * hildon_window_remove_toolbar: + * @self: A @HildonWindow + * @toolbar: A #GtkToolbar to remove from the HildonWindow + * + * Removes a toolbar from the window. + **/ +void +hildon_window_remove_toolbar (HildonWindow *self, GtkToolbar *toolbar) +{ + GtkContainer *vbox = GTK_CONTAINER (self->priv->vbox); + + g_return_if_fail (self && HILDON_IS_WINDOW (self)); + + gtk_container_remove (vbox, GTK_WIDGET(toolbar)); +} + +/** + * hildon_window_get_menu: + * @self : #HildonWindow + * + * Gets the #GtMenu assigned to the #HildonAppview. + * + * Return value: The #GtkMenu assigned to this application view. + **/ +GtkMenu * +hildon_window_get_menu (HildonWindow * self) +{ + g_return_val_if_fail (self && HILDON_IS_WINDOW (self), NULL); + + return GTK_MENU (self->priv->menu); +} + + +/** + * hildon_window_set_menu: + * @self: A #HildonWindow + * @menu: The #GtkMenu to be used for this #HildonWindow + * + * Sets the menu to be used for this window. This menu overrides + * a program-wide menu that may have been set with + * hildon_program_set_common_menu. Pass NULL to remove the current + * menu. + **/ +void +hildon_window_set_menu (HildonWindow *self, GtkMenu *menu) +{ + g_return_if_fail (HILDON_IS_WINDOW (self)); + + if (self->priv->menu != NULL) { + gtk_menu_detach (GTK_MENU (self->priv->menu)); + g_object_unref (self->priv->menu); + } + + self->priv->menu = (menu != NULL) ? GTK_WIDGET (menu) : NULL; + if (self->priv->menu != NULL) { + gtk_widget_set_name (self->priv->menu, "menu_force_with_corners"); + gtk_menu_attach_to_widget (GTK_MENU (self->priv->menu), GTK_WIDGET (self), &detach_menu_func); + g_object_ref (GTK_MENU (self->priv->menu)); + gtk_widget_show_all (GTK_WIDGET (self->priv->menu)); + } +} + +/** + * hildon_window_get_is_topmost: + * @self: A #HildonWindow + * + * Return value: Whether or not the #HildonWindow is currenltly activated + * by the window manager. + **/ +gboolean +hildon_window_get_is_topmost(HildonWindow *self){ + g_return_val_if_fail (HILDON_IS_WINDOW (self), FALSE); + + return self->priv->is_topmost; +} + diff --git a/src/hildon-window.h b/src/hildon-window.h new file mode 100644 index 0000000..5a14220 --- /dev/null +++ b/src/hildon-window.h @@ -0,0 +1,112 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + + +#ifndef __HILDON_WINDOW_H__ +#define __HILDON_WINDOW_H__ + +#include +#include +#include +#include +#include +#include + +#include "hildon-defines.h" + +G_BEGIN_DECLS + +#define HILDON_WINDOW_LONG_PRESS_TIME 1500 /* in ms */ + +#define HILDON_TYPE_WINDOW ( hildon_window_get_type() ) +#define HILDON_WINDOW(obj) \ + (GTK_CHECK_CAST (obj, HILDON_TYPE_WINDOW, HildonWindow)) +#define HILDON_WINDOW_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST ((klass),\ + HILDON_TYPE_WINDOW, HildonWindowClass)) +#define HILDON_IS_WINDOW(obj) (GTK_CHECK_TYPE (obj, HILDON_TYPE_WINDOW)) +#define HILDON_IS_WINDOW_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_WINDOW)) + +typedef struct _HildonWindow HildonWindow; +typedef struct _HildonWindowClass HildonWindowClass; + +/** + * HildonWindowPrivate: + * + * This structure contains just internal data. + * It should not be accessed directly. + */ +typedef struct _HildonWindowPrivate HildonWindowPrivate; + +struct _HildonWindow +{ + GtkWindow parent; + + /*private*/ + HildonWindowPrivate *priv; +}; + +enum +{ + HILDON_WINDOW_CO_COPY, + HILDON_WINDOW_CO_CUT, + HILDON_WINDOW_CO_PASTE +}; + +struct _HildonWindowClass +{ + GtkWindowClass parent_class; + + /* opera hacks for clip board operation */ + void (*clipboard_operation)(HildonWindow *hwindow, int operation); + /* Padding for future extension */ + void (*_hildon_reserved1)(void); + void (*_hildon_reserved2)(void); + void (*_hildon_reserved3)(void); +}; + + +GType hildon_window_get_type (void); + +GtkWidget * hildon_window_new (void); + +void hildon_window_add_with_scrollbar(HildonWindow *self, + GtkWidget *child); + +GtkMenu * hildon_window_get_menu (HildonWindow *self); +void hildon_window_set_menu (HildonWindow *self, + GtkMenu *menu); + +void hildon_window_add_toolbar (HildonWindow *self, + GtkToolbar *toolbar); + +void hildon_window_remove_toolbar (HildonWindow *self, + GtkToolbar *toolbar); + +gboolean hildon_window_get_is_topmost (HildonWindow *self); + + +G_END_DECLS +#endif /* __HILDON_WINDOW_H__ */ diff --git a/src/hildon-wizard-dialog.c b/src/hildon-wizard-dialog.c new file mode 100644 index 0000000..d775d5a --- /dev/null +++ b/src/hildon-wizard-dialog.c @@ -0,0 +1,487 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * Fixes: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-wizard-dialog + * @short_description: A widget to create a guided installation + * process wizard + * + * #HildonWizardDialog is a widget to create a guided installation + * process. The dialog has four standard buttons, previous, next, + * finish, cancel, and contains several pages with optional icons. + * Response buttons are dimmed/undimmed automatically and the standard + * icon is shown/hidden in response to page navigation. The notebook + * widget provided by users contains the actual wizard pages. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hildon-wizard-dialog.h" + +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#define _(String) dgettext(PACKAGE, String) + +static GtkDialogClass *parent_class; + +static void class_init (HildonWizardDialogClass *wizard_dialog_class); + +static void init (HildonWizardDialog *wizard_dialog); + +static void create_title (HildonWizardDialog *wizard_dialog); + +static void set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); + +static void get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static void finalize (GObject *object); + +static void response (HildonWizardDialog *wizard, + gint response_id, + gpointer unused); + +static void make_buttons_sensitive (HildonWizardDialog *wizard_dialog, + gboolean previous, + gboolean finish, + gboolean next); + +enum { + PROP_ZERO, + PROP_WIZARD_NAME, + PROP_WIZARD_NOTEBOOK, + PROP_WIZARD_AUTOTITLE +}; + +struct _HildonWizardDialogPrivate { + gchar *wizard_name; + GtkNotebook *notebook; + GtkBox *box; + GtkWidget *image; + gboolean autotitle; +}; + + +GType +hildon_wizard_dialog_get_type (void) +{ + static GType wizard_dialog_type = 0; + + if (!wizard_dialog_type) { + + static const GTypeInfo wizard_dialog_info = { + sizeof (HildonWizardDialogClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (HildonWizardDialog), + 0, /* n_preallocs */ + (GInstanceInitFunc) init, + }; + + wizard_dialog_type = g_type_register_static (GTK_TYPE_DIALOG, + "HildonWizardDialog", + &wizard_dialog_info, + 0); + } + + return wizard_dialog_type; +} + +static void +class_init (HildonWizardDialogClass *wizard_dialog_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (wizard_dialog_class); + + parent_class = g_type_class_peek_parent (wizard_dialog_class); + + g_type_class_add_private (wizard_dialog_class, + sizeof(HildonWizardDialogPrivate)); + + /* Override virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + + /** + * HildonWizardDialog:wizard-name: + * + * The name of the wizard. + */ + g_object_class_install_property (object_class, PROP_WIZARD_NAME, + g_param_spec_string + ("wizard-name", + "Wizard Name", + "The name of the HildonWizardDialog", + NULL, + G_PARAM_READWRITE)); + + /** + * HildonWizardDialog:wizard-notebook: + * + * The notebook object, which is used by the HildonWizardDialog. + */ + g_object_class_install_property(object_class, PROP_WIZARD_NOTEBOOK, + g_param_spec_object + ("wizard-notebook", + "Wizard Notebook", + "GtkNotebook object to be used in the " + "HildonWizardDialog", + GTK_TYPE_NOTEBOOK, G_PARAM_READWRITE)); + + /** + * HildonWizardDialog:autotitle + * + * If the wizard should automatically try to change the window title when changing steps. + * Set to FALSE if you'd like to override the default behaviour. + * + * Since: 0.14.5 + */ + g_object_class_install_property(object_class, PROP_WIZARD_AUTOTITLE, + g_param_spec_boolean + ("autotitle", + "AutoTitle", + "If the wizard should autotitle itself", + TRUE, + G_PARAM_READWRITE)); +} + +static void +finalize (GObject *object) +{ + HildonWizardDialog *dialog = HILDON_WIZARD_DIALOG (object); + g_return_if_fail (dialog != NULL); + + if (dialog->priv->wizard_name != NULL) + g_free (HILDON_WIZARD_DIALOG (object)->priv->wizard_name); + + if (G_OBJECT_CLASS (parent_class)->finalize) + G_OBJECT_CLASS (parent_class)->finalize(object); +} + +/* Disable or enable the Previous, Next and Finish buttons */ +static void +make_buttons_sensitive (HildonWizardDialog *wizard_dialog, + gboolean previous, + gboolean finish, + gboolean next) +{ + gtk_dialog_set_response_sensitive (GTK_DIALOG (wizard_dialog), + HILDON_WIZARD_DIALOG_PREVIOUS, + previous); + + gtk_dialog_set_response_sensitive (GTK_DIALOG (wizard_dialog), + HILDON_WIZARD_DIALOG_FINISH, + finish); + + gtk_dialog_set_response_sensitive (GTK_DIALOG (wizard_dialog), + HILDON_WIZARD_DIALOG_NEXT, + next); +} + +static void +init (HildonWizardDialog *wizard_dialog) +{ + /* Initialize private structure for faster member access */ + HildonWizardDialogPrivate *priv = + G_TYPE_INSTANCE_GET_PRIVATE (wizard_dialog, + HILDON_TYPE_WIZARD_DIALOG, + HildonWizardDialogPrivate); + + GtkDialog *dialog = GTK_DIALOG (wizard_dialog); + + /* Init internal widgets */ + GtkWidget *vbox = gtk_vbox_new (FALSE, 0); + gtk_dialog_set_has_separator (dialog, FALSE); + wizard_dialog->priv = priv; + priv->box = GTK_BOX (gtk_hbox_new (FALSE, 0)); + priv->image = gtk_image_new_from_icon_name ("qgn_widg_wizard", + HILDON_ICON_SIZE_WIDG_WIZARD); + + /* Default values for user provided properties */ + priv->notebook = NULL; + priv->wizard_name = NULL; + priv->autotitle = TRUE; + + /* Build wizard layout */ + gtk_box_pack_start_defaults (GTK_BOX (dialog->vbox), GTK_WIDGET (priv->box)); + gtk_box_pack_start_defaults (GTK_BOX (priv->box), GTK_WIDGET (vbox)); + gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (priv->image), FALSE, FALSE, 0); + + /* Add response buttons: finish, previous, next, cancel */ + gtk_dialog_add_button (dialog, _("ecdg_bd_wizard_finish"), HILDON_WIZARD_DIALOG_FINISH); + gtk_dialog_add_button (dialog, _("ecdg_bd_wizard_previous"), HILDON_WIZARD_DIALOG_PREVIOUS); + gtk_dialog_add_button (dialog, _("ecdg_bd_wizard_next"), HILDON_WIZARD_DIALOG_NEXT); + gtk_dialog_add_button (dialog, _("ecdg_bd_wizard_cancel"), HILDON_WIZARD_DIALOG_CANCEL); + + /* Set initial button states: previous and finish buttons are disabled */ + make_buttons_sensitive (wizard_dialog, FALSE, FALSE, TRUE); + + /* Show all the internal widgets */ + gtk_widget_show_all (GTK_WIDGET (dialog->vbox)); + + /* connect to dialog's response signal */ + g_signal_connect (G_OBJECT (dialog), "response", + G_CALLBACK (response), NULL); +} + +static void +set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + HildonWizardDialogPrivate *priv = HILDON_WIZARD_DIALOG(object)->priv; + + switch (property_id) { + + case PROP_WIZARD_AUTOTITLE: + + priv->autotitle = g_value_get_boolean (value); + + if (priv->autotitle && + priv->wizard_name && + priv->notebook) + create_title (HILDON_WIZARD_DIALOG (object)); + else if (priv->wizard_name) + gtk_window_set_title (GTK_WINDOW (object), priv->wizard_name); + + break; + + case PROP_WIZARD_NAME: + + /* Set new wizard name. This name will appear in titlebar */ + if (priv->wizard_name) + g_free (priv->wizard_name); + + gchar *str = (gchar *) g_value_get_string (value); + g_return_if_fail (str != NULL); + + priv->wizard_name = g_strdup (str); + + /* We need notebook in order to create title, since page information + is used in title generation */ + + if (priv->notebook && priv->autotitle) + create_title (HILDON_WIZARD_DIALOG (object)); + + break; + + case PROP_WIZARD_NOTEBOOK: { + + GtkNotebook *book = GTK_NOTEBOOK (g_value_get_object (value)); + g_return_if_fail (book != NULL); + + priv->notebook = book; + + /* Set the default properties for the notebook (disable tabs, + * and remove borders) to make it look like a nice wizard widget */ + gtk_notebook_set_show_tabs (priv->notebook, FALSE); + gtk_notebook_set_show_border (priv->notebook, FALSE); + gtk_box_pack_start_defaults (GTK_BOX( priv->box), GTK_WIDGET (priv->notebook)); + + /* Show the notebook so that a gtk_widget_show on the dialog is + * all that is required to display the dialog correctly */ + gtk_widget_show (priv->notebook); + + /* Update dialog title to reflect current page stats etc */ + if (priv->wizard_name && priv->autotitle) + create_title (HILDON_WIZARD_DIALOG (object)); + + } break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + HildonWizardDialogPrivate *priv = HILDON_WIZARD_DIALOG (object)->priv; + + switch (property_id) { + + case PROP_WIZARD_NAME: + g_value_set_string (value, priv->wizard_name); + break; + + case PROP_WIZARD_NOTEBOOK: + g_value_set_object (value, priv->notebook); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +/* + * Creates the title of the dialog taking into account the current + * page of the notebook. + */ +static void +create_title (HildonWizardDialog *wizard_dialog) +{ + gint pages, current; + gchar *str = NULL; + HildonWizardDialogPrivate *priv = wizard_dialog->priv; + GtkNotebook *notebook = priv->notebook; + + if (!notebook) + return; + + /* Get page information, we'll need that when creating title */ + pages = gtk_notebook_get_n_pages (notebook); + current = gtk_notebook_get_current_page (priv->notebook); + if (current < 0) + current = 0; + + /* the welcome title on the initial page */ + if (current == 0) { + str = g_strdup_printf (_("ecdg_ti_wizard_welcome"), + priv->wizard_name, pages); + } else { + const gchar *steps = gtk_notebook_get_tab_label_text (notebook, + gtk_notebook_get_nth_page (notebook, current)); + + str = g_strdup_printf (_("ecdg_ti_wizard_step"), + priv->wizard_name, current + 1, pages, steps); + } + + /* Update the dialog to display the generated title */ + gtk_window_set_title (GTK_WINDOW (wizard_dialog), str); + g_free (str); +} + +/* + * Response signal handler. This function is needed because GtkDialog's + * handler for this signal closes the dialog and we don't want that, we + * want to change pages and, dimm certain response buttons. Overriding the + * virtual function would not work because that would be called after the + * signal handler implemented by GtkDialog. + * FIXME: There is a much saner way to do that [MDK] + */ +static void +response (HildonWizardDialog *wizard_dialog, + gint response_id, + gpointer unused) +{ + HildonWizardDialogPrivate *priv = wizard_dialog->priv; + GtkNotebook *notebook = priv->notebook; + gint current = 0; + gint last = gtk_notebook_get_n_pages (notebook) - 1; + gboolean is_first, is_last; + + switch (response_id) { + + case HILDON_WIZARD_DIALOG_PREVIOUS: + gtk_notebook_prev_page (notebook); /* go to previous page */ + break; + + case HILDON_WIZARD_DIALOG_NEXT: + gtk_notebook_next_page (notebook); /* go to next page */ + break; + + case HILDON_WIZARD_DIALOG_CANCEL: + case HILDON_WIZARD_DIALOG_FINISH: + return; + + } + + current = gtk_notebook_get_current_page (notebook); + is_last = current == last; + is_first = current == 0; + + /* If first page, previous and finish are disabled, + if last page, next is disabled */ + make_buttons_sensitive (wizard_dialog, + !is_first, !is_first, !is_last); + + /* Don't let the dialog close */ + g_signal_stop_emission_by_name (wizard_dialog, "response"); + + /* We show the default image on first and last pages */ + if (current == last || current == 0) + gtk_widget_show (GTK_WIDGET(priv->image)); + else + gtk_widget_hide (GTK_WIDGET(priv->image)); + + /* New page number may appear in the title, update it */ + if (priv->autotitle) + create_title (wizard_dialog); +} + +/** + * hildon_wizard_dialog_new: + * @parent: a #GtkWindow + * @wizard_name: the name of dialog + * @notebook: the notebook to be shown on the dialog + * + * Creates a new #HildonWizardDialog. + * + * Returns: a new #HildonWizardDialog + */ +GtkWidget* +hildon_wizard_dialog_new (GtkWindow *parent, + const char *wizard_name, + GtkNotebook *notebook) +{ + GtkWidget *widget; + + g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL); + + widget = GTK_WIDGET (g_object_new + (HILDON_TYPE_WIZARD_DIALOG, + "wizard-name", wizard_name, + "wizard-notebook", notebook, NULL)); + + if (parent) + gtk_window_set_transient_for (GTK_WINDOW (widget), parent); + + return widget; +} diff --git a/src/hildon-wizard-dialog.h b/src/hildon-wizard-dialog.h new file mode 100644 index 0000000..38de909 --- /dev/null +++ b/src/hildon-wizard-dialog.h @@ -0,0 +1,86 @@ +/* + * This file is part of hildon-libs + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Michael Dominic Kostrzewa + * Fixes: Michael Dominic Kostrzewa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; version 2.1 of + * the License. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __HILDON_WIZARD_DIALOG_H__ +#define __HILDON_WIZARD_DIALOG_H__ + +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define HILDON_TYPE_WIZARD_DIALOG (hildon_wizard_dialog_get_type()) + +#define HILDON_WIZARD_DIALOG(obj) (GTK_CHECK_CAST ((obj), \ + HILDON_TYPE_WIZARD_DIALOG, HildonWizardDialog)) + +#define HILDON_WIZARD_DIALOG_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), \ + HILDON_TYPE_WIZARD_DIALOG, HildonWizardDialogClass)) + +#define HILDON_IS_WIZARD_DIALOG(obj) (GTK_CHECK_TYPE ((obj), \ + HILDON_TYPE_WIZARD_DIALOG)) + +#define HILDON_IS_WIZARD_DIALOG_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), \ + HILDON_TYPE_WIZARD_DIALOG)) + +typedef struct _HildonWizardDialog HildonWizardDialog; + +typedef struct _HildonWizardDialogClass HildonWizardDialogClass; + +typedef struct _HildonWizardDialogPrivate HildonWizardDialogPrivate; + +/* button response IDs */ +enum { + HILDON_WIZARD_DIALOG_CANCEL = GTK_RESPONSE_CANCEL, + HILDON_WIZARD_DIALOG_PREVIOUS = 0, + HILDON_WIZARD_DIALOG_NEXT, + HILDON_WIZARD_DIALOG_FINISH +}; + +struct _HildonWizardDialog { + GtkDialog parent; + HildonWizardDialogPrivate *priv; +}; + +struct _HildonWizardDialogClass { + GtkDialogClass parent_class; + void (*_gtk_reserved1) (void); + void (*_gtk_reserved2) (void); + void (*_gtk_reserved3) (void); + void (*_gtk_reserved4) (void); +}; + + +GType hildon_wizard_dialog_get_type (void) G_GNUC_CONST; + +GtkWidget* hildon_wizard_dialog_new (GtkWindow *parent, + const char *wizard_name, + GtkNotebook *notebook); + +G_END_DECLS + +#endif /* __HILDON_WIZARD_DIALOG_H__ */ -- 1.7.9.5