From 69a11338fe0cc36a868e5812b590f5437622988a Mon Sep 17 00:00:00 2001 From: Alberto Garcia Date: Thu, 30 Apr 2009 13:10:26 +0200 Subject: [PATCH] Renamed src/ to hildon/ * src/ * Makefile.am * configure.ac * doc/Makefile.am * doc/hildon.types * po/POTFILES.in: Renamed src/ to hildon/ * examples/*.c * debian/changelog * debian/rules: Include directly in all examples. --- ChangeLog | 15 + Makefile.am | 2 +- configure.ac | 10 +- debian/changelog | 1 + debian/rules | 1 - doc/Makefile.am | 8 +- doc/hildon.types | 108 +- examples/hildon-app-menu-example.c | 2 +- examples/hildon-banner-example.c | 2 +- examples/hildon-banner-long-example.c | 2 +- examples/hildon-bread-crumb-trail-example.c | 2 +- examples/hildon-button-example.c | 2 +- examples/hildon-caption-example.c | 2 +- examples/hildon-check-button-example.c | 2 +- examples/hildon-code-dialog-example.c | 2 +- examples/hildon-color-button-example.c | 2 +- examples/hildon-color-chooser-example.c | 2 +- examples/hildon-color-pop-example.c | 2 +- examples/hildon-controlbar-example.c | 2 +- examples/hildon-date-button-example.c | 2 +- examples/hildon-date-editor-example.c | 2 +- examples/hildon-dialog-example.c | 2 +- examples/hildon-edit-toolbar-example.c | 2 +- examples/hildon-entry-example.c | 2 +- examples/hildon-find-toolbar-example.c | 2 +- examples/hildon-finger-example.c | 2 +- examples/hildon-get-password-dialog-example.c | 2 +- examples/hildon-hvolumebar-example.c | 2 +- examples/hildon-hvolumebar-insensitive-example.c | 2 +- .../hildon-hvolumebar-insensitive-map-example.c | 2 +- examples/hildon-hvolumebar-timer-example.c | 2 +- examples/hildon-icon-sizes-example.c | 2 +- examples/hildon-insensitive-example.c | 2 +- examples/hildon-logical-color-example.c | 2 +- examples/hildon-login-dialog-example.c | 2 +- examples/hildon-lookup-example.c | 2 +- examples/hildon-note-example.c | 2 +- examples/hildon-number-editor-example.c | 2 +- .../hildon-pannable-area-buttons-scroll-example.c | 2 +- .../hildon-pannable-area-gesture-signals-example.c | 2 +- .../hildon-pannable-area-scroll-jump-example.c | 2 +- examples/hildon-pannable-area-touch-grid-example.c | 2 +- examples/hildon-pannable-area-touch-list-example.c | 2 +- examples/hildon-pannable-area-tree-view-example.c | 2 +- examples/hildon-pannable-area-tuning-example.c | 2 +- examples/hildon-picker-button-example.c | 2 +- .../hildon-picker-button-multicolumn-example.c | 2 +- examples/hildon-progress-indicator-example.c | 2 +- examples/hildon-remote-texture-example.c | 2 +- examples/hildon-scrolled-window-example.c | 2 +- examples/hildon-seekbar-example.c | 2 +- examples/hildon-set-password-dialog-example.c | 2 +- examples/hildon-sort-dialog-example.c | 2 +- examples/hildon-stackable-window-example.c | 2 +- examples/hildon-text-view-example.c | 2 +- examples/hildon-thumb-scrollbar-example.c | 2 +- examples/hildon-time-button-example.c | 2 +- examples/hildon-time-editor-example.c | 2 +- examples/hildon-time-picker-example.c | 2 +- examples/hildon-toolbar-example.c | 2 +- examples/hildon-toolbar-seekbar-example.c | 2 +- examples/hildon-touch-selector-entry-example.c | 2 +- examples/hildon-touch-selector-example.c | 2 +- .../hildon-touch-selector-multi-cells-example.c | 2 +- examples/hildon-vvolumebar-example.c | 2 +- examples/hildon-weekday-picker-example.c | 2 +- examples/hildon-window-cmn-menu-example.c | 2 +- examples/hildon-window-example.c | 2 +- examples/hildon-window-menu-example.c | 2 +- examples/hildon-wizard-dialog-example.c | 2 +- hildon/Makefile.am | 235 ++ hildon/hildon-animation-actor-private.h | 81 + hildon/hildon-animation-actor.c | 1198 ++++++ hildon/hildon-animation-actor.h | 162 + hildon/hildon-app-menu-private.h | 53 + hildon/hildon-app-menu.c | 1123 +++++ hildon/hildon-app-menu.h | 103 + hildon/hildon-banner-private.h | 55 + hildon/hildon-banner.c | 1238 ++++++ hildon/hildon-banner.h | 116 + hildon/hildon-bread-crumb-trail.c | 791 ++++ hildon/hildon-bread-crumb-trail.h | 90 + hildon/hildon-bread-crumb-widget.c | 517 +++ hildon/hildon-bread-crumb-widget.h | 79 + hildon/hildon-bread-crumb.c | 129 + hildon/hildon-bread-crumb.h | 64 + hildon/hildon-button.c | 1022 +++++ hildon/hildon-button.h | 177 + hildon/hildon-calendar-popup-private.h | 45 + hildon/hildon-calendar-popup.c | 528 +++ hildon/hildon-calendar-popup.h | 91 + hildon/hildon-calendar-private.h | 121 + hildon/hildon-calendar.c | 4307 ++++++++++++++++++++ hildon/hildon-calendar.h | 180 + hildon/hildon-caption-private.h | 53 + hildon/hildon-caption.c | 1236 ++++++ hildon/hildon-caption.h | 168 + hildon/hildon-check-button.c | 263 ++ hildon/hildon-check-button.h | 85 + hildon/hildon-code-dialog-private.h | 46 + hildon/hildon-code-dialog.c | 685 ++++ hildon/hildon-code-dialog.h | 92 + hildon/hildon-color-button-private.h | 43 + hildon/hildon-color-button.c | 648 +++ hildon/hildon-color-button.h | 97 + hildon/hildon-color-chooser-dialog-private.h | 73 + hildon/hildon-color-chooser-dialog.c | 1148 ++++++ hildon/hildon-color-chooser-dialog.h | 84 + hildon/hildon-color-chooser-private.h | 63 + hildon/hildon-color-chooser.c | 1365 +++++++ hildon/hildon-color-chooser.h | 87 + hildon/hildon-controlbar-private.h | 44 + hildon/hildon-controlbar.c | 893 ++++ hildon/hildon-controlbar.h | 105 + hildon/hildon-date-button.c | 221 + hildon/hildon-date-button.h | 87 + hildon/hildon-date-editor-private.h | 65 + hildon/hildon-date-editor.c | 1570 +++++++ hildon/hildon-date-editor.h | 114 + hildon/hildon-date-selector.c | 904 ++++ hildon/hildon-date-selector.h | 103 + hildon/hildon-defines.c | 58 + hildon/hildon-defines.h | 124 + hildon/hildon-dialog.c | 231 ++ hildon/hildon-dialog.h | 101 + hildon/hildon-edit-toolbar.c | 324 ++ hildon/hildon-edit-toolbar.h | 79 + hildon/hildon-entry.c | 250 ++ hildon/hildon-entry.h | 84 + hildon/hildon-find-toolbar-private.h | 49 + hildon/hildon-find-toolbar.c | 924 +++++ hildon/hildon-find-toolbar.h | 111 + hildon/hildon-font-selection-dialog-private.h | 75 + hildon/hildon-font-selection-dialog.c | 1417 +++++++ hildon/hildon-font-selection-dialog.h | 91 + hildon/hildon-get-password-dialog-private.h | 45 + hildon/hildon-get-password-dialog.c | 672 +++ hildon/hildon-get-password-dialog.h | 96 + hildon/hildon-gtk.c | 500 +++ hildon/hildon-gtk.h | 90 + hildon/hildon-helper.c | 508 +++ hildon/hildon-helper.h | 65 + hildon/hildon-hvolumebar.c | 377 ++ hildon/hildon-hvolumebar.h | 76 + hildon/hildon-login-dialog-private.h | 46 + hildon/hildon-login-dialog.c | 430 ++ hildon/hildon-login-dialog.h | 91 + hildon/hildon-main.c | 121 + hildon/hildon-main.h | 28 + hildon/hildon-marshalers.list | 32 + hildon/hildon-note-private.h | 59 + hildon/hildon-note.c | 1053 +++++ hildon/hildon-note.h | 116 + hildon/hildon-number-editor-private.h | 56 + hildon/hildon-number-editor.c | 1053 +++++ hildon/hildon-number-editor.h | 98 + hildon/hildon-pannable-area.c | 3278 +++++++++++++++ hildon/hildon-pannable-area.h | 177 + hildon/hildon-picker-button-private.h | 30 + hildon/hildon-picker-button.c | 614 +++ hildon/hildon-picker-button.h | 94 + hildon/hildon-picker-dialog.c | 643 +++ hildon/hildon-picker-dialog.h | 103 + hildon/hildon-private.c | 81 + hildon/hildon-private.h | 43 + hildon/hildon-program-private.h | 55 + hildon/hildon-program.c | 843 ++++ hildon/hildon-program.h | 133 + hildon/hildon-range-editor-private.h | 51 + hildon/hildon-range-editor.c | 1079 +++++ hildon/hildon-range-editor.h | 131 + hildon/hildon-remote-texture-private.h | 84 + hildon/hildon-remote-texture.c | 943 +++++ hildon/hildon-remote-texture.h | 136 + hildon/hildon-seekbar-private.h | 47 + hildon/hildon-seekbar.c | 618 +++ hildon/hildon-seekbar.h | 101 + hildon/hildon-set-password-dialog-private.h | 56 + hildon/hildon-set-password-dialog.c | 743 ++++ hildon/hildon-set-password-dialog.h | 91 + hildon/hildon-sort-dialog-private.h | 57 + hildon/hildon-sort-dialog.c | 589 +++ hildon/hildon-sort-dialog.h | 100 + hildon/hildon-sound.c | 129 + hildon/hildon-sound.h | 37 + hildon/hildon-stackable-window-private.h | 49 + hildon/hildon-stackable-window.c | 258 ++ hildon/hildon-stackable-window.h | 100 + hildon/hildon-text-view.c | 342 ++ hildon/hildon-text-view.h | 79 + hildon/hildon-time-button.c | 188 + hildon/hildon-time-button.h | 82 + hildon/hildon-time-editor-private.h | 85 + hildon/hildon-time-editor.c | 1936 +++++++++ hildon/hildon-time-editor.h | 173 + hildon/hildon-time-picker-private.h | 84 + hildon/hildon-time-picker.c | 1019 +++++ hildon/hildon-time-picker.h | 92 + hildon/hildon-time-selector.c | 731 ++++ hildon/hildon-time-selector.h | 107 + hildon/hildon-touch-selector-column.h | 74 + hildon/hildon-touch-selector-entry.c | 533 +++ hildon/hildon-touch-selector-entry.h | 95 + hildon/hildon-touch-selector-private.h | 36 + hildon/hildon-touch-selector.c | 2120 ++++++++++ hildon/hildon-touch-selector.h | 220 + hildon/hildon-version.h.in | 39 + hildon/hildon-volumebar-private.h | 56 + hildon/hildon-volumebar-range.c | 326 ++ hildon/hildon-volumebar-range.h | 85 + hildon/hildon-volumebar.c | 806 ++++ hildon/hildon-volumebar.h | 108 + hildon/hildon-vvolumebar.c | 283 ++ hildon/hildon-vvolumebar.h | 77 + hildon/hildon-weekday-picker-private.h | 44 + hildon/hildon-weekday-picker.c | 565 +++ hildon/hildon-weekday-picker.h | 102 + hildon/hildon-window-private.h | 89 + hildon/hildon-window-stack-private.h | 37 + hildon/hildon-window-stack.c | 679 +++ hildon/hildon-window-stack.h | 137 + hildon/hildon-window.c | 2176 ++++++++++ hildon/hildon-window.h | 140 + hildon/hildon-wizard-dialog-private.h | 52 + hildon/hildon-wizard-dialog.c | 555 +++ hildon/hildon-wizard-dialog.h | 109 + hildon/hildon.h | 87 + po/POTFILES.in | 192 +- src/Makefile.am | 235 -- src/hildon-animation-actor-private.h | 81 - src/hildon-animation-actor.c | 1198 ------ src/hildon-animation-actor.h | 162 - src/hildon-app-menu-private.h | 53 - src/hildon-app-menu.c | 1123 ----- src/hildon-app-menu.h | 103 - src/hildon-banner-private.h | 55 - src/hildon-banner.c | 1238 ------ src/hildon-banner.h | 116 - src/hildon-bread-crumb-trail.c | 791 ---- src/hildon-bread-crumb-trail.h | 90 - src/hildon-bread-crumb-widget.c | 517 --- src/hildon-bread-crumb-widget.h | 79 - src/hildon-bread-crumb.c | 129 - src/hildon-bread-crumb.h | 64 - src/hildon-button.c | 1022 ----- src/hildon-button.h | 177 - src/hildon-calendar-popup-private.h | 45 - src/hildon-calendar-popup.c | 528 --- src/hildon-calendar-popup.h | 91 - src/hildon-calendar-private.h | 121 - src/hildon-calendar.c | 4307 -------------------- src/hildon-calendar.h | 180 - src/hildon-caption-private.h | 53 - src/hildon-caption.c | 1236 ------ src/hildon-caption.h | 168 - src/hildon-check-button.c | 263 -- src/hildon-check-button.h | 85 - src/hildon-code-dialog-private.h | 46 - src/hildon-code-dialog.c | 685 ---- src/hildon-code-dialog.h | 92 - src/hildon-color-button-private.h | 43 - src/hildon-color-button.c | 648 --- src/hildon-color-button.h | 97 - src/hildon-color-chooser-dialog-private.h | 73 - src/hildon-color-chooser-dialog.c | 1148 ------ src/hildon-color-chooser-dialog.h | 84 - src/hildon-color-chooser-private.h | 63 - src/hildon-color-chooser.c | 1365 ------- src/hildon-color-chooser.h | 87 - src/hildon-controlbar-private.h | 44 - src/hildon-controlbar.c | 893 ---- src/hildon-controlbar.h | 105 - src/hildon-date-button.c | 221 - src/hildon-date-button.h | 87 - src/hildon-date-editor-private.h | 65 - src/hildon-date-editor.c | 1570 ------- src/hildon-date-editor.h | 114 - src/hildon-date-selector.c | 904 ---- src/hildon-date-selector.h | 103 - src/hildon-defines.c | 58 - src/hildon-defines.h | 124 - src/hildon-dialog.c | 231 -- src/hildon-dialog.h | 101 - src/hildon-edit-toolbar.c | 324 -- src/hildon-edit-toolbar.h | 79 - src/hildon-entry.c | 250 -- src/hildon-entry.h | 84 - src/hildon-find-toolbar-private.h | 49 - src/hildon-find-toolbar.c | 924 ----- src/hildon-find-toolbar.h | 111 - src/hildon-font-selection-dialog-private.h | 75 - src/hildon-font-selection-dialog.c | 1417 ------- src/hildon-font-selection-dialog.h | 91 - src/hildon-get-password-dialog-private.h | 45 - src/hildon-get-password-dialog.c | 672 --- src/hildon-get-password-dialog.h | 96 - src/hildon-gtk.c | 500 --- src/hildon-gtk.h | 90 - src/hildon-helper.c | 508 --- src/hildon-helper.h | 65 - src/hildon-hvolumebar.c | 377 -- src/hildon-hvolumebar.h | 76 - src/hildon-login-dialog-private.h | 46 - src/hildon-login-dialog.c | 430 -- src/hildon-login-dialog.h | 91 - src/hildon-main.c | 121 - src/hildon-main.h | 28 - src/hildon-marshalers.list | 32 - src/hildon-note-private.h | 59 - src/hildon-note.c | 1053 ----- src/hildon-note.h | 116 - src/hildon-number-editor-private.h | 56 - src/hildon-number-editor.c | 1053 ----- src/hildon-number-editor.h | 98 - src/hildon-pannable-area.c | 3278 --------------- src/hildon-pannable-area.h | 177 - src/hildon-picker-button-private.h | 30 - src/hildon-picker-button.c | 614 --- src/hildon-picker-button.h | 94 - src/hildon-picker-dialog.c | 643 --- src/hildon-picker-dialog.h | 103 - src/hildon-private.c | 81 - src/hildon-private.h | 43 - src/hildon-program-private.h | 55 - src/hildon-program.c | 843 ---- src/hildon-program.h | 133 - src/hildon-range-editor-private.h | 51 - src/hildon-range-editor.c | 1079 ----- src/hildon-range-editor.h | 131 - src/hildon-remote-texture-private.h | 84 - src/hildon-remote-texture.c | 943 ----- src/hildon-remote-texture.h | 136 - src/hildon-seekbar-private.h | 47 - src/hildon-seekbar.c | 618 --- src/hildon-seekbar.h | 101 - src/hildon-set-password-dialog-private.h | 56 - src/hildon-set-password-dialog.c | 743 ---- src/hildon-set-password-dialog.h | 91 - src/hildon-sort-dialog-private.h | 57 - src/hildon-sort-dialog.c | 589 --- src/hildon-sort-dialog.h | 100 - src/hildon-sound.c | 129 - src/hildon-sound.h | 37 - src/hildon-stackable-window-private.h | 49 - src/hildon-stackable-window.c | 258 -- src/hildon-stackable-window.h | 100 - src/hildon-text-view.c | 342 -- src/hildon-text-view.h | 79 - src/hildon-time-button.c | 188 - src/hildon-time-button.h | 82 - src/hildon-time-editor-private.h | 85 - src/hildon-time-editor.c | 1936 --------- src/hildon-time-editor.h | 173 - src/hildon-time-picker-private.h | 84 - src/hildon-time-picker.c | 1019 ----- src/hildon-time-picker.h | 92 - src/hildon-time-selector.c | 731 ---- src/hildon-time-selector.h | 107 - src/hildon-touch-selector-column.h | 74 - src/hildon-touch-selector-entry.c | 533 --- src/hildon-touch-selector-entry.h | 95 - src/hildon-touch-selector-private.h | 36 - src/hildon-touch-selector.c | 2120 ---------- src/hildon-touch-selector.h | 220 - src/hildon-version.h.in | 39 - src/hildon-volumebar-private.h | 56 - src/hildon-volumebar-range.c | 326 -- src/hildon-volumebar-range.h | 85 - src/hildon-volumebar.c | 806 ---- src/hildon-volumebar.h | 108 - src/hildon-vvolumebar.c | 283 -- src/hildon-vvolumebar.h | 77 - src/hildon-weekday-picker-private.h | 44 - src/hildon-weekday-picker.c | 565 --- src/hildon-weekday-picker.h | 102 - src/hildon-window-private.h | 89 - src/hildon-window-stack-private.h | 37 - src/hildon-window-stack.c | 679 --- src/hildon-window-stack.h | 137 - src/hildon-window.c | 2176 ---------- src/hildon-window.h | 140 - src/hildon-wizard-dialog-private.h | 52 - src/hildon-wizard-dialog.c | 555 --- src/hildon-wizard-dialog.h | 109 - src/hildon.h | 87 - 385 files changed, 58657 insertions(+), 58642 deletions(-) create mode 100644 hildon/Makefile.am create mode 100644 hildon/hildon-animation-actor-private.h create mode 100644 hildon/hildon-animation-actor.c create mode 100644 hildon/hildon-animation-actor.h create mode 100644 hildon/hildon-app-menu-private.h create mode 100644 hildon/hildon-app-menu.c create mode 100644 hildon/hildon-app-menu.h create mode 100644 hildon/hildon-banner-private.h create mode 100644 hildon/hildon-banner.c create mode 100644 hildon/hildon-banner.h create mode 100644 hildon/hildon-bread-crumb-trail.c create mode 100644 hildon/hildon-bread-crumb-trail.h create mode 100644 hildon/hildon-bread-crumb-widget.c create mode 100644 hildon/hildon-bread-crumb-widget.h create mode 100644 hildon/hildon-bread-crumb.c create mode 100644 hildon/hildon-bread-crumb.h create mode 100644 hildon/hildon-button.c create mode 100644 hildon/hildon-button.h create mode 100644 hildon/hildon-calendar-popup-private.h create mode 100644 hildon/hildon-calendar-popup.c create mode 100644 hildon/hildon-calendar-popup.h create mode 100644 hildon/hildon-calendar-private.h create mode 100644 hildon/hildon-calendar.c create mode 100644 hildon/hildon-calendar.h create mode 100644 hildon/hildon-caption-private.h create mode 100644 hildon/hildon-caption.c create mode 100644 hildon/hildon-caption.h create mode 100644 hildon/hildon-check-button.c create mode 100644 hildon/hildon-check-button.h create mode 100644 hildon/hildon-code-dialog-private.h create mode 100644 hildon/hildon-code-dialog.c create mode 100644 hildon/hildon-code-dialog.h create mode 100644 hildon/hildon-color-button-private.h create mode 100644 hildon/hildon-color-button.c create mode 100644 hildon/hildon-color-button.h create mode 100644 hildon/hildon-color-chooser-dialog-private.h create mode 100644 hildon/hildon-color-chooser-dialog.c create mode 100644 hildon/hildon-color-chooser-dialog.h create mode 100644 hildon/hildon-color-chooser-private.h create mode 100644 hildon/hildon-color-chooser.c create mode 100644 hildon/hildon-color-chooser.h create mode 100644 hildon/hildon-controlbar-private.h create mode 100644 hildon/hildon-controlbar.c create mode 100644 hildon/hildon-controlbar.h create mode 100644 hildon/hildon-date-button.c create mode 100644 hildon/hildon-date-button.h create mode 100644 hildon/hildon-date-editor-private.h create mode 100644 hildon/hildon-date-editor.c create mode 100644 hildon/hildon-date-editor.h create mode 100644 hildon/hildon-date-selector.c create mode 100644 hildon/hildon-date-selector.h create mode 100644 hildon/hildon-defines.c create mode 100644 hildon/hildon-defines.h create mode 100644 hildon/hildon-dialog.c create mode 100644 hildon/hildon-dialog.h create mode 100644 hildon/hildon-edit-toolbar.c create mode 100644 hildon/hildon-edit-toolbar.h create mode 100644 hildon/hildon-entry.c create mode 100644 hildon/hildon-entry.h create mode 100644 hildon/hildon-find-toolbar-private.h create mode 100644 hildon/hildon-find-toolbar.c create mode 100644 hildon/hildon-find-toolbar.h create mode 100644 hildon/hildon-font-selection-dialog-private.h create mode 100644 hildon/hildon-font-selection-dialog.c create mode 100644 hildon/hildon-font-selection-dialog.h create mode 100644 hildon/hildon-get-password-dialog-private.h create mode 100644 hildon/hildon-get-password-dialog.c create mode 100644 hildon/hildon-get-password-dialog.h create mode 100644 hildon/hildon-gtk.c create mode 100644 hildon/hildon-gtk.h create mode 100644 hildon/hildon-helper.c create mode 100644 hildon/hildon-helper.h create mode 100644 hildon/hildon-hvolumebar.c create mode 100644 hildon/hildon-hvolumebar.h create mode 100644 hildon/hildon-login-dialog-private.h create mode 100644 hildon/hildon-login-dialog.c create mode 100644 hildon/hildon-login-dialog.h create mode 100644 hildon/hildon-main.c create mode 100644 hildon/hildon-main.h create mode 100644 hildon/hildon-marshalers.list create mode 100644 hildon/hildon-note-private.h create mode 100644 hildon/hildon-note.c create mode 100644 hildon/hildon-note.h create mode 100644 hildon/hildon-number-editor-private.h create mode 100644 hildon/hildon-number-editor.c create mode 100644 hildon/hildon-number-editor.h create mode 100644 hildon/hildon-pannable-area.c create mode 100644 hildon/hildon-pannable-area.h create mode 100644 hildon/hildon-picker-button-private.h create mode 100644 hildon/hildon-picker-button.c create mode 100644 hildon/hildon-picker-button.h create mode 100644 hildon/hildon-picker-dialog.c create mode 100644 hildon/hildon-picker-dialog.h create mode 100644 hildon/hildon-private.c create mode 100644 hildon/hildon-private.h create mode 100644 hildon/hildon-program-private.h create mode 100644 hildon/hildon-program.c create mode 100644 hildon/hildon-program.h create mode 100644 hildon/hildon-range-editor-private.h create mode 100644 hildon/hildon-range-editor.c create mode 100644 hildon/hildon-range-editor.h create mode 100644 hildon/hildon-remote-texture-private.h create mode 100644 hildon/hildon-remote-texture.c create mode 100644 hildon/hildon-remote-texture.h create mode 100644 hildon/hildon-seekbar-private.h create mode 100644 hildon/hildon-seekbar.c create mode 100644 hildon/hildon-seekbar.h create mode 100644 hildon/hildon-set-password-dialog-private.h create mode 100644 hildon/hildon-set-password-dialog.c create mode 100644 hildon/hildon-set-password-dialog.h create mode 100644 hildon/hildon-sort-dialog-private.h create mode 100644 hildon/hildon-sort-dialog.c create mode 100644 hildon/hildon-sort-dialog.h create mode 100644 hildon/hildon-sound.c create mode 100644 hildon/hildon-sound.h create mode 100644 hildon/hildon-stackable-window-private.h create mode 100644 hildon/hildon-stackable-window.c create mode 100644 hildon/hildon-stackable-window.h create mode 100644 hildon/hildon-text-view.c create mode 100644 hildon/hildon-text-view.h create mode 100644 hildon/hildon-time-button.c create mode 100644 hildon/hildon-time-button.h create mode 100644 hildon/hildon-time-editor-private.h create mode 100644 hildon/hildon-time-editor.c create mode 100644 hildon/hildon-time-editor.h create mode 100644 hildon/hildon-time-picker-private.h create mode 100644 hildon/hildon-time-picker.c create mode 100644 hildon/hildon-time-picker.h create mode 100644 hildon/hildon-time-selector.c create mode 100644 hildon/hildon-time-selector.h create mode 100644 hildon/hildon-touch-selector-column.h create mode 100644 hildon/hildon-touch-selector-entry.c create mode 100644 hildon/hildon-touch-selector-entry.h create mode 100644 hildon/hildon-touch-selector-private.h create mode 100644 hildon/hildon-touch-selector.c create mode 100644 hildon/hildon-touch-selector.h create mode 100644 hildon/hildon-version.h.in create mode 100644 hildon/hildon-volumebar-private.h create mode 100644 hildon/hildon-volumebar-range.c create mode 100644 hildon/hildon-volumebar-range.h create mode 100644 hildon/hildon-volumebar.c create mode 100644 hildon/hildon-volumebar.h create mode 100644 hildon/hildon-vvolumebar.c create mode 100644 hildon/hildon-vvolumebar.h create mode 100644 hildon/hildon-weekday-picker-private.h create mode 100644 hildon/hildon-weekday-picker.c create mode 100644 hildon/hildon-weekday-picker.h create mode 100644 hildon/hildon-window-private.h create mode 100644 hildon/hildon-window-stack-private.h create mode 100644 hildon/hildon-window-stack.c create mode 100644 hildon/hildon-window-stack.h create mode 100644 hildon/hildon-window.c create mode 100644 hildon/hildon-window.h create mode 100644 hildon/hildon-wizard-dialog-private.h create mode 100644 hildon/hildon-wizard-dialog.c create mode 100644 hildon/hildon-wizard-dialog.h create mode 100644 hildon/hildon.h delete mode 100644 src/Makefile.am delete mode 100644 src/hildon-animation-actor-private.h delete mode 100644 src/hildon-animation-actor.c delete mode 100644 src/hildon-animation-actor.h delete mode 100644 src/hildon-app-menu-private.h delete mode 100644 src/hildon-app-menu.c delete mode 100644 src/hildon-app-menu.h delete mode 100644 src/hildon-banner-private.h delete mode 100644 src/hildon-banner.c delete mode 100644 src/hildon-banner.h delete mode 100644 src/hildon-bread-crumb-trail.c delete mode 100644 src/hildon-bread-crumb-trail.h delete mode 100644 src/hildon-bread-crumb-widget.c delete mode 100644 src/hildon-bread-crumb-widget.h delete mode 100644 src/hildon-bread-crumb.c delete mode 100644 src/hildon-bread-crumb.h delete mode 100644 src/hildon-button.c delete mode 100644 src/hildon-button.h delete mode 100644 src/hildon-calendar-popup-private.h delete mode 100644 src/hildon-calendar-popup.c delete mode 100644 src/hildon-calendar-popup.h delete mode 100644 src/hildon-calendar-private.h delete mode 100644 src/hildon-calendar.c delete mode 100644 src/hildon-calendar.h delete mode 100644 src/hildon-caption-private.h delete mode 100644 src/hildon-caption.c delete mode 100644 src/hildon-caption.h delete mode 100644 src/hildon-check-button.c delete mode 100644 src/hildon-check-button.h delete mode 100644 src/hildon-code-dialog-private.h delete mode 100644 src/hildon-code-dialog.c delete mode 100644 src/hildon-code-dialog.h delete mode 100644 src/hildon-color-button-private.h delete mode 100644 src/hildon-color-button.c delete mode 100644 src/hildon-color-button.h delete mode 100644 src/hildon-color-chooser-dialog-private.h delete mode 100644 src/hildon-color-chooser-dialog.c delete mode 100644 src/hildon-color-chooser-dialog.h delete mode 100644 src/hildon-color-chooser-private.h delete mode 100644 src/hildon-color-chooser.c delete mode 100644 src/hildon-color-chooser.h delete mode 100644 src/hildon-controlbar-private.h delete mode 100644 src/hildon-controlbar.c delete mode 100644 src/hildon-controlbar.h delete mode 100644 src/hildon-date-button.c delete mode 100644 src/hildon-date-button.h delete mode 100644 src/hildon-date-editor-private.h delete mode 100644 src/hildon-date-editor.c delete mode 100644 src/hildon-date-editor.h delete mode 100644 src/hildon-date-selector.c delete mode 100644 src/hildon-date-selector.h delete mode 100644 src/hildon-defines.c delete mode 100644 src/hildon-defines.h delete mode 100644 src/hildon-dialog.c delete mode 100644 src/hildon-dialog.h delete mode 100644 src/hildon-edit-toolbar.c delete mode 100644 src/hildon-edit-toolbar.h delete mode 100644 src/hildon-entry.c delete mode 100644 src/hildon-entry.h delete mode 100644 src/hildon-find-toolbar-private.h delete mode 100644 src/hildon-find-toolbar.c delete mode 100644 src/hildon-find-toolbar.h delete mode 100644 src/hildon-font-selection-dialog-private.h delete mode 100644 src/hildon-font-selection-dialog.c delete mode 100644 src/hildon-font-selection-dialog.h delete mode 100644 src/hildon-get-password-dialog-private.h delete mode 100644 src/hildon-get-password-dialog.c delete mode 100644 src/hildon-get-password-dialog.h delete mode 100644 src/hildon-gtk.c delete mode 100644 src/hildon-gtk.h delete mode 100644 src/hildon-helper.c delete mode 100644 src/hildon-helper.h delete mode 100644 src/hildon-hvolumebar.c delete mode 100644 src/hildon-hvolumebar.h delete mode 100644 src/hildon-login-dialog-private.h delete mode 100644 src/hildon-login-dialog.c delete mode 100644 src/hildon-login-dialog.h delete mode 100644 src/hildon-main.c delete mode 100644 src/hildon-main.h delete mode 100644 src/hildon-marshalers.list delete mode 100644 src/hildon-note-private.h delete mode 100644 src/hildon-note.c delete mode 100644 src/hildon-note.h delete mode 100644 src/hildon-number-editor-private.h delete mode 100644 src/hildon-number-editor.c delete mode 100644 src/hildon-number-editor.h delete mode 100644 src/hildon-pannable-area.c delete mode 100644 src/hildon-pannable-area.h delete mode 100644 src/hildon-picker-button-private.h delete mode 100644 src/hildon-picker-button.c delete mode 100644 src/hildon-picker-button.h delete mode 100644 src/hildon-picker-dialog.c delete mode 100644 src/hildon-picker-dialog.h delete mode 100644 src/hildon-private.c delete mode 100644 src/hildon-private.h delete mode 100644 src/hildon-program-private.h delete mode 100644 src/hildon-program.c delete mode 100644 src/hildon-program.h delete mode 100644 src/hildon-range-editor-private.h delete mode 100644 src/hildon-range-editor.c delete mode 100644 src/hildon-range-editor.h delete mode 100644 src/hildon-remote-texture-private.h delete mode 100644 src/hildon-remote-texture.c delete mode 100644 src/hildon-remote-texture.h delete mode 100644 src/hildon-seekbar-private.h delete mode 100644 src/hildon-seekbar.c delete mode 100644 src/hildon-seekbar.h delete mode 100644 src/hildon-set-password-dialog-private.h delete mode 100644 src/hildon-set-password-dialog.c delete mode 100644 src/hildon-set-password-dialog.h delete mode 100644 src/hildon-sort-dialog-private.h delete mode 100644 src/hildon-sort-dialog.c delete mode 100644 src/hildon-sort-dialog.h delete mode 100644 src/hildon-sound.c delete mode 100644 src/hildon-sound.h delete mode 100644 src/hildon-stackable-window-private.h delete mode 100644 src/hildon-stackable-window.c delete mode 100644 src/hildon-stackable-window.h delete mode 100644 src/hildon-text-view.c delete mode 100644 src/hildon-text-view.h delete mode 100644 src/hildon-time-button.c delete mode 100644 src/hildon-time-button.h delete mode 100644 src/hildon-time-editor-private.h delete mode 100644 src/hildon-time-editor.c delete mode 100644 src/hildon-time-editor.h delete mode 100644 src/hildon-time-picker-private.h delete mode 100644 src/hildon-time-picker.c delete mode 100644 src/hildon-time-picker.h delete mode 100644 src/hildon-time-selector.c delete mode 100644 src/hildon-time-selector.h delete mode 100644 src/hildon-touch-selector-column.h delete mode 100644 src/hildon-touch-selector-entry.c delete mode 100644 src/hildon-touch-selector-entry.h delete mode 100644 src/hildon-touch-selector-private.h delete mode 100644 src/hildon-touch-selector.c delete mode 100644 src/hildon-touch-selector.h delete mode 100644 src/hildon-version.h.in delete mode 100644 src/hildon-volumebar-private.h delete mode 100644 src/hildon-volumebar-range.c delete mode 100644 src/hildon-volumebar-range.h delete mode 100644 src/hildon-volumebar.c delete mode 100644 src/hildon-volumebar.h delete mode 100644 src/hildon-vvolumebar.c delete mode 100644 src/hildon-vvolumebar.h delete mode 100644 src/hildon-weekday-picker-private.h delete mode 100644 src/hildon-weekday-picker.c delete mode 100644 src/hildon-weekday-picker.h delete mode 100644 src/hildon-window-private.h delete mode 100644 src/hildon-window-stack-private.h delete mode 100644 src/hildon-window-stack.c delete mode 100644 src/hildon-window-stack.h delete mode 100644 src/hildon-window.c delete mode 100644 src/hildon-window.h delete mode 100644 src/hildon-wizard-dialog-private.h delete mode 100644 src/hildon-wizard-dialog.c delete mode 100644 src/hildon-wizard-dialog.h delete mode 100644 src/hildon.h diff --git a/ChangeLog b/ChangeLog index f8153cd..ec661ee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2009-04-30 Alberto Garcia + + * src/ + * Makefile.am + * configure.ac + * doc/Makefile.am + * doc/hildon.types + * po/POTFILES.in: + Renamed src/ to hildon/ + + * examples/*.c + * debian/changelog + * debian/rules: + Include directly in all examples. + 2009-04-29 Alejandro Pinheiro * src/hildon-sort-dialog.c diff --git a/Makefile.am b/Makefile.am index 57a6bd2..d03f6a9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = src \ +SUBDIRS = hildon \ pkgconfig \ examples \ tests \ diff --git a/configure.ac b/configure.ac index a978fe5..75eda6f 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_INIT([Hildon gtk widgets], [2.1.69], [hildon@projects.maemo.org], [hildon]) AC_CANONICAL_SYSTEM AM_CONFIG_HEADER(config.h) -AC_CONFIG_SRCDIR([src/hildon-window.h]) +AC_CONFIG_SRCDIR([hildon/hildon-window.h]) AC_CONFIG_MACRO_DIR([m4]) AM_MAINTAINER_MODE @@ -192,14 +192,14 @@ CFLAGS="$CFLAGS $MAEMO_CHANGES $MAEMO_GTK" # default vars for the examples # includes all the low-level flags # FIXME Add esd and gconf flags -HILDON_OBJ_CFLAGS="\$(CFLAGS) \$(GTK_CFLAGS) \$(CHECK_CFLAGS) \$(GCONF_CFLAGS) -I\$(top_builddir)/src/" -HILDON_OBJ_LIBS="\$(top_builddir)/src/libhildon-\$(API_VERSION_MAJOR).la \$(GTK_LIBS) \$(GCONF_LIBS) \$(CHECK_LIBS) `pkg-config --libs gthread-2.0`" +HILDON_OBJ_CFLAGS="\$(CFLAGS) \$(GTK_CFLAGS) \$(CHECK_CFLAGS) \$(GCONF_CFLAGS) -I\$(top_builddir)/hildon/" +HILDON_OBJ_LIBS="\$(top_builddir)/hildon/libhildon-\$(API_VERSION_MAJOR).la \$(GTK_LIBS) \$(GCONF_LIBS) \$(CHECK_LIBS) `pkg-config --libs gthread-2.0`" AC_SUBST(HILDON_OBJ_CFLAGS) AC_SUBST(HILDON_OBJ_LIBS) AC_CONFIG_FILES([Makefile \ - src/Makefile \ - src/hildon-version.h \ + hildon/Makefile \ + hildon/hildon-version.h \ pkgconfig/Makefile \ examples/Makefile \ pkgconfig/hildon.pc \ diff --git a/debian/changelog b/debian/changelog index 23c1e61..a147f9e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,7 @@ libhildon (2.1.69-1~unreleased) unstable; urgency=low * unreleased bump + * Don't need to fix example files anymore in debian/rules -- Alberto Garcia Thu, 30 Apr 2009 13:30:03 +0200 diff --git a/debian/rules b/debian/rules index 152068d..8e0d7b0 100755 --- a/debian/rules +++ b/debian/rules @@ -24,5 +24,4 @@ $(DEB_SRCDIR)/configure: binary-post-install/libhildon1-examples:: ( cd $(DEB_SRCDIR)/debian/libhildon1-examples/usr/share/doc/libhildon1-examples/examples && \ - sed -i 's_"hildon.h"__' *.c && \ mv Makefile.static Makefile ) diff --git a/doc/Makefile.am b/doc/Makefile.am index b50ccd0..3b2493f 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -12,13 +12,13 @@ SCAN_OPTIONS =--deprecated-guards="HILDON_DISABLE_DEPRECATED" SCANOBJ_OPTIONS =--type-init-func="gtk_type_init(0)" -DOC_SOURCE_DIR = $(top_srcdir)/src -DOC_BUILD_DIR = $(top_builddir)/src +DOC_SOURCE_DIR = $(top_srcdir)/hildon +DOC_BUILD_DIR = $(top_builddir)/hildon -HFILE_GLOB = $(top_srcdir)/src/*.h +HFILE_GLOB = $(top_srcdir)/hildon/*.h -CFILE_GLOB = $(top_srcdir)/src/*.c +CFILE_GLOB = $(top_srcdir)/hildon/*.c IGNORE_HFILES = hildon-banner-private.h \ hildon-calendar-popup-private.h \ diff --git a/doc/hildon.types b/doc/hildon.types index a1bf776..8f35a2d 100644 --- a/doc/hildon.types +++ b/doc/hildon.types @@ -1,57 +1,57 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include hildon_banner_get_type hildon_calendar_popup_get_type diff --git a/examples/hildon-app-menu-example.c b/examples/hildon-app-menu-example.c index 7518441..b018056 100644 --- a/examples/hildon-app-menu-example.c +++ b/examples/hildon-app-menu-example.c @@ -23,7 +23,7 @@ */ #include -#include "hildon.h" +#include static void menu_button_clicked (GtkButton *button, diff --git a/examples/hildon-banner-example.c b/examples/hildon-banner-example.c index d1f85f7..2cb399c 100644 --- a/examples/hildon-banner-example.c +++ b/examples/hildon-banner-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include static gboolean on_animation_idle (GtkWidget *banner) diff --git a/examples/hildon-banner-long-example.c b/examples/hildon-banner-long-example.c index f0ce84c..baa3e2d 100644 --- a/examples/hildon-banner-long-example.c +++ b/examples/hildon-banner-long-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include static gboolean on_fire_clicked (GtkWidget *widget) diff --git a/examples/hildon-bread-crumb-trail-example.c b/examples/hildon-bread-crumb-trail-example.c index 983bd88..6f0a39e 100644 --- a/examples/hildon-bread-crumb-trail-example.c +++ b/examples/hildon-bread-crumb-trail-example.c @@ -27,7 +27,7 @@ #include #include -#include "hildon.h" +#include GtkWidget *treeview; gchar *current_root; diff --git a/examples/hildon-button-example.c b/examples/hildon-button-example.c index 4abfd39..3a7c0f0 100644 --- a/examples/hildon-button-example.c +++ b/examples/hildon-button-example.c @@ -23,7 +23,7 @@ */ #include -#include "hildon.h" +#include static GtkWidget *horizontal_layout; static GtkWidget *images; diff --git a/examples/hildon-caption-example.c b/examples/hildon-caption-example.c index 57b3156..188cbd9 100644 --- a/examples/hildon-caption-example.c +++ b/examples/hildon-caption-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include int main (int argc, diff --git a/examples/hildon-check-button-example.c b/examples/hildon-check-button-example.c index c9805f3..fca96bf 100644 --- a/examples/hildon-check-button-example.c +++ b/examples/hildon-check-button-example.c @@ -20,7 +20,7 @@ * */ -#include "hildon.h" +#include static void button_toggled_cb (HildonCheckButton *button, diff --git a/examples/hildon-code-dialog-example.c b/examples/hildon-code-dialog-example.c index 2936de4..a43ac09 100644 --- a/examples/hildon-code-dialog-example.c +++ b/examples/hildon-code-dialog-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include static gboolean on_input (void); diff --git a/examples/hildon-color-button-example.c b/examples/hildon-color-button-example.c index 2c7a3c9..42a17bb 100644 --- a/examples/hildon-color-button-example.c +++ b/examples/hildon-color-button-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include int main (int argc, diff --git a/examples/hildon-color-chooser-example.c b/examples/hildon-color-chooser-example.c index b9b2946..46df717 100644 --- a/examples/hildon-color-chooser-example.c +++ b/examples/hildon-color-chooser-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include int main (int argc, diff --git a/examples/hildon-color-pop-example.c b/examples/hildon-color-pop-example.c index 9dc5525..7988bdd 100644 --- a/examples/hildon-color-pop-example.c +++ b/examples/hildon-color-pop-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include #include gpointer diff --git a/examples/hildon-controlbar-example.c b/examples/hildon-controlbar-example.c index 9999b83..8594971 100644 --- a/examples/hildon-controlbar-example.c +++ b/examples/hildon-controlbar-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include static gboolean on_show_value_clicked (GtkWidget *widget, HildonControlbar *bar) diff --git a/examples/hildon-date-button-example.c b/examples/hildon-date-button-example.c index cb6c17e..46d3de7 100644 --- a/examples/hildon-date-button-example.c +++ b/examples/hildon-date-button-example.c @@ -22,7 +22,7 @@ */ #include #include -#include "hildon.h" +#include static void on_picker_value_changed (HildonPickerButton * button, gpointer data) diff --git a/examples/hildon-date-editor-example.c b/examples/hildon-date-editor-example.c index e498335..0685bfe 100644 --- a/examples/hildon-date-editor-example.c +++ b/examples/hildon-date-editor-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include static gboolean on_error (GtkWidget *widget, HildonDateTimeError error_type); diff --git a/examples/hildon-dialog-example.c b/examples/hildon-dialog-example.c index a6d2f03..695b561 100644 --- a/examples/hildon-dialog-example.c +++ b/examples/hildon-dialog-example.c @@ -22,7 +22,7 @@ * */ -#include "hildon.h" +#include int main (int argc, diff --git a/examples/hildon-edit-toolbar-example.c b/examples/hildon-edit-toolbar-example.c index 02c5153..e8d156d 100644 --- a/examples/hildon-edit-toolbar-example.c +++ b/examples/hildon-edit-toolbar-example.c @@ -21,7 +21,7 @@ */ #include -#include "hildon.h" +#include typedef enum { diff --git a/examples/hildon-entry-example.c b/examples/hildon-entry-example.c index bd2a1e6..cdb718d 100644 --- a/examples/hildon-entry-example.c +++ b/examples/hildon-entry-example.c @@ -21,7 +21,7 @@ */ #include -#include "hildon.h" +#include HildonEntry *mainentry; diff --git a/examples/hildon-find-toolbar-example.c b/examples/hildon-find-toolbar-example.c index de7ba1e..a1fe651 100644 --- a/examples/hildon-find-toolbar-example.c +++ b/examples/hildon-find-toolbar-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include HildonFindToolbar *toolbar = NULL; diff --git a/examples/hildon-finger-example.c b/examples/hildon-finger-example.c index a6e4f5e..139ebf5 100644 --- a/examples/hildon-finger-example.c +++ b/examples/hildon-finger-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include gboolean on_button_press (GtkWidget *widget, diff --git a/examples/hildon-get-password-dialog-example.c b/examples/hildon-get-password-dialog-example.c index 8079a71..d560ceb 100644 --- a/examples/hildon-get-password-dialog-example.c +++ b/examples/hildon-get-password-dialog-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include int main (int argc, diff --git a/examples/hildon-hvolumebar-example.c b/examples/hildon-hvolumebar-example.c index 2e664c4..c382981 100644 --- a/examples/hildon-hvolumebar-example.c +++ b/examples/hildon-hvolumebar-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include void on_mute_clicked (GtkWidget *clicked, diff --git a/examples/hildon-hvolumebar-insensitive-example.c b/examples/hildon-hvolumebar-insensitive-example.c index dcc1756..1efe41f 100644 --- a/examples/hildon-hvolumebar-insensitive-example.c +++ b/examples/hildon-hvolumebar-insensitive-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include int main (int argc, diff --git a/examples/hildon-hvolumebar-insensitive-map-example.c b/examples/hildon-hvolumebar-insensitive-map-example.c index bb1a6eb..567520c 100644 --- a/examples/hildon-hvolumebar-insensitive-map-example.c +++ b/examples/hildon-hvolumebar-insensitive-map-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include int main (int argc, diff --git a/examples/hildon-hvolumebar-timer-example.c b/examples/hildon-hvolumebar-timer-example.c index 69c3d77..2eb7d63 100644 --- a/examples/hildon-hvolumebar-timer-example.c +++ b/examples/hildon-hvolumebar-timer-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include gboolean on_idle (void); diff --git a/examples/hildon-icon-sizes-example.c b/examples/hildon-icon-sizes-example.c index fa3c083..9a4f773 100644 --- a/examples/hildon-icon-sizes-example.c +++ b/examples/hildon-icon-sizes-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include int main (int argc, diff --git a/examples/hildon-insensitive-example.c b/examples/hildon-insensitive-example.c index 6aa6f3f..1e0f34b 100644 --- a/examples/hildon-insensitive-example.c +++ b/examples/hildon-insensitive-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include int main (int argc, diff --git a/examples/hildon-logical-color-example.c b/examples/hildon-logical-color-example.c index b772a27..ce1cd7e 100644 --- a/examples/hildon-logical-color-example.c +++ b/examples/hildon-logical-color-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include int main (int argc, diff --git a/examples/hildon-login-dialog-example.c b/examples/hildon-login-dialog-example.c index d8fd0a4..c603ee1 100644 --- a/examples/hildon-login-dialog-example.c +++ b/examples/hildon-login-dialog-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include int main (int argc, diff --git a/examples/hildon-lookup-example.c b/examples/hildon-lookup-example.c index 2e2a014..4c337b2 100644 --- a/examples/hildon-lookup-example.c +++ b/examples/hildon-lookup-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include static GtkWidget* create_button_with_icon (const gchar *icon); diff --git a/examples/hildon-note-example.c b/examples/hildon-note-example.c index aee5372..95155dc 100644 --- a/examples/hildon-note-example.c +++ b/examples/hildon-note-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include static gboolean on_information_clicked (GtkWidget *widget, gpointer data) diff --git a/examples/hildon-number-editor-example.c b/examples/hildon-number-editor-example.c index bdfd3dd..b1f9e3c 100644 --- a/examples/hildon-number-editor-example.c +++ b/examples/hildon-number-editor-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include int main (int argc, diff --git a/examples/hildon-pannable-area-buttons-scroll-example.c b/examples/hildon-pannable-area-buttons-scroll-example.c index c6f031e..e7d26a8 100644 --- a/examples/hildon-pannable-area-buttons-scroll-example.c +++ b/examples/hildon-pannable-area-buttons-scroll-example.c @@ -23,7 +23,7 @@ * */ -#include "hildon.h" +#include GtkWidget *btn; diff --git a/examples/hildon-pannable-area-gesture-signals-example.c b/examples/hildon-pannable-area-gesture-signals-example.c index a738d1c..07243e3 100644 --- a/examples/hildon-pannable-area-gesture-signals-example.c +++ b/examples/hildon-pannable-area-gesture-signals-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include enum { TEXT_COLUMN, OPTIONAL_COLUMN, N_COLUMNS }; diff --git a/examples/hildon-pannable-area-scroll-jump-example.c b/examples/hildon-pannable-area-scroll-jump-example.c index d9f9912..738f31e 100644 --- a/examples/hildon-pannable-area-scroll-jump-example.c +++ b/examples/hildon-pannable-area-scroll-jump-example.c @@ -28,7 +28,7 @@ #include #include #include -#include "hildon.h" +#include enum { PIXBUF_COLUMN, TEXT_COLUMN, N_COLUMNS }; diff --git a/examples/hildon-pannable-area-touch-grid-example.c b/examples/hildon-pannable-area-touch-grid-example.c index f23806b..02afb5b 100644 --- a/examples/hildon-pannable-area-touch-grid-example.c +++ b/examples/hildon-pannable-area-touch-grid-example.c @@ -25,7 +25,7 @@ */ #include -#include "hildon.h" +#include enum { diff --git a/examples/hildon-pannable-area-touch-list-example.c b/examples/hildon-pannable-area-touch-list-example.c index 9ffdd78..3c96546 100644 --- a/examples/hildon-pannable-area-touch-list-example.c +++ b/examples/hildon-pannable-area-touch-list-example.c @@ -25,7 +25,7 @@ */ #include -#include "hildon.h" +#include enum { diff --git a/examples/hildon-pannable-area-tree-view-example.c b/examples/hildon-pannable-area-tree-view-example.c index 3a95619..17f32e1 100644 --- a/examples/hildon-pannable-area-tree-view-example.c +++ b/examples/hildon-pannable-area-tree-view-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include enum { TEXT_COLUMN, N_COLUMNS }; diff --git a/examples/hildon-pannable-area-tuning-example.c b/examples/hildon-pannable-area-tuning-example.c index b3b8376..83db661 100644 --- a/examples/hildon-pannable-area-tuning-example.c +++ b/examples/hildon-pannable-area-tuning-example.c @@ -29,7 +29,7 @@ #include #include #include -#include "hildon.h" +#include typedef struct { GtkWidget *pannable; diff --git a/examples/hildon-picker-button-example.c b/examples/hildon-picker-button-example.c index d1cdbb5..4d10fbf 100644 --- a/examples/hildon-picker-button-example.c +++ b/examples/hildon-picker-button-example.c @@ -16,7 +16,7 @@ #include #include -#include "hildon.h" +#include static void on_picker_value_changed (HildonPickerButton * button, gpointer data) diff --git a/examples/hildon-picker-button-multicolumn-example.c b/examples/hildon-picker-button-multicolumn-example.c index 0913eb1..5c63b16 100644 --- a/examples/hildon-picker-button-multicolumn-example.c +++ b/examples/hildon-picker-button-multicolumn-example.c @@ -16,7 +16,7 @@ #include #include -#include "hildon.h" +#include static GtkWidget * create_touch_selector (void) diff --git a/examples/hildon-progress-indicator-example.c b/examples/hildon-progress-indicator-example.c index 8685d0f..d7bae1e 100644 --- a/examples/hildon-progress-indicator-example.c +++ b/examples/hildon-progress-indicator-example.c @@ -20,7 +20,7 @@ * */ -#include "hildon.h" +#include HildonTextView *textview; GtkTextBuffer *buffer; diff --git a/examples/hildon-remote-texture-example.c b/examples/hildon-remote-texture-example.c index aa2f889..536f3f2 100644 --- a/examples/hildon-remote-texture-example.c +++ b/examples/hildon-remote-texture-example.c @@ -6,7 +6,7 @@ #include #include #include -#include "hildon.h" +#include #include "hildon-remote-texture.h" #define W 800 diff --git a/examples/hildon-scrolled-window-example.c b/examples/hildon-scrolled-window-example.c index 0ef67e3..31cf4b8 100644 --- a/examples/hildon-scrolled-window-example.c +++ b/examples/hildon-scrolled-window-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include int main (int argc, diff --git a/examples/hildon-seekbar-example.c b/examples/hildon-seekbar-example.c index 8f1c432..bb9890f 100644 --- a/examples/hildon-seekbar-example.c +++ b/examples/hildon-seekbar-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include int main (int argc, diff --git a/examples/hildon-set-password-dialog-example.c b/examples/hildon-set-password-dialog-example.c index a16b10d..f025a9b 100644 --- a/examples/hildon-set-password-dialog-example.c +++ b/examples/hildon-set-password-dialog-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include int main (int argc, diff --git a/examples/hildon-sort-dialog-example.c b/examples/hildon-sort-dialog-example.c index 8bdfcf3..5ff16e7 100644 --- a/examples/hildon-sort-dialog-example.c +++ b/examples/hildon-sort-dialog-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include int main (int argc, char **argv) diff --git a/examples/hildon-stackable-window-example.c b/examples/hildon-stackable-window-example.c index 566a2df..5991d97 100644 --- a/examples/hildon-stackable-window-example.c +++ b/examples/hildon-stackable-window-example.c @@ -20,7 +20,7 @@ * */ -#include "hildon.h" +#include static gint global_stack_count = 1; diff --git a/examples/hildon-text-view-example.c b/examples/hildon-text-view-example.c index bf70973..d3d4843 100644 --- a/examples/hildon-text-view-example.c +++ b/examples/hildon-text-view-example.c @@ -20,7 +20,7 @@ * */ -#include "hildon.h" +#include HildonTextView *textview; GtkTextBuffer *buffer; diff --git a/examples/hildon-thumb-scrollbar-example.c b/examples/hildon-thumb-scrollbar-example.c index cab55f6..2fcfac3 100644 --- a/examples/hildon-thumb-scrollbar-example.c +++ b/examples/hildon-thumb-scrollbar-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include int main (int argc, diff --git a/examples/hildon-time-button-example.c b/examples/hildon-time-button-example.c index ef2ea4e..990fb84 100644 --- a/examples/hildon-time-button-example.c +++ b/examples/hildon-time-button-example.c @@ -1,6 +1,6 @@ #include #include -#include "hildon.h" +#include static void on_picker_value_changed (HildonPickerButton * button, gpointer data) diff --git a/examples/hildon-time-editor-example.c b/examples/hildon-time-editor-example.c index ae23277..2d903ab 100644 --- a/examples/hildon-time-editor-example.c +++ b/examples/hildon-time-editor-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include int main (int argc, char **argv) diff --git a/examples/hildon-time-picker-example.c b/examples/hildon-time-picker-example.c index 36b026b..151f57e 100644 --- a/examples/hildon-time-picker-example.c +++ b/examples/hildon-time-picker-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include int main (int argc, diff --git a/examples/hildon-toolbar-example.c b/examples/hildon-toolbar-example.c index f444ea4..6c8ad0c 100644 --- a/examples/hildon-toolbar-example.c +++ b/examples/hildon-toolbar-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include gboolean has_toolbar = FALSE; diff --git a/examples/hildon-toolbar-seekbar-example.c b/examples/hildon-toolbar-seekbar-example.c index b9a9175..eeb11ca 100644 --- a/examples/hildon-toolbar-seekbar-example.c +++ b/examples/hildon-toolbar-seekbar-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include int main (int argc, diff --git a/examples/hildon-touch-selector-entry-example.c b/examples/hildon-touch-selector-entry-example.c index 8f4b0d1..46e0f48 100644 --- a/examples/hildon-touch-selector-entry-example.c +++ b/examples/hildon-touch-selector-entry-example.c @@ -21,7 +21,7 @@ #include #include -#include "hildon.h" +#include static const gchar* artists [] = { "AC/DC", diff --git a/examples/hildon-touch-selector-example.c b/examples/hildon-touch-selector-example.c index 12e9e22..8d80707 100644 --- a/examples/hildon-touch-selector-example.c +++ b/examples/hildon-touch-selector-example.c @@ -23,7 +23,7 @@ #include #include -#include "hildon.h" +#include static GtkWidget *create_selector (); static GtkWidget *get_visible_content (GtkWidget * window); diff --git a/examples/hildon-touch-selector-multi-cells-example.c b/examples/hildon-touch-selector-multi-cells-example.c index e9a9a79..ddc74ca 100644 --- a/examples/hildon-touch-selector-multi-cells-example.c +++ b/examples/hildon-touch-selector-multi-cells-example.c @@ -23,7 +23,7 @@ #include #include -#include "hildon.h" +#include static GtkWidget *create_selector (); static GtkWidget *get_visible_content (GtkWidget * window); diff --git a/examples/hildon-vvolumebar-example.c b/examples/hildon-vvolumebar-example.c index 15f76ed..19dadea 100644 --- a/examples/hildon-vvolumebar-example.c +++ b/examples/hildon-vvolumebar-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include int main (int argc, diff --git a/examples/hildon-weekday-picker-example.c b/examples/hildon-weekday-picker-example.c index dfd90b1..9ae3729 100644 --- a/examples/hildon-weekday-picker-example.c +++ b/examples/hildon-weekday-picker-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include int main (int argc, diff --git a/examples/hildon-window-cmn-menu-example.c b/examples/hildon-window-cmn-menu-example.c index b1f2915..911f366 100644 --- a/examples/hildon-window-cmn-menu-example.c +++ b/examples/hildon-window-cmn-menu-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include int main (int argc, diff --git a/examples/hildon-window-example.c b/examples/hildon-window-example.c index f75fc55..b85a37e 100644 --- a/examples/hildon-window-example.c +++ b/examples/hildon-window-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include int main (int argc, diff --git a/examples/hildon-window-menu-example.c b/examples/hildon-window-menu-example.c index 4347399..ebb0566 100644 --- a/examples/hildon-window-menu-example.c +++ b/examples/hildon-window-menu-example.c @@ -26,7 +26,7 @@ #include #include #include -#include "hildon.h" +#include int main (int argc, diff --git a/examples/hildon-wizard-dialog-example.c b/examples/hildon-wizard-dialog-example.c index 90f4f08..5e41985 100644 --- a/examples/hildon-wizard-dialog-example.c +++ b/examples/hildon-wizard-dialog-example.c @@ -27,7 +27,7 @@ #include #include #include -#include "hildon.h" +#include gboolean on_page_switch (GtkNotebook *notebook, diff --git a/hildon/Makefile.am b/hildon/Makefile.am new file mode 100644 index 0000000..5b8ddee --- /dev/null +++ b/hildon/Makefile.am @@ -0,0 +1,235 @@ +INCLUDES = -DG_LOG_DOMAIN=\"hildon-@API_VERSION_MAJOR@\" \ + -DLOCALEDIR=\"$(localedir)\" + +CLEANFILES = \ + hildon-enum-types.c \ + hildon-enum-types.h \ + hildon-marshalers.h \ + hildon-marshalers.c + +EXTRA_DIST = hildon-marshalers.list + +lib_LTLIBRARIES = libhildon-@API_VERSION_MAJOR@.la + +libhildon_@API_VERSION_MAJOR@_la_LDFLAGS = $(HILDON_WIDGETS_LT_LDFLAGS) + +libhildon_@API_VERSION_MAJOR@_la_LIBADD = \ + $(GTK_LIBS) \ + $(GCONF_LIBS) \ + $(CANBERRA_LIBS) \ + @HILDON_LT_LDFLAGS@ + +libhildon_@API_VERSION_MAJOR@_la_CFLAGS = \ + $(GTK_CFLAGS) \ + $(GCONF_CFLAGS) \ + $(EXTRA_CFLAGS) \ + $(CANBERRA_CFLAGS) + +libhildon_@API_VERSION_MAJOR@_la_SOURCES = \ + hildon-private.c \ + hildon-controlbar.c \ + hildon-seekbar.c \ + hildon-note.c \ + hildon-volumebar.c \ + hildon-sound.c \ + hildon-volumebar-range.c \ + hildon-hvolumebar.c \ + hildon-vvolumebar.c \ + hildon-calendar-popup.c \ + hildon-date-editor.c \ + hildon-time-editor.c \ + hildon-time-picker.c \ + hildon-date-selector.c \ + hildon-time-selector.c \ + hildon-touch-selector.c \ + hildon-touch-selector-entry.c \ + hildon-picker-dialog.c \ + hildon-picker-button.c \ + hildon-date-button.c \ + hildon-time-button.c \ + hildon-helper.c \ + hildon-weekday-picker.c \ + hildon-number-editor.c \ + hildon-range-editor.c \ + hildon-get-password-dialog.c \ + hildon-set-password-dialog.c \ + hildon-sort-dialog.c \ + hildon-font-selection-dialog.c \ + hildon-login-dialog.c \ + hildon-wizard-dialog.c \ + hildon-color-chooser.c \ + hildon-color-button.c \ + hildon-color-chooser-dialog.c \ + hildon-defines.c \ + hildon-find-toolbar.c \ + hildon-edit-toolbar.c \ + hildon-banner.c \ + hildon-caption.c \ + hildon-window.c \ + hildon-stackable-window.c \ + hildon-window-stack.c \ + hildon-animation-actor.c \ + hildon-remote-texture.c \ + hildon-program.c \ + hildon-code-dialog.c \ + hildon-enum-types.c \ + hildon-marshalers.c \ + hildon-calendar.c \ + hildon-pannable-area.c \ + hildon-entry.c \ + hildon-text-view.c \ + hildon-bread-crumb-trail.c \ + hildon-bread-crumb.c \ + hildon-bread-crumb-widget.c \ + hildon-app-menu.c \ + hildon-button.c \ + hildon-check-button.c \ + hildon-gtk.c \ + hildon-dialog.c \ + hildon-main.c + +libhildon_@API_VERSION_MAJOR@_built_public_headers = \ + hildon-enum-types.h \ + hildon-marshalers.h + +libhildon_@API_VERSION_MAJOR@_includedir = \ + $(includedir)/$(PACKAGE)-$(API_VERSION_MAJOR)/$(PACKAGE) + +libhildon_@API_VERSION_MAJOR@_public_headers = \ + hildon-banner.h \ + hildon-calendar-popup.h \ + hildon-caption.h \ + hildon-code-dialog.h \ + hildon-color-button.h \ + hildon-color-chooser-dialog.h \ + hildon-color-chooser.h \ + hildon-controlbar.h \ + hildon-date-editor.h \ + hildon-defines.h \ + hildon-find-toolbar.h \ + hildon-edit-toolbar.h \ + hildon-helper.h \ + hildon-font-selection-dialog.h \ + hildon-get-password-dialog.h \ + hildon-hvolumebar.h \ + hildon-login-dialog.h \ + hildon-note.h \ + hildon-number-editor.h \ + hildon-program.h \ + hildon-range-editor.h \ + hildon-seekbar.h \ + hildon-set-password-dialog.h \ + hildon-sort-dialog.h \ + hildon-sound.h \ + hildon-time-editor.h \ + hildon-time-picker.h \ + hildon-date-selector.h \ + hildon-time-selector.h \ + hildon-touch-selector.h \ + hildon-touch-selector-column.h \ + hildon-touch-selector-entry.h \ + hildon-picker-dialog.h \ + hildon-picker-button.h \ + hildon-date-button.h \ + hildon-time-button.h \ + hildon-volumebar-range.h \ + hildon-volumebar.h \ + hildon-vvolumebar.h \ + hildon-weekday-picker.h \ + hildon.h \ + hildon-window.h \ + hildon-stackable-window.h \ + hildon-window-stack.h \ + hildon-animation-actor.h \ + hildon-remote-texture.h \ + hildon-wizard-dialog.h \ + hildon-calendar.h \ + hildon-pannable-area.h \ + hildon-entry.h \ + hildon-text-view.h \ + hildon-bread-crumb-trail.h \ + hildon-bread-crumb.h \ + hildon-app-menu.h \ + hildon-dialog.h \ + hildon-button.h \ + hildon-check-button.h \ + hildon-gtk.h \ + hildon-version.h \ + hildon-main.h + +libhildon_@API_VERSION_MAJOR@_include_HEADERS = \ + $(libhildon_@API_VERSION_MAJOR@_public_headers) \ + $(libhildon_@API_VERSION_MAJOR@_built_public_headers) + +noinst_HEADERS = hildon-banner-private.h \ + hildon-calendar-popup-private.h \ + hildon-private.h \ + hildon-caption-private.h \ + hildon-code-dialog-private.h \ + hildon-picker-button-private.h \ + hildon-color-button-private.h \ + hildon-color-chooser-dialog-private.h \ + hildon-color-chooser-private.h \ + hildon-controlbar-private.h \ + hildon-date-editor-private.h \ + hildon-find-toolbar-private.h \ + hildon-font-selection-dialog-private.h \ + hildon-get-password-dialog-private.h \ + hildon-login-dialog-private.h \ + hildon-note-private.h \ + hildon-number-editor-private.h \ + hildon-program-private.h \ + hildon-range-editor-private.h \ + hildon-seekbar-private.h \ + hildon-set-password-dialog-private.h \ + hildon-sort-dialog-private.h \ + hildon-time-editor-private.h \ + hildon-time-picker-private.h \ + hildon-volumebar-private.h \ + hildon-weekday-picker-private.h \ + hildon-window-private.h \ + hildon-stackable-window-private.h \ + hildon-window-stack-private.h \ + hildon-animation-actor-private.h \ + hildon-remote-texture-private.h \ + hildon-wizard-dialog-private.h \ + hildon-calendar-private.h \ + hildon-app-menu-private.h \ + hildon-bread-crumb-widget.h \ + hildon-touch-selector-private.h + +# Don't build the library until we have built the header that it needs: +$(OBJECTS) $(libhildon_$(API_VERSION_MAJOR)_la_OBJECTS): hildon-enum-types.h hildon-marshalers.c hildon-marshalers.h + +hildon-enum-types.h: @REBUILD@ $(libhildon_$(API_VERSION_MAJOR)_public_headers) Makefile + (cd $(srcdir) && glib-mkenums \ + --fhead "#ifndef __HILDON_ENUM_TYPES_H__\n" \ + --fhead "#define __HILDON_ENUM_TYPES_H__\n" \ + --fhead "\n" \ + --fhead "#include \n" \ + --fhead "\n" \ + --fhead "G_BEGIN_DECLS\n" \ + --fhead "\n" \ + --fprod "/* Enumerations from \"@filename@\" */\n" \ + --vhead "GType @enum_name@_get_type (void);\n#define HILDON_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \ + --ftail "\nG_END_DECLS\n\n#endif /* __HILDON_ENUM_TYPES_H__ */" \ + $(libhildon_$(API_VERSION_MAJOR)_public_headers)) > $@ + +hildon-enum-types.c: @REBUILD@ $(libhildon_$(API_VERSION_MAJOR)_public_headers) Makefile + (cd $(srcdir) && glib-mkenums \ + --fhead "#undef HILDON_DISABLE_DEPRECATED\n" \ + --fhead "#include \"hildon.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" \ + $(libhildon_$(API_VERSION_MAJOR)_public_headers)) > $@ + +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.h"' >hildon-marshalers.c + glib-genmarshal --prefix _hildon_marshal --body hildon-marshalers.list >>hildon-marshalers.c + diff --git a/hildon/hildon-animation-actor-private.h b/hildon/hildon-animation-actor-private.h new file mode 100644 index 0000000..6ab3763 --- /dev/null +++ b/hildon/hildon-animation-actor-private.h @@ -0,0 +1,81 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_ANIMATION_ACTOR_PRIVATE_H__ +#define __HILDON_ANIMATION_ACTOR_PRIVATE_H__ + +G_BEGIN_DECLS + +typedef struct _HildonAnimationActorPrivate HildonAnimationActorPrivate; + +#define HILDON_ANIMATION_ACTOR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_ANIMATION_ACTOR, HildonAnimationActorPrivate)); + +struct _HildonAnimationActorPrivate +{ + guint ready : 1; + + guint set_show : 1; + guint set_position : 1; + guint set_rotation : 3; + guint set_scale : 1; + guint set_anchor : 1; + guint set_parent : 1; + + guint show; + guint opacity; + + guint gravity; + guint anchor_x; + guint anchor_y; + + guint position_x; + guint position_y; + guint depth; + + guint32 x_rotation_angle; + guint x_rotation_y; + guint x_rotation_z; + + guint32 y_rotation_angle; + guint y_rotation_x; + guint y_rotation_z; + + guint32 z_rotation_angle; + guint z_rotation_x; + guint z_rotation_y; + + guint32 scale_x; + guint32 scale_y; + + GtkWindow* parent; + gulong parent_map_event_cb_id; + + gulong map_event_cb_id; +}; + +G_END_DECLS + +#endif /* __HILDON_ANIMATION_ACTOR_PRIVATE_H__ */ diff --git a/hildon/hildon-animation-actor.c b/hildon/hildon-animation-actor.c new file mode 100644 index 0000000..0d623d8 --- /dev/null +++ b/hildon/hildon-animation-actor.c @@ -0,0 +1,1198 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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-animation-window + * @short_description: Widget representing an animation actor for + * WM-assisted animation effects in the Hildon framework. + * + * The #HildonAnimationActor is a GTK+ widget which represents an + * animation actor for WM-assisted animation effects in the Hildon + * framework. It derives from #GtkWindow and can host any widgets much + * like a normal window. The special features available to the + * animation actor is the ability to set its position, scale factor + * and rotation. These parameters are interpreted by Hildon's + * compositing window manager to alter the on-screen representation of + * the animation actor window. Bear in mind, however, that by design + * decision, animation actors are not reactive -- the widgets placed + * in such window will not receive keyboard, motion or button + * events. Animation actors are input-transparent -- the input events + * will be sent to the underlying real windows and widgets. + * + * The animation actors may exist in a parented or an unparented + * state. To be displayed, animations actors must be parented to + * another top-level window widget. Animation actors display on top + * (in front) of the standard window contents unless the position + * (depth, z-coordinate) is specifically adjusted. Animation actors in + * an unparented state do not display at all. + * + * Parented animation actors are placed in the coordinate space of the + * parent window and visually become a part of the parent window + * iteslf -- they inherit the transformations and effects enforced by + * the window manager on the parent window (task switcher animations, + * minimize events, etc.). + * + * All animation actor settings (position, scale, rotation, opacity, + * depth) can be applied to unparented actors, but will only take + * effect as the actor is parented to a top-level window and that + * window is shown. All settings are preserved during + * unparenting/reparenting. + * + * The #HildonAnimationActor API closely follows the #ClutterActor + * API. Please take a look at the #ClutterActor description for the + * modelview transformations order that applies to + * HildonAnimationActor and ClutterActor alike. + * + * Animation actor widget controls the animation actor as it is + * transformed by the window manager using ClientMessage X11 + * events. It tries to minimize the amount of such events and couples + * conceptually related parameters (visibility and opacity, position + * and depth) to the same message. The API, however, offers + * convenience functions for the programmer to be able to modify every + * parameter individually. + * + * + * Basic HildonAnimationActor example + * + * static void + * animation_cb (void *obj) + * { + * HildonAnimationActor *actor = HILDON_ANIMATION_ACTOR (obj); + * + * static int x_inc = 1; + * static int y_inc = 1; + * static int x = 0; + * static int y = 0; + * static int r = 0; + * + * if (((x_inc > 0) && (x > 800)) || + * ((x_inc < 0) && (x < 1))) + * x_inc = -x_inc; + * if (((y_inc > 0) && (y > 480)) || + * ((y_inc < 0) && (y < 1))) + * y_inc = -y_inc; + * + * x += x_inc; + * y += y_inc; + * r ++; + * + * // Set animation actor position and rotation + * hildon_animation_actor_set_position (actor, x, y); + * hildon_animation_actor_set_rotation (actor, + * HILDON_AA_Z_AXIS, + * r, + * 0, 0, 0); + * } + * + * int + * main (int argc, char **argv) + * { + * GtkWidget *win; + * GtkWidget *image; + * GtkWidget *actor; + * + * gtk_init (&argc, &argv); + * + * // ... set up a normal window + * win = hildon_window_new (); + * g_signal_connect (win, "destroy", G_CALLBACK (gtk_main_quit), NULL); + * gtk_widget_show_all (win); + * + * // ... load an image + * image = gtk_image_new_from_file ("image.jpg"); + * + * actor = hildon_animation_actor_new(); + * gtk_container_add (GTK_CONTAINER (actor), image); + * + * // Parent the animation actor + * hildon_animation_actor_set_parent (HILDON_ANIMATION_ACTOR (actor), win); + * + * // Set anchor point to the actor center + * hildon_animation_actor_set_anchor_from_gravity (HILDON_ANIMATION_ACTOR (actor), + HILDON_AA_CENTER_GRAVITY); + * + * gtk_widget_show_all (actor); + * + * // Set up animation + * g_timeout_add (100, (GSourceFunc)animation_cb, actor); + * + * gtk_main (); + * + * return 0; + * } + * + * + */ + +#include +#include + +#include "hildon-animation-actor.h" +#include "hildon-animation-actor-private.h" + +G_DEFINE_TYPE (HildonAnimationActor, hildon_animation_actor, GTK_TYPE_WINDOW); + +static GdkFilterReturn +hildon_animation_actor_event_filter (GdkXEvent *xevent, + GdkEvent *event, + gpointer data); +static void +hildon_animation_actor_update_ready (HildonAnimationActor *self); +static void +hildon_animation_actor_send_pending_messages (HildonAnimationActor *self); +static void +hildon_animation_actor_send_all_messages (HildonAnimationActor *self); +static gboolean +hildon_animation_actor_parent_map_event (GtkWidget *parent, + GdkEvent *event, + gpointer user_data); +static gboolean +hildon_animation_actor_map_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data); + +static guint32 show_atom; +static guint32 position_atom; +static guint32 rotation_atom; +static guint32 scale_atom; +static guint32 anchor_atom; +static guint32 parent_atom; +static guint32 ready_atom; + +static gboolean atoms_initialized = FALSE; + +static void +hildon_animation_actor_realize (GtkWidget *widget) +{ + GdkDisplay *display; + Atom wm_type, applet_type; + + GTK_WIDGET_CLASS (hildon_animation_actor_parent_class)->realize (widget); + + /* Set animation actor window type. */ + + display = gdk_drawable_get_display (widget->window); + + wm_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"); + applet_type = gdk_x11_get_xatom_by_name_for_display (display, "_HILDON_WM_WINDOW_TYPE_ANIMATION_ACTOR"); + + XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (widget->window), wm_type, + XA_ATOM, 32, PropModeReplace, + (unsigned char *) &applet_type, 1); + + /* This is a bit of a hack, but for the sake of speed (it is assumed that + * once HildonAnimationActor is created, a lot of ClientMessages will + * follow), we cache all ClientMessages atoms in static variables. */ + + if (!atoms_initialized) + { + show_atom = + gdk_x11_get_xatom_by_name_for_display + (display, "_HILDON_ANIMATION_CLIENT_MESSAGE_SHOW"); + position_atom = + gdk_x11_get_xatom_by_name_for_display + (display, "_HILDON_ANIMATION_CLIENT_MESSAGE_POSITION"); + rotation_atom = + gdk_x11_get_xatom_by_name_for_display + (display, "_HILDON_ANIMATION_CLIENT_MESSAGE_ROTATION"); + scale_atom = + gdk_x11_get_xatom_by_name_for_display + (display, "_HILDON_ANIMATION_CLIENT_MESSAGE_SCALE"); + anchor_atom = + gdk_x11_get_xatom_by_name_for_display + (display, "_HILDON_ANIMATION_CLIENT_MESSAGE_ANCHOR"); + parent_atom = + gdk_x11_get_xatom_by_name_for_display + (display, "_HILDON_ANIMATION_CLIENT_MESSAGE_PARENT"); + ready_atom = + gdk_x11_get_xatom_by_name_for_display + (display, "_HILDON_ANIMATION_CLIENT_READY"); +#if 0 + g_debug ("show atom = %lu\n", show_atom); + g_debug ("position atom = %lu\n", position_atom); + g_debug ("rotation atom = %lu\n", rotation_atom); + g_debug ("scale atom = %lu\n", scale_atom); + g_debug ("anchor atom = %lu\n", anchor_atom); + g_debug ("parent atom = %lu\n", parent_atom); + g_debug ("ready atom = %lu\n", ready_atom); +#endif + + atoms_initialized = TRUE; + } + + /* Wait for a ready message */ + + gdk_window_add_filter (widget->window, + hildon_animation_actor_event_filter, + widget); +} + +static void +hildon_animation_actor_unrealize (GtkWidget *widget) +{ + gdk_window_remove_filter (widget->window, + hildon_animation_actor_event_filter, + widget); + + GTK_WIDGET_CLASS (hildon_animation_actor_parent_class)->unrealize (widget); +} + +static void +hildon_animation_actor_show (GtkWidget *widget) +{ + HildonAnimationActor *self = HILDON_ANIMATION_ACTOR (widget); + + GTK_WIDGET_CLASS (hildon_animation_actor_parent_class)->show (widget); + hildon_animation_actor_set_show (self, 1); +} + +static void +hildon_animation_actor_hide (GtkWidget *widget) +{ + HildonAnimationActor *self = HILDON_ANIMATION_ACTOR (widget); + + hildon_animation_actor_set_show (self, 0); + GTK_WIDGET_CLASS (hildon_animation_actor_parent_class)->hide (widget); +} + +static void +hildon_animation_actor_class_init (HildonAnimationActorClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + widget_class->realize = hildon_animation_actor_realize; + widget_class->unrealize = hildon_animation_actor_unrealize; + widget_class->show = hildon_animation_actor_show; + widget_class->hide = hildon_animation_actor_hide; + + g_type_class_add_private (klass, sizeof (HildonAnimationActorPrivate)); +} + +static void +hildon_animation_actor_init (HildonAnimationActor *self) +{ + HildonAnimationActorPrivate + *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); + + /* Default non-zero values for the private variables */ + + priv->scale_x = 1 << 16; + priv->scale_y = 1 << 16; + priv->opacity = 0xff; +} + +/** + * hildon_animation_actor_new: + * + * Creates a new #HildonAnimationActor. + * + * Return value: A #HildonAnimationActor + * + * Since: 2.2 + **/ +GtkWidget* +hildon_animation_actor_new (void) +{ + HildonAnimationActor *newwindow = g_object_new (HILDON_TYPE_ANIMATION_ACTOR, NULL); + + gtk_window_set_decorated (GTK_WINDOW (newwindow), FALSE); + + return GTK_WIDGET (newwindow); +} + +/* + * An filter for GDK X11 events, waiting for PropertyNotify (window property + * changes) events, keeping track of animation actor ready atom. + * Having the ready atom set on the window by the window manager will trigger + * updates of actor parameters (position/rotation/etc...) to be sent off + * to the window manager for processing. + */ +static GdkFilterReturn +hildon_animation_actor_event_filter (GdkXEvent *xevent, + GdkEvent *event, + gpointer data) +{ + HildonAnimationActor *self = HILDON_ANIMATION_ACTOR (data); + XAnyEvent *any = xevent; + + if (any->type == PropertyNotify) + { + XPropertyEvent *property = xevent; + + if (property->atom == ready_atom) + { + hildon_animation_actor_update_ready (self); + } + } + + return GDK_FILTER_CONTINUE; +} + +/* + * Check for the ready atom on the animation actor X11 window. + * If present, send all pending animation actor messages to the + * window manager. + */ +static void +hildon_animation_actor_update_ready (HildonAnimationActor *self) +{ + HildonAnimationActorPrivate + *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); + GtkWidget *widget = GTK_WIDGET (self); + Display *display = GDK_WINDOW_XDISPLAY (widget->window); + Window window = GDK_WINDOW_XID (widget->window); + + int status; + gint xerror; + + Atom actual_type; + int actual_format; + unsigned long nitems, bytes_after; + unsigned char *prop = NULL; + + /* Check for the "ready" property */ + + gdk_error_trap_push (); + status = XGetWindowProperty (display, window, + ready_atom, 0, 32, + False, XA_ATOM, + &actual_type, &actual_format, + &nitems, &bytes_after, &prop); + xerror = gdk_error_trap_pop(); + + if (prop) + { + /* We do not actually use the property value for anything, + * it is enough that the property is set. */ + + XFree (prop); + } + + if (xerror || + (status != Success) || (actual_type != XA_ATOM) || + (actual_format != 32) || (nitems != 1)) + { + priv->ready = 0; + return; + } + + if (priv->ready) + { + /* The ready flag has been set once already. This means that + * the WM has restarted. Trigger re-mapping of the widget to + * update the texture actor first. Then push all animation + * actor settings anew. */ + + priv->map_event_cb_id = + g_signal_connect (G_OBJECT (self), + "map-event", + G_CALLBACK(hildon_animation_actor_map_event), + self); + + if (GTK_WIDGET_MAPPED (GTK_WIDGET (self))) + { + gtk_widget_unmap (GTK_WIDGET (self)); + gtk_widget_map (GTK_WIDGET (self)); + } + + return; + } + + priv->ready = 1; + + /* Send all pending messages */ + + hildon_animation_actor_send_pending_messages (self); +} + +static void +hildon_animation_actor_send_pending_messages (HildonAnimationActor *self) +{ + HildonAnimationActorPrivate + *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); + + if (priv->set_anchor) + { + if (priv->gravity == 0) + hildon_animation_actor_set_anchor (self, + priv->anchor_x, + priv->anchor_y); + else + hildon_animation_actor_set_anchor_from_gravity (self, + priv->gravity); + } + + if (priv->set_position) + hildon_animation_actor_set_position_full (self, + priv->position_x, + priv->position_y, + priv->depth); + + if (priv->set_rotation & (1 << HILDON_AA_X_AXIS)) + hildon_animation_actor_set_rotationx (self, + HILDON_AA_X_AXIS, + priv->x_rotation_angle, + 0, + priv->x_rotation_y, + priv->x_rotation_z); + + if (priv->set_rotation & (1 << HILDON_AA_Y_AXIS)) + hildon_animation_actor_set_rotationx (self, + HILDON_AA_Y_AXIS, + priv->y_rotation_angle, + priv->y_rotation_x, + 0, + priv->y_rotation_z); + + if (priv->set_rotation & (1 << HILDON_AA_Z_AXIS)) + hildon_animation_actor_set_rotationx (self, + HILDON_AA_Z_AXIS, + priv->z_rotation_angle, + priv->z_rotation_x, + priv->z_rotation_y, + 0); + + if (priv->set_scale) + hildon_animation_actor_set_scalex (self, + priv->scale_x, + priv->scale_y); + + if (priv->set_parent) + hildon_animation_actor_set_parent (self, + priv->parent); + + if (priv->set_show) + hildon_animation_actor_set_show_full (self, + priv->show, priv->opacity); +} + +static void +hildon_animation_actor_send_all_messages (HildonAnimationActor *self) +{ + HildonAnimationActorPrivate + *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); + + priv->set_anchor = 1; + priv->set_position = 1; + priv->set_rotation = (1 << HILDON_AA_X_AXIS) | + (1 << HILDON_AA_Y_AXIS) | + (1 << HILDON_AA_Z_AXIS); + priv->set_scale = 1; + priv->set_parent = 1; + priv->set_show = 1; + + hildon_animation_actor_send_pending_messages (self); +} + +/* ------------------------------------------------------------- */ + +/** + * hildon_animation_actor_send_message: + * @self: A #HildonAnimationActor + * @message_type: Message id for the animation actor message. + * @l0: 1st animation actor message parameter. + * @l1: 2nd animation actor message parameter. + * @l2: 3rd animation actor message parameter. + * @l3: 4th animation actor message parameter. + * @l4: 5th animation actor message parameter. + * + * Sends an X11 ClientMessage event to the window manager with + * the specified parameters -- id (@message_type) and data (@l0, + * @l1, @l2, @l3, @l4). + * + * This is an internal utility function that application will + * not need to call directly. + * + * Since: 2.2 + **/ +void +hildon_animation_actor_send_message (HildonAnimationActor *self, + guint32 message_type, + guint32 l0, + guint32 l1, + guint32 l2, + guint32 l3, + guint32 l4) +{ + GtkWidget *widget = GTK_WIDGET (self); + Display *display = GDK_WINDOW_XDISPLAY (widget->window); + Window window = GDK_WINDOW_XID (widget->window); +#if 0 + XClientMessageEvent event; + + event.type = ClientMessage; + event.window = window; + event.message_type = (Atom)message_type; + event.format = 32; + event.data.l[0] = l0; + event.data.l[1] = l1; + event.data.l[2] = l2; + event.data.l[3] = l3; + event.data.l[4] = l4; +#else + XEvent event = { 0 }; + + event.xclient.type = ClientMessage; + event.xclient.window = window; + event.xclient.message_type = (Atom)message_type; + event.xclient.format = 32; + event.xclient.data.l[0] = l0; + event.xclient.data.l[1] = l1; + event.xclient.data.l[2] = l2; + event.xclient.data.l[3] = l3; + event.xclient.data.l[4] = l4; +#endif + +#if 0 + g_debug ("%lu (%lu %lu %lu %lu %lu) -> %lu\n", + message_type, + l0, l1, l2, l3, l4, + window); +#endif + + XSendEvent (display, window, True, + StructureNotifyMask, + (XEvent *)&event); +} + +/** + * hildon_animation_actor_set_show_full: + * @self: A #HildonAnimationActor + * @show: A boolean flag setting the visibility of the animation actor. + * @opacity: Desired opacity setting + * + * Send a message to the window manager setting the visibility of + * the animation actor. This will only affect the visibility of + * the animation actor set by the compositing window manager in its own + * rendering pipeline, after X has drawn the window to the off-screen + * buffer. This setting, naturally, has no effect if the #HildonAnimationActor + * widget is not visible in X11 terms (i.e. realized and mapped). + * + * Furthermore, if a widget is parented, its final visibility will be + * affected by that of the parent window. + * + * The opacity setting ranges from zero (0), being completely transparent + * to 255 (0xff) being fully opaque. + * + * If the animation actor WM-counterpart is not ready, the show message + * will be queued until the WM is ready for it. + * + * Since: 2.2 + **/ +void +hildon_animation_actor_set_show_full (HildonAnimationActor *self, + gint show, + gint opacity) +{ + HildonAnimationActorPrivate + *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); + GtkWidget *widget = GTK_WIDGET (self); + + if (opacity > 255) + opacity = 255; + + if (opacity < 0) + opacity = 0; + + priv->show = show; + priv->opacity = opacity; + priv->set_show = 1; + + if (GTK_WIDGET_MAPPED (widget) && priv->ready) + { + /* Defer show messages until the animation actor is parented + * and the parent window is mapped */ + + if (!priv->parent || !GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent))) + return; + + hildon_animation_actor_send_message (self, + show_atom, + show, opacity, + 0, 0, 0); + priv->set_show = 0; + } +} + +/** + * hildon_animation_actor_set_show: + * @self: A #HildonAnimationActor + * @show: A boolean flag setting the visibility of the animation actor. + * + * This function is a shortcut for hildon_animation_actor_set_show_full(), + * setting the overall actor visibility without changing it's opacity + * setting. + * + * Since: 2.2 + **/ +void +hildon_animation_actor_set_show (HildonAnimationActor *self, + gint show) +{ + HildonAnimationActorPrivate + *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); + + hildon_animation_actor_set_show_full (self, + show, priv->opacity); +} + +/** + * hildon_animation_actor_set_opacity: + * @self: A #HildonAnimationActor + * @opacity: Desired opacity setting + * + * This function is a shortcut for hildon_animation_actor_set_show_full(), + * setting actor opacity without changing it's overall visibility. + * + * See hildon_animation_actor_set_show_full() for description of the range + * of values @opacity argument takes. + * + * Since: 2.2 + **/ +void +hildon_animation_actor_set_opacity (HildonAnimationActor *self, + gint opacity) +{ + HildonAnimationActorPrivate + *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); + + hildon_animation_actor_set_show_full (self, + priv->show, opacity); +} + +/** + * hildon_animation_actor_set_position_full: + * @self: A #HildonAnimationActor + * @x: Desired X coordinate + * @y: Desired Y coordinate + * @depth: Desired window depth (Z coordinate) + * + * Send a message to the window manager setting the position of the + * animation actor. This will set the position of the animation + * actor off-screen bitmap as it is rendered to the screen. The + * position of the actor is relative to the parent window. The actor + * is also subject to the animation effects rendered by the compositing + * window manager on that window (like those by task switcher). + * + * The window depth affects the stacking of animation actors within + * a parent window and, more generally, the stacking of clutter actors + * within a stage/container. The default depth is 0 and a parent + * window's container will have it's window texture stacked at that level. + * The stacking at any depth level is sequential -- animation actor B + * created/parented after animation actor A will obscure the latter + * if they overlap. + * + * Animation actors with non-zero depth settings are subject to scaling as + * per the global scene perspective setup, which limits the depth setting + * as the primary parameter to control the stacking order. Since the + * stacking order follows the parenting order, it may be better to use + * hildon_animation_actor_set_parent() for setting the stacking. + * + * If the animation actor WM-counterpart is not ready, the show message + * will be queued until the WM is ready for it. + * + * Since: 2.2 + **/ +void +hildon_animation_actor_set_position_full (HildonAnimationActor *self, + gint x, + gint y, + gint depth) +{ + HildonAnimationActorPrivate + *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); + GtkWidget *widget = GTK_WIDGET (self); + + priv->position_x = x; + priv->position_y = y; + priv->depth = depth; + priv->set_position = 1; + + if (GTK_WIDGET_MAPPED (widget) && priv->ready) + { + hildon_animation_actor_send_message (self, + position_atom, + x, y, depth, + 0, 0); + priv->set_position = 0; + } +} + +/** + * hildon_animation_actor_set_position: + * @self: A #HildonAnimationActor + * @x: Desired window X coordinate + * @y: Desired window Y coordinate + * + * A shortcut for hildon_animation_actor_set_position_full(), + * changing the window position, but preserving it's depth setting. + * + * Since: 2.2 + **/ +void +hildon_animation_actor_set_position (HildonAnimationActor *self, + gint x, + gint y) +{ + HildonAnimationActorPrivate + *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); + + hildon_animation_actor_set_position_full (self, + x, y, priv->depth); +} + +/** + * hildon_animation_actor_set_depth: + * @self: A #HildonAnimationActor + * @depth: Desired window depth (Z coordinate) + * + * A shortcut for hildon_animation_actor_set_position_full(), + * changing the window depth, but preserving it's position. + * + * Since: 2.2 + **/ +void +hildon_animation_actor_set_depth (HildonAnimationActor *self, + gint depth) +{ + HildonAnimationActorPrivate + *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); + + hildon_animation_actor_set_position_full (self, + priv->position_x, + priv->position_y, + depth); +} + +/** + * hildon_animation_actor_set_scalex: + * @self: A #HildonAnimationActor + * @x_scale: Window's desired scale factor along the X-axis + * @y_scale: Window's desired scale factor along the Y-axis + * + * This function is just like hildon_animation_actor_set_scale(), + * but the scale factors are given as 16-bit fixed-point number. + * + * Since: 2.2 + **/ +void +hildon_animation_actor_set_scalex (HildonAnimationActor *self, + gint32 x_scale, + gint32 y_scale) +{ + HildonAnimationActorPrivate + *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); + GtkWidget *widget = GTK_WIDGET (self); + + priv->scale_x = x_scale; + priv->scale_y = y_scale; + priv->set_scale = 1; + + if (GTK_WIDGET_MAPPED (widget) && priv->ready) + { + hildon_animation_actor_send_message (self, + scale_atom, + x_scale, y_scale, + 0, 0, 0); + priv->set_scale = 0; + } +} + +/** + * hildon_animation_actor_set_scale: + * @self: A #HildonAnimationActor + * @x_scale: Window's desired scale factor along the X-axis + * @y_scale: Window's desired scale factor along the Y-axis + * + * Send a message to the window manager setting the scale factors of the + * animation actor. This will set the scale factors on the animation + * actor off-screen bitmap as it is rendered to the screen. If the + * animation actor is parented to another top-level window, the + * animation effects rendered by the compositing window manager + * on that top-level window (like those by task switcher) will + * also affect the animation actor. + * + * If the animation actor WM-counterpart is not ready, the show message + * will be queued until the WM is ready for it. + * + * Since: 2.2 + **/ +void +hildon_animation_actor_set_scale (HildonAnimationActor *self, + double x_scale, + double y_scale) +{ + gint32 f_x_scale = x_scale * (1 << 16); + gint32 f_y_scale = y_scale * (1 << 16); + + hildon_animation_actor_set_scalex (self, f_x_scale, f_y_scale); +} + +/** + * hildon_animation_actor_set_rotationx: + * @self: A #HildonAnimationActor + * @axis: The rotation axis. + * @degrees: The rotation angle in degrees. + * @x: Center of the rotation, X coordinate. + * @y: Center of the rotation, Y coordinate. + * @z: Center of the rotation, Z coordinate. + * + * This function is just like hildon_animation_actor_set_rotation(), + * but the rotation angle is given as 16-bit fixed-point number. + * + * Since: 2.2 + **/ +void +hildon_animation_actor_set_rotationx (HildonAnimationActor *self, + gint axis, + gint32 degrees, + gint x, + gint y, + gint z) +{ + HildonAnimationActorPrivate + *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); + GtkWidget *widget = GTK_WIDGET (self); + + guint mask = 0; + + switch (axis) + { + case HILDON_AA_X_AXIS: + priv->x_rotation_angle = degrees; + priv->x_rotation_y = y; + priv->x_rotation_z = z; + mask = (1 << HILDON_AA_X_AXIS); + break; + case HILDON_AA_Y_AXIS: + priv->y_rotation_angle = degrees; + priv->y_rotation_x = x; + priv->y_rotation_z = z; + mask = (1 << HILDON_AA_Y_AXIS); + break; + case HILDON_AA_Z_AXIS: + priv->z_rotation_angle = degrees; + priv->z_rotation_x = x; + priv->z_rotation_y = y; + mask = (1 << HILDON_AA_Z_AXIS); + break; + default: + return; + } + + priv->set_rotation |= mask; + + if (GTK_WIDGET_MAPPED (widget) && priv->ready) + { + hildon_animation_actor_send_message (self, + rotation_atom, + axis, degrees, x, y, z); + priv->set_rotation &= ~mask; + } +} + +/** + * hildon_animation_actor_set_rotation: + * @self: A #HildonAnimationActor + * @axis: The rotation axis. + * @degrees: The rotation angle in degrees. + * @x: Center of the rotation, X coordinate. + * @y: Center of the rotation, Y coordinate. + * @z: Center of the rotation, Z coordinate. + * + * Send a message to the window manager setting the animation actor + * rotation around one of the three axes. The rotation center coordinates + * depend on the axis of rotation: + * + * * %HILDON_AA_X_AXIS requires @y and @z coordinates. + * * %HILDON_AA_Y_AXIS requires @x and @z coordinates. + * * %HILDON_AA_Z_AXIS requires @x and @y coordinates. + * + * If the animation actor WM-counterpart is not ready, the show message + * will be queued until the WM is ready for it. + * + * Since: 2.2 + **/ +void +hildon_animation_actor_set_rotation (HildonAnimationActor *self, + gint axis, + double degrees, + gint x, + gint y, + gint z) +{ + gint32 f_degrees = degrees * (1 << 16); + + hildon_animation_actor_set_rotationx (self, axis, f_degrees, x, y, z); +} + +/** + * hildon_animation_actor_set_anchor: + * @self: A #HildonAnimationActor + * @x: The X coordinate of the anchor point. + * @y: The Y coordinate of the anchor point. + * + * Send a message to the window manager setting the anchor point for + * the animation actor. The anchor point is the point to which the + * actor position within its parent it is relative. + * + * If the animation actor WM-counterpart is not ready, the show message + * will be queued until the WM is ready for it. + * + * Since: 2.2 + **/ +void +hildon_animation_actor_set_anchor (HildonAnimationActor *self, + gint x, + gint y) +{ + HildonAnimationActorPrivate + *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); + GtkWidget *widget = GTK_WIDGET (self); + + priv->gravity = 0; + priv->anchor_x = x; + priv->anchor_y = y; + priv->set_anchor = 1; + + if (GTK_WIDGET_MAPPED (widget) && priv->ready) + { + hildon_animation_actor_send_message (self, + anchor_atom, + 0, x, y, + 0, 0); + priv->set_anchor = 0; + } +} + +/** + * hildon_animation_actor_set_anchor_from_gravity: + * @self: A #HildonAnimationActor + * @gravity: The gravity constant. + * + * Send a message to the window manager setting the anchor point for + * the animation actor. The anchor point is the point to which the + * actor position within its parent it is relative. Instead of being + * defined in (x, y)-coordinates, the anchor point is defined in the + * relative "gravity" constant as: + * + * * %HILDON_AA_N_GRAVITY translates to (width / 2, 0) coordinate + * * %HILDON_AA_NE_GRAVITY translates to (width, 0) coordinate + * * %HILDON_AA_E_GRAVITY translates to (width, height / 2) coordinate + * * %HILDON_AA_SE_GRAVITY translates to (width, height) coordinate + * * %HILDON_AA_S_GRAVITY translates to (width / 2, height) coordinate + * * %HILDON_AA_SW_GRAVITY translates to (0, height) coordinate + * * %HILDON_AA_W_GRAVITY translates to (0, height / 2) coordinate + * * %HILDON_AA_NW_GRAVITY translates to (0, 0) coordinate + * * %HILDON_AA_CENTER_GRAVITY translates to (width / 2, height / 2) coordinate + * + * If the animation actor WM-counterpart is not ready, the show message + * will be queued until the WM is ready for it. + * + * Since: 2.2 + **/ +void +hildon_animation_actor_set_anchor_from_gravity (HildonAnimationActor *self, + guint gravity) +{ + HildonAnimationActorPrivate + *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); + GtkWidget *widget = GTK_WIDGET (self); + + priv->gravity = gravity; + priv->set_anchor = 1; + + if (GTK_WIDGET_MAPPED (widget) && priv->ready) + { + hildon_animation_actor_send_message (self, + anchor_atom, + gravity, 0, 0, + 0, 0); + priv->set_anchor = 0; + } +} + +/* + * This callback will be triggered by the parent widget of + * an animation actor when it is mapped. The compositing + * window manager is now ready to parent the animation actor + * into the target parent window. + */ +static gboolean +hildon_animation_actor_parent_map_event (GtkWidget *parent, + GdkEvent *event, + gpointer user_data) +{ + hildon_animation_actor_set_parent (HILDON_ANIMATION_ACTOR (user_data), + GTK_WINDOW (parent)); + return FALSE; +} + +/* + * This callback will be triggered by the widget re-mapping + * itself in case of WM restarting. The point is to push all + * animation actor parameters anew to the WM. + */ +static gboolean +hildon_animation_actor_map_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data) +{ + HildonAnimationActor + *self = HILDON_ANIMATION_ACTOR (user_data); + HildonAnimationActorPrivate + *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); + + hildon_animation_actor_send_all_messages (self); + + /* Disconnect the "map-event" handler after the "emergency resend all + * actor parameters" drill is over. */ + + if (priv->map_event_cb_id) + { + g_signal_handler_disconnect (self, + priv->map_event_cb_id); + priv->map_event_cb_id = 0; + } + + return FALSE; +} + +/** + * hildon_animation_actor_set_parent: + * @self: A #HildonAnimationActor + * @parent: A #GtkWindow that the actor will be parented to. + * + * Send a message to the window manager setting the parent window + * for the animation actor. Parenting an actor will not affect the + * X window that the HildonAnimationActor represents, but it's off-screen + * bitmap as it is handled by the compositing window manager. + * + * Parenting an animation actor will affect its visibility as set + * by the gtk_widget_show(), gtk_widget_hide() and + * hildon_animation_actor_set_show(). The animation actor will only be + * visible when the top-level window it is parented is visible. + * + * Passing %NULL as a @parent argument will unparent the animation actor. + * This will restore the actor's visibility if it was suppressed by + * being unparented or parented to an unmapped window. + * + * If the animation actor WM-counterpart is not ready, the show message + * will be queued until the WM is ready for it. + * + * Since: 2.2 + **/ +void +hildon_animation_actor_set_parent (HildonAnimationActor *self, + GtkWindow *parent) +{ + HildonAnimationActorPrivate + *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); + GtkWidget *widget = GTK_WIDGET (self); + + gtk_window_set_transient_for (GTK_WINDOW (self), parent); + + if (priv->parent != parent) + { + /* Setting a new parent */ + + if (priv->parent) + { + if (priv->parent_map_event_cb_id) + g_signal_handler_disconnect (priv->parent, + priv->parent_map_event_cb_id); + + /* Might need a synchronized "parent(0)" or "parent(new parent)" + * message here before we can safely decrease the reference count. */ + + g_object_unref (priv->parent); + } + + priv->parent = parent; + priv->set_parent = 1; + + if (parent != 0) + { + /* The widget is being (re)parented, not unparented. */ + + g_object_ref (parent); + + priv->parent_map_event_cb_id = + g_signal_connect (G_OBJECT (priv->parent), + "map-event", + G_CALLBACK(hildon_animation_actor_parent_map_event), + self); + } + else + { + priv->parent_map_event_cb_id = 0; + } + } + + if (GTK_WIDGET_MAPPED (widget) && priv->ready) + { + Window win = 0; + + /* If the animation actor is being unparented or parented to an + * unmapped widget, force its visibility to "hidden". */ + + if (!priv->parent || !GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent))) + { + hildon_animation_actor_send_message (self, + show_atom, + 0, priv->opacity, + 0, 0, 0); + } + + /* If the widget is being parented (parent != 0), only proceed when + * the parent widget is realized, since we need the X window id of + * the parent. If the widget is being unparented (parent == 0), pass + * the "special" window id of 0 in the message. */ + + if (priv->parent) + { + if (!GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent))) + return; + + GdkWindow *gdk = GTK_WIDGET (parent)->window; + win = GDK_WINDOW_XID (gdk); + } + + hildon_animation_actor_send_message (self, + parent_atom, + win, + 0, 0, 0, 0); + priv->set_parent = 0; + + /* Set animation actor visibility to desired value (in case it was + * forced off when the actor was parented into an unmapped widget). */ + + hildon_animation_actor_send_message (self, + show_atom, + priv->show, priv->opacity, + 0, 0, 0); + priv->set_show = 0; + } +} + diff --git a/hildon/hildon-animation-actor.h b/hildon/hildon-animation-actor.h new file mode 100644 index 0000000..a92e5c2 --- /dev/null +++ b/hildon/hildon-animation-actor.h @@ -0,0 +1,162 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_ANIMATION_ACTOR_H__ +#define __HILDON_ANIMATION_ACTOR_H__ + +#include "hildon-window.h" + +G_BEGIN_DECLS + +#define HILDON_TYPE_ANIMATION_ACTOR \ + (hildon_animation_actor_get_type()) + +#define HILDON_ANIMATION_ACTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + HILDON_TYPE_ANIMATION_ACTOR, \ + HildonAnimationActor)) + +#define HILDON_ANIMATION_ACTOR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + HILDON_TYPE_ANIMATION_ACTOR, \ + HildonAnimationActorClass)) + +#define HILDON_IS_ANIMATION_ACTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + HILDON_TYPE_ANIMATION_ACTOR)) + +#define HILDON_IS_ANIMATION_ACTOR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + HILDON_TYPE_ANIMATION_ACTOR)) + +#define HILDON_ANIMATION_ACTOR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + HILDON_TYPE_ANIMATION_ACTOR, \ + HildonAnimationActorClass)) + +typedef struct _HildonAnimationActor HildonAnimationActor; +typedef struct _HildonAnimationActorClass HildonAnimationActorClass; + +struct _HildonAnimationActorClass +{ + GtkWindowClass parent_class; + + /* Padding for future extension */ + void (*_hildon_reserved1)(void); + void (*_hildon_reserved2)(void); + void (*_hildon_reserved3)(void); + void (*_hildon_reserved4)(void); +}; + +struct _HildonAnimationActor +{ + GtkWindow parent; +}; + +#define HILDON_AA_X_AXIS 0 +#define HILDON_AA_Y_AXIS 1 +#define HILDON_AA_Z_AXIS 2 + +#define HILDON_AA_N_GRAVITY 1 +#define HILDON_AA_NE_GRAVITY 2 +#define HILDON_AA_E_GRAVITY 3 +#define HILDON_AA_SE_GRAVITY 4 +#define HILDON_AA_S_GRAVITY 5 +#define HILDON_AA_SW_GRAVITY 6 +#define HILDON_AA_W_GRAVITY 7 +#define HILDON_AA_NW_GRAVITY 8 +#define HILDON_AA_CENTER_GRAVITY 9 + +GType +hildon_animation_actor_get_type (void) G_GNUC_CONST; + +GtkWidget* +hildon_animation_actor_new (void); + +void +hildon_animation_actor_send_message (HildonAnimationActor *self, + guint32 message_type, + guint32 l0, + guint32 l1, + guint32 l2, + guint32 l3, + guint32 l4); +void +hildon_animation_actor_set_show_full (HildonAnimationActor *self, + gint show, + gint opacity); +void +hildon_animation_actor_set_show (HildonAnimationActor *self, + gint show); +void +hildon_animation_actor_set_opacity (HildonAnimationActor *self, + gint opacity); +void +hildon_animation_actor_set_position_full (HildonAnimationActor *self, + gint x, + gint y, + gint depth); +void +hildon_animation_actor_set_position (HildonAnimationActor *self, + gint x, + gint y); +void +hildon_animation_actor_set_depth (HildonAnimationActor *self, + gint depth); +void +hildon_animation_actor_set_scalex (HildonAnimationActor *self, + gint32 x_scale, + gint32 y_scale); +void +hildon_animation_actor_set_scale (HildonAnimationActor *self, + double x_scale, + double y_scale); +void +hildon_animation_actor_set_rotationx (HildonAnimationActor *self, + gint axis, + gint32 degrees, + gint x, + gint y, + gint z); +void +hildon_animation_actor_set_rotation (HildonAnimationActor *self, + gint axis, + double degrees, + gint x, + gint y, + gint z); +void +hildon_animation_actor_set_anchor (HildonAnimationActor *self, + gint x, + gint y); +void +hildon_animation_actor_set_anchor_from_gravity (HildonAnimationActor *self, + guint gravity); +void +hildon_animation_actor_set_parent (HildonAnimationActor *self, + GtkWindow *parent); + +G_END_DECLS + +#endif /* __HILDON_ANIMATION_ACTOR_H__ */ diff --git a/hildon/hildon-app-menu-private.h b/hildon/hildon-app-menu-private.h new file mode 100644 index 0000000..dc9ba07 --- /dev/null +++ b/hildon/hildon-app-menu-private.h @@ -0,0 +1,53 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +#ifndef __HILDON_APP_MENU_PRIVATE_H__ +#define __HILDON_APP_MENU_PRIVATE_H__ + +G_BEGIN_DECLS + +#define HILDON_APP_MENU_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_APP_MENU, HildonAppMenuPrivate)); + +struct _HildonAppMenuPrivate +{ + GtkBox *filters_hbox; + GtkBox *vbox; + GtkTable *table; + GtkWindow *parent_window; + GdkWindow *transfer_window; + gboolean pressed_outside; + GList *buttons; + GList *filters; + guint columns; + gint width_request; + guint find_intruder_idle_id; + guint hide_idle_id; +}; + +void G_GNUC_INTERNAL +hildon_app_menu_set_parent_window (HildonAppMenu *self, + GtkWindow *parent_window); + +gpointer G_GNUC_INTERNAL +hildon_app_menu_get_parent_window (HildonAppMenu *self); + +G_END_DECLS + +#endif /* __HILDON_APP_MENU_PRIVATE_H__ */ diff --git a/hildon/hildon-app-menu.c b/hildon/hildon-app-menu.c new file mode 100644 index 0000000..5aa56f0 --- /dev/null +++ b/hildon/hildon-app-menu.c @@ -0,0 +1,1123 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +/** + * SECTION:hildon-app-menu + * @short_description: Widget representing the application menu in the Hildon framework. + * + * The #HildonAppMenu is a GTK widget which represents an application + * menu in the Hildon framework. + * + * This menu opens from the top of the screen and contains a number of + * entries (#GtkButton) organized in one or two columns, depending on + * the size of the screen (the number of columns changes automatically + * if the screen is resized). Entries are added left to right and top + * to bottom. + * + * Besides that, the #HildonAppMenu can contain a group of filter buttons + * (#GtkToggleButton or #GtkRadioButton). + * + * To use a #HildonAppMenu, add it to a #HildonWindow using + * hildon_window_set_app_menu(). The menu will appear when the user + * presses the window title bar. Alternatively, you can show it by + * hand using hildon_app_menu_popup(). + * + * The menu will be automatically hidden when one of its buttons is + * clicked. Use g_signal_connect_after() when connecting callbacks to + * buttons to make sure that they're called after the menu + * disappears. Alternatively, you can add the button to the menu + * before connecting any callback. + * + * Although implemented with a #GtkWindow, #HildonAppMenu behaves like + * a normal ref-counted widget, so g_object_ref(), g_object_unref(), + * g_object_ref_sink() and friends will behave just like with any + * other non-toplevel widget. + * + * + * Creating a HildonAppMenu + * + * GtkWidget *win; + * HildonAppMenu *menu; + * GtkWidget *button; + * GtkWidget *filter; + * + * win = hildon_stackable_window_new (); + * menu = HILDON_APP_MENU (hildon_app_menu_new ()); + * + * // Create a button and add it to the menu + * button = gtk_button_new_with_label ("Menu command one"); + * g_signal_connect_after (button, "clicked", G_CALLBACK (button_one_clicked), userdata); + * hildon_app_menu_append (menu, GTK_BUTTON (button)); + * + * // Another button + * button = gtk_button_new_with_label ("Menu command two"); + * g_signal_connect_after (button, "clicked", G_CALLBACK (button_two_clicked), userdata); + * hildon_app_menu_append (menu, GTK_BUTTON (button)); + * + * // Create a filter and add it to the menu + * filter = gtk_radio_button_new_with_label (NULL, "Filter one"); + * gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (filter), FALSE); + * g_signal_connect_after (filter, "clicked", G_CALLBACK (filter_one_clicked), userdata); + * hildon_app_menu_add_filter (menu, GTK_BUTTON (filter)); + * + * // Add a new filter + * filter = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (filter), "Filter two"); + * gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (filter), FALSE); + * g_signal_connect_after (filter, "clicked", G_CALLBACK (filter_two_clicked), userdata); + * hildon_app_menu_add_filter (menu, GTK_BUTTON (filter)); + * + * // Show all menu items + * gtk_widget_show_all (GTK_WIDGET (menu)); + * + * // Add the menu to the window + * hildon_window_set_app_menu (HILDON_WINDOW (win), menu); + * + * + * + */ + +#include +#include +#include + +#include "hildon-gtk.h" +#include "hildon-app-menu.h" +#include "hildon-app-menu-private.h" +#include "hildon-window.h" +#include "hildon-banner.h" + +static GdkWindow * +grab_transfer_window_get (GtkWidget *widget); + +static void +hildon_app_menu_repack_items (HildonAppMenu *menu, + gint start_from); + +static void +hildon_app_menu_repack_filters (HildonAppMenu *menu); + +static gboolean +can_activate_accel (GtkWidget *widget, + guint signal_id, + gpointer user_data); + +static void +item_visibility_changed (GtkWidget *item, + GParamSpec *arg1, + HildonAppMenu *menu); + +static void +filter_visibility_changed (GtkWidget *item, + GParamSpec *arg1, + HildonAppMenu *menu); + +static void +remove_item_from_list (GList **list, + gpointer item); + +static void +hildon_app_menu_apply_style (GtkWidget *widget); + +G_DEFINE_TYPE (HildonAppMenu, hildon_app_menu, GTK_TYPE_WINDOW); + +/** + * hildon_app_menu_new: + * + * Creates a new #HildonAppMenu. + * + * Return value: A #HildonAppMenu. + * + * Since: 2.2 + **/ +GtkWidget * +hildon_app_menu_new (void) +{ + GtkWidget *menu = g_object_new (HILDON_TYPE_APP_MENU, NULL); + return menu; +} + +/** + * hildon_app_menu_insert: + * @menu : A #HildonAppMenu + * @item : A #GtkButton to add to the #HildonAppMenu + * @position : The position in the item list where @item is added (from 0 to n-1). + * + * Adds @item to @menu at the position indicated by @position. + * + * Since: 2.2 + */ +void +hildon_app_menu_insert (HildonAppMenu *menu, + GtkButton *item, + gint position) +{ + HildonAppMenuPrivate *priv; + + g_return_if_fail (HILDON_IS_APP_MENU (menu)); + g_return_if_fail (GTK_IS_BUTTON (item)); + + priv = HILDON_APP_MENU_GET_PRIVATE(menu); + + /* Force widget size */ + hildon_gtk_widget_set_theme_size (GTK_WIDGET (item), + HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH); + + /* Add the item to the menu */ + gtk_widget_show (GTK_WIDGET (item)); + g_object_ref_sink (item); + priv->buttons = g_list_insert (priv->buttons, item, position); + hildon_app_menu_repack_items (menu, position); + + /* Enable accelerators */ + g_signal_connect (item, "can-activate-accel", G_CALLBACK (can_activate_accel), NULL); + + /* Close the menu when the button is clicked */ + g_signal_connect_swapped (item, "clicked", G_CALLBACK (gtk_widget_hide), menu); + g_signal_connect (item, "notify::visible", G_CALLBACK (item_visibility_changed), menu); + + /* Remove item from list when it is destroyed */ + g_object_weak_ref (G_OBJECT (item), (GWeakNotify) remove_item_from_list, &(priv->buttons)); +} + +/** + * hildon_app_menu_append: + * @menu : A #HildonAppMenu + * @item : A #GtkButton to add to the #HildonAppMenu + * + * Adds @item to the end of the menu's item list. + * + * Since: 2.2 + */ +void +hildon_app_menu_append (HildonAppMenu *menu, + GtkButton *item) +{ + hildon_app_menu_insert (menu, item, -1); +} + +/** + * hildon_app_menu_prepend: + * @menu : A #HildonAppMenu + * @item : A #GtkButton to add to the #HildonAppMenu + * + * Adds @item to the beginning of the menu's item list. + * + * Since: 2.2 + */ +void +hildon_app_menu_prepend (HildonAppMenu *menu, + GtkButton *item) +{ + hildon_app_menu_insert (menu, item, 0); +} + +/** + * hildon_app_menu_reorder_child: + * @menu : A #HildonAppMenu + * @item : A #GtkButton to move + * @position : The new position to place @item (from 0 to n-1). + * + * Moves a #GtkButton to a new position within #HildonAppMenu. + * + * Since: 2.2 + */ +void +hildon_app_menu_reorder_child (HildonAppMenu *menu, + GtkButton *item, + gint position) +{ + HildonAppMenuPrivate *priv; + gint old_position; + + g_return_if_fail (HILDON_IS_APP_MENU (menu)); + g_return_if_fail (GTK_IS_BUTTON (item)); + g_return_if_fail (position >= 0); + + priv = HILDON_APP_MENU_GET_PRIVATE (menu); + old_position = g_list_index (priv->buttons, item); + + g_return_if_fail (old_position >= 0); + + /* Move the item */ + priv->buttons = g_list_remove (priv->buttons, item); + priv->buttons = g_list_insert (priv->buttons, item, position); + + hildon_app_menu_repack_items (menu, MIN (old_position, position)); +} + +/** + * hildon_app_menu_add_filter: + * @menu : A #HildonAppMenu + * @filter : A #GtkButton to add to the #HildonAppMenu. + * + * Adds the @filter to @menu. + * + * Since: 2.2 + */ +void +hildon_app_menu_add_filter (HildonAppMenu *menu, + GtkButton *filter) +{ + HildonAppMenuPrivate *priv; + + g_return_if_fail (HILDON_IS_APP_MENU (menu)); + g_return_if_fail (GTK_IS_BUTTON (filter)); + + priv = HILDON_APP_MENU_GET_PRIVATE(menu); + + /* Force widget size */ + hildon_gtk_widget_set_theme_size (GTK_WIDGET (filter), + HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH); + + /* Add the filter to the menu */ + gtk_widget_show (GTK_WIDGET (filter)); + g_object_ref_sink (filter); + priv->filters = g_list_append (priv->filters, filter); + hildon_app_menu_repack_filters (menu); + + /* Enable accelerators */ + g_signal_connect (filter, "can-activate-accel", G_CALLBACK (can_activate_accel), NULL); + + /* Close the menu when the button is clicked */ + g_signal_connect_swapped (filter, "clicked", G_CALLBACK (gtk_widget_hide), menu); + g_signal_connect (filter, "notify::visible", G_CALLBACK (filter_visibility_changed), menu); + + /* Remove filter from list when it is destroyed */ + g_object_weak_ref (G_OBJECT (filter), (GWeakNotify) remove_item_from_list, &(priv->filters)); +} + +static void +hildon_app_menu_set_columns (HildonAppMenu *menu, + guint columns) +{ + HildonAppMenuPrivate *priv; + + g_return_if_fail (HILDON_IS_APP_MENU (menu)); + g_return_if_fail (columns > 0); + + priv = HILDON_APP_MENU_GET_PRIVATE (menu); + + if (columns != priv->columns) { + priv->columns = columns; + hildon_app_menu_repack_items (menu, 0); + } +} + +static void +parent_window_topmost_notify (HildonWindow *parent_win, + GParamSpec *arg1, + GtkWidget *menu) +{ + if (!hildon_window_get_is_topmost (parent_win)) + gtk_widget_hide (menu); +} + +static void +parent_window_unmapped (HildonWindow *parent_win, + GtkWidget *menu) +{ + gtk_widget_hide (menu); +} + +void G_GNUC_INTERNAL +hildon_app_menu_set_parent_window (HildonAppMenu *self, + GtkWindow *parent_window) +{ + HildonAppMenuPrivate *priv; + + g_return_if_fail (HILDON_IS_APP_MENU (self)); + g_return_if_fail (parent_window == NULL || GTK_IS_WINDOW (parent_window)); + + priv = HILDON_APP_MENU_GET_PRIVATE(self); + + /* Disconnect old handlers, if any */ + if (priv->parent_window) { + g_signal_handlers_disconnect_by_func (priv->parent_window, parent_window_topmost_notify, self); + g_signal_handlers_disconnect_by_func (priv->parent_window, parent_window_unmapped, self); + } + + /* Connect a new handler */ + if (parent_window) { + g_signal_connect (parent_window, "notify::is-topmost", G_CALLBACK (parent_window_topmost_notify), self); + g_signal_connect (parent_window, "unmap", G_CALLBACK (parent_window_unmapped), self); + } + + priv->parent_window = parent_window; + + if (parent_window == NULL && GTK_WIDGET_VISIBLE (self)) + gtk_widget_hide (GTK_WIDGET (self)); +} + +gpointer G_GNUC_INTERNAL +hildon_app_menu_get_parent_window (HildonAppMenu *self) +{ + HildonAppMenuPrivate *priv; + + g_return_val_if_fail (HILDON_IS_APP_MENU (self), NULL); + + priv = HILDON_APP_MENU_GET_PRIVATE (self); + + return priv->parent_window; +} + +static void +screen_size_changed (GdkScreen *screen, + HildonAppMenu *menu) +{ + hildon_app_menu_apply_style (GTK_WIDGET (menu)); + + if (gdk_screen_get_width (screen) > gdk_screen_get_height (screen)) { + hildon_app_menu_set_columns (menu, 2); + } else { + hildon_app_menu_set_columns (menu, 1); + } +} + +static gboolean +can_activate_accel (GtkWidget *widget, + guint signal_id, + gpointer user_data) +{ + return GTK_WIDGET_VISIBLE (widget); +} + +static void +item_visibility_changed (GtkWidget *item, + GParamSpec *arg1, + HildonAppMenu *menu) +{ + HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE (menu); + + hildon_app_menu_repack_items (menu, g_list_index (priv->buttons, item)); +} + +static void +filter_visibility_changed (GtkWidget *item, + GParamSpec *arg1, + HildonAppMenu *menu) +{ + hildon_app_menu_repack_filters (menu); +} + +static void +remove_item_from_list (GList **list, + gpointer item) +{ + *list = g_list_remove (*list, item); +} + +static void +hildon_app_menu_show_all (GtkWidget *widget) +{ + HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE (widget); + + /* Show children, but not self. */ + g_list_foreach (priv->buttons, (GFunc) gtk_widget_show_all, NULL); + g_list_foreach (priv->filters, (GFunc) gtk_widget_show_all, NULL); +} + + +static void +hildon_app_menu_hide_all (GtkWidget *widget) +{ + HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE (widget); + + /* Hide children, but not self. */ + g_list_foreach (priv->buttons, (GFunc) gtk_widget_hide_all, NULL); + g_list_foreach (priv->filters, (GFunc) gtk_widget_hide_all, NULL); +} + +/* + * There's a race condition that can freeze the UI if a dialog appears + * between a HildonAppMenu and its parent window, see NB#100468 + */ +static gboolean +hildon_app_menu_find_intruder (gpointer data) +{ + GtkWidget *widget = GTK_WIDGET (data); + HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE (widget); + + priv->find_intruder_idle_id = 0; + + /* If there's a window between the menu and its parent window, hide the menu */ + if (priv->parent_window) { + gboolean intruder_found = FALSE; + GdkScreen *screen = gtk_widget_get_screen (widget); + GList *stack = gdk_screen_get_window_stack (screen); + GList *parent_pos = g_list_find (stack, GTK_WIDGET (priv->parent_window)->window); + GList *toplevels = gtk_window_list_toplevels (); + GList *i; + + for (i = toplevels; i != NULL && !intruder_found; i = i->next) { + if (i->data != widget && i->data != priv->parent_window) { + if (g_list_find (parent_pos, GTK_WIDGET (i->data)->window)) { + /* HildonBanners are not closed automatically when + * a new window appears, so we must close them by + * hand to make the AppMenu work as expected. + * Yes, this is a hack. See NB#111027 */ + if (HILDON_IS_BANNER (i->data)) { + gtk_widget_hide (i->data); + } else { + intruder_found = TRUE; + } + } + } + } + + g_list_foreach (stack, (GFunc) g_object_unref, NULL); + g_list_free (stack); + g_list_free (toplevels); + + if (intruder_found) + gtk_widget_hide (widget); + } + + return FALSE; +} + +static void +hildon_app_menu_map (GtkWidget *widget) +{ + HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE(widget); + + GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->map (widget); + + /* Grab pointer and keyboard */ + if (priv->transfer_window == NULL) { + gboolean has_grab = FALSE; + + priv->transfer_window = grab_transfer_window_get (widget); + + if (gdk_pointer_grab (priv->transfer_window, TRUE, + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | + GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | + GDK_POINTER_MOTION_MASK, NULL, NULL, + GDK_CURRENT_TIME) == GDK_GRAB_SUCCESS) { + if (gdk_keyboard_grab (priv->transfer_window, TRUE, + GDK_CURRENT_TIME) == GDK_GRAB_SUCCESS) { + has_grab = TRUE; + } else { + gdk_display_pointer_ungrab (gtk_widget_get_display (widget), + GDK_CURRENT_TIME); + } + } + + if (has_grab) { + gtk_grab_add (widget); + } else { + gdk_window_destroy (priv->transfer_window); + priv->transfer_window = NULL; + } + } + + /* Make the menu temporary when it's mapped, so it's closed if a + * new window appears */ + gtk_window_set_is_temporary (GTK_WINDOW (widget), TRUE); + + priv->find_intruder_idle_id = gdk_threads_add_idle (hildon_app_menu_find_intruder, widget); +} + +static void +hildon_app_menu_unmap (GtkWidget *widget) +{ + HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE(widget); + + /* Remove the grab */ + if (priv->transfer_window != NULL) { + gdk_display_pointer_ungrab (gtk_widget_get_display (widget), + GDK_CURRENT_TIME); + gtk_grab_remove (widget); + + gdk_window_destroy (priv->transfer_window); + priv->transfer_window = NULL; + } + + GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->unmap (widget); + + gtk_window_set_is_temporary (GTK_WINDOW (widget), FALSE); +} + +static void +hildon_app_menu_grab_notify (GtkWidget *widget, + gboolean was_grabbed) +{ + if (GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->grab_notify) + GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->grab_notify (widget, was_grabbed); + + if (!was_grabbed && GTK_WIDGET_VISIBLE (widget)) + gtk_widget_hide (widget); +} + +static gboolean +hildon_app_menu_hide_idle (gpointer widget) +{ + HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE (widget); + gtk_widget_hide (GTK_WIDGET (widget)); + priv->hide_idle_id = 0; + return FALSE; +} + +/* Send keyboard accelerators to the parent window, if necessary. + * This code is heavily based on gtk_menu_key_press () + */ +static gboolean +hildon_app_menu_key_press (GtkWidget *widget, + GdkEventKey *event) +{ + GtkWindow *parent_window; + HildonAppMenuPrivate *priv; + + g_return_val_if_fail (HILDON_IS_APP_MENU (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + if (GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->key_press_event (widget, event)) + return TRUE; + + priv = HILDON_APP_MENU_GET_PRIVATE (widget); + parent_window = priv->parent_window; + + if (parent_window) { + guint accel_key, accel_mods; + GdkModifierType consumed_modifiers; + GdkDisplay *display; + GSList *accel_groups; + GSList *list; + + display = gtk_widget_get_display (widget); + + /* Figure out what modifiers went into determining the key symbol */ + gdk_keymap_translate_keyboard_state (gdk_keymap_get_for_display (display), + event->hardware_keycode, event->state, event->group, + NULL, NULL, NULL, &consumed_modifiers); + + accel_key = gdk_keyval_to_lower (event->keyval); + accel_mods = event->state & gtk_accelerator_get_default_mod_mask () & ~consumed_modifiers; + + /* If lowercasing affects the keysym, then we need to include SHIFT in the modifiers, + * We re-upper case when we match against the keyval, but display and save in caseless form. + */ + if (accel_key != event->keyval) + accel_mods |= GDK_SHIFT_MASK; + + accel_groups = gtk_accel_groups_from_object (G_OBJECT (parent_window)); + + for (list = accel_groups; list; list = list->next) { + GtkAccelGroup *accel_group = list->data; + + if (gtk_accel_group_query (accel_group, accel_key, accel_mods, NULL)) { + gtk_window_activate_key (parent_window, event); + priv->hide_idle_id = gdk_threads_add_idle (hildon_app_menu_hide_idle, widget); + break; + } + } + } + + return TRUE; +} + +static gboolean +hildon_app_menu_button_press (GtkWidget *widget, + GdkEventButton *event) +{ + int x, y; + HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE(widget); + + gdk_window_get_position (widget->window, &x, &y); + + /* Whether the button has been pressed outside the widget */ + priv->pressed_outside = (event->x_root < x || event->x_root > x + widget->allocation.width || + event->y_root < y || event->y_root > y + widget->allocation.height); + + if (GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->button_press_event) { + return GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->button_press_event (widget, event); + } else { + return FALSE; + } +} + +static gboolean +hildon_app_menu_button_release (GtkWidget *widget, + GdkEventButton *event) +{ + HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE(widget); + + if (priv->pressed_outside) { + int x, y; + gboolean released_outside; + + gdk_window_get_position (widget->window, &x, &y); + + /* Whether the button has been released outside the widget */ + released_outside = (event->x_root < x || event->x_root > x + widget->allocation.width || + event->y_root < y || event->y_root > y + widget->allocation.height); + + if (released_outside) { + gtk_widget_hide (widget); + } + + priv->pressed_outside = FALSE; /* Always reset pressed_outside to FALSE */ + } + + if (GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->button_release_event) { + return GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->button_release_event (widget, event); + } else { + return FALSE; + } +} + +static gboolean +hildon_app_menu_delete_event_handler (GtkWidget *widget, + GdkEventAny *event) +{ + /* Hide the menu if it receives a delete-event, but don't destroy it */ + gtk_widget_hide (widget); + return TRUE; +} + +/* Grab transfer window (based on the one from GtkMenu) */ +static GdkWindow * +grab_transfer_window_get (GtkWidget *widget) +{ + GdkWindow *window; + GdkWindowAttr attributes; + gint attributes_mask; + + attributes.x = 0; + attributes.y = 0; + attributes.width = 10; + attributes.height = 10; + attributes.window_type = GDK_WINDOW_TEMP; + attributes.wclass = GDK_INPUT_ONLY; + attributes.override_redirect = TRUE; + attributes.event_mask = 0; + + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR; + + window = gdk_window_new (gtk_widget_get_root_window (widget), + &attributes, attributes_mask); + gdk_window_set_user_data (window, widget); + + gdk_window_show (window); + + return window; +} + +static void +hildon_app_menu_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE (widget); + + GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->size_request (widget, requisition); + + requisition->width = priv->width_request; +} + +static void +hildon_app_menu_realize (GtkWidget *widget) +{ + Atom property, window_type; + Display *xdisplay; + GdkDisplay *gdkdisplay; + GdkScreen *screen; + + GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->realize (widget); + + gdk_window_set_decorations (widget->window, GDK_DECOR_BORDER); + + gdkdisplay = gdk_drawable_get_display (widget->window); + xdisplay = GDK_WINDOW_XDISPLAY (widget->window); + + property = gdk_x11_get_xatom_by_name_for_display (gdkdisplay, "_NET_WM_WINDOW_TYPE"); + window_type = XInternAtom (xdisplay, "_HILDON_WM_WINDOW_TYPE_APP_MENU", False); + XChangeProperty (xdisplay, GDK_WINDOW_XID (widget->window), property, + XA_ATOM, 32, PropModeReplace, (guchar *) &window_type, 1); + + /* Detect any screen changes */ + screen = gtk_widget_get_screen (widget); + g_signal_connect (screen, "size-changed", G_CALLBACK (screen_size_changed), widget); + + /* Force menu to set the initial layout */ + screen_size_changed (screen, HILDON_APP_MENU (widget)); +} + +static void +hildon_app_menu_unrealize (GtkWidget *widget) +{ + GdkScreen *screen = gtk_widget_get_screen (widget); + /* Disconnect "size-changed" signal handler */ + g_signal_handlers_disconnect_by_func (screen, G_CALLBACK (screen_size_changed), widget); + + GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->unrealize (widget); +} + +static void +hildon_app_menu_apply_style (GtkWidget *widget) +{ + GdkScreen *screen; + guint horizontal_spacing, vertical_spacing, filter_vertical_spacing; + guint inner_border, external_border; + HildonAppMenuPrivate *priv; + + priv = HILDON_APP_MENU_GET_PRIVATE (widget); + + gtk_widget_style_get (widget, + "horizontal-spacing", &horizontal_spacing, + "vertical-spacing", &vertical_spacing, + "filter-vertical-spacing", &filter_vertical_spacing, + "inner-border", &inner_border, + "external-border", &external_border, + NULL); + + /* Set spacings */ + gtk_table_set_row_spacings (priv->table, vertical_spacing); + gtk_table_set_col_spacings (priv->table, horizontal_spacing); + gtk_box_set_spacing (priv->vbox, filter_vertical_spacing); + + /* Set inner border */ + gtk_container_set_border_width (GTK_CONTAINER (widget), inner_border); + + /* Compute width request */ + screen = gtk_widget_get_screen (widget); + if (gdk_screen_get_width (screen) < gdk_screen_get_height (screen)) { + external_border = 0; + } + priv->width_request = gdk_screen_get_width (screen) - external_border * 2; + gtk_window_move (GTK_WINDOW (widget), external_border, 0); + gtk_widget_queue_resize (widget); +} + +static void +hildon_app_menu_style_set (GtkWidget *widget, + GtkStyle *previous_style) +{ + if (GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->style_set) + GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->style_set (widget, previous_style); + + hildon_app_menu_apply_style (widget); +} + +static void +hildon_app_menu_repack_filters (HildonAppMenu *menu) +{ + HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE(menu); + GList *iter; + + for (iter = priv->filters; iter != NULL; iter = iter->next) { + GtkWidget *filter = GTK_WIDGET (iter->data); + GtkWidget *parent = gtk_widget_get_parent (filter); + if (parent) { + g_object_ref (filter); + gtk_container_remove (GTK_CONTAINER (parent), filter); + } + } + + for (iter = priv->filters; iter != NULL; iter = iter->next) { + GtkWidget *filter = GTK_WIDGET (iter->data); + if (GTK_WIDGET_VISIBLE (filter)) { + gtk_box_pack_start (GTK_BOX (priv->filters_hbox), filter, TRUE, TRUE, 0); + g_object_unref (filter); + /* GtkButton must be realized for accelerators to work */ + gtk_widget_realize (filter); + } + } +} + +/* + * When items displayed in the menu change (e.g, a new item is added, + * an item is hidden or the list is reordered), the layout must be + * updated. To do this we repack all items starting from a given one. + */ +static void +hildon_app_menu_repack_items (HildonAppMenu *menu, + gint start_from) +{ + HildonAppMenuPrivate *priv; + gint row, col; + GList *iter; + + priv = HILDON_APP_MENU_GET_PRIVATE(menu); + + /* Remove buttons from their parent */ + if (start_from != -1) { + for (iter = g_list_nth (priv->buttons, start_from); iter != NULL; iter = iter->next) { + GtkWidget *item = GTK_WIDGET (iter->data); + GtkWidget *parent = gtk_widget_get_parent (item); + if (parent) { + g_object_ref (item); + gtk_container_remove (GTK_CONTAINER (parent), item); + } + } + + /* If items have been removed, recalculate the size of the menu */ + gtk_window_resize (GTK_WINDOW (menu), 1, 1); + } + + /* Add buttons */ + row = col = 0; + for (iter = priv->buttons; iter != NULL; iter = iter->next) { + GtkWidget *item = GTK_WIDGET (iter->data); + if (GTK_WIDGET_VISIBLE (item)) { + /* Don't add an item to the table if it's already there */ + if (gtk_widget_get_parent (item) == NULL) { + gtk_table_attach_defaults (priv->table, item, col, col + 1, row, row + 1); + g_object_unref (item); + /* GtkButton must be realized for accelerators to work */ + gtk_widget_realize (item); + } + if (++col == priv->columns) { + col = 0; + row++; + } + } + } + + /* The number of rows/columns might have changed, so we have to + * resize the table */ + if (col == 0) { + gtk_table_resize (priv->table, MAX (row, 1), priv->columns); + } else { + gtk_table_resize (priv->table, row + 1, priv->columns); + } +} + +/** + * hildon_app_menu_popup: + * @menu: a #HildonAppMenu + * @parent_window: a #GtkWindow + * + * Displays a menu on top of a window and makes it available for + * selection. + * + * Since: 2.2 + **/ +void +hildon_app_menu_popup (HildonAppMenu *menu, + GtkWindow *parent_window) +{ + HildonAppMenuPrivate *priv; + gboolean show_menu = FALSE; + GList *i; + + g_return_if_fail (HILDON_IS_APP_MENU (menu)); + g_return_if_fail (GTK_IS_WINDOW (parent_window)); + + priv = HILDON_APP_MENU_GET_PRIVATE (menu); + + /* Don't show menu if it doesn't contain visible items */ + for (i = priv->buttons; i && !show_menu; i = i->next) + show_menu = GTK_WIDGET_VISIBLE (i->data); + + for (i = priv->filters; i && !show_menu; i = i->next) + show_menu = GTK_WIDGET_VISIBLE (i->data); + + if (show_menu) { + hildon_app_menu_set_parent_window (menu, parent_window); + gtk_widget_show (GTK_WIDGET (menu)); + } + +} + +/** + * hildon_app_menu_get_items: + * @menu: a #HildonAppMenu + * + * Returns a list of all items (regular items, not filters) contained + * in @menu. + * + * Returns: a newly-allocated list containing the items in @menu + * + * Since: 2.2 + **/ +GList * +hildon_app_menu_get_items (HildonAppMenu *menu) +{ + HildonAppMenuPrivate *priv; + + g_return_val_if_fail (HILDON_IS_APP_MENU (menu), NULL); + + priv = HILDON_APP_MENU_GET_PRIVATE (menu); + + return g_list_copy (priv->buttons); +} + +/** + * hildon_app_menu_get_filters: + * @menu: a #HildonAppMenu + * + * Returns a list of all filters contained in @menu. + * + * Returns: a newly-allocated list containing the filters in @menu + * + * Since: 2.2 + **/ +GList * +hildon_app_menu_get_filters (HildonAppMenu *menu) +{ + HildonAppMenuPrivate *priv; + + g_return_val_if_fail (HILDON_IS_APP_MENU (menu), NULL); + + priv = HILDON_APP_MENU_GET_PRIVATE (menu); + + return g_list_copy (priv->filters); +} + +static void +hildon_app_menu_init (HildonAppMenu *menu) +{ + GtkWidget *alignment; + HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE(menu); + + /* Initialize private variables */ + priv->parent_window = NULL; + priv->transfer_window = NULL; + priv->pressed_outside = FALSE; + priv->buttons = NULL; + priv->filters = NULL; + priv->columns = 2; + priv->width_request = -1; + priv->find_intruder_idle_id = 0; + priv->hide_idle_id = 0; + + /* Create boxes and tables */ + priv->filters_hbox = GTK_BOX (gtk_hbox_new (TRUE, 0)); + priv->vbox = GTK_BOX (gtk_vbox_new (FALSE, 0)); + priv->table = GTK_TABLE (gtk_table_new (1, priv->columns, TRUE)); + + /* Align the filters to the center */ + alignment = gtk_alignment_new (0.5, 0.5, 0, 0); + gtk_container_add (GTK_CONTAINER (alignment), GTK_WIDGET (priv->filters_hbox)); + + /* Pack everything */ + gtk_container_add (GTK_CONTAINER (menu), GTK_WIDGET (priv->vbox)); + gtk_box_pack_start (priv->vbox, alignment, TRUE, TRUE, 0); + gtk_box_pack_start (priv->vbox, GTK_WIDGET (priv->table), TRUE, TRUE, 0); + + /* Make menu a modal window */ + gtk_window_set_modal (GTK_WINDOW (menu), TRUE); + + /* This should be treated like a normal, ref-counted widget */ + g_object_force_floating (G_OBJECT (menu)); + GTK_WINDOW (menu)->has_user_ref_count = FALSE; + + gtk_widget_show_all (GTK_WIDGET (priv->vbox)); +} + +static void +hildon_app_menu_finalize (GObject *object) +{ + HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE(object); + + if (priv->find_intruder_idle_id) { + g_source_remove (priv->find_intruder_idle_id); + priv->find_intruder_idle_id = 0; + } + + if (priv->hide_idle_id) { + g_source_remove (priv->hide_idle_id); + priv->hide_idle_id = 0; + } + + if (priv->parent_window) { + g_signal_handlers_disconnect_by_func (priv->parent_window, parent_window_topmost_notify, object); + g_signal_handlers_disconnect_by_func (priv->parent_window, parent_window_unmapped, object); + } + + if (priv->transfer_window) + gdk_window_destroy (priv->transfer_window); + + g_list_foreach (priv->buttons, (GFunc) g_object_unref, NULL); + g_list_foreach (priv->filters, (GFunc) g_object_unref, NULL); + + g_list_free (priv->buttons); + g_list_free (priv->filters); + + g_signal_handlers_destroy (object); + G_OBJECT_CLASS (hildon_app_menu_parent_class)->finalize (object); +} + +static void +hildon_app_menu_class_init (HildonAppMenuClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass *)klass; + GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; + + gobject_class->finalize = hildon_app_menu_finalize; + widget_class->show_all = hildon_app_menu_show_all; + widget_class->hide_all = hildon_app_menu_hide_all; + widget_class->map = hildon_app_menu_map; + widget_class->unmap = hildon_app_menu_unmap; + widget_class->realize = hildon_app_menu_realize; + widget_class->unrealize = hildon_app_menu_unrealize; + widget_class->grab_notify = hildon_app_menu_grab_notify; + widget_class->key_press_event = hildon_app_menu_key_press; + widget_class->button_press_event = hildon_app_menu_button_press; + widget_class->button_release_event = hildon_app_menu_button_release; + widget_class->style_set = hildon_app_menu_style_set; + widget_class->delete_event = hildon_app_menu_delete_event_handler; + widget_class->size_request = hildon_app_menu_size_request; + + g_type_class_add_private (klass, sizeof (HildonAppMenuPrivate)); + + gtk_widget_class_install_style_property ( + widget_class, + g_param_spec_uint ( + "horizontal-spacing", + "Horizontal spacing on menu items", + "Horizontal spacing between each menu item. Does not apply to filter buttons.", + 0, G_MAXUINT, 16, + G_PARAM_READABLE)); + + gtk_widget_class_install_style_property ( + widget_class, + g_param_spec_uint ( + "vertical-spacing", + "Vertical spacing on menu items", + "Vertical spacing between each menu item. Does not apply to filter buttons.", + 0, G_MAXUINT, 16, + G_PARAM_READABLE)); + + gtk_widget_class_install_style_property ( + widget_class, + g_param_spec_uint ( + "filter-vertical-spacing", + "Vertical spacing between filters and menu items", + "Vertical spacing between filters and menu items", + 0, G_MAXUINT, 8, + G_PARAM_READABLE)); + + gtk_widget_class_install_style_property ( + widget_class, + g_param_spec_uint ( + "inner-border", + "Border between menu edges and buttons", + "Border between menu edges and buttons", + 0, G_MAXUINT, 16, + G_PARAM_READABLE)); + + gtk_widget_class_install_style_property ( + widget_class, + g_param_spec_uint ( + "external-border", + "Border between menu and screen edges (in horizontal mode)", + "Border between the right and left edges of the menu and " + "the screen edges (in horizontal mode)", + 0, G_MAXUINT, 50, + G_PARAM_READABLE)); +} diff --git a/hildon/hildon-app-menu.h b/hildon/hildon-app-menu.h new file mode 100644 index 0000000..f0a20bb --- /dev/null +++ b/hildon/hildon-app-menu.h @@ -0,0 +1,103 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +#ifndef __HILDON_APP_MENU_H__ +#define __HILDON_APP_MENU_H__ + +#include + +G_BEGIN_DECLS + +#define HILDON_TYPE_APP_MENU \ + (hildon_app_menu_get_type()) + +#define HILDON_APP_MENU(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + HILDON_TYPE_APP_MENU, HildonAppMenu)) + +#define HILDON_APP_MENU_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + HILDON_TYPE_APP_MENU, HildonAppMenuClass)) + +#define HILDON_IS_APP_MENU(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_APP_MENU)) + +#define HILDON_IS_APP_MENU_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_APP_MENU)) + +#define HILDON_APP_MENU_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + HILDON_TYPE_APP_MENU, HildonAppMenuClass)) + +typedef struct _HildonAppMenu HildonAppMenu; + +typedef struct _HildonAppMenuClass HildonAppMenuClass; + +typedef struct _HildonAppMenuPrivate HildonAppMenuPrivate; + +struct _HildonAppMenuClass +{ + GtkWindowClass parent_class; +}; + +struct _HildonAppMenu +{ + GtkWindow parent; +}; + +GType +hildon_app_menu_get_type (void) G_GNUC_CONST; + +GtkWidget * +hildon_app_menu_new (void); + +void +hildon_app_menu_append (HildonAppMenu *menu, + GtkButton *item); + +void +hildon_app_menu_prepend (HildonAppMenu *menu, + GtkButton *item); + +void +hildon_app_menu_insert (HildonAppMenu *menu, + GtkButton *item, + gint position); + +void +hildon_app_menu_reorder_child (HildonAppMenu *menu, + GtkButton *item, + gint position); + +void +hildon_app_menu_add_filter (HildonAppMenu *menu, + GtkButton *filter); + +void +hildon_app_menu_popup (HildonAppMenu *menu, + GtkWindow *parent_window); + +GList * +hildon_app_menu_get_items (HildonAppMenu *menu); + +GList * +hildon_app_menu_get_filters (HildonAppMenu *menu); + +G_END_DECLS + +#endif /* __HILDON_APP_MENU_H__ */ diff --git a/hildon/hildon-banner-private.h b/hildon/hildon-banner-private.h new file mode 100644 index 0000000..8f4f581 --- /dev/null +++ b/hildon/hildon-banner-private.h @@ -0,0 +1,55 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_PRIVATE_H__ +#define __HILDON_BANNER_PRIVATE_H__ + +G_BEGIN_DECLS + +typedef struct _HildonBannerPrivate HildonBannerPrivate; + +#define HILDON_BANNER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_BANNER, HildonBannerPrivate)); + +struct _HildonBannerPrivate +{ + GtkWidget *main_item; + GtkWidget *label; + GtkWidget *layout; + guint timeout_id; + guint is_timed : 1, has_been_wrapped : 1, has_been_truncated : 1; + guint timeout; + GtkWindow *parent; +}; + +/* For internal use of hildon libraries only */ +void G_GNUC_INTERNAL +hildon_gtk_label_set_text_n_lines (GtkLabel *label, + const gchar *text, + gint max_lines); + +G_END_DECLS + +#endif /* __HILDON_BANNER_PRIVATE_H__ */ diff --git a/hildon/hildon-banner.c b/hildon/hildon-banner.c new file mode 100644 index 0000000..0d65edc --- /dev/null +++ b/hildon/hildon-banner.c @@ -0,0 +1,1238 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006, 2007 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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-banner + * @short_description: A widget used to display timed notifications. + * + * #HildonBanner is a small, pop-up window that can be used to display + * a short, timed notification or information to the user. It can + * communicate that a task has been finished or that the application + * state has changed. + * + * Hildon provides convenient funtions to create and show banners. To + * create and show information banners you can use + * hildon_banner_show_information(), hildon_banner_show_informationf() + * or hildon_banner_show_information_with_markup(). + * + * Two more kinds of banners are maintained for backward compatibility + * but are no longer recommended in Hildon 2.2. These are the animated + * banner (created with hildon_banner_show_animation()) and the + * progress banner (created with hildon_banner_show_progress()). See + * hildon_gtk_window_set_progress_indicator() for the preferred way of + * showing progress notifications in Hildon 2.2. + * + * Information banners dissapear automatically after a certain + * period. This is stored in the #HildonBanner:timeout property (in + * miliseconds), and can be changed using hildon_banner_set_timeout(). + * + * Note that #HildonBanners should only be used to display + * non-critical pieces of information. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#undef HILDON_DISABLE_DEPRECATED + +#include "hildon-banner.h" +#include "hildon-banner-private.h" +#include "hildon-defines.h" + +/* position relative to the screen */ + +#define HILDON_BANNER_WINDOW_X 0 + +#define HILDON_BANNER_WINDOW_Y HILDON_WINDOW_TITLEBAR_HEIGHT + +/* max widths */ + +#define HILDON_BANNER_PROGRESS_WIDTH 104 + +#define HILDON_BANNER_LABEL_MAX_TIMED \ + (800 - ((HILDON_MARGIN_TRIPLE) * 2)) + +#define HILDON_BANNER_LABEL_MAX_PROGRESS 375 /*265*/ + +/* default timeout */ + +#define HILDON_BANNER_DEFAULT_TIMEOUT 3000 + +/* default icons */ + +#define HILDON_BANNER_DEFAULT_PROGRESS_ANIMATION "indicator_update" + +/* animation related stuff */ + +#define HILDON_BANNER_ANIMATION_FRAMERATE ((float)1000/150) + +#define HILDON_BANNER_ANIMATION_TMPL "indicator_update%d" + +#define HILDON_BANNER_ANIMATION_NFRAMES 8 + +enum +{ + PROP_0, + PROP_PARENT_WINDOW, + PROP_IS_TIMED, + PROP_TIMEOUT +}; + +static GtkWidget* global_timed_banner = NULL; + +static GQuark +hildon_banner_timed_quark (void); + +static void +hildon_banner_bind_style (HildonBanner *self, + const gchar *name); + +static gboolean +hildon_banner_timeout (gpointer data); + +static gboolean +hildon_banner_clear_timeout (HildonBanner *self); + +static void +hildon_banner_ensure_timeout (HildonBanner *self); + +static void +hildon_banner_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); + +static void +hildon_banner_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +static void +hildon_banner_destroy (GtkObject *object); + +static GObject* +hildon_banner_real_get_instance (GObject *window, + gboolean timed); + +static GObject* +hildon_banner_constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params); + +static void +hildon_banner_finalize (GObject *object); + +static gboolean +hildon_banner_button_press_event (GtkWidget* widget, + GdkEventButton* event); + +static gboolean +hildon_banner_map_event (GtkWidget *widget, + GdkEventAny *event); +static void +hildon_banner_reset_wrap_state (HildonBanner *banner); + +static void +force_to_wrap_truncated (HildonBanner *banner); + +static void +hildon_banner_check_position (GtkWidget *widget); + +static void +hildon_banner_realize (GtkWidget *widget); + +static void +hildon_banner_class_init (HildonBannerClass *klass); + +static void +hildon_banner_init (HildonBanner *self); + +static void +hildon_banner_ensure_child (HildonBanner *self, + GtkWidget *user_widget, + guint pos, + GType type, + const gchar *first_property, + ...); + +static HildonBanner* +hildon_banner_get_instance_for_widget (GtkWidget *widget, + gboolean timed); + +G_DEFINE_TYPE (HildonBanner, hildon_banner, GTK_TYPE_WINDOW) + +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 widget and label name to make the correct rc-style attached into them */ +static void +hildon_banner_bind_style (HildonBanner *self, + const gchar *name_sufix) +{ + HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self); + gchar *name; + + g_assert (priv); + + name = g_strconcat ("HildonBannerLabel-", name_sufix, NULL); + gtk_widget_set_name (priv->label, name); + g_free (name); + + name = g_strconcat ("HildonBanner-", name_sufix, NULL); + gtk_widget_set_name (GTK_WIDGET (self), name); + g_free (name); +} + +/* In timeout function we automatically destroy timed banners */ +static gboolean +simulate_close (GtkWidget* widget) +{ + gboolean result = FALSE; + + /* 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)) + { + GdkEvent *event = gdk_event_new (GDK_DELETE); + event->any.window = g_object_ref (widget->window); + event->any.send_event = FALSE; + result = gtk_widget_event (widget, event); + gdk_event_free (event); + } + + return result; +} + +static gboolean +hildon_banner_timeout (gpointer data) +{ + GtkWidget *widget; + gboolean continue_timeout = FALSE; + + GDK_THREADS_ENTER (); + + g_assert (HILDON_IS_BANNER (data)); + + widget = GTK_WIDGET (data); + g_object_ref (widget); + + continue_timeout = simulate_close (widget); + + if (! continue_timeout) { + HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (data); + priv->timeout_id = 0; + gtk_widget_destroy (widget); + } + + g_object_unref (widget); + + GDK_THREADS_LEAVE (); + + return continue_timeout; +} + +static gboolean +hildon_banner_clear_timeout (HildonBanner *self) +{ + HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self); + g_assert (priv); + + if (priv->timeout_id != 0) { + g_source_remove (priv->timeout_id); + priv->timeout_id = 0; + return TRUE; + } + + return FALSE; +} + +static void +hildon_banner_ensure_timeout (HildonBanner *self) +{ + HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self); + g_assert (priv); + + if (priv->timeout_id == 0 && priv->is_timed && priv->timeout > 0) + priv->timeout_id = g_timeout_add (priv->timeout, + hildon_banner_timeout, self); +} + +static void +hildon_banner_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GtkWidget *window; + HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object); + g_assert (priv); + + switch (prop_id) { + + case PROP_TIMEOUT: + priv->timeout = g_value_get_uint (value); + break; + + case PROP_IS_TIMED: + priv->is_timed = g_value_get_boolean (value); + break; + + case PROP_PARENT_WINDOW: + window = g_value_get_object (value); + if (priv->parent) { + g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent); + } + + gtk_window_set_transient_for (GTK_WINDOW (object), (GtkWindow *) window); + priv->parent = (GtkWindow *) window; + + if (window) { + gtk_window_set_destroy_with_parent (GTK_WINDOW (object), TRUE); + g_object_add_weak_pointer(G_OBJECT (window), (gpointer) &priv->parent); + } + + 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) +{ + HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object); + g_assert (priv); + + switch (prop_id) + { + case PROP_TIMEOUT: + g_value_set_uint (value, priv->timeout); + break; + + case PROP_IS_TIMED: + g_value_set_boolean (value, 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) +{ + HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object); + g_assert (priv); + + HildonBanner *self; + GObject *parent_window = (GObject *) priv->parent; + + 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 (priv->is_timed && parent_window != 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) +{ + 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); + hildon_banner_reset_wrap_state (HILDON_BANNER (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; +} + +static void +hildon_banner_finalize (GObject *object) +{ + HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object); + + if (priv->parent) { + g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent); + } + + G_OBJECT_CLASS (hildon_banner_parent_class)->finalize (object); +} + +static gboolean +hildon_banner_button_press_event (GtkWidget* widget, + GdkEventButton* event) +{ + gboolean result = simulate_close (widget); + + if (!result) { + /* signal emission not stopped - basically behave like + * gtk_main_do_event() for a delete event, but just hide the + * banner instead of destroying it, as it is already meant to + * be destroyed by hildon_banner_timeout() (if it's timed) or + * the application (if it's not). */ + gtk_widget_hide (widget); + } + + return result; +} + +#if defined(MAEMO_GTK) +static void +hildon_banner_map (GtkWidget *widget) +{ + if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map) { + /* Make the banner temporary _before_ mapping it, to avoid closing + * other temporary windows */ + gtk_window_set_is_temporary (GTK_WINDOW (widget), TRUE); + + GTK_WIDGET_CLASS (hildon_banner_parent_class)->map (widget); + + /* Make the banner non-temporary _after_ mapping it, to avoid + * being closed by other non-temporary windows */ + gtk_window_set_is_temporary (GTK_WINDOW (widget), FALSE); + + hildon_banner_check_position (widget); + } +} +#endif + +/* 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; +} + +static void +hildon_banner_reset_wrap_state (HildonBanner *banner) +{ + PangoLayout *layout; + HildonBannerPrivate *priv; + + priv = HILDON_BANNER_GET_PRIVATE (banner); + g_assert (priv); + + layout = gtk_label_get_layout (GTK_LABEL (priv->label)); + + pango_layout_set_width (layout, -1); + priv->has_been_wrapped = FALSE; + priv->has_been_truncated = FALSE; + + gtk_widget_set_size_request (priv->label, -1, -1); + gtk_widget_set_size_request (GTK_WIDGET (banner), -1, -1); +} + +/* 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; + int height = -1; + PangoRectangle logical; + GtkRequisition requisition; + HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (banner); + + g_return_if_fail (priv); + + label = GTK_LABEL (priv->label); + + layout = gtk_label_get_layout (label); + + pango_layout_get_extents (layout, NULL, &logical); + width_text = PANGO_PIXELS (logical.width); + + width_max = priv->is_timed ? HILDON_BANNER_LABEL_MAX_TIMED + : HILDON_BANNER_LABEL_MAX_PROGRESS; + + /* If the width of the label is going to exceed the maximum allowed + * width, enforce the maximum allowed width now. + */ + if (priv->has_been_wrapped + || width_text >= width_max + || pango_layout_is_wrapped (layout)) { + /* Force wrapping by setting the maximum size */ + width = width_max; + + priv->has_been_wrapped = TRUE; + } + + /* Make the label update its layout; and update our layout pointer + * because the layout will be cleared and refreshed. + */ + gtk_widget_set_size_request (GTK_WIDGET (label), width, height); + gtk_widget_size_request (GTK_WIDGET (label), &requisition); + + layout = gtk_label_get_layout (label); + + /* If the layout has now been wrapped and exceeds 3 lines, we truncate + * the rest of the label according to spec. + */ + if (priv->has_been_truncated + || (pango_layout_is_wrapped (layout) + && pango_layout_get_line_count (layout) > 3)) { + int lines; + + pango_layout_get_extents (layout, NULL, &logical); + lines = pango_layout_get_line_count (layout); + + /* This calculation assumes that the same font is used + * throughout the banner -- this is usually the case on maemo + * + * FIXME: Pango >= 1.20 has pango_layout_set_height(). + */ + height = (PANGO_PIXELS (logical.height) * 3) / lines + 1; + priv->has_been_truncated = TRUE; + } + + /* Set the new width/height if applicable */ + gtk_widget_set_size_request (GTK_WIDGET (label), width, height); +} + + +static void +hildon_banner_check_position (GtkWidget *widget) +{ + gint x, y; + GtkRequisition req; + + gtk_widget_set_size_request (widget, gdk_screen_width (), -1); + + 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 = HILDON_BANNER_WINDOW_X; + + y = HILDON_BANNER_WINDOW_Y; + + gtk_window_move (GTK_WINDOW (widget), x, y); +} + +static void +hildon_banner_realize (GtkWidget *widget) +{ + GdkWindow *gdkwin; + GdkAtom atom; + guint32 portrait = 1; + const gchar *notification_type = "_HILDON_NOTIFICATION_TYPE_BANNER"; + HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (widget); + g_assert (priv); + + /* 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_NOTIFICATION); + gtk_window_set_transient_for (GTK_WINDOW (widget), (GtkWindow *) priv->parent); + + hildon_banner_check_position (widget); + + gdkwin = widget->window; + + /* Set the _HILDON_NOTIFICATION_TYPE property so Matchbox places the window correctly */ + atom = gdk_atom_intern ("_HILDON_NOTIFICATION_TYPE", FALSE); + gdk_property_change (gdkwin, atom, gdk_x11_xatom_to_atom (XA_STRING), 8, GDK_PROP_MODE_REPLACE, + (gpointer) notification_type, strlen (notification_type)); + + /* HildonBanner supports portrait mode */ + atom = gdk_atom_intern ("_HILDON_PORTRAIT_MODE_SUPPORT", FALSE); + gdk_property_change (gdkwin, atom, gdk_x11_xatom_to_atom (XA_CARDINAL), 32, + GDK_PROP_MODE_REPLACE, (gpointer) &portrait, 1); +} + +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->finalize = hildon_banner_finalize; + 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; + widget_class->button_press_event = hildon_banner_button_press_event; +#if defined(MAEMO_GTK) + widget_class->map = hildon_banner_map; +#endif + + /* Install properties. + We need construct properties for singleton purposes */ + + /** + * HildonBanner:parent-window: + * + * The window for which the banner will be singleton. + * + */ + 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)); + + /** + * HildonBanner:is-timed: + * + * Whether the banner is timed and goes away automatically. + * + */ + 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)); + + /** + * HildonBanner:timeout: + * + * The time before making the banner banner go away. This needs + * to be adjusted before the banner is mapped to the screen. + * + */ + g_object_class_install_property (object_class, PROP_TIMEOUT, + g_param_spec_uint ("timeout", + "Timeout", + "The time before making the banner banner go away", + 0, + 10000, + HILDON_BANNER_DEFAULT_TIMEOUT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +} + +static void +hildon_banner_init (HildonBanner *self) +{ + HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self); + g_assert (priv); + + priv->parent = NULL; + + /* Initialize the common layout inside banner */ + 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_label_set_line_wrap_mode (GTK_LABEL (priv->label), PANGO_WRAP_WORD_CHAR); + + gtk_container_set_border_width (GTK_CONTAINER (priv->layout), HILDON_MARGIN_DEFAULT); + gtk_container_add (GTK_CONTAINER (self), priv->layout); + gtk_box_pack_start (GTK_BOX (priv->layout), priv->label, TRUE, TRUE, 0); + + gtk_window_set_accept_focus (GTK_WINDOW (self), FALSE); + + hildon_banner_reset_wrap_state (self); + + gtk_widget_add_events (GTK_WIDGET (self), GDK_BUTTON_PRESS_MASK); +} + +/* 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; + HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self); + + g_assert (priv); + + widget = 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 (priv->layout), widget); + + /* Use user provided widget or create a new one */ + priv->main_item = widget = user_widget ? + user_widget : GTK_WIDGET (g_object_new_valist(type, first_property, args)); + gtk_box_pack_start (GTK_BOX (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 (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; + + 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); +} + +static GtkWidget * +hildon_banner_create_animation (void) +{ + GtkWidget *image; + GdkPixbufSimpleAnim *anim; + GdkPixbuf *frame; + GtkIconTheme *theme; + GError *error = NULL; + gchar *icon_name; + gint i; + + anim = gdk_pixbuf_simple_anim_new (HILDON_ICON_PIXEL_SIZE_STYLUS, + HILDON_ICON_PIXEL_SIZE_STYLUS, + HILDON_BANNER_ANIMATION_FRAMERATE); + gdk_pixbuf_simple_anim_set_loop (anim, TRUE); + theme = gtk_icon_theme_get_default (); + + for (i = 1; i <= HILDON_BANNER_ANIMATION_NFRAMES; i++) { + icon_name = g_strdup_printf (HILDON_BANNER_ANIMATION_TMPL, i); + frame = gtk_icon_theme_load_icon (theme, icon_name, HILDON_ICON_PIXEL_SIZE_STYLUS, + 0, &error); + + if (error) { + g_warning ("Icon theme lookup for icon `%s' failed: %s", + icon_name, error->message); + g_error_free (error); + error = NULL; + } else { + gdk_pixbuf_simple_anim_add_frame (anim, frame); + } + + g_object_unref (frame); + g_free (icon_name); + } + + image = gtk_image_new_from_animation (GDK_PIXBUF_ANIMATION (anim)); + g_object_unref (anim); + + return image; +} + +/** + * hildon_banner_show_information: + * @widget: the #GtkWidget that is the owner of the banner + * @icon_name: since Hildon 2.2 this parameter is not used anymore and + * any value that you pass will be ignored + * @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. + * + * Returns: The newly created banner + * + */ +GtkWidget* +hildon_banner_show_information (GtkWidget *widget, + const gchar *icon_name, + const gchar *text) +{ + HildonBanner *banner; + + g_return_val_if_fail (text != NULL, NULL); + + /* Prepare banner */ + banner = hildon_banner_get_instance_for_widget (widget, TRUE); + + hildon_banner_set_text (banner, text); + hildon_banner_bind_style (banner, "information"); + + /* Show the banner, since caller cannot do that */ + gtk_widget_show_all (GTK_WIDGET (banner)); + + return (GtkWidget *) banner; +} + +/** + * hildon_banner_show_informationf: + * @widget: the #GtkWidget that is the owner of the banner + * @icon_name: since Hildon 2.2 this parameter is not used anymore and + * any value that you pass will be ignored + * @format: a printf-like format string + * @Varargs: arguments for the format string + * + * A helper function for #hildon_banner_show_information with + * string formatting. + * + * Returns: the newly created banner + */ +GtkWidget* +hildon_banner_show_informationf (GtkWidget *widget, + const gchar *icon_name, + const gchar *format, + ...) +{ + g_return_val_if_fail (format != NULL, NULL); + + gchar *message; + va_list args; + GtkWidget *banner; + + va_start (args, format); + message = g_strdup_vprintf (format, args); + va_end (args); + + banner = hildon_banner_show_information (widget, icon_name, message); + + g_free (message); + + return banner; +} + +/** + * hildon_banner_show_information_with_markup: + * @widget: the #GtkWidget that wants to display banner + * @icon_name: since Hildon 2.2 this parameter is not used anymore and + * any value that you pass will be ignored + * @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. + * + * Returns: the newly created banner + * + */ +GtkWidget* +hildon_banner_show_information_with_markup (GtkWidget *widget, + const gchar *icon_name, + const gchar *markup) +{ + HildonBanner *banner; + + g_return_val_if_fail (icon_name == NULL || icon_name[0] != 0, NULL); + g_return_val_if_fail (markup != NULL, NULL); + + /* Prepare banner */ + banner = hildon_banner_get_instance_for_widget (widget, TRUE); + + hildon_banner_set_markup (banner, markup); + hildon_banner_bind_style (banner, "information"); + + /* Show the banner, since caller cannot do that */ + gtk_widget_show_all (GTK_WIDGET (banner)); + + return (GtkWidget *) banner; +} + +/** + * hildon_banner_show_animation: + * @widget: the #GtkWidget that wants to display banner + * @animation_name: since Hildon 2.2 this parameter is not used + * anymore and any value that you pass will be + * ignored + * @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 does 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 does not disappear + * automatically, you can separately ref the return value (this + * doesn't prevent the banner from disappearing, just the object from + * being 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 done with the banner. + * + * Deprecated: Hildon 2.2: use + * hildon_gtk_window_set_progress_indicator() instead. + */ +GtkWidget* +hildon_banner_show_animation (GtkWidget *widget, + const gchar *animation_name, + const gchar *text) +{ + HildonBanner *banner; + GtkWidget *image_widget; + + g_return_val_if_fail (text != NULL, NULL); + + image_widget = hildon_banner_create_animation (); + + /* 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_style (banner, "animation"); + + /* And show it */ + gtk_widget_show_all (GTK_WIDGET (banner)); + + return (GtkWidget *) 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 done with the banner. + * + * Deprecated: Hildon 2.2: use hildon_gtk_window_set_progress_indicator() instead. + */ +GtkWidget* +hildon_banner_show_progress (GtkWidget *widget, + GtkProgressBar *bar, + const gchar *text) +{ + HildonBanner *banner; + HildonBannerPrivate *priv; + + 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); + priv = HILDON_BANNER_GET_PRIVATE (banner); + g_assert (priv); + hildon_banner_ensure_child (banner, (GtkWidget *) bar, -1, GTK_TYPE_PROGRESS_BAR, NULL); + + gtk_widget_set_size_request (priv->main_item, + HILDON_BANNER_PROGRESS_WIDTH, -1); + + hildon_banner_set_text (banner, text); + hildon_banner_bind_style (banner, "progress"); + + /* 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. + * + */ +void +hildon_banner_set_text (HildonBanner *self, + const gchar *text) +{ + GtkLabel *label; + HildonBannerPrivate *priv; + const gchar *existing_text; + + g_return_if_fail (HILDON_IS_BANNER (self)); + + priv = HILDON_BANNER_GET_PRIVATE (self); + g_assert (priv); + + label = GTK_LABEL (priv->label); + existing_text = gtk_label_get_text (label); + + if (existing_text != NULL && + text != NULL && + strcmp (existing_text, text) != 0) { + gtk_label_set_text (label, text); + hildon_banner_reset_wrap_state (self); + } + + 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. + * + */ +void +hildon_banner_set_markup (HildonBanner *self, + const gchar *markup) +{ + GtkLabel *label; + HildonBannerPrivate *priv; + + g_return_if_fail (HILDON_IS_BANNER (self)); + + priv = HILDON_BANNER_GET_PRIVATE (self); + g_assert (priv); + + label = GTK_LABEL (priv->label); + gtk_label_set_markup (label, markup); + + hildon_banner_reset_wrap_state (self); + + 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. + * + * Note that this method only has effect if @self was created with + * hildon_banner_show_progress() + * + */ +void +hildon_banner_set_fraction (HildonBanner *self, + gdouble fraction) +{ + HildonBannerPrivate *priv; + + g_return_if_fail (HILDON_IS_BANNER (self)); + priv = HILDON_BANNER_GET_PRIVATE (self); + g_assert (priv); + + g_return_if_fail (GTK_IS_PROGRESS_BAR (priv->main_item)); + gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->main_item), fraction); +} + +/** + * hildon_banner_set_timeout: + * @self: a #HildonBanner widget + * @timeout: timeout to set in miliseconds. + * + * Sets the timeout on the banner. After the given amount of miliseconds + * has elapsed the banner will go away. Note that settings this only makes + * sense on the banners that are timed and that have not been yet displayed + * on the screen. + * + * Note that this method only has effect if @self is an information + * banner (created using hildon_banner_show_information() and + * friends). + */ +void +hildon_banner_set_timeout (HildonBanner *self, + guint timeout) +{ + HildonBannerPrivate *priv; + + g_return_if_fail (HILDON_IS_BANNER (self)); + priv = HILDON_BANNER_GET_PRIVATE (self); + g_assert (priv); + + priv->timeout = timeout; +} + +/** + * hildon_banner_set_icon: + * @self: a #HildonBanner widget + * @icon_name: the name of icon to use. Can be %NULL for default icon + * + * Sets the icon to be used in the banner. + * + * Deprecated: This function does nothing. As of hildon 2.2, hildon + * banners don't allow changing their icons. + */ +void +hildon_banner_set_icon (HildonBanner *self, + const gchar *icon_name) +{ +} + +/** + * hildon_banner_set_icon_from_file: + * @self: a #HildonBanner widget + * @icon_file: the filename of icon to use. Can be %NULL for default icon + * + * Sets the icon from its filename to be used in the banner. + * + * Deprecated: This function does nothing. As of hildon 2.2, hildon + * banners don't allow changing their icons. + */ +void +hildon_banner_set_icon_from_file (HildonBanner *self, + const gchar *icon_file) +{ +} diff --git a/hildon/hildon-banner.h b/hildon/hildon-banner.h new file mode 100644 index 0000000..bdd16a5 --- /dev/null +++ b/hildon/hildon-banner.h @@ -0,0 +1,116 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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 + +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; + +struct _HildonBanner +{ + GtkWindow parent; +}; + +struct _HildonBannerClass +{ + GtkWindowClass parent_class; +}; + +GType G_GNUC_CONST +hildon_banner_get_type (void); + +GtkWidget* +hildon_banner_show_information (GtkWidget *widget, + const gchar *icon_name, + const gchar *text); + +GtkWidget* +hildon_banner_show_informationf (GtkWidget *widget, + const gchar *icon_name, + const gchar *format, + ...); + +GtkWidget* +hildon_banner_show_information_with_markup (GtkWidget *widget, + const gchar *icon_name, + const gchar *markup); + +#ifndef HILDON_DISABLE_DEPRECATED +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); +#endif /* HILDON_DISABLE_DEPRECATED */ + +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); + +#ifndef HILDON_DISABLE_DEPRECATED +void +hildon_banner_set_icon (HildonBanner *self, + const gchar *icon_name); + +void +hildon_banner_set_icon_from_file (HildonBanner *self, + const gchar *icon_file); +#endif /* HILDON_DISABLE_DEPRECATED */ + +void +hildon_banner_set_timeout (HildonBanner *self, + guint timeout); + +G_END_DECLS + +#endif /* __HILDON_BANNER_H__ */ diff --git a/hildon/hildon-bread-crumb-trail.c b/hildon/hildon-bread-crumb-trail.c new file mode 100644 index 0000000..5ed23e0 --- /dev/null +++ b/hildon/hildon-bread-crumb-trail.c @@ -0,0 +1,791 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2007 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * Author: Xan Lopez + * + * 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, or (at your option) any later version. + * + * 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-bread-crumb-trail + * @short_description: Widget used to represent a specific path in a hierarchical tree. + * Stability: Unstable + * + * HildonBreadCrumbTrail is a GTK widget used to represent the currently active path in + * some kind of hierarchical structure (file system, media library, structured document, etc). + * + * It has built-in support for text and icon bread crumbs, but the trail only requires a very + * simple interface to be implemented for its children and thus new types of items can be + * implemented if needed. See #HildonBreadCrumb for more details. + */ + +#undef HILDON_DISABLE_DEPRECATED + +#include + +#include "hildon-marshalers.h" +#include "hildon-bread-crumb-trail.h" +#include "hildon-bread-crumb-widget.h" + +#define HILDON_BREAD_CRUMB_TRAIL_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_BREAD_CRUMB_TRAIL, HildonBreadCrumbTrailPrivate)) + +struct _HildonBreadCrumbTrailPrivate +{ + GtkWidget *back_button; + GList *item_list; + GtkWidget *arrow; +}; + +/* Signals */ + +enum { + CRUMB_CLICKED, + MOVE_PARENT, + LAST_SIGNAL +}; + +/* Properties */ + +enum { + PROP_0 +}; + +static void hildon_bread_crumb_trail_size_request (GtkWidget *widget, + GtkRequisition *requisition); +static void hildon_bread_crumb_trail_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); +static void hildon_bread_crumb_trail_add (GtkContainer *container, + GtkWidget *widget); +static void hildon_bread_crumb_trail_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data); +static void hildon_bread_crumb_trail_remove (GtkContainer *container, + GtkWidget *widget); +static void hildon_bread_crumb_trail_finalize (GObject *object); +static void hildon_bread_crumb_trail_scroll_back (GtkWidget *button, + HildonBreadCrumbTrail *bct); +static void hildon_bread_crumb_trail_update_back_button_sensitivity (HildonBreadCrumbTrail *bct); +static void hildon_bread_crumb_trail_move_parent (HildonBreadCrumbTrail *bct); + +static gpointer get_bread_crumb_id (HildonBreadCrumb *item); + +static guint bread_crumb_trail_signals[LAST_SIGNAL] = { 0 }; + +/* GType methods */ + +G_DEFINE_TYPE (HildonBreadCrumbTrail, hildon_bread_crumb_trail, GTK_TYPE_CONTAINER) + +static void +hildon_bread_crumb_trail_class_init (HildonBreadCrumbTrailClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass*)klass; + GtkObjectClass *object_class = (GtkObjectClass*)klass; + GtkWidgetClass *widget_class = (GtkWidgetClass*)klass; + GtkContainerClass *container_class = (GtkContainerClass*)klass; + GtkBindingSet *binding_set; + + /* GObject signals */ + gobject_class->finalize = hildon_bread_crumb_trail_finalize; + + /* GtkWidget signals */ + widget_class->size_request = hildon_bread_crumb_trail_size_request; + widget_class->size_allocate = hildon_bread_crumb_trail_size_allocate; + + /* GtkContainer signals */ + container_class->add = hildon_bread_crumb_trail_add; + container_class->forall = hildon_bread_crumb_trail_forall; + container_class->remove = hildon_bread_crumb_trail_remove; + + /* HildonBreadCrumbTrail signals */ + klass->move_parent = hildon_bread_crumb_trail_move_parent; + + /* Style properties */ + +#define _BREAD_CRUMB_TRAIL_MINIMUM_WIDTH 10 + + /* FIXME: is this the best way to do it? */ + gtk_widget_class_install_style_property (widget_class, + g_param_spec_int ("minimum-width", + "Minimum width", + "The minimum width in characters the children widgets will request", + 0, + G_MAXINT, + _BREAD_CRUMB_TRAIL_MINIMUM_WIDTH, + G_PARAM_READABLE)); + +#define _BREAD_CRUMB_TRAIL_ARROW_SIZE 34 + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_int ("arrow-size", + "Arrow size", + "Size of the back button arrow", + 0, + G_MAXINT, + _BREAD_CRUMB_TRAIL_ARROW_SIZE, + G_PARAM_READABLE)); + /* Signals */ + bread_crumb_trail_signals[CRUMB_CLICKED] = + g_signal_new ("crumb-clicked", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (HildonBreadCrumbTrailClass, crumb_clicked), + g_signal_accumulator_true_handled, NULL, + _hildon_marshal_BOOLEAN__POINTER, + G_TYPE_BOOLEAN, 1, + G_TYPE_POINTER); + + bread_crumb_trail_signals[MOVE_PARENT] = + g_signal_new ("move-parent", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (HildonBreadCrumbTrailClass, move_parent), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + + /* Binding set */ + binding_set = gtk_binding_set_by_class (widget_class); + + gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0, + "move-parent", 0); + gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, 0, + "move-parent", 0); + + /* Private data */ + g_type_class_add_private (gobject_class, sizeof (HildonBreadCrumbTrailPrivate)); +} + +static void +hildon_bread_crumb_trail_finalize (GObject *object) +{ + HildonBreadCrumbTrailPrivate *priv = HILDON_BREAD_CRUMB_TRAIL (object)->priv; + + g_list_free (priv->item_list); + + G_OBJECT_CLASS (hildon_bread_crumb_trail_parent_class)->finalize (object); +} + +static void +hildon_bread_crumb_trail_move_parent (HildonBreadCrumbTrail *bct) +{ + if (g_list_length (bct->priv->item_list) > 1) + { + g_signal_emit_by_name (HILDON_BREAD_CRUMB (bct->priv->item_list->next->data), + "crumb-activated"); + } +} + +static void +hildon_bread_crumb_trail_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + GList *p; + GtkRequisition child_requisition; + HildonBreadCrumbTrail *bct; + HildonBreadCrumbTrailPrivate *priv; + gint minimum_width, width = 0; + PangoLayout *layout; + gchar *tmp = NULL; + + bct= HILDON_BREAD_CRUMB_TRAIL (widget); + priv = bct->priv; + + requisition->height = 0; + requisition->width = 0; + + gtk_widget_size_request (priv->back_button, &child_requisition); + requisition->width = child_requisition.width; + requisition->height = child_requisition.height; + + if (priv->item_list) + { + /* Add minimum width for one item */ + /* TODO: this can be probably cached */ + gtk_widget_style_get (widget, + "minimum-width", &minimum_width, + NULL); + + tmp = g_strnfill ((gsize)minimum_width, 'm'); + layout = gtk_widget_create_pango_layout (widget, tmp); + g_free (tmp); + pango_layout_get_size (layout, &width, NULL); + requisition->width += PANGO_PIXELS (width); + g_object_unref (layout); + } + + /* Button requisitions */ + for (p = priv->item_list; p; p = p->next) + { + GtkWidget *child = GTK_WIDGET (p->data); + + if (GTK_WIDGET_VISIBLE (child)) + gtk_widget_size_request (child, &child_requisition); + } + + /* Border width */ + requisition->width += GTK_CONTAINER (widget)->border_width * 2; + requisition->height += GTK_CONTAINER (widget)->border_width * 2; + + widget->requisition = *requisition; +} + +/* Document me please */ + +static void +hildon_bread_crumb_trail_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + GtkRequisition req; + gint natural_width, natural_height; + HildonBreadCrumb *item; + GtkAllocation child_allocation; + GtkRequisition child_requisition; + GtkWidget *child; + gint allocation_width; + gint border_width, width; + gint extra_space; + GList *p, *first_show, *first_hide; + gint back_button_size; + HildonBreadCrumbTrailPrivate *priv = HILDON_BREAD_CRUMB_TRAIL (widget)->priv; + gboolean rtl; + + /* Get the rtl status */ + rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL); + + widget->allocation = *allocation; + + border_width = (gint) GTK_CONTAINER (widget)->border_width; + allocation_width = allocation->width - 2 * border_width; + + /* Allocate the back button */ + if (rtl) + child_allocation.x = allocation->width - border_width; + else + child_allocation.x = allocation->x + border_width; + + child_allocation.y = allocation->y + border_width; + gtk_widget_get_child_requisition (priv->back_button, &child_requisition); + /* We want the back button to be a square */ + back_button_size = MAX (child_requisition.width, child_requisition.height); + child_allocation.width = child_allocation.height = back_button_size; + + if (rtl) + child_allocation.x -= back_button_size; + + gtk_widget_size_allocate (priv->back_button, &child_allocation); + + if (!rtl) + child_allocation.x += back_button_size; + + /* If there are no buttons there's nothing else to do */ + if (priv->item_list == NULL) + return; + + /* We find out how many buttons can we show, starting from the + the last one in the logical path (the first item in the list) */ + + width = back_button_size; + p = priv->item_list; + first_show = NULL; + first_hide = NULL; + extra_space = 0; + + for (p = priv->item_list; p; p = p->next) + { + item = HILDON_BREAD_CRUMB (p->data); + child = GTK_WIDGET (item); + + /* Does the widget fit with its natural size? */ + hildon_bread_crumb_get_natural_size (item, + &natural_width, + &natural_height); + + if (width + natural_width <= allocation_width) + { + /* Yes, it does */ + first_show = p; + first_hide = p->next; + width += natural_width; + } + else + { + /* No, it doesn't. Allocate as much as possible + and stop */ + child_allocation.width = allocation_width - width; + + gtk_widget_size_request (child, &req); + + if (child_allocation.width > req.width) + { + first_hide = p->next; + gtk_widget_set_child_visible (child, TRUE); + + if (rtl) + child_allocation.x -= child_allocation.width; + + gtk_widget_size_allocate (child, &child_allocation); + + if (!rtl) + child_allocation.x += child_allocation.width; + } + else + { + extra_space = child_allocation.width; + } + + break; + } + } + + /* Not enough items to fill the breadcrumb? */ + if (p == NULL && width < allocation_width) + { + extra_space = allocation_width - width; + } + + /* Allocate the other buttons */ + for (p = first_show; p; p = p->prev) + { + item = HILDON_BREAD_CRUMB (p->data); + child = GTK_WIDGET (item); + + /* Does the widget fit with its natural size? */ + hildon_bread_crumb_get_natural_size (item, + &natural_width, + &natural_height); + + /* If I'm the last and there's extra space, use it */ + if (p->prev == NULL && extra_space != 0) + { + natural_width += extra_space; + } + + child_allocation.width = natural_width; + gtk_widget_set_child_visible (child, TRUE); + + if (rtl) + child_allocation.x -= child_allocation.width; + + gtk_widget_size_allocate (child, &child_allocation); + + if (!rtl) + child_allocation.x += child_allocation.width; + } + + for (p = first_hide; p; p = p->next) + { + item = HILDON_BREAD_CRUMB (p->data); + gtk_widget_set_child_visible (GTK_WIDGET (item), FALSE); + } +} + +static gpointer +get_bread_crumb_id (HildonBreadCrumb *item) +{ + return g_object_get_data (G_OBJECT (item), "bread-crumb-id"); +} + +static void +crumb_activated_cb (GtkWidget *button, + HildonBreadCrumbTrail *bct) +{ + gboolean signal_handled = FALSE; + + g_signal_emit (bct, bread_crumb_trail_signals[CRUMB_CLICKED], 0, + get_bread_crumb_id (HILDON_BREAD_CRUMB (button)), + &signal_handled); + + if (signal_handled == FALSE) + { + GtkWidget *child; + gboolean focus_last_item = FALSE; + HildonBreadCrumbTrailPrivate *priv; + + priv = bct->priv; + + child = GTK_WIDGET (priv->item_list->data); + + /* We remove the tip of the list until we hit the clicked button */ + while (child && child != button) + { + if (GTK_WIDGET_HAS_FOCUS (child)) + focus_last_item = TRUE; + + gtk_container_remove (GTK_CONTAINER (bct), child); + + if (priv->item_list == NULL) + return; + + child = GTK_WIDGET (priv->item_list->data); + } + + if (focus_last_item) + gtk_widget_grab_focus (GTK_WIDGET (bct->priv->item_list->data)); + } +} + +static void +hildon_bread_crumb_trail_add (GtkContainer *container, + GtkWidget *widget) +{ + gtk_widget_set_parent (widget, GTK_WIDGET (container)); + + if (HILDON_IS_BREAD_CRUMB (widget)) + { + HildonBreadCrumbTrail *bct = HILDON_BREAD_CRUMB_TRAIL (container); + + g_signal_connect (G_OBJECT (widget), "crumb-activated", + G_CALLBACK (crumb_activated_cb), container); + + bct->priv->item_list = g_list_prepend (bct->priv->item_list, widget); + + hildon_bread_crumb_trail_update_back_button_sensitivity (bct); + } +} + +static void +hildon_bread_crumb_trail_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) +{ + g_return_if_fail (callback != NULL); + g_return_if_fail (HILDON_IS_BREAD_CRUMB_TRAIL (container)); + + GList *children; + HildonBreadCrumbTrailPrivate *priv = HILDON_BREAD_CRUMB_TRAIL (container)->priv; + + children = priv->item_list; + + while (children) + { + GtkWidget *child; + child = GTK_WIDGET (children->data); + children = children->next; + + (*callback) (child, callback_data); + } + + if (include_internals && priv->back_button) + { + (*callback) (priv->back_button, callback_data); + } +} + +static void +hildon_bread_crumb_trail_remove (GtkContainer *container, + GtkWidget *widget) +{ + GList *p, *next; + HildonBreadCrumbTrailPrivate *priv; + gboolean was_visible = GTK_WIDGET_VISIBLE (widget); + + priv = HILDON_BREAD_CRUMB_TRAIL (container)->priv; + + p = priv->item_list; + + while (p) + { + next = p->next; + + if (widget == GTK_WIDGET (p->data)) + { + g_signal_handlers_disconnect_by_func (widget, G_CALLBACK (crumb_activated_cb), + HILDON_BREAD_CRUMB_TRAIL (container)); + gtk_widget_unparent (widget); + + priv->item_list = g_list_delete_link (priv->item_list, p); + + hildon_bread_crumb_trail_update_back_button_sensitivity (HILDON_BREAD_CRUMB_TRAIL (container)); + + if (was_visible) + { + gtk_widget_queue_resize (GTK_WIDGET (container)); + } + } + + p = next; + } +} + +static void +hildon_bread_crumb_trail_update_back_button_sensitivity (HildonBreadCrumbTrail *bct) +{ + guint list_length; + HildonBreadCrumbTrailPrivate *priv = bct->priv; + + list_length = g_list_length (priv->item_list); + + if (list_length <= 1) + { + gtk_widget_set_sensitive (priv->back_button, FALSE); + } + else + { + gtk_widget_set_sensitive (priv->back_button, TRUE); + } +} + +static GtkWidget* +create_back_button (HildonBreadCrumbTrail *bct) +{ + GtkWidget *button; + GtkWidget *arrow; + gint arrow_size; + + gtk_widget_push_composite_child (); + + button = gtk_button_new (); + gtk_widget_set_name (button, "hildon-bread-crumb-back-button"); + gtk_widget_set_sensitive (button, FALSE); + + arrow = gtk_arrow_new (GTK_ARROW_LEFT, GTK_SHADOW_NONE); + bct->priv->arrow = arrow; + gtk_widget_style_get (GTK_WIDGET (bct), + "arrow-size", &arrow_size, + NULL); + gtk_widget_set_size_request (arrow, arrow_size, arrow_size); + + gtk_container_add (GTK_CONTAINER (button), arrow); + gtk_container_add (GTK_CONTAINER (bct), button); + gtk_widget_show_all (button); + + gtk_widget_pop_composite_child (); + + return button; +} + +static void +hildon_bread_crumb_trail_init (HildonBreadCrumbTrail *bct) +{ + HildonBreadCrumbTrailPrivate *priv = HILDON_BREAD_CRUMB_TRAIL_GET_PRIVATE (bct); + + GTK_WIDGET_SET_FLAGS (bct, GTK_NO_WINDOW); + gtk_widget_set_redraw_on_allocate (GTK_WIDGET (bct), FALSE); + + bct->priv = priv; + priv->item_list = NULL; + + priv->back_button = create_back_button (bct); + g_signal_connect (priv->back_button, "clicked", + G_CALLBACK (hildon_bread_crumb_trail_scroll_back), + bct); +} + +static void +hildon_bread_crumb_trail_scroll_back (GtkWidget *button, + HildonBreadCrumbTrail *bct) +{ + hildon_bread_crumb_trail_move_parent (bct); +} + +static void +attach_bread_crumb (HildonBreadCrumbTrail *bct, + GtkWidget *bread_crumb, + gpointer id, + GDestroyNotify destroy) +{ + g_object_set_data_full (G_OBJECT (bread_crumb), "bread-crumb-id", id, destroy); + + gtk_container_add (GTK_CONTAINER (bct), bread_crumb); + + gtk_widget_show (bread_crumb); +} + +/* PUBLIC API */ + +/** + * hildon_bread_crumb_trail_new: + * + * Creates a new #HildonBreadCrumbTrail widget. + * + * Returns: a #GtkWidget pointer of newly created bread crumb trail + * widget + * + * Stability: Unstable + */ + +GtkWidget* +hildon_bread_crumb_trail_new (void) +{ + return GTK_WIDGET (g_object_new (HILDON_TYPE_BREAD_CRUMB_TRAIL, NULL)); +} + +/** + * hildon_bread_crumb_trail_push: + * @bct: pointer to #HildonBreadCrumbTrail + * @item: the #HildonBreadCrumb to be added to the trail + * @id: optional id for the bread crumb + * @destroy: GDestroyNotify callback to be called when the bread crumb is destroyed + * + * Adds a new bread crumb to the end of the trail. + * + * Stability: Unstable + */ + +void +hildon_bread_crumb_trail_push (HildonBreadCrumbTrail *bct, + HildonBreadCrumb *item, + gpointer id, + GDestroyNotify destroy) +{ + GtkWidget *widget; + + g_return_if_fail (HILDON_IS_BREAD_CRUMB_TRAIL (bct)); + g_return_if_fail (HILDON_IS_BREAD_CRUMB (item)); + + widget = GTK_WIDGET (item); + + attach_bread_crumb (bct, widget, id, destroy); +} + +/** + * hildon_bread_crumb_trail_push_text: + * @bct: pointer to #HildonBreadCrumbTrail + * @text: content of the new bread crumb + * @id: optional id for the bread crumb + * @destroy: GDestroyNotify callback to be called when the bread crumb is destroyed + * + * Adds a new bread crumb to the end of the trail containing the specified text. + * + * Stability: Unstable + */ + +void +hildon_bread_crumb_trail_push_text (HildonBreadCrumbTrail *bct, + const gchar *text, + gpointer id, + GDestroyNotify destroy) +{ + GtkWidget *widget; + + g_return_if_fail (HILDON_IS_BREAD_CRUMB_TRAIL (bct)); + g_return_if_fail (text != NULL); + + widget = _hildon_bread_crumb_widget_new_with_text (text); + if (bct->priv->item_list == NULL) + { + g_object_set (G_OBJECT (widget), "show-separator", FALSE, NULL); + } + attach_bread_crumb (bct, widget, id, destroy); +} + +/** + * hildon_bread_crumb_trail_push_icon: + * @bct: pointer to #HildonBreadCrumbTrail + * @text: content of the new bread crumb + * @icon: a widget to set as the icon in the bread crumb + * @id: optional id for the bread crumb + * @destroy: GDestroyNotify callback to be called when the bread crumb is destroyed + * + * Adds a new bread crumb to the end of the trail containing the specified text and + * icon. + * + * Stability: Unstable + */ + +void +hildon_bread_crumb_trail_push_icon (HildonBreadCrumbTrail *bct, + const gchar *text, + GtkWidget *icon, + gpointer id, + GDestroyNotify destroy) +{ + GtkWidget *widget; + + g_return_if_fail (HILDON_IS_BREAD_CRUMB_TRAIL (bct)); + g_return_if_fail (text != NULL); + g_return_if_fail (GTK_IS_WIDGET (icon)); + + widget = _hildon_bread_crumb_widget_new_with_icon (icon, text); + if (bct->priv->item_list == NULL) + { + g_object_set (G_OBJECT (widget), "show-separator", FALSE, NULL); + } + attach_bread_crumb (bct, widget, id, destroy); +} + +/** + * hildon_bread_crumb_trail_pop: + * @bct: pointer to #HildonBreadCrumbTrail + * + * Removes the last bread crumb from the trail. + * + * Stability: Unstable + */ + +void +hildon_bread_crumb_trail_pop (HildonBreadCrumbTrail *bct) +{ + GtkWidget *child; + HildonBreadCrumbTrailPrivate *priv; + + g_return_if_fail (HILDON_IS_BREAD_CRUMB_TRAIL (bct)); + + priv = bct->priv; + + if (priv->item_list == NULL) + return; + + if (priv->item_list) + { + child = GTK_WIDGET (priv->item_list->data); + gtk_container_remove (GTK_CONTAINER (bct), child); + } + + hildon_bread_crumb_trail_update_back_button_sensitivity (bct); +} + +/** + * hildon_bread_crumb_trail_clear: + * @bct: pointer to #HildonBreadCrumbTrail + * + * Removes all the bread crumbs from the bread crumb trail. + * + * Stability: Unstable + */ + +void +hildon_bread_crumb_trail_clear (HildonBreadCrumbTrail *bct) +{ + HildonBreadCrumbTrailPrivate *priv; + + g_return_if_fail (HILDON_IS_BREAD_CRUMB_TRAIL (bct)); + + priv = bct->priv; + + while (priv->item_list) + { + hildon_bread_crumb_trail_pop (bct); + } + + /* + Sensitivity hack from hell. We need to do this while + http://bugzilla.gnome.org/show_bug.cgi?id=56070 is not + fixed to allow repeated clicking on the back button if + someone clears and rebuilds the trail when it's clicked + */ + gtk_widget_hide (priv->back_button); + gtk_widget_show (priv->back_button); +} diff --git a/hildon/hildon-bread-crumb-trail.h b/hildon/hildon-bread-crumb-trail.h new file mode 100644 index 0000000..71695ce --- /dev/null +++ b/hildon/hildon-bread-crumb-trail.h @@ -0,0 +1,90 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2007 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * Author: Xan Lopez + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#ifndef __HILDON_BREAD_CRUMB_TRAIL_H__ +#define __HILDON_BREAD_CRUMB_TRAIL_H__ + +#include + +#include "hildon-bread-crumb.h" + +G_BEGIN_DECLS + +typedef struct _HildonBreadCrumbTrail HildonBreadCrumbTrail; +typedef struct _HildonBreadCrumbTrailClass HildonBreadCrumbTrailClass; +typedef struct _HildonBreadCrumbTrailPrivate HildonBreadCrumbTrailPrivate; + +#define HILDON_TYPE_BREAD_CRUMB_TRAIL (hildon_bread_crumb_trail_get_type ()) +#define HILDON_BREAD_CRUMB_TRAIL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HILDON_TYPE_BREAD_CRUMB_TRAIL, HildonBreadCrumbTrail)) +#define HILDON_BREAD_CRUMB_TRAIL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), HILDON_TYPE_BREAD_CRUMB_TRAIL, HildonBreadCrumbTrailClass)) +#define HILDON_IS_BREAD_CRUMB_TRAIL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_BREAD_CRUMB_TRAIL)) +#define HILDON_IS_BREAD_CRUMB_TRAIL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_BREAD_CRUMB_TRAIL)) +#define HILDON_BREAD_CRUMB_TRAIL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), HILDON_TYPE_BREAD_CRUMB_TRAIL, HildonBreadCrumbTrailClass)) + +struct _HildonBreadCrumbTrail +{ + GtkContainer parent; + + HildonBreadCrumbTrailPrivate *priv; +}; + +struct _HildonBreadCrumbTrailClass +{ + GtkContainerClass parent_class; + + void (*crumb_clicked) (HildonBreadCrumbTrail *bct, + gpointer id); + + /* Signals used for keybindings */ + void (*move_parent) (HildonBreadCrumbTrail *bct); + + /* Padding for future expansion */ + void (*_hildon_bct_reserved1) (void); + void (*_hildon_bct_reserved2) (void); + void (*_hildon_bct_reserved3) (void); + void (*_hildon_bct_reserved4) (void); +}; + +GType hildon_bread_crumb_trail_get_type (void) G_GNUC_CONST; +GtkWidget *hildon_bread_crumb_trail_new (void); +void hildon_bread_crumb_trail_push (HildonBreadCrumbTrail *bct, HildonBreadCrumb *item, + gpointer id, GDestroyNotify destroy); +void hildon_bread_crumb_trail_push_text (HildonBreadCrumbTrail *bct, const gchar *text, + gpointer id, GDestroyNotify destroy); +void hildon_bread_crumb_trail_push_icon (HildonBreadCrumbTrail *bct, + const gchar *text, + GtkWidget *icon, + gpointer id, + GDestroyNotify destroy); +void hildon_bread_crumb_trail_pop (HildonBreadCrumbTrail *bct); +void hildon_bread_crumb_trail_clear (HildonBreadCrumbTrail *bct); + +G_END_DECLS + +#endif + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-bread-crumb-widget.c b/hildon/hildon-bread-crumb-widget.c new file mode 100644 index 0000000..22e4411 --- /dev/null +++ b/hildon/hildon-bread-crumb-widget.c @@ -0,0 +1,517 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2007 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * Author: Xan Lopez + * + * 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, or (at your option) any later version. + * + * 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 + * + */ + +#undef HILDON_DISABLE_DEPRECATED + +#include "hildon-bread-crumb-widget.h" +#include "hildon-defines.h" + +#define HILDON_BREAD_CRUMB_WIDGET_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_BREAD_CRUMB_WIDGET, HildonBreadCrumbWidgetPrivate)) + +struct _HildonBreadCrumbWidgetPrivate +{ + GtkWidget *hbox; + GtkWidget *label; + GtkWidget *icon; + GtkWidget *arrow; + gchar *text; + + GtkPositionType icon_position; + gboolean constructed; + gboolean show_separator; +}; + +/* Signals */ + +enum { + LAST_SIGNAL +}; + +/* Properties */ + +enum { + PROP_0, + PROP_TEXT, + PROP_ICON, + PROP_ICON_POSITION, + PROP_SHOW_SEPARATOR +}; + +/* +static guint bread_crumb_item_signals[LAST_SIGNAL] = { 0 }; +*/ + +/* GType methods */ + +static void hildon_bread_crumb_widget_finalize (GObject *object); +static void hildon_bread_crumb_widget_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec); +static void hildon_bread_crumb_widget_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec); +static GObject* hildon_bread_crumb_widget_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_params); +static void hildon_bread_crumb_widget_set_contents (HildonBreadCrumbWidget *bread_crumb); + +static void hildon_bread_crumb_widget_clicked (GtkButton *button); + +static void hildon_bread_crumb_widget_bread_crumb_init (HildonBreadCrumbIface *iface); + +static void hildon_bread_crumb_widget_get_natural_size (HildonBreadCrumb *bread_crumb, + gint *width, + gint *height); + +G_DEFINE_TYPE_WITH_CODE (HildonBreadCrumbWidget, hildon_bread_crumb_widget, GTK_TYPE_BUTTON, + G_IMPLEMENT_INTERFACE (HILDON_TYPE_BREAD_CRUMB, + hildon_bread_crumb_widget_bread_crumb_init)) + +static void +hildon_bread_crumb_widget_class_init (HildonBreadCrumbWidgetClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass*)klass; + GtkButtonClass *button_class = (GtkButtonClass*)klass; + + /* GObject signals */ + gobject_class->constructor = hildon_bread_crumb_widget_constructor; + gobject_class->finalize = hildon_bread_crumb_widget_finalize; + gobject_class->set_property = hildon_bread_crumb_widget_set_property; + gobject_class->get_property = hildon_bread_crumb_widget_get_property; + + /* GtkButton signals */ + button_class->clicked = hildon_bread_crumb_widget_clicked; + + /* Properties */ + g_object_class_install_property (gobject_class, + PROP_TEXT, + g_param_spec_string ("text", + "Text", + "Text of the label widget inside the bread crumb", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (gobject_class, + PROP_ICON, + g_param_spec_object ("icon", + "Icon", + "Image that will appear next to the bread crumb text", + GTK_TYPE_WIDGET, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (gobject_class, + PROP_ICON_POSITION, + g_param_spec_enum ("icon-position", + "Icon position", + "The position of the image relative to the text", + GTK_TYPE_POSITION_TYPE, + GTK_POS_LEFT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (gobject_class, + PROP_SHOW_SEPARATOR, + g_param_spec_boolean ("show-separator", + "Show separator", + "Show the separator attached to the item", + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + /* Private data */ + g_type_class_add_private (gobject_class, sizeof (HildonBreadCrumbWidgetPrivate)); +} + +static void +hildon_bread_crumb_widget_bread_crumb_init (HildonBreadCrumbIface *iface) +{ + iface->get_natural_size = hildon_bread_crumb_widget_get_natural_size; +} + +static GObject* +hildon_bread_crumb_widget_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_params) +{ + GObject *object; + HildonBreadCrumbWidget *bread_crumb; + HildonBreadCrumbWidgetPrivate *priv; + + object = (* G_OBJECT_CLASS (hildon_bread_crumb_widget_parent_class)->constructor) (type, + n_construct_properties, + construct_params); + + bread_crumb = HILDON_BREAD_CRUMB_WIDGET (object); + priv = bread_crumb->priv; + priv->constructed = TRUE; + + priv->hbox = gtk_hbox_new (FALSE, 6); + gtk_container_add (GTK_CONTAINER (bread_crumb), priv->hbox); + + /* Separator */ + priv->arrow = gtk_arrow_new (GTK_ARROW_RIGHT, GTK_SHADOW_NONE); + gtk_widget_set_name (priv->arrow, "hildon-bread-crumb-separator-arrow"); + gtk_box_pack_start (GTK_BOX (priv->hbox), priv->arrow, FALSE, FALSE, 0); + + if (priv->show_separator) + gtk_widget_show (priv->arrow); + + gtk_widget_set_no_show_all (priv->arrow, TRUE); + + /* Contents base container */ + bread_crumb->contents = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT); + gtk_container_add (GTK_CONTAINER (priv->hbox), bread_crumb->contents); + gtk_widget_show (bread_crumb->contents); + + if (priv->text || priv->icon) + hildon_bread_crumb_widget_set_contents (bread_crumb); + + /* Show everything */ + gtk_widget_show (priv->hbox); + + return object; +} + +static void +hildon_bread_crumb_widget_init (HildonBreadCrumbWidget *item) +{ + HildonBreadCrumbWidgetPrivate *priv = HILDON_BREAD_CRUMB_WIDGET_GET_PRIVATE (item); + + item->priv = priv; + + item->contents = NULL; + + priv->constructed = FALSE; + priv->text = NULL; + priv->icon = NULL; + priv->icon_position = GTK_POS_LEFT; + priv->show_separator = TRUE; +} + +static void +hildon_bread_crumb_widget_finalize (GObject *object) +{ + HildonBreadCrumbWidgetPrivate *priv = HILDON_BREAD_CRUMB_WIDGET (object)->priv; + + g_free (priv->text); + + G_OBJECT_CLASS (hildon_bread_crumb_widget_parent_class)->finalize (object); +} + +static void +hildon_bread_crumb_widget_clicked (GtkButton *button) +{ + hildon_bread_crumb_activated (HILDON_BREAD_CRUMB (button)); +} + +static void +hildon_bread_crumb_widget_set_contents (HildonBreadCrumbWidget *bread_crumb) +{ + GtkWidget *icon = NULL; + HildonBreadCrumbWidgetPrivate *priv = bread_crumb->priv; + + if (!priv->constructed) + return; + + if (!priv->text && !priv->icon) + return; + + /* If the icon exists, keep it */ + if (priv->icon) + { + icon = g_object_ref (priv->icon); + if (icon->parent) + gtk_container_remove (GTK_CONTAINER (icon->parent), icon); + priv->icon = NULL; + } + + /* Reset contents */ + if (bread_crumb->contents) + gtk_container_remove (GTK_CONTAINER (priv->hbox), + bread_crumb->contents); + + if (icon) + { + priv->icon = icon; + if (priv->icon_position == GTK_POS_LEFT || + priv->icon_position == GTK_POS_RIGHT) + bread_crumb->contents = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT); + else + bread_crumb->contents = gtk_vbox_new (FALSE, HILDON_MARGIN_DEFAULT); + + if (priv->icon_position == GTK_POS_LEFT || + priv->icon_position == GTK_POS_TOP) + gtk_box_pack_start (GTK_BOX (bread_crumb->contents), priv->icon, + FALSE, FALSE, 0); + else + gtk_box_pack_end (GTK_BOX (bread_crumb->contents), priv->icon, + FALSE, FALSE, 0); + + if (priv->text) + { + priv->label = gtk_label_new (priv->text); + g_object_set (G_OBJECT (priv->label), "xalign", 0.0, NULL); + gtk_label_set_ellipsize (GTK_LABEL (priv->label), + PANGO_ELLIPSIZE_END); + + if (priv->icon_position == GTK_POS_RIGHT || + priv->icon_position == GTK_POS_BOTTOM) + gtk_box_pack_start (GTK_BOX (bread_crumb->contents), priv->label, + TRUE, TRUE, 0); + else + gtk_box_pack_end (GTK_BOX (bread_crumb->contents), priv->label, + TRUE, TRUE, 0); + + } + + gtk_box_pack_start (GTK_BOX (priv->hbox), bread_crumb->contents, + TRUE, TRUE, 0); + gtk_widget_show_all (bread_crumb->contents); + + g_object_unref (icon); + } + else + { + /* Only text */ + bread_crumb->contents = gtk_hbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX (priv->hbox), bread_crumb->contents, + TRUE, TRUE, 0); + + priv->label = gtk_label_new (priv->text); + g_object_set (G_OBJECT (priv->label), "xalign", 0.0, NULL); + gtk_label_set_ellipsize (GTK_LABEL (priv->label), + PANGO_ELLIPSIZE_END); + gtk_box_pack_start (GTK_BOX (bread_crumb->contents), priv->label, TRUE, TRUE, 0); + + gtk_widget_show_all (bread_crumb->contents); + } +} + +static void +hildon_bread_crumb_widget_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + HildonBreadCrumbWidget *item = HILDON_BREAD_CRUMB_WIDGET (object); + + switch (prop_id) + { + case PROP_TEXT: + _hildon_bread_crumb_widget_set_text (item, g_value_get_string (value)); + break; + case PROP_ICON: + _hildon_bread_crumb_widget_set_icon (item, (GtkWidget*)g_value_get_object (value)); + break; + case PROP_ICON_POSITION: + _hildon_bread_crumb_widget_set_icon_position (item, g_value_get_enum (value)); + break; + case PROP_SHOW_SEPARATOR: + _hildon_bread_crumb_widget_set_show_separator (item, g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +hildon_bread_crumb_widget_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + HildonBreadCrumbWidget *item = HILDON_BREAD_CRUMB_WIDGET (object); + + switch (prop_id) + { + case PROP_TEXT: + g_value_set_string (value, item->priv->text); + break; + case PROP_ICON: + g_value_set_object (value, (GObject *)item->priv->icon); + break; + case PROP_ICON_POSITION: + g_value_set_enum (value, item->priv->icon_position); + break; + case PROP_SHOW_SEPARATOR: + g_value_set_boolean (value, item->priv->show_separator); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +void +_hildon_bread_crumb_widget_set_text (HildonBreadCrumbWidget *item, + const gchar *text) +{ + HildonBreadCrumbWidgetPrivate *priv; + + g_return_if_fail (HILDON_IS_BREAD_CRUMB_WIDGET (item)); + + priv = item->priv; + + if (priv->text) + g_free (priv->text); + + priv->text = g_strdup (text); + + hildon_bread_crumb_widget_set_contents (item); + + g_object_notify (G_OBJECT (item), "text"); +} + +const gchar* +_hildon_bread_crumb_widget_get_text (HildonBreadCrumbWidget *item) +{ + HildonBreadCrumbWidgetPrivate *priv; + + g_return_val_if_fail (HILDON_IS_BREAD_CRUMB_WIDGET (item), NULL); + + priv = item->priv; + + return priv->text; +} + +void +_hildon_bread_crumb_widget_set_show_separator (HildonBreadCrumbWidget *item, + gboolean show_separator) +{ + HildonBreadCrumbWidgetPrivate *priv; + + g_return_if_fail (HILDON_IS_BREAD_CRUMB_WIDGET (item)); + + priv = item->priv; + + if (priv->show_separator == show_separator) + return; + + priv->show_separator = show_separator; + + if (!priv->constructed) + return; + + if (show_separator) + gtk_widget_show (priv->arrow); + else + gtk_widget_hide (priv->arrow); + + g_object_notify (G_OBJECT (item), "show-separator"); +} + +static void +hildon_bread_crumb_widget_get_natural_size (HildonBreadCrumb *bread_crumb, + gint *natural_width, + gint *natural_height) +{ + GtkRequisition widget_req, label_req; + gint width, height; + PangoLayout *layout; + HildonBreadCrumbWidget *item; + HildonBreadCrumbWidgetPrivate *priv; + + g_return_if_fail (HILDON_IS_BREAD_CRUMB_WIDGET (bread_crumb)); + + item = HILDON_BREAD_CRUMB_WIDGET (bread_crumb); + priv = item->priv; + + gtk_widget_size_request (GTK_WIDGET (item), &widget_req); + + layout = gtk_widget_create_pango_layout (priv->label, priv->text); + pango_layout_get_pixel_size (layout, &width, &height); + g_object_unref (layout); + + if (natural_width) + { + *natural_width = widget_req.width; + /* Substract the size request of the label */ + gtk_widget_size_request (priv->label, &label_req); + *natural_width -= label_req.width; + + /* Add the "natural" width for the label */ + *natural_width += width; + *natural_width += GTK_CONTAINER (item)->border_width * 2; + } + + if (natural_height) + { + *natural_height = widget_req.height; + *natural_height += GTK_CONTAINER (item)->border_width * 2; + } +} + +GtkWidget* +_hildon_bread_crumb_widget_new () +{ + return GTK_WIDGET (g_object_new (HILDON_TYPE_BREAD_CRUMB_WIDGET, NULL)); +} + +GtkWidget* +_hildon_bread_crumb_widget_new_with_text (const gchar *text) +{ + return GTK_WIDGET (g_object_new (HILDON_TYPE_BREAD_CRUMB_WIDGET, + "text", text, + NULL)); +} + +GtkWidget* +_hildon_bread_crumb_widget_new_with_icon (GtkWidget *icon, const gchar *text) +{ + return GTK_WIDGET (g_object_new (HILDON_TYPE_BREAD_CRUMB_WIDGET, + "icon", icon, + "text", text, + NULL)); +} + +void +_hildon_bread_crumb_widget_set_icon (HildonBreadCrumbWidget *bread_crumb, + GtkWidget *icon) +{ + HildonBreadCrumbWidgetPrivate *priv; + + g_return_if_fail (HILDON_IS_BREAD_CRUMB_WIDGET (bread_crumb)); + + priv = bread_crumb->priv; + + priv->icon = icon; + + hildon_bread_crumb_widget_set_contents (bread_crumb); + + g_object_notify (G_OBJECT (bread_crumb), "icon"); +} + +void +_hildon_bread_crumb_widget_set_icon_position (HildonBreadCrumbWidget *bread_crumb, + GtkPositionType icon_position) +{ + HildonBreadCrumbWidgetPrivate *priv; + + g_return_if_fail (HILDON_IS_BREAD_CRUMB_WIDGET (bread_crumb)); + + priv = bread_crumb->priv; + + if (priv->icon_position == icon_position) + return; + + priv->icon_position = icon_position; + + hildon_bread_crumb_widget_set_contents (bread_crumb); + + g_object_notify (G_OBJECT (bread_crumb), "icon-position"); +} diff --git a/hildon/hildon-bread-crumb-widget.h b/hildon/hildon-bread-crumb-widget.h new file mode 100644 index 0000000..4c04c23 --- /dev/null +++ b/hildon/hildon-bread-crumb-widget.h @@ -0,0 +1,79 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2007 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * Author: Xan Lopez + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#ifndef __HILDON_BREAD_CRUMB_WIDGET_H__ +#define __HILDON_BREAD_CRUMB_WIDGET_H__ + +#include + +#include "hildon-bread-crumb.h" + +G_BEGIN_DECLS + +typedef struct _HildonBreadCrumbWidget HildonBreadCrumbWidget; +typedef struct _HildonBreadCrumbWidgetClass HildonBreadCrumbWidgetClass; +typedef struct _HildonBreadCrumbWidgetPrivate HildonBreadCrumbWidgetPrivate; + +#define HILDON_TYPE_BREAD_CRUMB_WIDGET (hildon_bread_crumb_widget_get_type ()) +#define HILDON_BREAD_CRUMB_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HILDON_TYPE_BREAD_CRUMB_WIDGET, HildonBreadCrumbWidget)) +#define HILDON_BREAD_CRUMB_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), HILDON_TYPE_BREAD_CRUMB_WIDGET, HildonBreadCrumbWidgetClass)) +#define HILDON_IS_BREAD_CRUMB_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_BREAD_CRUMB_WIDGET)) +#define HILDON_IS_BREAD_CRUMB_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_BREAD_CRUMB_WIDGET)) +#define HILDON_BREAD_CRUMB_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), HILDON_TYPE_BREAD_CRUMB_WIDGET, HildonBreadCrumbWidgetClass)) + +struct _HildonBreadCrumbWidget +{ + GtkButton parent; + + GtkWidget *contents; + + HildonBreadCrumbWidgetPrivate *priv; +}; + +struct _HildonBreadCrumbWidgetClass +{ + GtkButtonClass parent_class; +}; + +GType hildon_bread_crumb_widget_get_type (void) G_GNUC_CONST; +GtkWidget *_hildon_bread_crumb_widget_new (void); +GtkWidget *_hildon_bread_crumb_widget_new_with_text (const gchar *label); +GtkWidget *_hildon_bread_crumb_widget_new_with_icon (GtkWidget *icon, const gchar *text); +void _hildon_bread_crumb_widget_set_text (HildonBreadCrumbWidget *item, const gchar *text); +const gchar *_hildon_bread_crumb_widget_get_text (HildonBreadCrumbWidget *item); +void _hildon_bread_crumb_widget_set_show_separator (HildonBreadCrumbWidget *item, + gboolean show_separator); +void _hildon_bread_crumb_widget_set_icon (HildonBreadCrumbWidget *bread_crumb_widget, + GtkWidget *icon); +void _hildon_bread_crumb_widget_set_icon_position (HildonBreadCrumbWidget *bread_crumb, + GtkPositionType icon_position); + +G_END_DECLS + +#endif + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-bread-crumb.c b/hildon/hildon-bread-crumb.c new file mode 100644 index 0000000..e9bc4f0 --- /dev/null +++ b/hildon/hildon-bread-crumb.c @@ -0,0 +1,129 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2007 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * Author: Xan Lopez + * + * 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, or (at your option) any later version. + * + * 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-bread-crumb + * @short_description: Interface for elements in a #HildonBreadCrumbTrail + * + * #HildonBreadCrumb is an interface for creating new types of items + * for the #HildonBreadCrumbTrail widget. + */ + +#undef HILDON_DISABLE_DEPRECATED + +#include "hildon-bread-crumb.h" + +static void hildon_bread_crumb_base_init (gpointer g_class); + +GType +hildon_bread_crumb_get_type (void) +{ + static GType bread_crumb_type = 0; + + if (G_UNLIKELY (bread_crumb_type == 0)) + { + const GTypeInfo bread_crumb_info = + { + sizeof (HildonBreadCrumbIface), /* class_size */ + hildon_bread_crumb_base_init, /* base_init */ + NULL, /* base_finalize */ + NULL, + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, + 0, + NULL + }; + + bread_crumb_type = + g_type_register_static (G_TYPE_INTERFACE, "HildonBreadCrumb", + &bread_crumb_info, 0); + + g_type_interface_add_prerequisite (bread_crumb_type, GTK_TYPE_WIDGET); + } + + return bread_crumb_type; +} + +static void +hildon_bread_crumb_base_init (gpointer g_class) +{ + static gboolean initialized = FALSE; + + if (initialized == FALSE) + { + g_signal_new ("crumb-activated", + HILDON_TYPE_BREAD_CRUMB, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (HildonBreadCrumbIface, crumb_activated), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + initialized = TRUE; + } +} + +/** + * hildon_bread_crumb_get_natural_size: + * @bread_crumb: A #HildonBreadCrumb + * @width: location to store the natural width request of the @bread_crumb + * @height: location to store the natural height request of the @bread_crumb + * + * Function to ask the @bread_crumb its preferred width and height requisition. + * Natural size is different to size_request in that it's not the minimum space + * the widget needs, but the ideal space it'd like to be allocated. For example, + * in the case of a label the natural size would be the width and height needed + * to show the full label without line breaks. + * + **/ + +void +hildon_bread_crumb_get_natural_size (HildonBreadCrumb *bread_crumb, + gint *width, + gint *height) +{ + g_return_if_fail (HILDON_IS_BREAD_CRUMB (bread_crumb)); + + (* HILDON_BREAD_CRUMB_GET_IFACE (bread_crumb)->get_natural_size) (bread_crumb, width, height); +} + +/** + * hildon_bread_crumb_activated: + * @bread_crumb: a #HildonBreadCrumb + * + * Emits the "crumb-activated" signal. The signal is meant to indicate that + * the user has interacted with the bread crumb. + **/ + +void +hildon_bread_crumb_activated (HildonBreadCrumb *bread_crumb) +{ + g_return_if_fail (HILDON_IS_BREAD_CRUMB (bread_crumb)); + + g_signal_emit_by_name (bread_crumb, "crumb-activated"); +} + + diff --git a/hildon/hildon-bread-crumb.h b/hildon/hildon-bread-crumb.h new file mode 100644 index 0000000..8ce0c83 --- /dev/null +++ b/hildon/hildon-bread-crumb.h @@ -0,0 +1,64 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2007 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * Author: Xan Lopez + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#ifndef __HILDON_BREAD_CRUMB_H__ +#define __HILDON_BREAD_CRUMB_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _HildonBreadCrumb HildonBreadCrumb; +typedef struct _HildonBreadCrumbIface HildonBreadCrumbIface; + +#define HILDON_TYPE_BREAD_CRUMB (hildon_bread_crumb_get_type ()) +#define HILDON_BREAD_CRUMB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HILDON_TYPE_BREAD_CRUMB, HildonBreadCrumb)) +#define HILDON_BREAD_CRUMB_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), HILDON_TYPE_BREAD_CRUMB, HildonBreadCrumbIface)) +#define HILDON_IS_BREAD_CRUMB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_BREAD_CRUMB)) +#define HILDON_BREAD_CRUMB_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), HILDON_TYPE_BREAD_CRUMB, HildonBreadCrumbIface)) + +struct _HildonBreadCrumbIface +{ + GTypeInterface g_iface; + + /* virtual table */ + void (* get_natural_size) (HildonBreadCrumb *bread_crumb, + gint *natural_width, gint *natural_height); + /* signals */ + void (* crumb_activated) (HildonBreadCrumb *bread_crumb); +}; + +GType hildon_bread_crumb_get_type (void) G_GNUC_CONST; +void hildon_bread_crumb_get_natural_size (HildonBreadCrumb *bread_crumb, + gint *width, gint *height); +void hildon_bread_crumb_activated (HildonBreadCrumb *bread_crumb); + +G_END_DECLS + +#endif + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-button.c b/hildon/hildon-button.c new file mode 100644 index 0000000..7123152 --- /dev/null +++ b/hildon/hildon-button.c @@ -0,0 +1,1022 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +/** + * SECTION:hildon-button + * @short_description: Widget representing a button in the Hildon framework. + * + * The #HildonButton is a GTK widget which represents a clickable + * button. It is derived from the #GtkButton widget and provides + * additional commodities specific to the Hildon framework. + * + * The height of a #HildonButton can be set to either "finger" height + * or "thumb" height. It can also be configured to use halfscreen or + * fullscreen width. Alternatively, either dimension can be set to + * "auto" so it behaves like a standard #GtkButton. + * + * The #HildonButton can hold any valid child widget, but it usually + * contains two labels, named title and value, and it can also contain + * an image. The contents of the button are packed together inside a + * #GtkAlignment and they do not expand by default (they don't use the + * full space of the button). + * + * To change the alignment of both labels, use gtk_button_set_alignment() + * + * To make them expand and use the full space of the button, use + * hildon_button_set_alignment(). + * + * To change the relative alignment of each label, use + * hildon_button_set_title_alignment() and + * hildon_button_set_value_alignment(). + * + * In hildon-button-example.c included in the Hildon distribution you + * can see examples of how to create the most common button + * layouts. + * + * If only one label is needed, #GtkButton can be used as well, see + * also hildon_gtk_button_new(). + * + * + * Creating a HildonButton + * + * void + * button_clicked (HildonButton *button, gpointer user_data) + * { + * const gchar *title, *value; + * + * title = hildon_button_get_title (button); + * value = hildon_button_get_value (button); + * g_debug ("Button clicked with title '%s' and value '%s'", title, value); + * } + * + * GtkWidget * + * create_button (void) + * { + * GtkWidget *button; + * GtkWidget *image; + * + * button = hildon_button_new (HILDON_SIZE_AUTO_WIDTH | HILDON_SIZE_FINGER_HEIGHT, + * HILDON_BUTTON_ARRANGEMENT_VERTICAL); + * hildon_button_set_text (HILDON_BUTTON (button), "Some title", "Some value"); + * + * image = gtk_image_new_from_stock (GTK_STOCK_INFO, GTK_ICON_SIZE_BUTTON); + * hildon_button_set_image (HILDON_BUTTON (button), image); + * hildon_button_set_image_position (HILDON_BUTTON (button), GTK_POS_RIGHT); + * + * gtk_button_set_alignment (GTK_BUTTON (button), 0.0, 0.5); + * + * g_signal_connect (button, "clicked", G_CALLBACK (button_clicked), NULL); + * + * return button; + * } + * + * + */ + +#include "hildon-button.h" +#include "hildon-enum-types.h" +#include "hildon-gtk.h" +#include "hildon-helper.h" + +G_DEFINE_TYPE (HildonButton, hildon_button, GTK_TYPE_BUTTON); + +#define HILDON_BUTTON_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_BUTTON, HildonButtonPrivate)); + +typedef struct _HildonButtonPrivate HildonButtonPrivate; + +struct _HildonButtonPrivate +{ + GtkLabel *title; + GtkLabel *value; + GtkBox *hbox; + GtkWidget *label_box; + GtkWidget *alignment; + GtkWidget *image; + GtkPositionType image_position; + gfloat image_xalign; + gfloat image_yalign; + HildonButtonStyle style; +}; + +enum { + PROP_TITLE = 1, + PROP_VALUE, + PROP_SIZE, + PROP_ARRANGEMENT, + PROP_STYLE +}; + +static void +hildon_button_set_arrangement (HildonButton *button, + HildonButtonArrangement arrangement); + +static void +hildon_button_construct_child (HildonButton *button); + +static void +hildon_button_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + HildonButton *button = HILDON_BUTTON (object); + + switch (prop_id) + { + case PROP_TITLE: + hildon_button_set_title (button, g_value_get_string (value)); + break; + case PROP_VALUE: + hildon_button_set_value (button, g_value_get_string (value)); + break; + case PROP_SIZE: + hildon_gtk_widget_set_theme_size (GTK_WIDGET (button), g_value_get_flags (value)); + break; + case PROP_ARRANGEMENT: + hildon_button_set_arrangement (button, g_value_get_enum (value)); + break; + case PROP_STYLE: + hildon_button_set_style (button, g_value_get_enum (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +hildon_button_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + HildonButton *button = HILDON_BUTTON (object); + + switch (prop_id) + { + case PROP_TITLE: + g_value_set_string (value, hildon_button_get_title (button)); + break; + case PROP_VALUE: + g_value_set_string (value, hildon_button_get_value (button)); + break; + case PROP_STYLE: + g_value_set_enum (value, hildon_button_get_style (button)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +hildon_button_style_set (GtkWidget *widget, + GtkStyle *previous_style) +{ + guint horizontal_spacing, vertical_spacing, image_spacing; + HildonButtonPrivate *priv = HILDON_BUTTON_GET_PRIVATE (widget); + + if (GTK_WIDGET_CLASS (hildon_button_parent_class)->style_set) + GTK_WIDGET_CLASS (hildon_button_parent_class)->style_set (widget, previous_style); + + gtk_widget_style_get (widget, + "horizontal-spacing", &horizontal_spacing, + "vertical-spacing", &vertical_spacing, + "image-spacing", &image_spacing, + NULL); + + if (GTK_IS_HBOX (priv->label_box)) { + gtk_box_set_spacing (GTK_BOX (priv->label_box), horizontal_spacing); + } else { + gtk_box_set_spacing (GTK_BOX (priv->label_box), vertical_spacing); + } + + if (GTK_IS_BOX (priv->hbox)) { + gtk_box_set_spacing (priv->hbox, image_spacing); + } +} + +static void +hildon_button_finalize (GObject *object) +{ + HildonButtonPrivate *priv = HILDON_BUTTON_GET_PRIVATE (object); + + g_object_unref (priv->alignment); + g_object_unref (priv->label_box); + + G_OBJECT_CLASS (hildon_button_parent_class)->finalize (object); +} + +static void +hildon_button_class_init (HildonButtonClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass *)klass; + GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; + + gobject_class->set_property = hildon_button_set_property; + gobject_class->get_property = hildon_button_get_property; + gobject_class->finalize = hildon_button_finalize; + widget_class->style_set = hildon_button_style_set; + + g_object_class_install_property ( + gobject_class, + PROP_TITLE, + g_param_spec_string ( + "title", + "Title", + "Text of the title label inside the button", + NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + gobject_class, + PROP_VALUE, + g_param_spec_string ( + "value", + "Value", + "Text of the value label inside the button", + NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + gobject_class, + PROP_SIZE, + g_param_spec_flags ( + "size", + "Size", + "Size request for the button", + HILDON_TYPE_SIZE_TYPE, + HILDON_SIZE_AUTO, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property ( + gobject_class, + PROP_ARRANGEMENT, + g_param_spec_enum ( + "arrangement", + "Arrangement", + "How the button contents must be arranged", + HILDON_TYPE_BUTTON_ARRANGEMENT, + HILDON_BUTTON_ARRANGEMENT_HORIZONTAL, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property ( + gobject_class, + PROP_STYLE, + g_param_spec_enum ( + "style", + "Style", + "Visual style of the button", + HILDON_TYPE_BUTTON_STYLE, + HILDON_BUTTON_STYLE_NORMAL, + G_PARAM_READWRITE)); + + gtk_widget_class_install_style_property ( + widget_class, + g_param_spec_uint ( + "horizontal-spacing", + "Horizontal spacing between labels", + "Horizontal spacing between the title and value labels, when in horizontal mode", + 0, G_MAXUINT, 25, + G_PARAM_READABLE)); + + gtk_widget_class_install_style_property ( + widget_class, + g_param_spec_uint ( + "vertical-spacing", + "Vertical spacing between labels", + "Vertical spacing between the title and value labels, when in vertical mode", + 0, G_MAXUINT, 5, + G_PARAM_READABLE)); + + g_type_class_add_private (klass, sizeof (HildonButtonPrivate)); +} + +static void +hildon_button_init (HildonButton *self) +{ + HildonButtonPrivate *priv = HILDON_BUTTON_GET_PRIVATE (self); + + priv->title = GTK_LABEL (gtk_label_new (NULL)); + priv->value = GTK_LABEL (gtk_label_new (NULL)); + priv->alignment = gtk_alignment_new (0.5, 0.5, 0, 0); + priv->image = NULL; + priv->image_position = GTK_POS_LEFT; + priv->image_xalign = 0.5; + priv->image_yalign = 0.5; + priv->hbox = NULL; + priv->label_box = NULL; + + gtk_widget_set_name (GTK_WIDGET (priv->title), "hildon-button-title"); + gtk_widget_set_name (GTK_WIDGET (priv->value), "hildon-button-value"); + + hildon_button_set_style (self, HILDON_BUTTON_STYLE_NORMAL); + + gtk_misc_set_alignment (GTK_MISC (priv->title), 0, 0.5); + gtk_misc_set_alignment (GTK_MISC (priv->value), 0, 0.5); + + g_object_ref_sink (priv->alignment); + + /* The labels are not shown automatically, see hildon_button_set_(title|value) */ + gtk_widget_set_no_show_all (GTK_WIDGET (priv->title), TRUE); + gtk_widget_set_no_show_all (GTK_WIDGET (priv->value), TRUE); + + gtk_button_set_focus_on_click (GTK_BUTTON (self), FALSE); +} + +/** + * hildon_button_add_title_size_group: + * @button: a #HildonButton + * @size_group: A #GtkSizeGroup for the button title (main label) + * + * Adds the title label of @button to @size_group. + * + * Since: 2.2 + **/ +void +hildon_button_add_title_size_group (HildonButton *button, + GtkSizeGroup *size_group) +{ + HildonButtonPrivate *priv; + + g_return_if_fail (HILDON_IS_BUTTON (button)); + g_return_if_fail (GTK_IS_SIZE_GROUP (size_group)); + + priv = HILDON_BUTTON_GET_PRIVATE (button); + + gtk_size_group_add_widget (size_group, GTK_WIDGET (priv->title)); +} + +/** + * hildon_button_add_value_size_group: + * @button: a #HildonButton + * @size_group: A #GtkSizeGroup for the button value (secondary label) + * + * Adds the value label of @button to @size_group. + * + * Since: 2.2 + **/ +void +hildon_button_add_value_size_group (HildonButton *button, + GtkSizeGroup *size_group) +{ + HildonButtonPrivate *priv; + + g_return_if_fail (HILDON_IS_BUTTON (button)); + g_return_if_fail (GTK_IS_SIZE_GROUP (size_group)); + + priv = HILDON_BUTTON_GET_PRIVATE (button); + + gtk_size_group_add_widget (size_group, GTK_WIDGET (priv->value)); +} + +/** + * hildon_button_add_image_size_group: + * @button: a #HildonButton + * @size_group: A #GtkSizeGroup for the button image + * + * Adds the image of @button to @size_group. You must add an image + * using hildon_button_set_image() before calling this function. + * + * Since: 2.2 + **/ +void +hildon_button_add_image_size_group (HildonButton *button, + GtkSizeGroup *size_group) +{ + HildonButtonPrivate *priv; + + g_return_if_fail (HILDON_IS_BUTTON (button)); + g_return_if_fail (GTK_IS_SIZE_GROUP (size_group)); + + priv = HILDON_BUTTON_GET_PRIVATE (button); + + g_return_if_fail (GTK_IS_WIDGET (priv->image)); + + gtk_size_group_add_widget (size_group, GTK_WIDGET (priv->image)); +} + +/** + * hildon_button_add_size_groups: + * @button: a #HildonButton + * @title_size_group: A #GtkSizeGroup for the button title (main label), or %NULL + * @value_size_group: A #GtkSizeGroup group for the button value (secondary label), or %NULL + * @image_size_group: A #GtkSizeGroup group for the button image, or %NULL + * + * Convenience function to add title, value and image to size + * groups. %NULL size groups will be ignored. + * + * Since: 2.2 + **/ +void +hildon_button_add_size_groups (HildonButton *button, + GtkSizeGroup *title_size_group, + GtkSizeGroup *value_size_group, + GtkSizeGroup *image_size_group) +{ + if (title_size_group) + hildon_button_add_title_size_group (button, title_size_group); + + if (value_size_group) + hildon_button_add_value_size_group (button, value_size_group); + + if (image_size_group) + hildon_button_add_image_size_group (button, image_size_group); +} + +/** + * hildon_button_new: + * @size: Flags to set the size of the button. + * @arrangement: How the labels must be arranged. + * + * Creates a new #HildonButton. To set text in the labels, use + * hildon_button_set_title() and + * hildon_button_set_value(). Alternatively, you can add a custom + * child widget using gtk_container_add(). + * + * Returns: a new #HildonButton + * + * Since: 2.2 + **/ +GtkWidget * +hildon_button_new (HildonSizeType size, + HildonButtonArrangement arrangement) +{ + return hildon_button_new_with_text (size, arrangement, NULL, NULL); +} + +/** + * hildon_button_new_with_text: + * @size: Flags to set the size of the button. + * @arrangement: How the labels must be arranged. + * @title: Title of the button (main label), or %NULL + * @value: Value of the button (secondary label), or %NULL + * + * Creates a new #HildonButton with two labels, @title and @value. + * + * If you just don't want to use one of the labels, set it to + * %NULL. You can set it to a non-%NULL value at any time later using + * hildon_button_set_title() or hildon_button_set_value() . + * + * Returns: a new #HildonButton + * + * Since: 2.2 + **/ +GtkWidget * +hildon_button_new_with_text (HildonSizeType size, + HildonButtonArrangement arrangement, + const gchar *title, + const gchar *value) +{ + GtkWidget *button; + + /* Create widget */ + button = g_object_new (HILDON_TYPE_BUTTON, + "size", size, + "title", title, + "value", value, + "arrangement", arrangement, + NULL); + + return button; +} + +static void +hildon_button_set_arrangement (HildonButton *button, + HildonButtonArrangement arrangement) +{ + HildonButtonPrivate *priv; + + priv = HILDON_BUTTON_GET_PRIVATE (button); + + /* Pack everything */ + if (arrangement == HILDON_BUTTON_ARRANGEMENT_VERTICAL) { + priv->label_box = gtk_vbox_new (FALSE, 0); + hildon_helper_set_logical_font (GTK_WIDGET (priv->value), "SmallSystemFont"); + } else { + priv->label_box = gtk_hbox_new (FALSE, 0); + } + + g_object_ref_sink (priv->label_box); + + /* If we pack both labels with (TRUE, TRUE) or (FALSE, FALSE) they + * can be painted outside of the button in some situations, see + * NB#88126 and NB#110689 */ + gtk_box_pack_start (GTK_BOX (priv->label_box), GTK_WIDGET (priv->title), FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (priv->label_box), GTK_WIDGET (priv->value), TRUE, TRUE, 0); + + hildon_button_construct_child (button); +} + +/** + * hildon_button_set_title: + * @button: a #HildonButton + * @title: a new title (main label) for the button, or %NULL + * + * Sets the title (main label) of @button to @title. + * + * This will clear any previously set title. + * + * If @title is set to %NULL, the title label will be hidden and the + * value label will be realigned. + * + * Since: 2.2 + **/ +void +hildon_button_set_title (HildonButton *button, + const gchar *title) +{ + HildonButtonPrivate *priv; + + g_return_if_fail (HILDON_IS_BUTTON (button)); + + priv = HILDON_BUTTON_GET_PRIVATE (button); + gtk_label_set_text (priv->title, title); + + /* If the button has no title, hide the label so the value is + * properly aligned */ + if (title) { + hildon_button_construct_child (button); + gtk_widget_show (GTK_WIDGET (priv->title)); + } else { + gtk_widget_hide (GTK_WIDGET (priv->title)); + } + + g_object_notify (G_OBJECT (button), "title"); +} + +/** + * hildon_button_set_value: + * @button: a #HildonButton + * @value: a new value (secondary label) for the button, or %NULL + * + * Sets the value (secondary label) of @button to @value. + * + * This will clear any previously set value. + * + * If @value is set to %NULL, the value label will be hidden and the + * title label will be realigned. + * + * Since: 2.2 + **/ +void +hildon_button_set_value (HildonButton *button, + const gchar *value) +{ + HildonButtonPrivate *priv; + + g_return_if_fail (HILDON_IS_BUTTON (button)); + + priv = HILDON_BUTTON_GET_PRIVATE (button); + gtk_label_set_text (priv->value, value); + + /* If the button has no value, hide the label so the title is + * properly aligned */ + if (value) { + hildon_button_construct_child (button); + gtk_widget_show (GTK_WIDGET (priv->value)); + } else { + gtk_widget_hide (GTK_WIDGET (priv->value)); + } + + g_object_notify (G_OBJECT (button), "value"); +} + +/** + * hildon_button_get_title: + * @button: a #HildonButton + * + * Fetches the text from the main label (title) of @button, + * as set by hildon_button_set_title() or hildon_button_set_text(). + * If the label text has not been set the return value will be %NULL. + * This will be the case if you create an empty button with + * hildon_button_new() to use as a container. + * + * Returns: The text of the title label. This string is owned by the + * widget and must not be modified or freed. + * + * Since: 2.2 + **/ +const gchar * +hildon_button_get_title (HildonButton *button) +{ + HildonButtonPrivate *priv; + + g_return_val_if_fail (HILDON_IS_BUTTON (button), NULL); + + priv = HILDON_BUTTON_GET_PRIVATE (button); + + return gtk_label_get_text (priv->title); +} + +/** + * hildon_button_get_value: + * @button: a #HildonButton + * + * Fetches the text from the secondary label (value) of @button, + * as set by hildon_button_set_value() or hildon_button_set_text(). + * If the label text has not been set the return value will be %NULL. + * This will be the case if you create an empty button with hildon_button_new() + * to use as a container. + * + * Returns: The text of the value label. This string is owned by the + * widget and must not be modified or freed. + * + * Since: 2.2 + **/ +const gchar * +hildon_button_get_value (HildonButton *button) +{ + HildonButtonPrivate *priv; + + g_return_val_if_fail (HILDON_IS_BUTTON (button), NULL); + + priv = HILDON_BUTTON_GET_PRIVATE (button); + + return gtk_label_get_text (priv->value); +} + +/** + * hildon_button_set_text: + * @button: a #HildonButton + * @title: new text for the button title (main label) + * @value: new text for the button value (secondary label) + * + * Convenience function to change both labels of a #HildonButton + * + * Since: 2.2 + **/ +void +hildon_button_set_text (HildonButton *button, + const gchar *title, + const gchar *value) +{ + hildon_button_set_title (button, title); + hildon_button_set_value (button, value); +} + +/** + * hildon_button_set_image: + * @button: a #HildonButton + * @image: a widget to set as the button image + * + * Sets the image of @button to the given widget. The previous image + * (if any) will be removed. + * + * Since: 2.2 + **/ +void +hildon_button_set_image (HildonButton *button, + GtkWidget *image) +{ + HildonButtonPrivate *priv; + + g_return_if_fail (HILDON_IS_BUTTON (button)); + g_return_if_fail (!image || GTK_IS_WIDGET (image)); + + priv = HILDON_BUTTON_GET_PRIVATE (button); + + /* Return if there's nothing to do */ + if (image == priv->image) + return; + + if (priv->image && priv->image->parent) + gtk_container_remove (GTK_CONTAINER (priv->image->parent), priv->image); + + priv->image = image; + + hildon_button_construct_child (button); +} + +/** + * hildon_button_get_image: + * @button: a #HildonButton + * + * Gets the widget that is currenty set as the image of @button, + * previously set with hildon_button_set_image() + * + * Returns: a #GtkWidget or %NULL in case there is no image + * + * Since: 2.2 + **/ +GtkWidget * +hildon_button_get_image (HildonButton *button) +{ + HildonButtonPrivate *priv; + + g_return_val_if_fail (HILDON_IS_BUTTON (button), NULL); + + priv = HILDON_BUTTON_GET_PRIVATE (button); + + return priv->image; +} + +/** + * hildon_button_set_image_position: + * @button: a #HildonButton + * @position: the position of the image (%GTK_POS_LEFT or %GTK_POS_RIGHT) + * + * Sets the position of the image inside @button. Only %GTK_POS_LEFT + * and %GTK_POS_RIGHT are currently supported. + * + * Since: 2.2 + **/ +void +hildon_button_set_image_position (HildonButton *button, + GtkPositionType position) +{ + HildonButtonPrivate *priv; + + g_return_if_fail (HILDON_IS_BUTTON (button)); + g_return_if_fail (position == GTK_POS_LEFT || position == GTK_POS_RIGHT); + + priv = HILDON_BUTTON_GET_PRIVATE (button); + + /* Return if there's nothing to do */ + if (priv->image_position == position) + return; + + priv->image_position = position; + + hildon_button_construct_child (button); +} + +/** + * hildon_button_set_alignment: + * @button: a #HildonButton + * @xalign: the horizontal alignment of the contents, from 0 (left) to 1 (right). + * @yalign: the vertical alignment of the contents, from 0 (top) to 1 (bottom). + * @xscale: the amount that the child widget expands horizontally to fill up unused space, from 0 to 1 + * @yscale: the amount that the child widget expands vertically to fill up unused space, from 0 to 1 + * + * Sets the alignment of the contents of the widget. If you don't need + * to change @xscale or @yscale you can just use + * gtk_button_set_alignment() instead. + * + * Note that for this method to work properly the, child widget of + * @button must be a #GtkAlignment. That's what #HildonButton uses by + * default, so this function will work unless you add a custom widget + * to @button. + * + * Since: 2.2 + **/ +void +hildon_button_set_alignment (HildonButton *button, + gfloat xalign, + gfloat yalign, + gfloat xscale, + gfloat yscale) +{ + HildonButtonPrivate *priv; + GtkWidget *child; + + g_return_if_fail (HILDON_IS_BUTTON (button)); + + priv = HILDON_BUTTON_GET_PRIVATE (button); + + child = gtk_bin_get_child (GTK_BIN (button)); + + /* If the button has no child, use priv->alignment, which is the default one */ + if (child == NULL) + child = priv->alignment; + + if (GTK_IS_ALIGNMENT (child)) { + gtk_alignment_set (GTK_ALIGNMENT (priv->alignment), xalign, yalign, xscale, yscale); + } +} + +/** + * hildon_button_set_title_alignment: + * @button: a #HildonButton + * @xalign: the horizontal alignment of the title label, from 0 (left) to 1 (right). + * @yalign: the vertical alignment of the title label, from 0 (top) to 1 (bottom). + * + * Sets the alignment of the title label. See also + * hildon_button_set_alignment() to set the alignment of the whole + * contents of the button. + * + * Since: 2.2 + **/ +void +hildon_button_set_title_alignment (HildonButton *button, + gfloat xalign, + gfloat yalign) +{ + HildonButtonPrivate *priv; + + g_return_if_fail (HILDON_IS_BUTTON (button)); + + priv = HILDON_BUTTON_GET_PRIVATE (button); + + gtk_misc_set_alignment (GTK_MISC (priv->title), xalign, yalign); +} + +/** + * hildon_button_set_value_alignment: + * @button: a #HildonButton + * @xalign: the horizontal alignment of the value label, from 0 (left) to 1 (right). + * @yalign: the vertical alignment of the value label, from 0 (top) to 1 (bottom). + * + * Sets the alignment of the value label. See also + * hildon_button_set_alignment() to set the alignment of the whole + * contents of the button. + * + * Since: 2.2 + **/ +void +hildon_button_set_value_alignment (HildonButton *button, + gfloat xalign, + gfloat yalign) +{ + HildonButtonPrivate *priv; + + g_return_if_fail (HILDON_IS_BUTTON (button)); + + priv = HILDON_BUTTON_GET_PRIVATE (button); + + gtk_misc_set_alignment (GTK_MISC (priv->value), xalign, yalign); +} + +/** + * hildon_button_set_image_alignment: + * @button: a #HildonButton + * @xalign: the horizontal alignment of the image, from 0 (left) to 1 (right). + * @yalign: the vertical alignment of the image, from 0 (top) to 1 (bottom). + * + * Sets the alignment of the image. See also + * hildon_button_set_alignment() to set the alignment of the whole + * contents of the button. + * + * Since: 2.2 + **/ +void +hildon_button_set_image_alignment (HildonButton *button, + gfloat xalign, + gfloat yalign) +{ + HildonButtonPrivate *priv; + + g_return_if_fail (HILDON_IS_BUTTON (button)); + + priv = HILDON_BUTTON_GET_PRIVATE (button); + + /* Return if there's nothing to do */ + if (priv->image_xalign == xalign && priv->image_yalign == yalign) + return; + + priv->image_xalign = xalign; + priv->image_yalign = yalign; + + hildon_button_construct_child (button); +} + +/** + * hildon_button_set_style: + * @button: A #HildonButton + * @style: A #HildonButtonStyle for @button + * + * Sets the style of @button to @style. This changes the visual + * appearance of the button (colors, font sizes) according to the + * particular style chosen, but the general layout is not altered. + * + * Use %HILDON_BUTTON_STYLE_NORMAL to make it look like a normal + * #HildonButton, or %HILDON_BUTTON_STYLE_PICKER to make it look like + * a #HildonPickerButton. + * + * Since: 2.2 + */ +void +hildon_button_set_style (HildonButton *button, + HildonButtonStyle style) +{ + HildonButtonPrivate *priv; + const gchar *color; + + g_return_if_fail (HILDON_IS_BUTTON (button)); + + switch (style) { + case HILDON_BUTTON_STYLE_NORMAL: + color = "SecondaryTextColor"; + break; + case HILDON_BUTTON_STYLE_PICKER: + color = "ActiveTextColor"; + break; + default: + g_return_if_reached (); + } + + priv = HILDON_BUTTON_GET_PRIVATE (button); + + hildon_helper_set_logical_color (GTK_WIDGET (priv->value), GTK_RC_FG, GTK_STATE_NORMAL, color); + hildon_helper_set_logical_color (GTK_WIDGET (priv->value), GTK_RC_FG, GTK_STATE_PRELIGHT, color); + + priv->style = style; + + g_object_notify (G_OBJECT (button), "style"); +} + +/** + * hildon_button_get_style: + * @button: A #HildonButton + * + * Gets the visual style of the button. + * + * Returns: a #HildonButtonStyle + * + * Since: 2.2 + */ +HildonButtonStyle +hildon_button_get_style (HildonButton *button) +{ + HildonButtonPrivate *priv; + + g_return_val_if_fail (HILDON_IS_BUTTON (button), HILDON_BUTTON_STYLE_NORMAL); + + priv = HILDON_BUTTON_GET_PRIVATE (button); + + return priv->style; +} + +static void +hildon_button_construct_child (HildonButton *button) +{ + HildonButtonPrivate *priv = HILDON_BUTTON_GET_PRIVATE (button); + GtkWidget *child; + gint image_spacing; + const gchar *title, *value; + + /* Don't do anything if the button is not constructed yet */ + if (G_UNLIKELY (priv->label_box == NULL)) + return; + + /* Don't do anything if the button has no contents */ + title = gtk_label_get_text (priv->title); + value = gtk_label_get_text (priv->value); + if (!priv->image && !title[0] && !value[0]) + return; + + /* Save a ref to the image, and remove it from its container if necessary */ + if (priv->image) { + g_object_ref (priv->image); + if (priv->image->parent != NULL) + gtk_container_remove (GTK_CONTAINER (priv->image->parent), priv->image); + } + + if (priv->label_box->parent != NULL) { + gtk_container_remove (GTK_CONTAINER (priv->label_box->parent), priv->label_box); + } + + /* Remove the child from the container and add priv->alignment */ + child = gtk_bin_get_child (GTK_BIN (button)); + if (child != NULL && child != priv->alignment) { + gtk_container_remove (GTK_CONTAINER (button), child); + child = NULL; + } + + if (child == NULL) { + gtk_container_add (GTK_CONTAINER (button), GTK_WIDGET (priv->alignment)); + } + + /* Create a new hbox */ + if (priv->hbox) { + gtk_container_remove (GTK_CONTAINER (priv->alignment), GTK_WIDGET (priv->hbox)); + } + gtk_widget_style_get (GTK_WIDGET (button), "image-spacing", &image_spacing, NULL); + priv->hbox = GTK_BOX (gtk_hbox_new (FALSE, image_spacing)); + gtk_container_add (GTK_CONTAINER (priv->alignment), GTK_WIDGET (priv->hbox)); + + /* Pack the image and the alignment in the new hbox */ + if (priv->image && priv->image_position == GTK_POS_LEFT) + gtk_box_pack_start (priv->hbox, priv->image, FALSE, FALSE, 0); + + gtk_box_pack_start (priv->hbox, priv->label_box, TRUE, TRUE, 0); + + if (priv->image && priv->image_position == GTK_POS_RIGHT) + gtk_box_pack_start (priv->hbox, priv->image, FALSE, FALSE, 0); + + /* Set image alignment and remove previously set ref */ + if (priv->image) { + gtk_misc_set_alignment (GTK_MISC (priv->image), priv->image_xalign, priv->image_yalign); + g_object_unref (priv->image); + } + + /* Show everything */ + gtk_widget_show_all (GTK_WIDGET (priv->alignment)); +} diff --git a/hildon/hildon-button.h b/hildon/hildon-button.h new file mode 100644 index 0000000..d3b703c --- /dev/null +++ b/hildon/hildon-button.h @@ -0,0 +1,177 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +#ifndef __HILDON_BUTTON_H__ +#define __HILDON_BUTTON_H__ + +#include "hildon-gtk.h" + +G_BEGIN_DECLS + +#define HILDON_TYPE_BUTTON \ + (hildon_button_get_type()) + +#define HILDON_BUTTON(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + HILDON_TYPE_BUTTON, HildonButton)) + +#define HILDON_BUTTON_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + HILDON_TYPE_BUTTON, HildonButtonClass)) + +#define HILDON_IS_BUTTON(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_BUTTON)) + +#define HILDON_IS_BUTTON_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_BUTTON)) + +#define HILDON_BUTTON_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + HILDON_TYPE_BUTTON, HildonButtonClass)) + +typedef struct _HildonButton HildonButton; + +typedef struct _HildonButtonClass HildonButtonClass; + +struct _HildonButtonClass +{ + GtkButtonClass parent_class; +}; + +struct _HildonButton +{ + GtkButton parent; +}; + + +/** + * HildonButtonArrangement: + * @HILDON_BUTTON_ARRANGEMENT_HORIZONTAL: Labels are arranged from left to right + * @HILDON_BUTTON_ARRANGEMENT_VERTICAL: Labels are arranged from top to bottom + * + * Describes the arrangement of labels inside a #HildonButton + * + **/ +typedef enum { + HILDON_BUTTON_ARRANGEMENT_HORIZONTAL, + HILDON_BUTTON_ARRANGEMENT_VERTICAL +} HildonButtonArrangement; + +/** + * HildonButtonStyle: + * @HILDON_BUTTON_STYLE_NORMAL: The button will look like a normal #HildonButton + * @HILDON_BUTTON_STYLE_PICKER: The button will look like a #HildonPickerButton + * + * Describes the visual style of a #HildonButton + **/ +typedef enum { + HILDON_BUTTON_STYLE_NORMAL, + HILDON_BUTTON_STYLE_PICKER +} HildonButtonStyle; + +GType +hildon_button_get_type (void) G_GNUC_CONST; + +GtkWidget * +hildon_button_new (HildonSizeType size, + HildonButtonArrangement arrangement); + +GtkWidget * +hildon_button_new_with_text (HildonSizeType size, + HildonButtonArrangement arrangement, + const gchar *title, + const gchar *value); + +void +hildon_button_set_title (HildonButton *button, + const gchar *title); + +void +hildon_button_set_value (HildonButton *button, + const gchar *value); + +const gchar * +hildon_button_get_title (HildonButton *button); + +const gchar * +hildon_button_get_value (HildonButton *button); + +void +hildon_button_set_text (HildonButton *button, + const gchar *title, + const gchar *value); + +void +hildon_button_set_image (HildonButton *button, + GtkWidget *image); + +GtkWidget * +hildon_button_get_image (HildonButton *button); + +void +hildon_button_set_image_position (HildonButton *button, + GtkPositionType position); + +void +hildon_button_set_alignment (HildonButton *button, + gfloat xalign, + gfloat yalign, + gfloat xscale, + gfloat yscale); +void +hildon_button_set_title_alignment (HildonButton *button, + gfloat xalign, + gfloat yalign); + +void +hildon_button_set_value_alignment (HildonButton *button, + gfloat xalign, + gfloat yalign); + +void +hildon_button_set_image_alignment (HildonButton *button, + gfloat xalign, + gfloat yalign); + +void +hildon_button_add_title_size_group (HildonButton *button, + GtkSizeGroup *size_group); +void +hildon_button_add_value_size_group (HildonButton *button, + GtkSizeGroup *size_group); + +void +hildon_button_add_image_size_group (HildonButton *button, + GtkSizeGroup *size_group); + +void +hildon_button_add_size_groups (HildonButton *button, + GtkSizeGroup *title_size_group, + GtkSizeGroup *value_size_group, + GtkSizeGroup *image_size_group); + +void +hildon_button_set_style (HildonButton *button, + HildonButtonStyle style); + +HildonButtonStyle +hildon_button_get_style (HildonButton *button); + +G_END_DECLS + +#endif /* __HILDON_BUTTON_H__ */ diff --git a/hildon/hildon-calendar-popup-private.h b/hildon/hildon-calendar-popup-private.h new file mode 100644 index 0000000..b237576 --- /dev/null +++ b/hildon/hildon-calendar-popup-private.h @@ -0,0 +1,45 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_PRIVATE_H__ +#define __HILDON_CALENDAR_POPUP_PRIVATE_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _HildonCalendarPopupPrivate HildonCalendarPopupPrivate; + +#define HILDON_CALENDAR_POPUP_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), HILDON_TYPE_CALENDAR_POPUP, HildonCalendarPopupPrivate)); + +struct _HildonCalendarPopupPrivate +{ + GtkWidget *cal; +}; + +G_END_DECLS + +#endif /* __HILDON_CALENDAR_POPUP_PRIVATE_H__ */ diff --git a/hildon/hildon-calendar-popup.c b/hildon/hildon-calendar-popup.c new file mode 100644 index 0000000..1396a31 --- /dev/null +++ b/hildon/hildon-calendar-popup.c @@ -0,0 +1,528 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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 + * @short_description: CalendarPopup allows choosing a date from a popup calendar. + * @see_also: #HildonDateEditor, #HildonTimeEditor + * + * HildonCalendarPopup is a dialog which contains a HildonCalendar. It + * also contains arrow buttons for changing the month/year. If an + * entered date is invalid, an information message will be shown. + * + * + * + * #HildonCalendarPopup has been deprecated since Hildon 2.2 and should not + * be used in newly written code. + * See Migrating Date Widgets + * section to know how to migrate this deprecated widget. + * + * + * + * + * HildonCalendarPopup example + * + * ... + * gint y, m, d; + * GtkWidget *parent, *popup; + * + * // get current date into &y, &m, &d... + * + * gtk_widget_get_ancestor (GTK_WIDGET (data), GTK_TYPE_WINDOW); + * popup = hildon_calendar_popup_new (GTK_WINDOW (parent), y, m, d); + * + * 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); + * + * // here set the new date + * } + * gtk_widget_destroy(popup); + * ... + * + * + * + */ + + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include + +#include "hildon-calendar-popup.h" +#include "hildon-calendar-popup-private.h" +#include "hildon-calendar.h" + +#define _(String)\ + dgettext("hildon-libs", String) + +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); + +static GtkDialog* parent_class; + +enum +{ + PROP_0, + PROP_DAY, + PROP_MONTH, + PROP_YEAR, + PROP_MIN_YEAR, + PROP_MAX_YEAR +}; + +GType G_GNUC_CONST +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); + g_assert (priv); + + /* Choose current date if the date is invalid: */ + init_dmy (year, month, day, &dtmp, &mtmp, &ytmp); + + /* Remove all visual markers */ + hildon_calendar_clear_marks (HILDON_CALENDAR (priv->cal)); + + /* Set a new date */ + hildon_calendar_select_month (HILDON_CALENDAR (priv->cal), mtmp - 1, ytmp); + hildon_calendar_select_day (HILDON_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. + * It's possible to pass NULL to any of the pointers if you don't need that data. + */ +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); + g_assert (priv); + + hildon_calendar_get_date (HILDON_CALENDAR (priv->cal), year, month, day); + if (month != NULL) + *month = *month + 1; + + if (day != NULL && + month != NULL && + year != NULL && + ! 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, 10000, + 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, 10000, + 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); + g_assert (priv); + + /* set the domain directory for different language */ + /* FIXME I can't exactly figure out why is this here... */ + if (set_domain) { + (void) bindtextdomain ("hildon-libs", LOCALEDIR); + set_domain = 0; + } + + priv->cal = hildon_calendar_new (); + + /* dialog options and packing */ + hildon_calendar_set_display_options (HILDON_CALENDAR (priv->cal), + HILDON_CALENDAR_SHOW_HEADING | + HILDON_CALENDAR_SHOW_DAY_NAMES | + HILDON_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), _("wdgt_bd_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 */ + /* FIXME That should be moved to on_realize */ + 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) +{ + g_assert (d != NULL); + g_assert (m != NULL); + g_assert (y != NULL); + + 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. */ +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)); + g_assert (priv); + + 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)); + g_assert (priv); + + 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/hildon-calendar-popup.h b/hildon/hildon-calendar-popup.h new file mode 100644 index 0000000..99810e5 --- /dev/null +++ b/hildon/hildon-calendar-popup.h @@ -0,0 +1,91 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#ifndef __HILDON_CALENDAR_POPUP_H__ +#define __HILDON_CALENDAR_POPUP_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _HildonCalendarPopup HildonCalendarPopup; + +typedef struct _HildonCalendarPopupClass HildonCalendarPopupClass; + +#define HILDON_TYPE_CALENDAR_POPUP \ + (hildon_calendar_popup_get_type()) + +#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)) + +#define HILDON_CALENDAR_POPUP_GET_CLASS(obj) \ + ((HildonCalendarPopupClass *) G_OBJECT_GET_CLASS(obj)) + +struct _HildonCalendarPopup +{ + GtkDialog parent; +}; + +struct _HildonCalendarPopupClass +{ + GtkDialogClass parent_class; +}; + +GType G_GNUC_CONST +hildon_calendar_popup_get_type (void); + +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__ */ + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-calendar-private.h b/hildon/hildon-calendar-private.h new file mode 100644 index 0000000..4d01ac4 --- /dev/null +++ b/hildon/hildon-calendar-private.h @@ -0,0 +1,121 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_PRIVATE_H__ +#define __HILDON_CALENDAR_PRIVATE_H__ + +#include + +G_BEGIN_DECLS + +#define HILDON_CALENDAR_GET_PRIVATE(widget) \ + (((HildonCalendarPrivate*)(HILDON_CALENDAR (widget)->private_data))) + +typedef struct _HildonCalendarPrivate HildonCalendarPrivate; + +struct _HildonCalendarPrivate +{ + GdkWindow *header_win; + GdkWindow *footer_win; + GdkWindow *day_name_win; + GdkWindow *main_win; + GdkWindow *week_win; + GdkWindow *arrow_win[4]; + + gint year_before; + guint header_h; + guint day_name_h; + guint main_h; + + guint arrow_state[4]; + /* guint arrow_width; This is now defined constant. Even normal Gtk don't allow to change this */ + guint arrow_width; + guint max_month_width; + guint max_year_width; + + guint day_width; + guint week_width; + + guint min_day_width; + guint max_day_char_width; + guint max_day_char_ascent; + guint max_day_char_descent; + guint max_label_char_ascent; + guint max_label_char_descent; + guint max_week_char_width; + + guint freeze_count; + + /* flags */ + guint dirty_header : 1; + guint dirty_day_names : 1; + guint dirty_main : 1; + guint dirty_week : 1; + + /* guint year_before : 1;*/ + + guint need_timer : 1; + + guint in_drag : 1; + guint drag_highlight : 1; + + guint32 timer; + gint click_child; + + /* Following variables are for current date */ + guint current_day; + guint current_month; + guint current_year; + + /* Keep track of day and month + * where mouse button was pressed + */ + guint pressed_day; + guint pressed_month; + + /* Boolean value to indicate if + * out of bound day was selected + */ + gboolean is_bad_day; + + /* Must check if we are sliding stylus */ + gboolean slide_stylus; + gint prev_row; + gint prev_col; + + gint week_start; + + gint drag_start_x; + gint drag_start_y; + + gint min_year; + gint max_year; + + char *abbreviated_dayname[7]; + char *monthname[12]; +}; + +G_END_DECLS + +#endif /* __HILDON_CALENDAR_PRIVATE_H__ */ diff --git a/hildon/hildon-calendar.c b/hildon/hildon-calendar.c new file mode 100644 index 0000000..bb4416c --- /dev/null +++ b/hildon/hildon-calendar.c @@ -0,0 +1,4307 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * GTK Calendar Widget + * Copyright (C) 1998 Cesar Miquel, Shawn T. Amundson and Mattias Groenlund + * + * lib_date routines + * Copyright (C) 1995, 1996, 1997, 1998 by Steffen Beyer + * + * HldonCalendar modifications + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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; either + * version 2 of the License, or (at your option) any later version. or (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +/** + * SECTION:hildon-calendar + * @short_description: A calendar widget + * + * #HildonCalendar is a slightly modified #GtkCalendar. It has an almost same API + * but a slightly different look and behaviour. Use this widget instead of + * standard #GtkCalendar or use #HildonDateEditor for more higher-level date setting + * operations. + * + * + * + * #HildonCalendar has been deprecated since Hildon 2.2 + * See Migrating Date Widgets + * section to know how to migrate this deprecated widget. + * + * + */ + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include +#endif + +#define _GNU_SOURCE /* needed for GNU nl_langinfo_l */ + +#include + +#ifdef HAVE_SYS_TIME_H +#include +#endif + +#include +#include +#include +#include + +#include +#include +#include + +#include "hildon-calendar.h" +#include "hildon-marshalers.h" +#include "hildon-calendar-private.h" + +/***************************************************************************/ +/* The following date routines are taken from the lib_date package. Keep + * them separate in case we want to update them if a newer lib_date comes + * out with fixes. */ + +typedef unsigned int N_int; + +typedef unsigned long N_long; + +typedef signed long Z_long; + +typedef enum { false = FALSE , true = TRUE } boolean; + +#define and && /* logical (boolean) operators: lower case */ + +#define or || + +static const N_int month_length [2][13] = +{ + { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, + { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } +}; + +static const N_int days_in_months[2][14] = +{ + { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, + { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } +}; + +static Z_long calc_days (N_int year, N_int mm, N_int dd); + +static N_int day_of_week (N_int year, N_int mm, N_int dd); + +static Z_long dates_difference (N_int year1, N_int mm1, N_int dd1, + N_int year2, N_int mm2, N_int dd2); + +static N_int weeks_in_year (N_int year); + +static boolean +leap (N_int year) +{ + return ((((year % 4) == 0) and ((year % 100) != 0)) or ((year % 400) == 0)); +} + +static N_int +day_of_week (N_int year, + N_int mm, + N_int dd) +{ + Z_long days; + + days = calc_days (year, mm, dd); + if (days > 0L) + { + days--; + days %= 7L; + days++; + } + return( (N_int) days ); +} + +static N_int +weeks_in_year (N_int year) +{ + return (52 + ((day_of_week(year,1,1)==4) or (day_of_week(year,12,31)==4))); +} + +static boolean +check_date (N_int year, + N_int mm, + N_int dd) +{ + if (year < 1) return(false); + if ((mm < 1) or (mm > 12)) return(false); + if ((dd < 1) or (dd > month_length[leap(year)][mm])) return(false); + return(true); +} + +static N_int +week_number (N_int year, + N_int mm, + N_int dd) +{ + N_int first; + + first = day_of_week (year,1,1) - 1; + return( (N_int) ( (dates_difference(year,1,1, year,mm,dd) + first) / 7L ) + + (first < 4) ); +} + +static Z_long +year_to_days (N_int year) +{ + return ( year * 365L + (year / 4) - (year / 100) + (year / 400) ); +} + +static Z_long +calc_days (N_int year, + N_int mm, + N_int dd) +{ + boolean lp; + + if (year < 1) return(0L); + if ((mm < 1) or (mm > 12)) return(0L); + if ((dd < 1) or (dd > month_length[(lp = leap(year))][mm])) return(0L); + return( year_to_days(--year) + days_in_months[lp][mm] + dd ); +} + +static boolean +week_of_year (N_int *week, + N_int *year, + N_int mm, + N_int dd) +{ + if (check_date(*year,mm,dd)) + { + *week = week_number(*year,mm,dd); + if (*week == 0) + *week = weeks_in_year(--(*year)); + else if (*week > weeks_in_year(*year)) + { + *week = 1; + (*year)++; + } + return(true); + } + return(false); +} + +static Z_long +dates_difference (N_int year1, + N_int mm1, + N_int dd1, + N_int year2, + N_int mm2, + N_int dd2) +{ + return (calc_days (year2, mm2, dd2) - calc_days (year1, mm1, dd1)); +} + +/*** END OF lib_date routines ********************************************/ + +/* HILDON: Spacings modified */ +#define HILDON_ARROW_SEP 5 /* Space between arrows and data */ + +#define HILDON_DAY_WIDTH 26 + +#define HILDON_DAY_HEIGHT 25 + +/* additional widths given to week number and day windows */ + +#define HILDON_WEEKS_EXTRA_WIDTH 8 + +#define HILDON_DAYS_EXTRA_WIDTH 8 + +/* Spacing around day/week headers and main area, inside those windows */ + +#define CALENDAR_MARGIN 0 + +/* Spacing around day/week headers and main area, outside those windows */ + +#define INNER_BORDER 0 /* 4 */ + +/* Separation between day headers and main area */ + +#define CALENDAR_YSEP 3 /* 4 */ + +/* Separation between week headers and main area */ + +#define CALENDAR_XSEP 6 /* 4 */ + +#define DAY_XSEP 0 /* not really good for small calendar */ + +#define DAY_YSEP 0 /* not really good for small calendar */ + +/* Color usage */ +#define HEADER_FG_COLOR(widget) \ + (& (widget)->style->fg[GTK_WIDGET_STATE (widget)]) + +#define HEADER_BG_COLOR(widget) \ + (& (widget)->style->bg[GTK_WIDGET_STATE (widget)]) + +#define SELECTED_BG_COLOR(widget) \ + (& (widget)->style->base[GTK_WIDGET_HAS_FOCUS (widget) ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE]) + +#define SELECTED_FG_COLOR(widget) \ + (& (widget)->style->text[GTK_WIDGET_HAS_FOCUS (widget) ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE]) + +#define NORMAL_DAY_COLOR(widget) \ + (& (widget)->style->fg[GTK_WIDGET_STATE (widget)]) + +#define PREV_MONTH_COLOR(widget) \ + (& (widget)->style->mid[GTK_WIDGET_STATE (widget)]) + +#define NEXT_MONTH_COLOR(widget) \ + (& (widget)->style->mid[GTK_WIDGET_STATE (widget)]) + +#define MARKED_COLOR(widget) \ + (& (widget)->style->fg[GTK_WIDGET_STATE (widget)]) + +#define BACKGROUND_COLOR(widget) \ + (& (widget)->style->base[GTK_WIDGET_STATE (widget)]) + +#define HIGHLIGHT_BACK_COLOR(widget) \ + (& (widget)->style->mid[GTK_WIDGET_STATE (widget)]) + +#define CALENDAR_INITIAL_TIMER_DELAY 200 + +#define CALENDAR_TIMER_DELAY 20 + +enum { + ARROW_YEAR_LEFT, + ARROW_YEAR_RIGHT, + ARROW_MONTH_LEFT, + ARROW_MONTH_RIGHT +}; + +enum { + MONTH_PREV, + MONTH_CURRENT, + MONTH_NEXT +}; + +enum { + MONTH_CHANGED_SIGNAL, + DAY_SELECTED_SIGNAL, + DAY_SELECTED_DOUBLE_CLICK_SIGNAL, + PREV_MONTH_SIGNAL, + NEXT_MONTH_SIGNAL, + PREV_YEAR_SIGNAL, + NEXT_YEAR_SIGNAL, + ERRONEOUS_DATE_SIGNAL, + SELECTED_DATE_SIGNAL, + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_YEAR, + PROP_MONTH, + PROP_DAY, + PROP_SHOW_HEADING, + PROP_SHOW_DAY_NAMES, + PROP_NO_MONTH_CHANGE, + PROP_SHOW_WEEK_NUMBERS, + PROP_WEEK_START, + PROP_MIN_YEAR, + PROP_MAX_YEAR, + PROP_LAST +}; + +static gint hildon_calendar_signals [LAST_SIGNAL] = { 0 }; + +static GtkWidgetClass* parent_class = NULL; + +typedef void (*HildonCalendarSignalDate) (GtkObject *object, guint arg1, guint arg2, guint arg3, gpointer data); + +static void +hildon_calendar_class_init (HildonCalendarClass *class); + +static void +hildon_calendar_init (HildonCalendar *calendar); + +static void +hildon_calendar_finalize (GObject *calendar); + +static void +hildon_calendar_destroy (GtkObject *calendar); + +static void +hildon_calendar_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); + +static void +hildon_calendar_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +static void +hildon_calendar_realize (GtkWidget *widget); + +static void +hildon_calendar_unrealize (GtkWidget *widget); + +static void +hildon_calendar_size_request (GtkWidget *widget, + GtkRequisition *requisition); + +static void +hildon_calendar_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); + +static gint +hildon_calendar_expose (GtkWidget *widget, + GdkEventExpose *event); + +static gint +hildon_calendar_button_press (GtkWidget *widget, + GdkEventButton *event); + +static gint +hildon_calendar_button_release (GtkWidget *widget, + GdkEventButton *event); + +static void +hildon_calendar_main_button (GtkWidget *widget, + GdkEventButton *event); + +static gint +hildon_calendar_motion_notify (GtkWidget *widget, + GdkEventMotion *event); + +static gint +hildon_calendar_enter_notify (GtkWidget *widget, + GdkEventCrossing *event); + +static gint +hildon_calendar_leave_notify (GtkWidget *widget, + GdkEventCrossing *event); + +static gint +hildon_calendar_key_press (GtkWidget *widget, + GdkEventKey *event); + +static gint +hildon_calendar_scroll (GtkWidget *widget, + GdkEventScroll *event); + +static void +hildon_calendar_grab_notify (GtkWidget *widget, + gboolean was_grabbed); + +static gboolean +hildon_calendar_focus_out (GtkWidget *widget, + GdkEventFocus *event); + +static void +hildon_calendar_state_changed (GtkWidget *widget, + GtkStateType previous_state); + +static void +hildon_calendar_style_set (GtkWidget *widget, + GtkStyle *previous_style); + +static void +hildon_calendar_paint_header (GtkWidget *widget); + +static void +hildon_calendar_paint_footer (GtkWidget *widget); + +static void +hildon_calendar_paint_day_names (GtkWidget *widget); + +static void +hildon_calendar_paint_week_numbers (GtkWidget *widget); + +static void +hildon_calendar_paint_main (GtkWidget *widget); + +static void +hildon_calendar_select_and_focus_day (HildonCalendar *calendar, + guint day); + +static void +hildon_calendar_paint_arrow (GtkWidget *widget, + guint arrow); + +static void +hildon_calendar_paint_day_num (GtkWidget *widget, + gint day); + +static void +hildon_calendar_paint_day (GtkWidget *widget, + gint row, + gint col); + +static void +hildon_calendar_compute_days (HildonCalendar *calendar); + +static gint +left_x_for_column (HildonCalendar *calendar, + gint column); + +static gint +top_y_for_row (HildonCalendar *calendar, + gint row); + +static void +hildon_calendar_drag_data_get (GtkWidget *widget, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, + guint time); + +static void +hildon_calendar_drag_data_received (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint time); + +static gboolean +hildon_calendar_drag_motion (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time); + +static void +hildon_calendar_drag_leave (GtkWidget *widget, + GdkDragContext *context, + guint time); + +static gboolean +hildon_calendar_drag_drop (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time); + +/* This function was added because we need to mark current day according to + * specifications + */ + +static void +hildon_calendar_check_current_date (HildonCalendar *calendar, + gint x, + gint y); + +GType G_GNUC_CONST +hildon_calendar_get_type (void) +{ + static GType calendar_type = 0; + + if (!calendar_type) + { + static const GTypeInfo calendar_info = + { + sizeof (HildonCalendarClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_calendar_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (HildonCalendar), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_calendar_init, + }; + + calendar_type = g_type_register_static (GTK_TYPE_WIDGET, "HildonCalendar", + &calendar_info, 0); + } + + return calendar_type; +} + +static void +locales_init (HildonCalendarPrivate *priv) +{ + /* Hildon: This is not exactly portable, see + * http://bugzilla.gnome.org/show_bug.cgi?id=343415 + * The labels need to be instance variables as the startup wizard changes + * locale on runtime. + */ + locale_t l; + + l = newlocale (LC_TIME_MASK, setlocale (LC_MESSAGES, NULL), NULL); + + priv->abbreviated_dayname[0] = g_locale_to_utf8 (nl_langinfo_l(ABDAY_1, l), + -1, NULL, NULL, NULL); + priv->abbreviated_dayname[1] = g_locale_to_utf8 (nl_langinfo_l(ABDAY_2, l), + -1, NULL, NULL, NULL); + priv->abbreviated_dayname[2] = g_locale_to_utf8 (nl_langinfo_l(ABDAY_3, l), + -1, NULL, NULL, NULL) ; + priv->abbreviated_dayname[3] = g_locale_to_utf8 (nl_langinfo_l(ABDAY_4, l), + -1, NULL, NULL, NULL); + priv->abbreviated_dayname[4] = g_locale_to_utf8 (nl_langinfo_l(ABDAY_5, l), + -1, NULL, NULL, NULL); + priv->abbreviated_dayname[5] = g_locale_to_utf8 (nl_langinfo_l(ABDAY_6, l), + -1, NULL, NULL, NULL); + priv->abbreviated_dayname[6] = g_locale_to_utf8 (nl_langinfo_l(ABDAY_7, l), + -1, NULL, NULL, NULL); + priv->monthname[0] = g_locale_to_utf8 (nl_langinfo_l(MON_1, l), + -1, NULL, NULL, NULL); + priv->monthname[1] = g_locale_to_utf8 (nl_langinfo_l(MON_2, l), + -1, NULL, NULL, NULL); + priv->monthname[2] = g_locale_to_utf8 (nl_langinfo_l(MON_3, l), + -1, NULL, NULL, NULL); + priv->monthname[3] = g_locale_to_utf8 (nl_langinfo_l(MON_4, l), + -1, NULL, NULL, NULL); + priv->monthname[4] = g_locale_to_utf8 (nl_langinfo_l(MON_5, l), + -1, NULL, NULL, NULL); + priv->monthname[5] = g_locale_to_utf8 (nl_langinfo_l(MON_6, l), + -1, NULL, NULL, NULL); + priv->monthname[6] = g_locale_to_utf8 (nl_langinfo_l(MON_7, l), + -1, NULL, NULL, NULL); + priv->monthname[7] = g_locale_to_utf8 (nl_langinfo_l(MON_8, l), + -1, NULL, NULL, NULL); + priv->monthname[8] = g_locale_to_utf8 (nl_langinfo_l(MON_9, l), + -1, NULL, NULL, NULL); + priv->monthname[9] = g_locale_to_utf8 (nl_langinfo_l(MON_10, l), + -1, NULL, NULL, NULL); + priv->monthname[10] = g_locale_to_utf8 (nl_langinfo_l(MON_11, l), + -1, NULL, NULL, NULL); + priv->monthname[11] = g_locale_to_utf8 (nl_langinfo_l(MON_12, l), + -1, NULL, NULL, NULL); + + freelocale (l); +} + +static void +hildon_calendar_class_init (HildonCalendarClass *class) +{ + GObjectClass *gobject_class; + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + + gobject_class = (GObjectClass*) class; + object_class = (GtkObjectClass*) class; + widget_class = (GtkWidgetClass*) class; + + parent_class = g_type_class_peek_parent (class); + + gobject_class->set_property = hildon_calendar_set_property; + gobject_class->get_property = hildon_calendar_get_property; + gobject_class->finalize = hildon_calendar_finalize; + + object_class->destroy = hildon_calendar_destroy; + + widget_class->realize = hildon_calendar_realize; + widget_class->unrealize = hildon_calendar_unrealize; + widget_class->expose_event = hildon_calendar_expose; + widget_class->size_request = hildon_calendar_size_request; + widget_class->size_allocate = hildon_calendar_size_allocate; + widget_class->button_press_event = hildon_calendar_button_press; + widget_class->button_release_event = hildon_calendar_button_release; + widget_class->motion_notify_event = hildon_calendar_motion_notify; + widget_class->enter_notify_event = hildon_calendar_enter_notify; + widget_class->leave_notify_event = hildon_calendar_leave_notify; + widget_class->key_press_event = hildon_calendar_key_press; + widget_class->scroll_event = hildon_calendar_scroll; + widget_class->style_set = hildon_calendar_style_set; + widget_class->state_changed = hildon_calendar_state_changed; + widget_class->grab_notify = hildon_calendar_grab_notify; + widget_class->focus_out_event = hildon_calendar_focus_out; + + widget_class->drag_data_get = hildon_calendar_drag_data_get; + widget_class->drag_motion = hildon_calendar_drag_motion; + widget_class->drag_leave = hildon_calendar_drag_leave; + widget_class->drag_drop = hildon_calendar_drag_drop; + widget_class->drag_data_received = hildon_calendar_drag_data_received; + + class->month_changed = NULL; + class->day_selected = NULL; + class->day_selected_double_click = NULL; + class->prev_month = NULL; + class->next_month = NULL; + class->prev_year = NULL; + class->next_year = NULL; + + /** + * HildonCalendar:year: + * + * The selected year. + */ + g_object_class_install_property (gobject_class, + PROP_YEAR, + g_param_spec_int ("year", + "Year", + "The selected year", + 0, G_MAXINT, 0, + GTK_PARAM_READWRITE)); + + /** + * HildonCalendar:month: + * + * The selected month as number between 0 and 11. + */ + g_object_class_install_property (gobject_class, + PROP_MONTH, + g_param_spec_int ("month", + "Month", + "The selected month (as a number between 0 and 11)", + 0, 11, 0, + GTK_PARAM_READWRITE)); + + /** + * HildonCalendar:day: + * + * The selected day as number between 1 and 31 or 0 to unselect the currently selected day. + */ + g_object_class_install_property (gobject_class, + PROP_DAY, + g_param_spec_int ("day", + "Day", + "The selected day (as a number between 1 and 31, or 0 to unselect the currently selected day)", + 0, 31, 0, + GTK_PARAM_READWRITE)); + + /** + * HildonCalendar:show-heading: + * + * Determines whether a heading is displayed. + * + */ + g_object_class_install_property (gobject_class, + PROP_SHOW_HEADING, + g_param_spec_boolean ("show-heading", + "Show Heading", + "If TRUE, a heading is displayed", + TRUE, + GTK_PARAM_READWRITE)); + + /** + * HildonCalendar:show-day-names: + * + * Determines whether day names are displayed. + * + */ + g_object_class_install_property (gobject_class, + PROP_SHOW_DAY_NAMES, + g_param_spec_boolean ("show-day-names", + "Show Day Names", + "If TRUE, day names are displayed", + TRUE, + GTK_PARAM_READWRITE)); + /** + * HildonCalendar:no-month-change: + * + * Determines whether the selected month can be changed. + * + */ + g_object_class_install_property (gobject_class, + PROP_NO_MONTH_CHANGE, + g_param_spec_boolean ("no-month-change", + "No Month Change", + "If TRUE, the selected month cannot be changed", + FALSE, + GTK_PARAM_READWRITE)); + + /** + * HildonCalendar:show-week-numbers: + * + * Determines whether week numbers are displayed. + * + */ + g_object_class_install_property (gobject_class, + PROP_SHOW_WEEK_NUMBERS, + g_param_spec_boolean ("show-week-numbers", + "Show Week Numbers", + "If TRUE, week numbers are displayed", + FALSE, + GTK_PARAM_READWRITE)); + + /** + * HildonCalendar:week-start: + * + * Determines the start day of the week (0 for Sunday, 1 for Monday etc.) + * + */ + g_object_class_install_property (gobject_class, + PROP_WEEK_START, + g_param_spec_int ("week-start", + "Week start day", + "First day of the week; 0 for Sunday, 1 for Monday etc.", + 0, 6, 0, + GTK_PARAM_READWRITE)); + + /** + * HildonCalendar:min-year: + * + * Minimum valid year (0 if no limit). + * + */ + g_object_class_install_property (gobject_class, + PROP_MIN_YEAR, + g_param_spec_int ("min-year", + "Minimum valid year", + "Minimum valid year (0 if no limit)", + 0, 10000, 0, + GTK_PARAM_READWRITE)); + + /** + * HildonCalendar:max-year: + * + * Maximum valid year (0 if no limit). + * + */ + g_object_class_install_property (gobject_class, + PROP_MAX_YEAR, + g_param_spec_int ("max-year", + "Maximum valid year", + "Maximum valid year (0 if no limit)", + 0, 10000, 0, + GTK_PARAM_READWRITE)); + + hildon_calendar_signals[MONTH_CHANGED_SIGNAL] = + g_signal_new ("month_changed", + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (HildonCalendarClass, month_changed), + NULL, NULL, + _hildon_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + hildon_calendar_signals[DAY_SELECTED_SIGNAL] = + g_signal_new ("day_selected", + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (HildonCalendarClass, day_selected), + NULL, NULL, + _hildon_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + hildon_calendar_signals[DAY_SELECTED_DOUBLE_CLICK_SIGNAL] = + g_signal_new ("day_selected_double_click", + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (HildonCalendarClass, day_selected_double_click), + NULL, NULL, + _hildon_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + hildon_calendar_signals[PREV_MONTH_SIGNAL] = + g_signal_new ("prev_month", + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (HildonCalendarClass, prev_month), + NULL, NULL, + _hildon_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + hildon_calendar_signals[NEXT_MONTH_SIGNAL] = + g_signal_new ("next_month", + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (HildonCalendarClass, next_month), + NULL, NULL, + _hildon_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + hildon_calendar_signals[PREV_YEAR_SIGNAL] = + g_signal_new ("prev_year", + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (HildonCalendarClass, prev_year), + NULL, NULL, + _hildon_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + hildon_calendar_signals[NEXT_YEAR_SIGNAL] = + g_signal_new ("next_year", + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (HildonCalendarClass, next_year), + NULL, NULL, + _hildon_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * HildonCalendar::erroneous-date: + * + * Emitted when the user tries to set a date which is outside the boundaries + * set by min-year and max-year properties. + * + */ + hildon_calendar_signals[ERRONEOUS_DATE_SIGNAL] = + g_signal_new ("erroneous_date", + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + _hildon_marshal_VOID__VOID, + G_TYPE_NONE, 0); + /** + * HildonCalendar::selected-date: + * + * Emitted on button-release when the user has selected a date. + * + */ + hildon_calendar_signals[SELECTED_DATE_SIGNAL] = + g_signal_new ("selected_date", + G_OBJECT_CLASS_TYPE(gobject_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + _hildon_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +hildon_calendar_init (HildonCalendar *calendar) +{ + time_t secs; + struct tm *tm; + gint i; + /* char buffer[255];*/ + /* time_t tmp_time;*/ + GtkWidget *widget; + HildonCalendarPrivate *private_data; + /* gchar *year_before;*/ + /* gint row; + gint col; */ + gchar *langinfo; + GDateWeekday week_1stday; + gint first_weekday; + guint week_origin; + + widget = GTK_WIDGET (calendar); + GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS); + + calendar->private_data = g_malloc (sizeof (HildonCalendarPrivate)); + private_data = HILDON_CALENDAR_GET_PRIVATE (calendar); + + /* Set defaults */ + secs = time (NULL); + tm = localtime (&secs); + calendar->month = tm->tm_mon; + calendar->year = 1900 + tm->tm_year; + + for (i=0;i<31;i++) + calendar->marked_date[i] = FALSE; + calendar->num_marked_dates = 0; + calendar->selected_day = tm->tm_mday; + + calendar->display_flags = ( HILDON_CALENDAR_SHOW_HEADING | + HILDON_CALENDAR_SHOW_DAY_NAMES ); + + /* Hildon: we should mark current day and we need to store current date */ + private_data->current_day = tm->tm_mday; + private_data->current_month = tm->tm_mon; + private_data->current_year = tm->tm_year + 1900; + + /* Hildon: following lines are for stylus sliding */ + private_data->slide_stylus = FALSE; + private_data->prev_row = -1; + private_data->prev_col = -1; + + /* Hildon: is_bad_day indicate if day was selected out of legal range */ + private_data->is_bad_day = FALSE; + + calendar->highlight_row = -1; + calendar->highlight_col = -1; + + calendar->focus_row = -1; + calendar->focus_col = -1; + calendar->xor_gc = NULL; + + private_data->max_year_width = 0; + private_data->max_month_width = 0; + private_data->max_day_char_width = 0; + private_data->max_week_char_width = 0; + + private_data->max_day_char_ascent = 0; + private_data->max_day_char_descent = 0; + private_data->max_label_char_ascent = 0; + private_data->max_label_char_descent = 0; + + /* private_data->arrow_width = 10;*/ + + private_data->freeze_count = 0; + + private_data->dirty_header = 0; + private_data->dirty_day_names = 0; + private_data->dirty_week = 0; + private_data->dirty_main = 0; + + private_data->need_timer = 0; + private_data->timer = 0; + private_data->click_child = -1; + + private_data->in_drag = 0; + private_data->drag_highlight = 0; + + private_data->min_year = 0; + private_data->max_year = 0; + + gtk_drag_dest_set (widget, 0, NULL, 0, GDK_ACTION_COPY); + gtk_drag_dest_add_text_targets (widget); + +#if 0 + private_data->year_before = 0; + + /* Translate to calendar:YM if you want years to be displayed + * before months; otherwise translate to calendar:MY. + * Do *not* translate it to anything else, if it + * it isn't calendar:YM or calendar:MY it will not work. + * + * Note that this flipping is in top the text direction flipping, + * so if you have a default text direction of RTL and YM, then + * the year will appear on the right. + */ + year_before = _("calendar:MY"); + if (strcmp (year_before, "calendar:YM") == 0) + private_data->year_before = 1; + else if (strcmp (year_before, "calendar:MY") != 0) + g_warning ("Whoever translated calendar:MY did so wrongly.\n"); +#endif + langinfo = nl_langinfo (_NL_TIME_FIRST_WEEKDAY); + first_weekday = langinfo[0]; + langinfo = nl_langinfo (_NL_TIME_WEEK_1STDAY); + week_origin = GPOINTER_TO_UINT (langinfo); + if (week_origin == 19971130) + week_1stday = G_DATE_SUNDAY; + else if (week_origin == 19971201) + week_1stday = G_DATE_MONDAY; + else if (g_date_valid_dmy ((week_origin % 100), + (week_origin / 100) % 100, + (week_origin / 10000))) + { + GDate *date; + date = g_date_new_dmy ((week_origin % 100), + (week_origin / 100) % 100, + (week_origin / 10000)); + week_1stday = g_date_get_weekday (date); + g_date_free (date); + } + else + { + g_warning ("Invalid value set for _NL_TIME_WEEK_1STDAY"); + week_1stday = G_DATE_SUNDAY; + } + + private_data->week_start = (week_1stday + first_weekday - 1) % 7; + + locales_init (private_data); +} + +GtkWidget* +hildon_calendar_new (void) +{ + return g_object_new (HILDON_TYPE_CALENDAR, NULL); +} + +/* column_from_x: returns the column 0-6 that the + * x pixel of the xwindow is in */ +static gint +column_from_x (HildonCalendar *calendar, + gint event_x) +{ + gint c, column; + gint x_left, x_right; + + column = -1; + + for (c = 0; c < 7; c++) + { + x_left = left_x_for_column (calendar, c); + x_right = x_left + HILDON_CALENDAR_GET_PRIVATE (calendar)->day_width; + + if (event_x >= x_left && event_x < x_right) + { + column = c; + break; + } + } + + return column; +} +#if 0 + static gint +row_height (HildonCalendar *calendar) +{ + return (HILDON_CALENDAR_GET_PRIVATE (calendar)->main_h - CALENDAR_MARGIN + - ((calendar->display_flags & HILDON_CALENDAR_SHOW_DAY_NAMES) + ? CALENDAR_YSEP : CALENDAR_MARGIN)) / 6; +} +#endif + +/* row_from_y: returns the row 0-5 that the + * y pixel of the xwindow is in */ +static gint +row_from_y (HildonCalendar *calendar, + gint event_y) +{ + gint r, row; + /*gint height;*/ + gint y_top, y_bottom; + + row = -1; + + for (r = 0; r < 6; r++) + { + y_top = top_y_for_row (calendar, r); + y_bottom = y_top + HILDON_DAY_HEIGHT /*height*/; + + if (event_y >= y_top && event_y < y_bottom) + { + row = r; + break; + } + } + + return row; +} + +/* left_x_for_column: returns the x coordinate + * for the left of the column */ +static gint +left_x_for_column (HildonCalendar *calendar, + gint column) +{ + gint width; + gint x_left; + + if (gtk_widget_get_direction (GTK_WIDGET (calendar)) == GTK_TEXT_DIR_RTL) + column = 6 - column; + + width = HILDON_CALENDAR_GET_PRIVATE (calendar)->day_width; + if (calendar->display_flags & HILDON_CALENDAR_SHOW_WEEK_NUMBERS) + x_left = CALENDAR_XSEP + (width + DAY_XSEP) * column; + else + x_left = CALENDAR_MARGIN + (width + DAY_XSEP) * column; + + return x_left; +} + +/* top_y_for_row: returns the y coordinate + * for the top of the row */ +static gint +top_y_for_row (HildonCalendar *calendar, + gint row) +{ + return (HILDON_CALENDAR_GET_PRIVATE (calendar)->main_h + - (CALENDAR_MARGIN + (6 - row) + * HILDON_DAY_HEIGHT)); +} + +static void +hildon_calendar_set_month_prev (HildonCalendar *calendar) +{ + HildonCalendarPrivate *priv = HILDON_CALENDAR_GET_PRIVATE (calendar); + gint month_len; + + if (calendar->display_flags & HILDON_CALENDAR_NO_MONTH_CHANGE) + return; + + if (calendar->month == 0) + { + if (!priv->min_year || calendar->year > priv->min_year) + { + calendar->month = 11; + calendar->year--; + } + } + else + calendar->month--; + + month_len = month_length[leap (calendar->year)][calendar->month + 1]; + + hildon_calendar_freeze (calendar); + hildon_calendar_compute_days (calendar); + + g_signal_emit (calendar, + hildon_calendar_signals[PREV_MONTH_SIGNAL], + 0); + g_signal_emit (calendar, + hildon_calendar_signals[MONTH_CHANGED_SIGNAL], + 0); + + if (month_len < calendar->selected_day) + { + calendar->selected_day = 0; + hildon_calendar_select_day (calendar, month_len); + } + else + { + if (calendar->selected_day < 0) + calendar->selected_day = calendar->selected_day + 1 + month_length[leap (calendar->year)][calendar->month + 1]; + hildon_calendar_select_day (calendar, calendar->selected_day); + } + + gtk_widget_queue_draw (GTK_WIDGET (calendar)); + hildon_calendar_thaw (calendar); +} + +static void +hildon_calendar_set_month_next (HildonCalendar *calendar) +{ + HildonCalendarPrivate *priv; + gint month_len; + + g_return_if_fail (GTK_IS_WIDGET (calendar)); + + priv = HILDON_CALENDAR_GET_PRIVATE (calendar); + + if (calendar->display_flags & HILDON_CALENDAR_NO_MONTH_CHANGE) + return; + + if (calendar->month == 11) + { + if (!priv->max_year || calendar->year < priv->max_year) + { + calendar->month = 0; + calendar->year++; + } + } + else + calendar->month++; + + hildon_calendar_freeze (calendar); + hildon_calendar_compute_days (calendar); + g_signal_emit (calendar, + hildon_calendar_signals[NEXT_MONTH_SIGNAL], + 0); + g_signal_emit (calendar, + hildon_calendar_signals[MONTH_CHANGED_SIGNAL], + 0); + + month_len = month_length[leap (calendar->year)][calendar->month + 1]; + + if (month_len < calendar->selected_day) + { + calendar->selected_day = 0; + hildon_calendar_select_day (calendar, month_len); + } + else + hildon_calendar_select_day (calendar, calendar->selected_day); + + gtk_widget_queue_draw (GTK_WIDGET (calendar)); + hildon_calendar_thaw (calendar); +} + +static void +hildon_calendar_set_year_prev (HildonCalendar *calendar) +{ + HildonCalendarPrivate *priv; + gint month_len; + + g_return_if_fail (GTK_IS_WIDGET (calendar)); + + priv = HILDON_CALENDAR_GET_PRIVATE (calendar); + + if (!priv->min_year || priv->min_year < calendar->year) + calendar->year--; + + hildon_calendar_freeze (calendar); + hildon_calendar_compute_days (calendar); + g_signal_emit (calendar, + hildon_calendar_signals[PREV_YEAR_SIGNAL], + 0); + g_signal_emit (calendar, + hildon_calendar_signals[MONTH_CHANGED_SIGNAL], + 0); + + month_len = month_length[leap (calendar->year)][calendar->month + 1]; + + if (month_len < calendar->selected_day) + { + calendar->selected_day = 0; + hildon_calendar_select_day (calendar, month_len); + } + else + hildon_calendar_select_day (calendar, calendar->selected_day); + + gtk_widget_queue_draw (GTK_WIDGET (calendar)); + hildon_calendar_thaw (calendar); +} + +static void +hildon_calendar_set_year_next (HildonCalendar *calendar) +{ + HildonCalendarPrivate *priv; + gint month_len; + + g_return_if_fail (GTK_IS_WIDGET (calendar)); + priv = HILDON_CALENDAR_GET_PRIVATE (calendar); + + hildon_calendar_freeze (calendar); + + if (!priv->max_year || priv->max_year > calendar->year) + calendar->year++; + + hildon_calendar_compute_days (calendar); + g_signal_emit (calendar, + hildon_calendar_signals[NEXT_YEAR_SIGNAL], + 0); + g_signal_emit (calendar, + hildon_calendar_signals[MONTH_CHANGED_SIGNAL], + 0); + + month_len = month_length[leap (calendar->year)][calendar->month + 1]; + + if (month_len < calendar->selected_day) + { + calendar->selected_day = 0; + hildon_calendar_select_day (calendar, month_len); + } + else + hildon_calendar_select_day (calendar, calendar->selected_day); + gtk_widget_queue_draw (GTK_WIDGET (calendar)); + hildon_calendar_thaw (calendar); +} + +static void +hildon_calendar_main_button (GtkWidget *widget, + GdkEventButton *event) +{ + HildonCalendar *calendar; + HildonCalendarPrivate *private_data; + gint x, y; + gint row, col; + gint day_month; + gint day; + + calendar = HILDON_CALENDAR (widget); + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + + x = (gint) (event->x); + y = (gint) (event->y); + + row = row_from_y (calendar, y); + col = column_from_x (calendar, x); + + /* If row or column isn't found, just return. */ + if (row == -1 || col == -1) + return; + + day_month = calendar->day_month[row][col]; + + if ((calendar->year == private_data->min_year && + calendar->month == 0 && day_month == MONTH_PREV) || + (calendar->year == private_data->max_year && + calendar->month == 11 && day_month == MONTH_NEXT)) + { + private_data->is_bad_day = TRUE; + g_signal_emit (calendar, hildon_calendar_signals[ERRONEOUS_DATE_SIGNAL], 0); + return; + } + + if (event->type == GDK_BUTTON_RELEASE) + { + day = calendar->day[row][col]; + + if (day_month == MONTH_PREV) + { + hildon_calendar_set_month_prev (calendar); + } + else if (day_month == MONTH_NEXT) + { + hildon_calendar_set_month_next (calendar); + } + + if (!GTK_WIDGET_HAS_FOCUS (widget)) + gtk_widget_grab_focus (widget); + + if (event->button == 1) + { + private_data->in_drag = 1; + private_data->drag_start_x = x; + private_data->drag_start_y = y; + } + + hildon_calendar_select_and_focus_day (calendar, day); + } + else if (event->type == GDK_2BUTTON_PRESS) + { + private_data->in_drag = 0; + private_data->slide_stylus = FALSE; + if (day_month == MONTH_CURRENT) + g_signal_emit (calendar, + hildon_calendar_signals[DAY_SELECTED_DOUBLE_CLICK_SIGNAL], 0); + } +} + +static void +hildon_calendar_realize_arrows (GtkWidget *widget) +{ + HildonCalendar *calendar; + HildonCalendarPrivate *private_data; + GdkWindowAttr attributes; + gint attributes_mask; + gint i; + guint arrow_vlength, arrow_hlength; + /*gboolean year_left;*/ + + g_return_if_fail (HILDON_IS_CALENDAR (widget)); + + calendar = HILDON_CALENDAR (widget); + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + + gtk_widget_style_get (widget, + "scroll-arrow-hlength", &arrow_hlength, + "scroll-arrow-vlength", &arrow_vlength, + NULL); + /* + if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) + year_left = private_data->year_before; + else + year_left = !private_data->year_before; + */ + /* Arrow windows ------------------------------------- */ + if (! (calendar->display_flags & HILDON_CALENDAR_NO_MONTH_CHANGE) + && (calendar->display_flags & HILDON_CALENDAR_SHOW_HEADING)) + { + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.visual = gtk_widget_get_visual (widget); + attributes.colormap = gtk_widget_get_colormap (widget); + attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK + | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + attributes.y = 0; + attributes.width = arrow_vlength; + attributes.height = arrow_hlength; + + attributes.x = (widget->allocation.width - private_data->max_year_width) / 2 - arrow_vlength - HILDON_ARROW_SEP; + private_data->arrow_win[ARROW_YEAR_LEFT] = gdk_window_new (private_data->header_win, + &attributes, attributes_mask); + + attributes.x = (widget->allocation.width + private_data->max_year_width) / 2 + HILDON_ARROW_SEP; + private_data->arrow_win[ARROW_YEAR_RIGHT] = gdk_window_new (private_data->header_win, + &attributes, attributes_mask); + attributes.x = (widget->allocation.width - private_data->max_month_width) / 2 - arrow_vlength - HILDON_ARROW_SEP; + private_data->arrow_win[ARROW_MONTH_LEFT] = gdk_window_new (private_data->footer_win, + &attributes, attributes_mask); + attributes.x = (widget->allocation.width + private_data->max_month_width) / 2 + HILDON_ARROW_SEP; + private_data->arrow_win[ARROW_MONTH_RIGHT] = gdk_window_new (private_data->footer_win, + &attributes, attributes_mask); + + /* + for (i = 0; i < 4; i++) + { + switch (i) + { + case ARROW_MONTH_LEFT: + if (year_left) + attributes.x = (widget->allocation.width - 2 * widget->style->xthickness + - (3 + 2*private_data->arrow_width + + private_data->max_month_width)); + else + attributes.x = 3; + break; + case ARROW_MONTH_RIGHT: + if (year_left) + attributes.x = (widget->allocation.width - 2 * widget->style->xthickness + - 3 - private_data->arrow_width); + else + attributes.x = (private_data->arrow_width + + private_data->max_month_width); + break; + case ARROW_YEAR_LEFT: + if (year_left) + attributes.x = 3; + else + attributes.x = (widget->allocation.width - 2 * widget->style->xthickness + - (3 + 2*private_data->arrow_width + + private_data->max_year_width)); + break; + case ARROW_YEAR_RIGHT: + if (year_left) + attributes.x = (private_data->arrow_width + + private_data->max_year_width); + else + attributes.x = (widget->allocation.width - 2 * widget->style->xthickness + - 3 - private_data->arrow_width); + break; + } + private_data->arrow_win[i] = gdk_window_new (private_data->header_win, + &attributes, + attributes_mask);*/ + + for (i = 0; i < 4; i++) + { + if (GTK_WIDGET_IS_SENSITIVE (widget)) + private_data->arrow_state[i] = GTK_STATE_NORMAL; + else + private_data->arrow_state[i] = GTK_STATE_INSENSITIVE; + gdk_window_set_background (private_data->arrow_win[i], + HEADER_BG_COLOR (GTK_WIDGET (calendar))); + gdk_window_show (private_data->arrow_win[i]); + gdk_window_set_user_data (private_data->arrow_win[i], widget); + } + } + else + { + for (i = 0; i < 4; i++) + private_data->arrow_win[i] = NULL; + } +} + +static void +hildon_calendar_realize_header (GtkWidget *widget) +{ + HildonCalendar *calendar; + HildonCalendarPrivate *private_data; + GdkWindowAttr attributes; + gint attributes_mask; + guint arrow_hlength; + + g_return_if_fail (HILDON_IS_CALENDAR (widget)); + + calendar = HILDON_CALENDAR (widget); + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + + gtk_widget_style_get (widget, + "scroll-arrow-hlength", &arrow_hlength, + NULL); + /* Header window ------------------------------------- */ + if (calendar->display_flags & HILDON_CALENDAR_SHOW_HEADING) + { + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.visual = gtk_widget_get_visual (widget); + attributes.colormap = gtk_widget_get_colormap (widget); + attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK; + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + attributes.x = 0 /*widget->style->xthickness*/; + attributes.y = 0 /*widget->style->ythickness*/; + attributes.width = widget->allocation.width; /* - 2 * attributes.x */; + attributes.height = arrow_hlength /*private_data->header_h - 2 * attributes.y*/; + private_data->header_win = gdk_window_new (widget->window, + &attributes, attributes_mask); + + attributes.y = arrow_hlength + 2 * CALENDAR_YSEP + private_data->main_h + private_data->day_name_h; + + private_data->footer_win = gdk_window_new(widget->window, + &attributes, attributes_mask); + + gdk_window_set_background (private_data->header_win, + HEADER_BG_COLOR (widget)); + gdk_window_set_background (private_data->footer_win, + HEADER_BG_COLOR (widget)); + + gdk_window_show (private_data->header_win); + gdk_window_show (private_data->footer_win); + gdk_window_set_user_data (private_data->header_win, widget); + gdk_window_set_user_data (private_data->footer_win, widget); + } + else + { + private_data->header_win = NULL; + private_data->footer_win = NULL; + } + hildon_calendar_realize_arrows (widget); +} + +static void +hildon_calendar_realize_day_names (GtkWidget *widget) +{ + HildonCalendar *calendar; + HildonCalendarPrivate *private_data; + GdkWindowAttr attributes; + gint attributes_mask; + + g_return_if_fail (HILDON_IS_CALENDAR (widget)); + + calendar = HILDON_CALENDAR (widget); + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + + /* Day names window --------------------------------- */ + if ( calendar->display_flags & HILDON_CALENDAR_SHOW_DAY_NAMES) + { + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.visual = gtk_widget_get_visual (widget); + attributes.colormap = gtk_widget_get_colormap (widget); + attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK; + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + attributes.x = HILDON_DAY_WIDTH + HILDON_WEEKS_EXTRA_WIDTH/*(widget->style->xthickness + INNER_BORDER)*/; + attributes.y = private_data->header_h; + attributes.width = widget->allocation.width - attributes.x; + attributes.height = private_data->day_name_h; + private_data->day_name_win = gdk_window_new (widget->window, + &attributes, + attributes_mask); + gdk_window_set_background (private_data->day_name_win, + BACKGROUND_COLOR ( GTK_WIDGET (calendar))); + + gdk_window_show (private_data->day_name_win); + gdk_window_set_user_data (private_data->day_name_win, widget); + } + else + { + private_data->day_name_win = NULL; + } +} + +static void +hildon_calendar_realize_week_numbers (GtkWidget *widget) +{ + HildonCalendar *calendar; + HildonCalendarPrivate *private_data; + GdkWindowAttr attributes; + gint attributes_mask; + + g_return_if_fail (HILDON_IS_CALENDAR (widget)); + + calendar = HILDON_CALENDAR (widget); + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + + /* Week number window -------------------------------- */ + if (calendar->display_flags & HILDON_CALENDAR_SHOW_WEEK_NUMBERS) + { + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.visual = gtk_widget_get_visual (widget); + attributes.colormap = gtk_widget_get_colormap (widget); + attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK; + + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + attributes.x = 0 /*widget->style->xthickness + INNER_BORDER*/; + attributes.y = private_data->header_h; + /*+ (widget->style->ythickness + INNER_BORDER))*/; + attributes.width = HILDON_DAY_WIDTH + HILDON_WEEKS_EXTRA_WIDTH; + attributes.height = private_data->main_h + private_data->day_name_h; + private_data->week_win = gdk_window_new (widget->window, + &attributes, attributes_mask); + gdk_window_set_background (private_data->week_win, + BACKGROUND_COLOR (GTK_WIDGET (calendar))); + gdk_window_show (private_data->week_win); + gdk_window_set_user_data (private_data->week_win, widget); + } + else + { + private_data->week_win = NULL; + } +} + +static void +hildon_calendar_realize (GtkWidget *widget) +{ + HildonCalendar *calendar; + HildonCalendarPrivate *private_data; + GdkWindowAttr attributes; + gint attributes_mask; + GdkGCValues values; + + calendar = HILDON_CALENDAR (widget); + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + + GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); + hildon_calendar_compute_days (calendar); + + attributes.x = widget->allocation.x; + attributes.y = widget->allocation.y; + attributes.width = widget->allocation.width; + attributes.height = widget->allocation.height; + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.event_mask = (gtk_widget_get_events (widget) + | GDK_EXPOSURE_MASK |GDK_KEY_PRESS_MASK | GDK_SCROLL_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_COLORMAP; + widget->window = gdk_window_new (widget->parent->window, + &attributes, attributes_mask); + + widget->style = gtk_style_attach (widget->style, widget->window); + + /* Header window ------------------------------------- */ + hildon_calendar_realize_header (widget); + /* Day names window --------------------------------- */ + hildon_calendar_realize_day_names (widget); + /* Week number window -------------------------------- */ + hildon_calendar_realize_week_numbers (widget); + /* Main Window -------------------------------------- */ + attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK + | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + | GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK); + + attributes.x = HILDON_DAY_WIDTH + HILDON_WEEKS_EXTRA_WIDTH /*private_data->week_width + (widget->style->ythickness + INNER_BORDER)*/; + attributes.y = (private_data->header_h + private_data->day_name_h + + (widget->style->ythickness + INNER_BORDER)); + attributes.width = (widget->allocation.width - attributes.x + /*- (widget->style->xthickness + INNER_BORDER)*/); + attributes.height = private_data->main_h; + private_data->main_win = gdk_window_new (widget->window, + &attributes, attributes_mask); + gdk_window_set_background (private_data->main_win, + BACKGROUND_COLOR ( GTK_WIDGET ( calendar))); + gdk_window_show (private_data->main_win); + gdk_window_set_user_data (private_data->main_win, widget); + gdk_window_set_background (widget->window, BACKGROUND_COLOR (widget)); + gdk_window_show (widget->window); + gdk_window_set_user_data (widget->window, widget); + + /* Set widgets gc */ + calendar->gc = gdk_gc_new (widget->window); + + values.foreground = widget->style->white; + values.function = GDK_XOR; + calendar->xor_gc = gdk_gc_new_with_values (widget->window, + &values, + GDK_GC_FOREGROUND | + GDK_GC_FUNCTION); +} + +static void +hildon_calendar_unrealize (GtkWidget *widget) +{ + HildonCalendar *calendar; + HildonCalendarPrivate *private_data; + gint i; + + calendar = HILDON_CALENDAR (widget); + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + + if (private_data->header_win) + { + for (i = 0; i < 4; i++) + { + if (private_data->arrow_win[i]) + { + gdk_window_set_user_data (private_data->arrow_win[i], NULL); + gdk_window_destroy (private_data->arrow_win[i]); + private_data->arrow_win[i] = NULL; + } + } + gdk_window_set_user_data (private_data->header_win, NULL); + gdk_window_destroy (private_data->header_win); + private_data->header_win = NULL; + gdk_window_set_user_data (private_data->footer_win, NULL); + gdk_window_destroy (private_data->footer_win); + private_data->footer_win = NULL; + } + + if (private_data->week_win) + { + gdk_window_set_user_data (private_data->week_win, NULL); + gdk_window_destroy (private_data->week_win); + private_data->week_win = NULL; + } + + if (private_data->main_win) + { + gdk_window_set_user_data (private_data->main_win, NULL); + gdk_window_destroy (private_data->main_win); + private_data->main_win = NULL; + } + if (private_data->day_name_win) + { + gdk_window_set_user_data (private_data->day_name_win, NULL); + gdk_window_destroy (private_data->day_name_win); + private_data->day_name_win = NULL; + } + if (calendar->xor_gc) + g_object_unref (calendar->xor_gc); + if (calendar->gc) + g_object_unref (calendar->gc); + + if (GTK_WIDGET_CLASS (parent_class)->unrealize) + (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); +} + +static void +hildon_calendar_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + HildonCalendar *calendar; + HildonCalendarPrivate *private_data; + PangoLayout *layout; + PangoRectangle logical_rect; + + /*gint height;*/ + gint i; + gchar buffer[255]; + /*gint calendar_margin = CALENDAR_MARGIN;*/ + gint header_width, main_width; + gint max_header_height = 0; + gint focus_width; + gint focus_padding; + gint arrow_hlength; + + calendar = HILDON_CALENDAR (widget); + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + gtk_widget_style_get (GTK_WIDGET (widget), + "focus-line-width", &focus_width, + "focus-padding", &focus_padding, + "scroll-arrow-hlength", &arrow_hlength, + NULL); + + layout = gtk_widget_create_pango_layout (widget, NULL); + + /* + * Calculate the requisition width for the widget. + */ + + /* Header width */ + + if (calendar->display_flags & HILDON_CALENDAR_SHOW_HEADING) + { + private_data->max_month_width = 0; + for (i = 0; i < 12; i++) + { + pango_layout_set_text (layout, private_data->monthname[i], -1); + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + private_data->max_month_width = MAX (private_data->max_month_width, + logical_rect.width + 8); + max_header_height = MAX (max_header_height, logical_rect.height); + } + private_data->max_year_width = 0; + for (i=0; i<10; i++) + { + g_snprintf (buffer, sizeof (buffer), "%d%d%d%d", i,i,i,i); + pango_layout_set_text (layout, buffer, -1); + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + private_data->max_year_width = MAX (private_data->max_year_width, + logical_rect.width + 8); + max_header_height = MAX (max_header_height, logical_rect.height); + } + } + else + { + private_data->max_month_width = 0; + private_data->max_year_width = 0; + } + + if (calendar->display_flags & HILDON_CALENDAR_NO_MONTH_CHANGE) + header_width = (private_data->max_month_width + + private_data->max_year_width + + 3 * 3); + else + header_width = (private_data->max_month_width + + private_data->max_year_width + + 4 * private_data->arrow_width + 3 * 3); + + /* Mainwindow labels width */ + + private_data->max_day_char_width = 0; + private_data->min_day_width = 0; + private_data->max_label_char_ascent = 0; + private_data->max_label_char_descent = 0; + + for (i = 0; i < 9; i++) + { + g_snprintf (buffer, sizeof (buffer), "%d%d", i, i); + pango_layout_set_text (layout, buffer, -1); + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + private_data->min_day_width = MAX (private_data->min_day_width, + logical_rect.width); + + private_data->max_day_char_ascent = MAX (private_data->max_label_char_ascent, + PANGO_ASCENT (logical_rect)); + private_data->max_day_char_descent = MAX (private_data->max_label_char_descent, + PANGO_DESCENT (logical_rect)); + } + /* We add one to max_day_char_width to be able to make the marked day "bold" */ + private_data->max_day_char_width = private_data->min_day_width / 2 + 1; + + if (calendar->display_flags & HILDON_CALENDAR_SHOW_DAY_NAMES) + for (i = 0; i < 7; i++) + { + pango_layout_set_text (layout, private_data->abbreviated_dayname[i], -1); + pango_layout_line_get_pixel_extents (pango_layout_get_lines (layout)->data, NULL, &logical_rect); + + /* Hildon: add 4 so that passive focus wouldn't overlap day names */ + private_data->min_day_width = MAX (private_data->min_day_width, logical_rect.width + 4); + private_data->max_label_char_ascent = MAX (private_data->max_label_char_ascent, + PANGO_ASCENT (logical_rect)); + private_data->max_label_char_descent = MAX (private_data->max_label_char_descent, + PANGO_DESCENT (logical_rect)); + } + + private_data->max_week_char_width = 0; + if (calendar->display_flags & HILDON_CALENDAR_SHOW_WEEK_NUMBERS) + for (i = 0; i < 9; i++) + { + g_snprintf (buffer, sizeof (buffer), "%d%d", i, i); + pango_layout_set_text (layout, buffer, -1); + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + private_data->max_week_char_width = MAX (private_data->max_week_char_width, + logical_rect.width / 2); + } + + main_width = (7 * (private_data->min_day_width + (focus_padding + focus_width) * 2) + (DAY_XSEP * 6) + CALENDAR_MARGIN * 2 + + (private_data->max_week_char_width + ? private_data->max_week_char_width * 2 + (focus_padding + focus_width) * 2 + CALENDAR_XSEP * 2 + : 0)); + + /* requisition->width = MAX (header_width, main_width + INNER_BORDER * 2) + widget->style->xthickness * 2; + * + * FIXME: header_width is broken, when Calendar is themed ! + * Next line is workaround for this bug + */ + requisition->width = (main_width + INNER_BORDER * 2) + widget->style->xthickness * 2 + HILDON_WEEKS_EXTRA_WIDTH + HILDON_DAYS_EXTRA_WIDTH; + + /* + * Calculate the requisition height for the widget. + * This is Hildon calculation + */ + + if (calendar->display_flags & HILDON_CALENDAR_SHOW_HEADING) + private_data->header_h = arrow_hlength + CALENDAR_YSEP; + else + private_data->header_h = 0; + + if (calendar->display_flags & HILDON_CALENDAR_SHOW_DAY_NAMES) + private_data->day_name_h = HILDON_DAY_HEIGHT; + else + private_data->day_name_h = 0; + + private_data->main_h = 6 * HILDON_DAY_HEIGHT; + requisition->height = 2 * private_data->header_h + private_data->day_name_h + private_data->main_h; + + g_object_unref (layout); +} + +static void +hildon_calendar_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + HildonCalendar *calendar; + HildonCalendarPrivate *private_data; + gint xthickness = widget->style->xthickness; + /*gint ythickness = widget->style->xthickness;*/ + gboolean year_left; + gint arrow_vlength, arrow_hlength; + + widget->allocation = *allocation; + + calendar = HILDON_CALENDAR (widget); + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + + if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) + year_left = private_data->year_before; + else + year_left = !private_data->year_before; + + gtk_widget_style_get (widget, + "scroll-arrow-vlength", &arrow_vlength, + "scroll-arrow-hlength", &arrow_hlength, + NULL); + + if (calendar->display_flags & HILDON_CALENDAR_SHOW_WEEK_NUMBERS) + { + /* this variable is introduced to avoid breaking week_width because + of HILDON_WEEKS_EXTRA_WIDTH and HILDON_DAYS_EXTRA_WIDTH appearing + in calculation of day_width */ + int real_day_width = (private_data->min_day_width + * ((allocation->width + - (xthickness + INNER_BORDER) * 2 + - (CALENDAR_MARGIN * 2) - (DAY_XSEP * 6) - CALENDAR_XSEP * 2)) + / (7 * private_data->min_day_width + private_data->max_week_char_width * 2)); + + private_data->day_width = (private_data->min_day_width + * ((allocation->width + - (HILDON_WEEKS_EXTRA_WIDTH + HILDON_DAYS_EXTRA_WIDTH) + - (xthickness + INNER_BORDER) * 2 + - (CALENDAR_MARGIN * 2) - (DAY_XSEP * 6) - CALENDAR_XSEP * 2)) + / (7 * private_data->min_day_width + private_data->max_week_char_width * 2)); + private_data->week_width = ((allocation->width - (xthickness + INNER_BORDER) * 2 + - (CALENDAR_MARGIN * 2) - (DAY_XSEP * 6) - CALENDAR_XSEP * 2 ) + - real_day_width * 7 + CALENDAR_MARGIN + CALENDAR_XSEP); + } + else + { + private_data->day_width = (allocation->width + - (xthickness + INNER_BORDER) * 2 + - (CALENDAR_MARGIN * 2) + - (DAY_XSEP * 6))/7; + private_data->week_width = 0; + } + + if (GTK_WIDGET_REALIZED (widget)) + { + gdk_window_move_resize (widget->window, + allocation->x, allocation->y, + allocation->width, allocation->height); + if (private_data->header_win) + gdk_window_move_resize (private_data->header_win, + 0, 0, widget->allocation.width, arrow_hlength); + if (private_data->arrow_win[ARROW_YEAR_LEFT]) + { + /* if (year_left) + gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_LEFT], + 3, 3, + private_data->arrow_width, + private_data->header_h - 7); + else + gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_LEFT], + (allocation->width - 2 * xthickness + - (3 + 2*private_data->arrow_width + + private_data->max_year_width)), + 3, + private_data->arrow_width, + private_data->header_h - 7);*/ + + gdk_window_move (private_data->arrow_win[ARROW_YEAR_LEFT], + (widget->allocation.width - private_data->max_year_width) / 2 - arrow_vlength - HILDON_ARROW_SEP, 0); + } + if (private_data->arrow_win[ARROW_YEAR_RIGHT]) + { + /* if (year_left) + gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_RIGHT], + (private_data->arrow_width + + private_data->max_year_width), + 3, + private_data->arrow_width, + private_data->header_h - 7); + else + gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_RIGHT], + (allocation->width - 2 * xthickness + - 3 - private_data->arrow_width), + 3, + private_data->arrow_width, + private_data->header_h - 7);*/ + gdk_window_move (private_data->arrow_win[ARROW_YEAR_RIGHT], + (widget->allocation.width + private_data->max_year_width) / 2 + HILDON_ARROW_SEP, 0); + } + if (private_data->footer_win) + gdk_window_move_resize (private_data->footer_win, + 0, private_data->header_h + private_data->day_name_h + private_data->main_h + CALENDAR_YSEP, + widget->allocation.width, arrow_hlength); + + if (private_data->arrow_win[ARROW_MONTH_LEFT]) + { + /* if (year_left) + gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_LEFT], + (allocation->width - 2 * xthickness + - (3 + 2*private_data->arrow_width + + private_data->max_month_width)), + 3, + private_data->arrow_width, + private_data->header_h - 7); + else + gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_LEFT], + 3, 3, + private_data->arrow_width, + private_data->header_h - 7); + */ + + gdk_window_move (private_data->arrow_win[ARROW_MONTH_LEFT], + (widget->allocation.width - private_data->max_month_width) / 2 - arrow_vlength - HILDON_ARROW_SEP, 0); + } + if (private_data->arrow_win[ARROW_MONTH_RIGHT]) + { + /* if (year_left) + gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_RIGHT], + (allocation->width - 2 * xthickness + - 3 - private_data->arrow_width), + 3, + private_data->arrow_width, + private_data->header_h - 7); + else + gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_RIGHT], + (private_data->arrow_width + + private_data->max_month_width), + 3, + private_data->arrow_width, + private_data->header_h - 7);*/ + gdk_window_move (private_data->arrow_win[ARROW_MONTH_RIGHT], + (widget->allocation.width + private_data->max_month_width) / 2 + HILDON_ARROW_SEP, 0); + } + + + if (private_data->day_name_win) + gdk_window_move_resize (private_data->day_name_win, + private_data->week_width, /*xthickness + INNER_BORDER*/ + private_data->header_h /*+ (widget->style->ythickness + INNER_BORDER)*/, + widget->allocation.width - private_data->week_width /*- (xthickness + INNER_BORDER) * 2*/, + private_data->day_name_h); + if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) + { + if (private_data->week_win) + gdk_window_move_resize (private_data->week_win, + 0 /*(xthickness + INNER_BORDER)*/, + private_data->header_h /*+ (widget->style->ythickness + INNER_BORDER)*/, + HILDON_DAY_WIDTH, + private_data->main_h + private_data->day_name_h); + gdk_window_move_resize (private_data->main_win, + private_data->week_width /* + (xthickness + INNER_BORDER)*/, + private_data->header_h + private_data->day_name_h + /*+ (widget->style->ythickness + INNER_BORDER)*/, + widget->allocation.width - private_data->week_width + /*- (xthickness + INNER_BORDER) * 2*/, + private_data->main_h); + } + else + { + gdk_window_move_resize (private_data->main_win, + 0 /*(xthickness + INNER_BORDER)*/, + private_data->header_h + private_data->day_name_h + /*+ (widget->style->ythickness + INNER_BORDER)*/, + widget->allocation.width + - private_data->week_width + /*- (xthickness + INNER_BORDER) * 2*/, + private_data->main_h); + if (private_data->week_win) + gdk_window_move_resize (private_data->week_win, + widget->allocation.width + - private_data->week_width + /*- (xthickness + INNER_BORDER)*/, + private_data->header_h + private_data->day_name_h + /*+ (widget->style->ythickness + INNER_BORDER)*/, + private_data->week_width, + private_data->main_h); + } + } +} + +static gboolean +hildon_calendar_expose (GtkWidget *widget, + GdkEventExpose *event) +{ + HildonCalendarPrivate *private_data; + + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + + if (GTK_WIDGET_DRAWABLE (widget)) + { + if (event->window == private_data->main_win) + hildon_calendar_paint_main (widget); + + if (event->window == private_data->header_win) + hildon_calendar_paint_header (widget); + if (event->window == private_data->footer_win) + hildon_calendar_paint_footer(widget); + + if (event->window == private_data->day_name_win) + hildon_calendar_paint_day_names (widget); + + if (event->window == private_data->week_win) + hildon_calendar_paint_week_numbers (widget); + } + + /* FIXME This appeared after 2.6 -> 2.10 migration. Without this the + * arrows disappear when spinning through the calendar. Apparently, something + * overdraws them somehow or the expose events go into blackhole. This is + * a dirty fix... but kinda works */ + + hildon_calendar_paint_header (widget); + hildon_calendar_paint_footer (widget); + + return FALSE; +} + +static void +hildon_calendar_paint_header (GtkWidget *widget) +{ + HildonCalendar *calendar; + GdkGC *gc; + char buffer[255]; + int x, y; + gint header_width, cal_height; + HildonCalendarPrivate *private_data; + PangoLayout *layout; + PangoRectangle logical_rect; + gint arrow_hlength; + + calendar = HILDON_CALENDAR (widget); + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + + if (private_data->freeze_count) + { + private_data->dirty_header = 1; + return; + } + + private_data->dirty_header = 0; + gc = calendar->gc; + + /* Clear window */ + gdk_window_clear (private_data->header_win); + + header_width = widget->allocation.width /*- 2 * widget->style->xthickness*/; + cal_height = widget->allocation.height; + + g_snprintf (buffer, sizeof (buffer), "%d", calendar->year); + layout = gtk_widget_create_pango_layout (widget, buffer); + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + + gtk_widget_style_get (widget, "scroll-arrow-hlength", &arrow_hlength, NULL); + + y = (arrow_hlength - logical_rect.height) / 2; + x = (widget->allocation.width - logical_rect.width) / 2; + + /* Draw year and its arrows */ + gdk_gc_set_foreground (gc, HEADER_FG_COLOR (GTK_WIDGET (calendar))); + gdk_draw_layout (private_data->header_win, gc, x, y, layout); + + hildon_calendar_paint_arrow (widget, ARROW_YEAR_LEFT); + hildon_calendar_paint_arrow (widget, ARROW_YEAR_RIGHT); + + g_object_unref (layout); +} + +static void +hildon_calendar_paint_footer (GtkWidget *widget) +{ + HildonCalendar *calendar; + GdkGC *gc; + char buffer[255]; + int x, y; + gint header_width, cal_height; + HildonCalendarPrivate *private_data; + PangoLayout *layout; + PangoRectangle logical_rect; + gint arrow_hlength; + + calendar = HILDON_CALENDAR (widget); + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + + if (private_data->freeze_count) + { + private_data->dirty_header = 1; + return; + } + + private_data->dirty_header = 0; + gc = calendar->gc; + + /* Clear window */ + gdk_window_clear (private_data->footer_win); + + header_width = widget->allocation.width - 2 * widget->style->xthickness; + cal_height = widget->allocation.height; + + /* Draw month and its arrows */ + g_snprintf (buffer, sizeof (buffer), "%s", private_data->monthname[calendar->month]); + layout = gtk_widget_create_pango_layout (widget, buffer); + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + + gtk_widget_style_get (widget, "scroll-arrow-hlength", &arrow_hlength, NULL); + + x = (widget->allocation.width - logical_rect.width) / 2; + y = (arrow_hlength - logical_rect.height) / 2; + + gdk_gc_set_foreground (gc, HEADER_FG_COLOR(GTK_WIDGET (calendar))); + gdk_draw_layout (private_data->footer_win, gc, x, y, layout); + + hildon_calendar_paint_arrow (widget, ARROW_MONTH_LEFT); + hildon_calendar_paint_arrow (widget, ARROW_MONTH_RIGHT); + + g_object_unref(layout); +} + +static void +hildon_calendar_paint_day_names (GtkWidget *widget) +{ + HildonCalendar *calendar; + GdkGC *gc; + char buffer[255]; + int day,i; + int day_width, cal_width; + gint cal_height; + int day_wid_sep; + PangoLayout *layout; + PangoRectangle logical_rect; + HildonCalendarPrivate *private_data; + gint focus_padding; + gint focus_width; + + g_return_if_fail (HILDON_IS_CALENDAR (widget)); + calendar = HILDON_CALENDAR (widget); + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + gc = calendar->gc; + + gtk_widget_style_get (GTK_WIDGET (widget), + "focus-line-width", &focus_width, + "focus-padding", &focus_padding, + NULL); + /* + * Handle freeze/thaw functionality + */ + + if (private_data->freeze_count) + { + private_data->dirty_day_names = 1; + return; + } + private_data->dirty_day_names = 0; + + /* + * Clear the window + */ + + gdk_window_clear (private_data->day_name_win); + + day_width = private_data->day_width; + cal_width = widget->allocation.width; + cal_height = widget->allocation.height; + day_wid_sep = day_width + DAY_XSEP; + + /* + * Draw rectangles as inverted background for the labels. + */ + + /* + * Write the labels + */ + + layout = gtk_widget_create_pango_layout (widget, NULL); + + gdk_gc_set_foreground (gc, SELECTED_FG_COLOR (widget)); + for (i = 0; i < 7; i++) + { + guint x = left_x_for_column (calendar, i); + + if (gtk_widget_get_direction (GTK_WIDGET (calendar)) == GTK_TEXT_DIR_RTL) + day = 6 - i; + else + day = i; + day = (day + private_data->week_start) % 7; + g_snprintf (buffer, sizeof (buffer), "%s", private_data->abbreviated_dayname[day]); + + pango_layout_set_text (layout, buffer, -1); + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + + /* Hildon: draw passive focus for day name */ + if (calendar->focus_col == i) + gtk_paint_box(GTK_WIDGET (calendar)->style, + private_data->day_name_win, + GTK_STATE_NORMAL, + GTK_SHADOW_OUT, NULL, + GTK_WIDGET (calendar), "passive-focus", + x, + 0, + logical_rect.width + 4, + HILDON_DAY_HEIGHT); + + gdk_draw_layout (private_data->day_name_win, gc, + x + 2, + CALENDAR_MARGIN + focus_width + focus_padding + logical_rect.y, + layout); + } + g_object_unref (layout); +} + +static void +hildon_calendar_paint_week_numbers (GtkWidget *widget) +{ + HildonCalendar *calendar; + GdkGC *gc; + guint row, week = 0, year; + gint x_loc; + char buffer[10]; + gint y_loc; + HildonCalendarPrivate *private_data; + PangoLayout *layout; + PangoRectangle logical_rect; + gint focus_padding; + gint focus_width; + + g_return_if_fail (HILDON_IS_CALENDAR (widget)); + g_return_if_fail (widget->window != NULL); + calendar = HILDON_CALENDAR (widget); + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + gc = calendar->gc; + + /* + * Handle freeze/thaw functionality + */ + + if (private_data->freeze_count) + { + private_data->dirty_week = 1; + return; + } + private_data->dirty_week = 0; + + gtk_widget_style_get (GTK_WIDGET (widget), + "focus-line-width", &focus_width, + "focus-padding", &focus_padding, + NULL); + + /* + * Clear the window + */ + + gdk_window_clear (private_data->week_win); + + /* + * Draw a rectangle as inverted background for the labels. + */ + + gdk_gc_set_foreground (gc, SELECTED_BG_COLOR (widget)); + + /* Hildon: don't paint background for weekday window */ + + /* + * Write the labels + */ + + layout = gtk_widget_create_pango_layout (widget, NULL); + + gdk_gc_set_foreground (gc, SELECTED_FG_COLOR (widget)); + gdk_draw_line(private_data->week_win, gc, + HILDON_DAY_WIDTH + 7, + 0, + HILDON_DAY_WIDTH + 7, + private_data->main_h + private_data->day_name_h); + + for (row = 0; row < 6; row++) + { + year = calendar->year; + if (calendar->day[row][6] < 15 && row > 3 && calendar->month == 11) + year++; + + g_return_if_fail (week_of_year (&week, &year, + ((calendar->day[row][6] < 15 && row > 3 ? 1 : 0) + + calendar->month) % 12 + 1, calendar->day[row][6])); + + g_snprintf (buffer, sizeof (buffer), "%d", week); + pango_layout_set_text (layout, buffer, -1); + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + + /* Hildon: draw passive focus for week */ + if (calendar->focus_row == row) + { + guint y = top_y_for_row (calendar, calendar->focus_row + 1); + + gtk_paint_box(GTK_WIDGET (calendar)->style, + private_data->week_win, + GTK_STATE_NORMAL, + GTK_SHADOW_OUT, NULL, + GTK_WIDGET (calendar), "passive-focus", + 0, y, + private_data->week_width/* - 4*/, + HILDON_DAY_HEIGHT); + } + + y_loc = private_data->day_name_h + top_y_for_row (calendar, row) + (HILDON_DAY_HEIGHT - logical_rect.height) / 2; + x_loc = (HILDON_DAY_WIDTH - logical_rect.width) / 2; + + gdk_draw_layout (private_data->week_win, gc, x_loc, y_loc, layout); + } + + g_object_unref (layout); +} + +static void +hildon_calendar_paint_day_num (GtkWidget *widget, + gint day) +{ + HildonCalendar *calendar; + gint r, c, row, col; + HildonCalendarPrivate *private_data; + g_return_if_fail (HILDON_IS_CALENDAR (widget)); + + calendar = HILDON_CALENDAR (widget); + + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + + row = -1; + col = -1; + for (r = 0; r < 6; r++) + for (c = 0; c < 7; c++) + if (calendar->day_month[r][c] == MONTH_CURRENT && + calendar->day[r][c] == day) + { + row = r; + col = c; + } + + g_return_if_fail (row != -1); + g_return_if_fail (col != -1); + + hildon_calendar_paint_day (widget, row, col); +} + +static void +hildon_calendar_paint_day (GtkWidget *widget, + gint row, + gint col) +{ + HildonCalendar *calendar; + GdkGC *gc; + gchar buffer[255]; + gint day; + gint x_left; + gint x_loc; + gint y_top; + gint y_loc; + gint focus_width; + + HildonCalendarPrivate *private_data; + PangoLayout *layout; + PangoRectangle logical_rect; + + g_return_if_fail (HILDON_IS_CALENDAR (widget)); + g_return_if_fail (row < 6); + g_return_if_fail (col < 7); + calendar = HILDON_CALENDAR (widget); + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + + if (private_data->main_win == NULL) return; + + /* + * Handle freeze/thaw functionality + */ + + if (private_data->freeze_count) + { + private_data->dirty_main = 1; + return; + } + + gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL); + + day = calendar->day[row][col]; + x_left = left_x_for_column (calendar, col); + y_top = top_y_for_row (calendar, row); + + gdk_window_clear_area (private_data->main_win, x_left, y_top, + HILDON_DAY_WIDTH, HILDON_DAY_HEIGHT); + + gc = calendar->gc; + + if (calendar->day_month[row][col] == MONTH_PREV) + { + gdk_gc_set_foreground (gc, PREV_MONTH_COLOR (GTK_WIDGET (calendar))); + } + else if (calendar->day_month[row][col] == MONTH_NEXT) + { + gdk_gc_set_foreground (gc, NEXT_MONTH_COLOR (GTK_WIDGET (calendar))); + } + else + { + if (calendar->selected_day == day) + { + /* Hildon: use custom graphics */ + gtk_paint_box(GTK_WIDGET (calendar)->style, + private_data->main_win, + GTK_STATE_NORMAL, + GTK_SHADOW_NONE, NULL, + GTK_WIDGET (calendar), "active-day", + x_left, y_top, + HILDON_DAY_WIDTH, + HILDON_DAY_HEIGHT); + } + if (calendar->marked_date[day-1]) + gdk_gc_set_foreground (gc, MARKED_COLOR (GTK_WIDGET (calendar))); + else + gdk_gc_set_foreground (gc, NORMAL_DAY_COLOR (GTK_WIDGET (calendar))); + if (calendar->selected_day == day) + gdk_gc_set_foreground (gc, SELECTED_FG_COLOR (GTK_WIDGET (calendar))); + else + gdk_gc_set_foreground (gc, & (GTK_WIDGET (calendar)->style->fg[GTK_WIDGET_STATE (calendar)])); + } + + if (GTK_WIDGET_HAS_FOCUS (calendar) && + calendar->focus_row == row && + calendar->focus_col == col) + { + GtkStateType state; + + if (calendar->selected_day == day) + state = GTK_WIDGET_HAS_FOCUS (widget) ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE; + else + state = GTK_STATE_NORMAL; + + gtk_paint_focus (widget->style, + private_data->main_win, + (calendar->selected_day == day) + ? GTK_STATE_SELECTED : GTK_STATE_NORMAL, + NULL, widget, "calendar-day", + x_left, y_top, + HILDON_DAY_WIDTH, + HILDON_DAY_HEIGHT); + } + + /* Hildon: paint green indicator for current day */ + if ((day == private_data->current_day && calendar->selected_day != + private_data->current_day) && (calendar->day_month[row][col] == MONTH_CURRENT)) + hildon_calendar_check_current_date (calendar, x_left, y_top); + + g_snprintf (buffer, sizeof (buffer), "%d", day); + layout = gtk_widget_create_pango_layout (widget, buffer); + pango_layout_get_pixel_extents (layout, NULL, &logical_rect); + + x_loc = x_left + (HILDON_DAY_WIDTH - logical_rect.width) / 2; + y_loc = y_top + (HILDON_DAY_HEIGHT - logical_rect.height) / 2; + + gdk_draw_layout (private_data->main_win, gc, + x_loc, y_loc, layout); + if (calendar->marked_date[day-1] && + calendar->day_month[row][col] == MONTH_CURRENT) + gdk_draw_layout (private_data->main_win, gc, + x_loc-1, y_loc, layout); + + g_object_unref (layout); +} + +static void +hildon_calendar_paint_main (GtkWidget *widget) +{ + HildonCalendarPrivate *private_data; + gint row, col; + + g_return_if_fail (HILDON_IS_CALENDAR (widget)); + g_return_if_fail (widget->window != NULL); + + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + + if (private_data->freeze_count) + { + private_data->dirty_main = 1; + return; + } + private_data->dirty_main = 0; + gdk_window_clear (private_data->main_win); + + for (col = 0; col < 7; col++) + for (row = 0; row < 6; row++) + hildon_calendar_paint_day (widget, row, col); +} + +static void +hildon_calendar_compute_days (HildonCalendar *calendar) +{ + HildonCalendarPrivate *private_data; + gint month; + gint year; + gint ndays_in_month; + gint ndays_in_prev_month; + gint first_day; + gint row; + gint col; + gint day; + + g_return_if_fail (HILDON_IS_CALENDAR (calendar)); + + private_data = HILDON_CALENDAR_GET_PRIVATE (GTK_WIDGET (calendar)); + + year = calendar->year; + month = calendar->month + 1; + + ndays_in_month = month_length[leap (year)][month]; + + first_day = day_of_week (year, month, 1); + first_day = (first_day + 7 - private_data->week_start) % 7; + + /* Compute days of previous month */ + if (month > 1) + ndays_in_prev_month = month_length[leap (year)][month-1]; + else + ndays_in_prev_month = month_length[leap (year)][12]; + day = ndays_in_prev_month - first_day + 1; + + row = 0; + if (first_day > 0) + { + for (col = 0; col < first_day; col++) + { + calendar->day[row][col] = day; + calendar->day_month[row][col] = MONTH_PREV; + day++; + } + } + + /* Compute days of current month */ + col = first_day; + for (day = 1; day <= ndays_in_month; day++) + { + calendar->day[row][col] = day; + calendar->day_month[row][col] = MONTH_CURRENT; + + col++; + if (col == 7) + { + row++; + col = 0; + } + } + + /* Compute days of next month */ + day = 1; + for (; row <= 5; row++) + { + for (; col <= 6; col++) + { + calendar->day[row][col] = day; + calendar->day_month[row][col] = MONTH_NEXT; + day++; + } + col = 0; + } +} + +/** + * hildon_calendar_get_display_options: + * @calendar: a #HildonCalendar + * + * Returns the current display options of @calendar. + * + * Return value: the display options. + **/ +HildonCalendarDisplayOptions +hildon_calendar_get_display_options (HildonCalendar *calendar) +{ + g_return_val_if_fail (HILDON_IS_CALENDAR (calendar), 0); + + return calendar->display_flags; +} + +/** + * hildon_calendar_set_display_options: + * @calendar: a #HildonCalendar + * @flags: the display options to set + * + * Sets display options (whether to display the heading and the month + * headings). + * + **/ +void +hildon_calendar_set_display_options (HildonCalendar *calendar, + HildonCalendarDisplayOptions flags) +{ + HildonCalendarPrivate *private_data; + gint resize = 0; + GtkWidget *widget; + gint i; + HildonCalendarDisplayOptions old_flags; + + g_return_if_fail (HILDON_IS_CALENDAR (calendar)); + + widget = GTK_WIDGET (calendar); + private_data = HILDON_CALENDAR_GET_PRIVATE (calendar); + old_flags = calendar->display_flags; + + if (GTK_WIDGET_REALIZED (widget)) + { + if ((flags ^ calendar->display_flags) & HILDON_CALENDAR_NO_MONTH_CHANGE) + { + resize ++; + if (! (flags & HILDON_CALENDAR_NO_MONTH_CHANGE) + && (private_data->header_win)) + { + calendar->display_flags &= ~HILDON_CALENDAR_NO_MONTH_CHANGE; + hildon_calendar_realize_arrows (widget); + } + else + { + for (i = 0; i < 4; i++) + { + if (private_data->arrow_win[i]) + { + gdk_window_set_user_data (private_data->arrow_win[i], + NULL); + gdk_window_destroy (private_data->arrow_win[i]); + private_data->arrow_win[i] = NULL; + } + } + } + } + + if ((flags ^ calendar->display_flags) & HILDON_CALENDAR_SHOW_HEADING) + { + resize++; + + if (flags & HILDON_CALENDAR_SHOW_HEADING) + { + calendar->display_flags |= HILDON_CALENDAR_SHOW_HEADING; + hildon_calendar_realize_header (widget); + } + else + { + for (i = 0; i < 4; i++) + { + if (private_data->arrow_win[i]) + { + gdk_window_set_user_data (private_data->arrow_win[i], + NULL); + gdk_window_destroy (private_data->arrow_win[i]); + private_data->arrow_win[i] = NULL; + } + } + gdk_window_set_user_data (private_data->header_win, NULL); + gdk_window_destroy (private_data->header_win); + private_data->header_win = NULL; + } + } + + + if ((flags ^ calendar->display_flags) & HILDON_CALENDAR_SHOW_DAY_NAMES) + { + resize++; + + if (flags & HILDON_CALENDAR_SHOW_DAY_NAMES) + { + calendar->display_flags |= HILDON_CALENDAR_SHOW_DAY_NAMES; + hildon_calendar_realize_day_names (widget); + } + else + { + gdk_window_set_user_data (private_data->day_name_win, NULL); + gdk_window_destroy (private_data->day_name_win); + private_data->day_name_win = NULL; + } + } + + if ((flags ^ calendar->display_flags) & HILDON_CALENDAR_SHOW_WEEK_NUMBERS) + { + resize++; + + if (flags & HILDON_CALENDAR_SHOW_WEEK_NUMBERS) + { + calendar->display_flags |= HILDON_CALENDAR_SHOW_WEEK_NUMBERS; + hildon_calendar_realize_week_numbers (widget); + } + else + { + gdk_window_set_user_data (private_data->week_win, NULL); + gdk_window_destroy (private_data->week_win); + private_data->week_win = NULL; + } + } + + if ((flags ^ calendar->display_flags) & HILDON_CALENDAR_WEEK_START_MONDAY) + g_warning ("HILDON_CALENDAR_WEEK_START_MONDAY is ignored; the first day of the week is determined from the locale"); + + calendar->display_flags = flags; + if (resize) + gtk_widget_queue_resize (GTK_WIDGET (calendar)); + + } + else + calendar->display_flags = flags; + + g_object_freeze_notify (G_OBJECT (calendar)); + if ((old_flags ^ calendar->display_flags) & HILDON_CALENDAR_SHOW_HEADING) + g_object_notify (G_OBJECT (calendar), "show-heading"); + if ((old_flags ^ calendar->display_flags) & HILDON_CALENDAR_SHOW_DAY_NAMES) + g_object_notify (G_OBJECT (calendar), "show-day-names"); + if ((old_flags ^ calendar->display_flags) & HILDON_CALENDAR_NO_MONTH_CHANGE) + g_object_notify (G_OBJECT (calendar), "no-month-change"); + if ((old_flags ^ calendar->display_flags) & HILDON_CALENDAR_SHOW_WEEK_NUMBERS) + g_object_notify (G_OBJECT (calendar), "show-week-numbers"); + g_object_thaw_notify (G_OBJECT (calendar)); +} + +gboolean +hildon_calendar_select_month (HildonCalendar *calendar, + guint month, + guint year) +{ + HildonCalendarPrivate *priv; + + g_return_val_if_fail (HILDON_IS_CALENDAR (calendar), FALSE); + g_return_val_if_fail (month <= 11, FALSE); + + priv = HILDON_CALENDAR_GET_PRIVATE (calendar); + + if (priv->max_year && year > priv->max_year) + year = priv->max_year; + if (priv->min_year && year < priv->min_year) + year = priv->min_year; + + calendar->month = month; + calendar->year = year; + + hildon_calendar_compute_days (calendar); + + gtk_widget_queue_draw (GTK_WIDGET (calendar)); + + g_object_freeze_notify (G_OBJECT (calendar)); + g_object_notify (G_OBJECT (calendar), "month"); + g_object_notify (G_OBJECT (calendar), "year"); + g_object_thaw_notify (G_OBJECT (calendar)); + + g_signal_emit (calendar, + hildon_calendar_signals[MONTH_CHANGED_SIGNAL], + 0); + return TRUE; +} + +void +hildon_calendar_select_day (HildonCalendar *calendar, + guint day) +{ + gint row, col; + HildonCalendarPrivate *priv; + g_return_if_fail (HILDON_IS_CALENDAR (calendar)); + g_return_if_fail (day <= 31); + priv = HILDON_CALENDAR_GET_PRIVATE (calendar); + + for (row = 0; row < 6; row ++) + for (col = 0; col < 7; col++) + { + if (calendar->day_month[row][col] == MONTH_CURRENT + && calendar->day[row][col] == day) + { + calendar->focus_row = row; + calendar->focus_col = col; + } + } + + if (calendar->month != priv->current_month || + calendar->year != priv->current_year) + hildon_calendar_unmark_day (calendar, priv->current_day); + + /* Deselect the old day */ + if (calendar->selected_day > 0) + { + gint selected_day; + + selected_day = calendar->selected_day; + calendar->selected_day = 0; + if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar))) + { + hildon_calendar_paint_day_num (GTK_WIDGET (calendar), selected_day); + } + } + + calendar->selected_day = day; + + /*printf("Selected day = %d\n", day);*/ + + /* Select the new day */ + if (day != 0) + { + if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar))) + { + hildon_calendar_paint_day_num (GTK_WIDGET (calendar), day); + } + } + + g_object_notify (G_OBJECT (calendar), "day"); + g_signal_emit (calendar, + hildon_calendar_signals[DAY_SELECTED_SIGNAL], + 0); +} + +static void +hildon_calendar_select_and_focus_day (HildonCalendar *calendar, + guint day) +{ + gint old_focus_row = calendar->focus_row; + gint old_focus_col = calendar->focus_col; + gint row; + gint col; + + for (row = 0; row < 6; row ++) + for (col = 0; col < 7; col++) + { + if (calendar->day_month[row][col] == MONTH_CURRENT + && calendar->day[row][col] == day) + { + calendar->focus_row = row; + calendar->focus_col = col; + } + } + + if (old_focus_row != -1 && old_focus_col != -1) + hildon_calendar_paint_day (GTK_WIDGET (calendar), old_focus_row, old_focus_col); + + hildon_calendar_select_day (calendar, day); +} + +void +hildon_calendar_clear_marks (HildonCalendar *calendar) +{ + guint day; + + g_return_if_fail (HILDON_IS_CALENDAR (calendar)); + + for (day = 0; day < 31; day++) + { + calendar->marked_date[day] = FALSE; + } + + calendar->num_marked_dates = 0; + + if (GTK_WIDGET_DRAWABLE (calendar)) + { + hildon_calendar_paint_main (GTK_WIDGET (calendar)); + } +} + +gboolean +hildon_calendar_mark_day (HildonCalendar *calendar, + guint day) +{ + g_return_val_if_fail (HILDON_IS_CALENDAR (calendar), FALSE); + if (day >= 1 && day <= 31 && calendar->marked_date[day-1] == FALSE) + { + calendar->marked_date[day - 1] = TRUE; + calendar->num_marked_dates++; + + if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar))) + hildon_calendar_paint_day_num (GTK_WIDGET (calendar), day-1); + } + + return TRUE; +} + +gboolean +hildon_calendar_unmark_day (HildonCalendar *calendar, + guint day) +{ + g_return_val_if_fail (HILDON_IS_CALENDAR (calendar), FALSE); + + if (day >= 1 && day <= 31 && calendar->marked_date[day-1] == TRUE) + { + calendar->marked_date[day - 1] = FALSE; + calendar->num_marked_dates--; + + if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar))) + hildon_calendar_paint_day_num (GTK_WIDGET (calendar), day-1); + } + + return TRUE; +} + +void +hildon_calendar_get_date (HildonCalendar *calendar, + guint *year, + guint *month, + guint *day) +{ + g_return_if_fail (HILDON_IS_CALENDAR (calendar)); + + if (year) + *year = calendar->year; + + if (month) + *month = calendar->month; + + if (day) + *day = calendar->selected_day; +} + +static void +arrow_action (HildonCalendar *calendar, + guint arrow) +{ + switch (arrow) + { + case ARROW_YEAR_LEFT: + hildon_calendar_set_year_prev (calendar); + break; + case ARROW_YEAR_RIGHT: + hildon_calendar_set_year_next (calendar); + break; + case ARROW_MONTH_LEFT: + hildon_calendar_set_month_prev (calendar); + break; + case ARROW_MONTH_RIGHT: + hildon_calendar_set_month_next (calendar); + break; + default:; + /* do nothing */ + } + + hildon_calendar_select_and_focus_day(calendar, calendar->selected_day); +} + +static gboolean +calendar_timer (gpointer data) +{ + HildonCalendar *calendar = data; + HildonCalendarPrivate *private_data = HILDON_CALENDAR_GET_PRIVATE (calendar); + gboolean retval = FALSE; + GtkSettings *settings; + guint timeout; + + gdk_window_process_updates (((GtkWidget *) calendar)->window, TRUE); + + settings = gtk_settings_get_default (); + g_object_get (settings, "gtk-timeout-repeat", &timeout, NULL); + timeout *= 8; + + GDK_THREADS_ENTER (); + + if (private_data->timer) + { + arrow_action (calendar, private_data->click_child); + + if (private_data->need_timer) + { + private_data->need_timer = FALSE; + private_data->timer = g_timeout_add (/*CALENDAR_TIMER_DELAY*/timeout, + (GSourceFunc) calendar_timer, + (gpointer) calendar); + } + else + retval = TRUE; + } + + GDK_THREADS_LEAVE (); + + return retval; +} + +static void +start_spinning (GtkWidget *widget, + gint click_child) +{ + HildonCalendarPrivate *private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + GtkSettings *settings; + guint timeout; + + settings = gtk_settings_get_default (); + g_object_get (settings, "gtk-timeout-repeat", &timeout, NULL); + timeout *= 8; + + private_data->click_child = click_child; + + if (!private_data->timer) + { + private_data->need_timer = TRUE; + private_data->timer = g_timeout_add (/*CALENDAR_INITIAL_TIMER_DELAY*/timeout, + calendar_timer, + (gpointer) widget); + } +} + +static void +stop_spinning (GtkWidget *widget) +{ + HildonCalendarPrivate *private_data; + + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + + if (private_data->timer) + { + g_source_remove (private_data->timer); + private_data->timer = 0; + private_data->need_timer = FALSE; + } +} + +static void +hildon_calendar_destroy (GtkObject *object) +{ + stop_spinning (GTK_WIDGET (object)); + + GTK_OBJECT_CLASS (parent_class)->destroy (object); +} + +static void +hildon_calendar_grab_notify (GtkWidget *widget, + gboolean was_grabbed) +{ + if (!was_grabbed) + stop_spinning (widget); +} + +static gboolean +hildon_calendar_focus_out (GtkWidget *widget, + GdkEventFocus *event) +{ + HildonCalendarPrivate *private_data; + + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + + stop_spinning (widget); + + private_data->in_drag = 0; + + return FALSE; +} + +static gboolean +hildon_calendar_button_press (GtkWidget *widget, + GdkEventButton *event) +{ + HildonCalendar *calendar; + HildonCalendarPrivate *private_data; + gint arrow = -1; + + calendar = HILDON_CALENDAR (widget); + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + + + if (event->type == GDK_2BUTTON_PRESS) + { + if (event->window == private_data->main_win) + hildon_calendar_main_button (widget, event); + } + else if (event->window == private_data->main_win) + { + gint x = (gint) (event->x); + gint y = (gint) (event->y); + gint row = row_from_y (calendar, y); + gint col = column_from_x (calendar, x); + private_data->pressed_day = calendar->day[row][col]; + + if ((calendar->year == private_data->min_year && + calendar->month == 0 + && calendar->day_month[row][col] == MONTH_PREV) || + (calendar->year == private_data->max_year && + calendar->month == 11 && + calendar->day_month[row][col] == MONTH_NEXT)) + {} + else if (calendar->day_month[row][col] == MONTH_CURRENT) + hildon_calendar_select_and_focus_day (calendar, private_data->pressed_day); + + /* Remember month where button was pressed */ + private_data->pressed_month = calendar->month; + private_data->slide_stylus = TRUE; + } + + if (!GTK_WIDGET_HAS_FOCUS (widget)) + gtk_widget_grab_focus (widget); + + for (arrow = ARROW_YEAR_LEFT; arrow <= ARROW_MONTH_RIGHT; arrow++) + { + if (event->window == private_data->arrow_win[arrow]) + { + + /* only call the action on single click, not double */ + if (event->type == GDK_BUTTON_PRESS) + { + if (event->button == 1) + start_spinning (widget, arrow); + + arrow_action (calendar, arrow); + } + + return TRUE; + } + } + + return TRUE; +} + +static gboolean +hildon_calendar_button_release (GtkWidget *widget, + GdkEventButton *event) +{ + HildonCalendar *calendar; + HildonCalendarPrivate *private_data; + + calendar = HILDON_CALENDAR (widget); + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + + if (event->window == private_data->main_win) + { + hildon_calendar_main_button (widget, event); + gint x = (gint) (event->x); + gint y = (gint) (event->y); + gint row = row_from_y (calendar, y); + gint col = column_from_x (calendar, x); + private_data->prev_col = -1; + private_data->prev_row = -1; + + if ((private_data->pressed_day == calendar->day[row][col]) && + (private_data->pressed_month == calendar->month)) + { + if (!private_data->is_bad_day) + { + g_signal_emit (calendar, hildon_calendar_signals[SELECTED_DATE_SIGNAL], 0); + } + else + { + private_data->is_bad_day = FALSE; + } + } + } + + if (event->button == 1) + { + stop_spinning (widget); + + if (private_data->in_drag) + private_data->in_drag = 0; + } + + private_data->slide_stylus = FALSE; + return TRUE; +} + +static gboolean +hildon_calendar_motion_notify (GtkWidget *widget, + GdkEventMotion *event) +{ + HildonCalendar *calendar; + HildonCalendarPrivate *private_data; + gint event_x, event_y; + gint row, col; + gint old_row, old_col; + + calendar = HILDON_CALENDAR (widget); + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + event_x = (gint) (event->x); + event_y = (gint) (event->y); + + if (event->window == private_data->main_win) + { + /* Hildon: make active day to move, when stylus is slided */ + if (private_data->slide_stylus) + { + gint c_row = row_from_y (calendar, event_y); + gint c_col = column_from_x (calendar, event_x); + + if (calendar->day_month[c_row][c_col] == MONTH_PREV || + calendar->day_month[c_row][c_col] == MONTH_NEXT) + { } + else if ((private_data->prev_row != c_row || private_data->prev_col != c_col) && + (calendar->highlight_row != -1 && calendar->highlight_col != -1)) + { + hildon_calendar_select_and_focus_day (calendar, + calendar->day[c_row][c_col]); + /* Update passive focus indicators work weekday number and name */ + hildon_calendar_paint_week_numbers (GTK_WIDGET (calendar)); + hildon_calendar_paint_day_names (GTK_WIDGET (calendar)); + } + private_data->prev_col = c_col; + private_data->prev_row = c_row; + } + if (private_data->in_drag) + { + if (gtk_drag_check_threshold (widget, + private_data->drag_start_x, private_data->drag_start_y, + event->x, event->y)) + { + GdkDragContext *context; + GtkTargetList *target_list = gtk_target_list_new (NULL, 0); + gtk_target_list_add_text_targets (target_list, 0); + context = gtk_drag_begin (widget, target_list, GDK_ACTION_COPY, + 1, (GdkEvent *)event); + + + private_data->in_drag = 0; + + gtk_target_list_unref (target_list); + gtk_drag_set_icon_default (context); + } + } + else + { + row = row_from_y (calendar, event_y); + col = column_from_x (calendar, event_x); + + if (row != calendar->highlight_row || calendar->highlight_col != col) + { + old_row = calendar->highlight_row; + old_col = calendar->highlight_col; + if (old_row > -1 && old_col > -1) + { + calendar->highlight_row = -1; + calendar->highlight_col = -1; + hildon_calendar_paint_day (widget, old_row, old_col); + } + + calendar->highlight_row = row; + calendar->highlight_col = col; + + if (row > -1 && col > -1) + hildon_calendar_paint_day (widget, row, col); + } + } + } + + return TRUE; +} + +static gboolean +hildon_calendar_enter_notify (GtkWidget *widget, + GdkEventCrossing *event) +{ + HildonCalendarPrivate *private_data; + + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + + if (event->window == private_data->arrow_win[ARROW_MONTH_LEFT]) + { + private_data->arrow_state[ARROW_MONTH_LEFT] = GTK_STATE_PRELIGHT; + hildon_calendar_paint_arrow (widget, ARROW_MONTH_LEFT); + } + + if (event->window == private_data->arrow_win[ARROW_MONTH_RIGHT]) + { + private_data->arrow_state[ARROW_MONTH_RIGHT] = GTK_STATE_PRELIGHT; + hildon_calendar_paint_arrow (widget, ARROW_MONTH_RIGHT); + } + + if (event->window == private_data->arrow_win[ARROW_YEAR_LEFT]) + { + private_data->arrow_state[ARROW_YEAR_LEFT] = GTK_STATE_PRELIGHT; + hildon_calendar_paint_arrow (widget, ARROW_YEAR_LEFT); + } + + if (event->window == private_data->arrow_win[ARROW_YEAR_RIGHT]) + { + private_data->arrow_state[ARROW_YEAR_RIGHT] = GTK_STATE_PRELIGHT; + hildon_calendar_paint_arrow (widget, ARROW_YEAR_RIGHT); + } + + return TRUE; +} + +static gboolean +hildon_calendar_leave_notify (GtkWidget *widget, + GdkEventCrossing *event) +{ + HildonCalendar *calendar; + HildonCalendarPrivate *private_data; + gint row; + gint col; + + calendar = HILDON_CALENDAR (widget); + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + + if (event->window == private_data->main_win) + { + row = calendar->highlight_row; + col = calendar->highlight_col; + calendar->highlight_row = -1; + calendar->highlight_col = -1; + if (row > -1 && col > -1) + hildon_calendar_paint_day (widget, row, col); + } + + if (event->window == private_data->arrow_win[ARROW_MONTH_LEFT]) + { + private_data->arrow_state[ARROW_MONTH_LEFT] = GTK_STATE_NORMAL; + hildon_calendar_paint_arrow (widget, ARROW_MONTH_LEFT); + } + + if (event->window == private_data->arrow_win[ARROW_MONTH_RIGHT]) + { + private_data->arrow_state[ARROW_MONTH_RIGHT] = GTK_STATE_NORMAL; + hildon_calendar_paint_arrow (widget, ARROW_MONTH_RIGHT); + } + + if (event->window == private_data->arrow_win[ARROW_YEAR_LEFT]) + { + private_data->arrow_state[ARROW_YEAR_LEFT] = GTK_STATE_NORMAL; + hildon_calendar_paint_arrow (widget, ARROW_YEAR_LEFT); + } + + if (event->window == private_data->arrow_win[ARROW_YEAR_RIGHT]) + { + private_data->arrow_state[ARROW_YEAR_RIGHT] = GTK_STATE_NORMAL; + hildon_calendar_paint_arrow (widget, ARROW_YEAR_RIGHT); + } + + return TRUE; +} + +static void +hildon_calendar_paint_arrow (GtkWidget *widget, + guint arrow) +{ + HildonCalendarPrivate *private_data; + GdkWindow *window; + GdkGC *gc; + HildonCalendar *calendar; + gint state; + guint arrow_hlength, arrow_vlength; + /* gint width, height;*/ + + calendar = HILDON_CALENDAR (widget); + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + gtk_widget_style_get (widget, + "scroll-arrow-hlength", &arrow_hlength, + "scroll-arrow-vlength", &arrow_vlength, + NULL); + + if (private_data->freeze_count) + { + private_data->dirty_header = 1; + return; + } + window = private_data->arrow_win[arrow]; + if (window) + { + state = private_data->arrow_state[arrow]; + gc = calendar->gc; + + /* gdk_window_clear (window);*/ + gdk_window_set_background (window, &(widget)->style->bg[state]); + /* gdk_drawable_get_size (window, &width, &height);*/ + /* gdk_window_clear_area (window, + 0,0, + width,height);*/ + + gdk_window_clear(window); + + /* Hildon: added support for dimmed arrows */ + if (((private_data->min_year && calendar->year <= private_data->min_year) || + (private_data->max_year && calendar->year >= private_data->max_year))) + { + if (private_data->min_year && + calendar->year <= private_data->min_year) + { + if (arrow == ARROW_YEAR_LEFT) + gtk_paint_arrow (widget->style, window, GTK_STATE_INSENSITIVE, + GTK_SHADOW_OUT, NULL, widget, "calendar", + GTK_ARROW_LEFT, TRUE, + 0, 0, arrow_vlength, arrow_hlength); + else if (arrow == ARROW_YEAR_RIGHT || arrow == ARROW_MONTH_RIGHT) + gtk_paint_arrow (widget->style, window, state, + GTK_SHADOW_OUT, NULL, widget, "calendar", + GTK_ARROW_RIGHT, TRUE, + 0, 0, arrow_vlength, arrow_hlength); + else if (arrow == ARROW_MONTH_LEFT && calendar->month != 0) + gtk_paint_arrow (widget->style, window, state, + GTK_SHADOW_OUT, NULL, widget, "calendar", + GTK_ARROW_LEFT, TRUE, + 0, 0, arrow_vlength, arrow_hlength); + else if (arrow == ARROW_MONTH_LEFT && !calendar->month) + gtk_paint_arrow (widget->style, window, GTK_STATE_INSENSITIVE, + GTK_SHADOW_OUT, NULL, widget, "calendar", + GTK_ARROW_LEFT, TRUE, + 0, 0, arrow_vlength, arrow_hlength); + } + else if (private_data->max_year && + calendar->year >= private_data->max_year) + { + if (arrow == ARROW_YEAR_RIGHT) + gtk_paint_arrow (widget->style, window, GTK_STATE_INSENSITIVE, + GTK_SHADOW_OUT, NULL, widget, "calendar", + GTK_ARROW_RIGHT, TRUE, + 0, 0, arrow_vlength, arrow_hlength); + else if (arrow == ARROW_YEAR_LEFT || arrow == ARROW_MONTH_LEFT) + gtk_paint_arrow (widget->style, window, state, + GTK_SHADOW_OUT, NULL, widget, "calendar", + GTK_ARROW_LEFT, TRUE, + 0, 0, arrow_vlength, arrow_hlength); + else if (arrow == ARROW_MONTH_RIGHT && calendar->month != 11) + gtk_paint_arrow (widget->style, window, state, + GTK_SHADOW_OUT, NULL, widget, "calendar", + GTK_ARROW_RIGHT, TRUE, + 0, 0, arrow_vlength, arrow_hlength); + else if (arrow == ARROW_MONTH_RIGHT && calendar->month == 11) + gtk_paint_arrow (widget->style, window, GTK_STATE_INSENSITIVE, + GTK_SHADOW_OUT, NULL, widget, "calendar", + GTK_ARROW_RIGHT, TRUE, + 0, 0, arrow_vlength, arrow_hlength); + } + } + else + { + if (arrow == ARROW_MONTH_LEFT || arrow == ARROW_YEAR_LEFT) + gtk_paint_arrow (widget->style, window, state, + GTK_SHADOW_OUT, NULL, widget, "calendar", + GTK_ARROW_LEFT, TRUE, + /* width/2 - 3, height/2 - 4, 8, 8);*/ + 0, 0, arrow_vlength, arrow_hlength); + else + gtk_paint_arrow (widget->style, window, state, + GTK_SHADOW_OUT, NULL, widget, "calendar", + GTK_ARROW_RIGHT, TRUE, + /* width/2 - 2, height/2 - 4, 8, 8);*/ + 0, 0, arrow_vlength, arrow_hlength); + } + } +} + +void +hildon_calendar_freeze (HildonCalendar *calendar) +{ + g_return_if_fail (HILDON_IS_CALENDAR (calendar)); + + HILDON_CALENDAR_GET_PRIVATE (calendar)->freeze_count++; +} + +void +hildon_calendar_thaw (HildonCalendar *calendar) +{ + HildonCalendarPrivate *private_data; + + g_return_if_fail (HILDON_IS_CALENDAR (calendar)); + + private_data = HILDON_CALENDAR_GET_PRIVATE (calendar); + + if (private_data->freeze_count) + if (!(--private_data->freeze_count)) + { + if (private_data->dirty_header) + if (GTK_WIDGET_DRAWABLE (calendar)) + hildon_calendar_paint_header (GTK_WIDGET (calendar)); + + if (private_data->dirty_day_names) + if (GTK_WIDGET_DRAWABLE (calendar)) + hildon_calendar_paint_day_names (GTK_WIDGET (calendar)); + + if (private_data->dirty_week) + if (GTK_WIDGET_DRAWABLE (calendar)) + hildon_calendar_paint_week_numbers (GTK_WIDGET (calendar)); + + if (private_data->dirty_main) + if (GTK_WIDGET_DRAWABLE (calendar)) + hildon_calendar_paint_main (GTK_WIDGET (calendar)); + } +} + +static void +hildon_calendar_set_background (GtkWidget *widget) +{ + HildonCalendarPrivate *private_data; + gint i; + + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + + if (GTK_WIDGET_REALIZED (widget)) + { + for (i = 0; i < 4; i++) + { + if (private_data->arrow_win[i]) + gdk_window_set_background (private_data->arrow_win[i], + HEADER_BG_COLOR (widget)); + } + if (private_data->header_win) + gdk_window_set_background (private_data->header_win, + HEADER_BG_COLOR (widget)); + if (private_data->day_name_win) + gdk_window_set_background (private_data->day_name_win, + BACKGROUND_COLOR (widget)); + if (private_data->week_win) + gdk_window_set_background (private_data->week_win, + BACKGROUND_COLOR (widget)); + if (private_data->main_win) + gdk_window_set_background (private_data->main_win, + BACKGROUND_COLOR (widget)); + if (widget->window) + gdk_window_set_background (widget->window, + BACKGROUND_COLOR (widget)); + } +} + +static void +hildon_calendar_style_set (GtkWidget *widget, + GtkStyle *previous_style) +{ + if (previous_style && GTK_WIDGET_REALIZED (widget)) + hildon_calendar_set_background(widget); +} + +static void +hildon_calendar_state_changed (GtkWidget *widget, + GtkStateType previous_state) +{ + HildonCalendarPrivate *private_data; + int i; + + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + + if (!GTK_WIDGET_IS_SENSITIVE (widget)) + { + private_data->in_drag = 0; + stop_spinning (widget); + } + + for (i = 0; i < 4; i++) + if (GTK_WIDGET_IS_SENSITIVE (widget)) + private_data->arrow_state[i] = GTK_STATE_NORMAL; + else + private_data->arrow_state[i] = GTK_STATE_INSENSITIVE; + + hildon_calendar_set_background (widget); +} + +static void +hildon_calendar_finalize (GObject *object) +{ + HildonCalendarPrivate *private_data; + int i; + + private_data = HILDON_CALENDAR_GET_PRIVATE (object); + + for (i = 0; i < 7; i++) + g_free (private_data->abbreviated_dayname[i]); + for (i = 0; i < 12; i++) + g_free (private_data->monthname[i]); + g_free (private_data); + + (* G_OBJECT_CLASS (parent_class)->finalize) (object); +} + +static gboolean +hildon_calendar_scroll (GtkWidget *widget, + GdkEventScroll *event) +{ + HildonCalendar *calendar = HILDON_CALENDAR (widget); + + if (event->direction == GDK_SCROLL_UP) + { + if (!GTK_WIDGET_HAS_FOCUS (widget)) + gtk_widget_grab_focus (widget); + hildon_calendar_set_month_prev (calendar); + } + else if (event->direction == GDK_SCROLL_DOWN) + { + if (!GTK_WIDGET_HAS_FOCUS (widget)) + gtk_widget_grab_focus (widget); + hildon_calendar_set_month_next (calendar); + } + else + return FALSE; + + return TRUE; +} + +static void +move_focus (HildonCalendar *calendar, + gint direction) +{ + GtkTextDirection text_dir = gtk_widget_get_direction (GTK_WIDGET (calendar)); + + if ((text_dir == GTK_TEXT_DIR_LTR && direction == -1) || + (text_dir == GTK_TEXT_DIR_RTL && direction == 1)) + { + if (calendar->focus_col > 0) + calendar->focus_col--; + else if (calendar->focus_row > 0) + { + calendar->focus_col = 6; + calendar->focus_row--; + } + } + else + { + if (calendar->focus_col < 6) + calendar->focus_col++; + else if (calendar->focus_row < 5) + { + calendar->focus_col = 0; + calendar->focus_row++; + } + } +} + +static gboolean +hildon_calendar_key_press (GtkWidget *widget, + GdkEventKey *event) +{ + HildonCalendar *calendar; + HildonCalendarPrivate *priv; + GtkSettings *settings; + gint return_val; + gint old_focus_row; + gint old_focus_col; + gint row, col, day; + gboolean knav; + + calendar = HILDON_CALENDAR (widget); + priv = HILDON_CALENDAR_GET_PRIVATE (calendar); + return_val = FALSE; + + old_focus_row = calendar->focus_row; + old_focus_col = calendar->focus_col; + + settings = gtk_settings_get_default (); + g_object_get (settings, "hildon-keyboard-navigation", &knav, NULL); + + switch (event->keyval) + { + case GDK_KP_Left: + case GDK_Left: + return_val = TRUE; + if (event->state & GDK_CONTROL_MASK) + hildon_calendar_set_month_prev (calendar); + else + { + /* if we are at the first allowed day of the minimum year/month then do nothing */ + if (calendar->year == priv->min_year && calendar->month == 0 && + calendar->day_month[old_focus_row][old_focus_col-1] == MONTH_PREV) + { + g_signal_emit (calendar, hildon_calendar_signals[ERRONEOUS_DATE_SIGNAL], 0); + return TRUE; + } + else /* else normal */ + { + move_focus (calendar, -1); + if (!knav) + { + hildon_calendar_paint_day (widget, old_focus_row, old_focus_col); + hildon_calendar_paint_day (widget, calendar->focus_row, + calendar->focus_col); + } + else if (knav) + { + gint day_month = calendar->day_month[calendar->focus_row][calendar->focus_col]; + if (day_month == MONTH_CURRENT && calendar->selected_day != 1) + { + hildon_calendar_select_day(calendar, calendar->selected_day - 1); + } + else + { + if (calendar->month != 0) { + calendar->selected_day = month_length[leap (calendar->year)][calendar->month]; + } else { + calendar->selected_day = month_length[leap (calendar->year -1)][12]; + } + hildon_calendar_set_month_prev (calendar); + } + hildon_calendar_paint_week_numbers (GTK_WIDGET (calendar)); + hildon_calendar_paint_day_names (GTK_WIDGET (calendar)); + } + } + } + break; + case GDK_KP_Right: + case GDK_Right: + return_val = TRUE; + if (event->state & GDK_CONTROL_MASK) + hildon_calendar_set_month_next (calendar); + else + { + if (calendar->year == priv->max_year && calendar->month == 11 && + calendar->day_month[old_focus_row][old_focus_col+1] == MONTH_NEXT) + { + g_signal_emit (calendar, hildon_calendar_signals[ERRONEOUS_DATE_SIGNAL], 0); + return TRUE; + } + else + { + move_focus (calendar, 1); + if (!knav) + { + hildon_calendar_paint_day (widget, old_focus_row, old_focus_col); + hildon_calendar_paint_day (widget, calendar->focus_row, + calendar->focus_col); + } + else if (knav) + { + gint day_month = calendar->day_month[calendar->focus_row][calendar->focus_col]; + if (day_month == MONTH_CURRENT) + { + hildon_calendar_select_day (calendar, calendar->selected_day + 1); + } + else + { + calendar->selected_day = 1; + hildon_calendar_set_month_next (calendar); + } + hildon_calendar_paint_week_numbers (GTK_WIDGET (calendar)); + hildon_calendar_paint_day_names (GTK_WIDGET (calendar)); + } + } + } + break; + case GDK_KP_Up: + case GDK_Up: + return_val = TRUE; + if (event->state & GDK_CONTROL_MASK) + hildon_calendar_set_year_prev (calendar); + else + { + if (calendar->year == priv->min_year && calendar->month == 0 && + calendar->day_month[old_focus_row-1][old_focus_col] == MONTH_PREV) + { + g_signal_emit (calendar, hildon_calendar_signals[ERRONEOUS_DATE_SIGNAL], 0); + return TRUE; + } + else + { + if (calendar->focus_row > 0) + calendar->focus_row--; + if (!knav) + { + hildon_calendar_paint_day (widget, old_focus_row, old_focus_col); + hildon_calendar_paint_day (widget, calendar->focus_row, + calendar->focus_col); + } + else if (knav) + { + gint day_month = calendar->day_month[calendar->focus_row][calendar->focus_col]; + if (day_month == MONTH_CURRENT) + { + if ((calendar->selected_day - 7) <= 0) + { + if (calendar->month != 0) + calendar->selected_day = month_length[leap (calendar->year)][calendar->month]; + else + calendar->selected_day = month_length[leap (calendar->year - 1)][12]; + hildon_calendar_set_month_prev (calendar); + } + else + { + hildon_calendar_select_day (calendar, calendar->selected_day - 7); + } + } + else + { + calendar->selected_day = calendar->day[calendar->focus_row][calendar->focus_col]; + hildon_calendar_set_month_prev (calendar); + } + hildon_calendar_paint_week_numbers (GTK_WIDGET (calendar)); + hildon_calendar_paint_day_names (GTK_WIDGET (calendar)); + } + } + } + break; + case GDK_KP_Down: + case GDK_Down: + return_val = TRUE; + if (event->state & GDK_CONTROL_MASK) + hildon_calendar_set_year_next (calendar); + else + { + if (calendar->year == priv->max_year && calendar->month == 11 && + calendar->day_month[old_focus_row+1][old_focus_col] == MONTH_NEXT) + { + g_signal_emit (calendar, hildon_calendar_signals[ERRONEOUS_DATE_SIGNAL], 0); + return TRUE; + } + else + { + + if (calendar->focus_row < 5) + calendar->focus_row++; + if (!knav) + { + hildon_calendar_paint_day (widget, old_focus_row, old_focus_col); + hildon_calendar_paint_day (widget, calendar->focus_row, + calendar->focus_col); + } + else if (knav) + { + gint day_month = calendar->day_month[calendar->focus_row][calendar->focus_col]; + if (day_month == MONTH_CURRENT) + { + if ((calendar->selected_day + 7) > + month_length[leap (calendar->year)][calendar->month + 1]) + { + calendar->selected_day = 1; + hildon_calendar_set_month_next (calendar); + } + else + { + hildon_calendar_select_day (calendar, calendar->selected_day + 7); + } + } + else + { + calendar->selected_day = calendar->day[calendar->focus_row][calendar->focus_col]; + hildon_calendar_set_month_next (calendar); + } + hildon_calendar_paint_week_numbers (GTK_WIDGET (calendar)); + hildon_calendar_paint_day_names (GTK_WIDGET (calendar)); + } + } + } + + break; + case GDK_KP_Space: + case GDK_space: + row = calendar->focus_row; + col = calendar->focus_col; + day = calendar->day[row][col]; + + if (row > -1 && col > -1) + { + return_val = TRUE; + hildon_calendar_freeze (calendar); + + if (calendar->day_month[row][col] == MONTH_PREV) + hildon_calendar_set_month_prev (calendar); + else if (calendar->day_month[row][col] == MONTH_NEXT) + hildon_calendar_set_month_next (calendar); + + hildon_calendar_select_and_focus_day (calendar, day); + + hildon_calendar_thaw (calendar); + } + } + + return return_val; +} + +static void +hildon_calendar_set_display_option (HildonCalendar *calendar, + HildonCalendarDisplayOptions flag, + gboolean setting) +{ + HildonCalendarDisplayOptions flags; + + if (setting) + flags = calendar->display_flags | flag; + else + flags = calendar->display_flags & ~flag; + + hildon_calendar_set_display_options (calendar, flags); +} + +static gboolean +hildon_calendar_get_display_option (HildonCalendar *calendar, + HildonCalendarDisplayOptions flag) +{ + return (calendar->display_flags & flag) != 0; +} + + +static void +hildon_calendar_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + HildonCalendar *calendar; + HildonCalendarPrivate *private_data; + gint val; + + calendar = HILDON_CALENDAR (object); + private_data = HILDON_CALENDAR_GET_PRIVATE (calendar); + + switch (prop_id) + { + case PROP_YEAR: + hildon_calendar_select_month (calendar, + calendar->month, + g_value_get_int (value)); + break; + case PROP_MONTH: + hildon_calendar_select_month (calendar, + g_value_get_int (value), + calendar->year); + break; + case PROP_DAY: + hildon_calendar_select_day (calendar, + g_value_get_int (value)); + break; + case PROP_SHOW_HEADING: + hildon_calendar_set_display_option (calendar, + HILDON_CALENDAR_SHOW_HEADING, + g_value_get_boolean (value)); + break; + case PROP_SHOW_DAY_NAMES: + hildon_calendar_set_display_option (calendar, + HILDON_CALENDAR_SHOW_DAY_NAMES, + g_value_get_boolean (value)); + break; + case PROP_NO_MONTH_CHANGE: + hildon_calendar_set_display_option (calendar, + HILDON_CALENDAR_NO_MONTH_CHANGE, + g_value_get_boolean (value)); + break; + case PROP_SHOW_WEEK_NUMBERS: + hildon_calendar_set_display_option (calendar, + HILDON_CALENDAR_SHOW_WEEK_NUMBERS, + g_value_get_boolean (value)); + break; + case PROP_WEEK_START: + private_data->week_start = g_value_get_int (value); + break; + case PROP_MIN_YEAR: + val = g_value_get_int (value); + if (val <= private_data->max_year || + val == 0 || private_data->max_year == 0) + { + private_data->min_year = val; + if (val && (calendar->year < val)) + hildon_calendar_select_month (calendar, + calendar->month, + private_data->min_year); + } + else + g_warning("min-year cannot be greater than max-year"); + break; + case PROP_MAX_YEAR: + val = g_value_get_int (value); + if (val >= private_data->min_year || + val == 0 || private_data->min_year == 0) + { + private_data->max_year = val; + if (val && (calendar->year > val)) + hildon_calendar_select_month (calendar, + calendar->month, + private_data->max_year); + } + else + g_warning("max-year cannot be less than min-year"); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +hildon_calendar_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + HildonCalendar *calendar; + HildonCalendarPrivate *private_data; + + calendar = HILDON_CALENDAR (object); + private_data = HILDON_CALENDAR_GET_PRIVATE (calendar); + + switch (prop_id) + { + case PROP_YEAR: + g_value_set_int (value, calendar->year); + break; + case PROP_MONTH: + g_value_set_int (value, calendar->month); + break; + case PROP_DAY: + g_value_set_int (value, calendar->selected_day); + break; + case PROP_SHOW_HEADING: + g_value_set_boolean (value, hildon_calendar_get_display_option (calendar, + HILDON_CALENDAR_SHOW_HEADING)); + break; + case PROP_SHOW_DAY_NAMES: + g_value_set_boolean (value, hildon_calendar_get_display_option (calendar, + HILDON_CALENDAR_SHOW_DAY_NAMES)); + break; + case PROP_NO_MONTH_CHANGE: + g_value_set_boolean (value, hildon_calendar_get_display_option (calendar, + HILDON_CALENDAR_NO_MONTH_CHANGE)); + break; + case PROP_SHOW_WEEK_NUMBERS: + g_value_set_boolean (value, hildon_calendar_get_display_option (calendar, + HILDON_CALENDAR_SHOW_WEEK_NUMBERS)); + break; + case PROP_WEEK_START: + g_value_set_int (value, private_data->week_start); + break; + case PROP_MIN_YEAR: + g_value_set_int (value, private_data->min_year); + break; + case PROP_MAX_YEAR: + g_value_set_int (value, private_data->max_year); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + +} + +static void +hildon_calendar_drag_data_get (GtkWidget *widget, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, + guint time) +{ + HildonCalendar *calendar = HILDON_CALENDAR (widget); + GDate *date; + gchar str[128]; + gsize len; + + date = g_date_new_dmy (calendar->selected_day, calendar->month + 1, calendar->year); + len = g_date_strftime (str, 127, "%x", date); + gtk_selection_data_set_text (selection_data, str, len); + + g_free (date); +} + +/* Get/set whether drag_motion requested the drag data and + * drag_data_received should thus not actually insert the data, + * since the data doesn't result from a drop. + */ +static void +set_status_pending (GdkDragContext *context, + GdkDragAction suggested_action) +{ + g_object_set_data (G_OBJECT (context), + "gtk-calendar-status-pending", + GINT_TO_POINTER (suggested_action)); +} + +static GdkDragAction +get_status_pending (GdkDragContext *context) +{ + return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (context), + "gtk-calendar-status-pending")); +} + +static void +hildon_calendar_drag_leave (GtkWidget *widget, + GdkDragContext *context, + guint time) +{ + HildonCalendarPrivate *private_data; + + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + private_data->drag_highlight = 0; + gtk_drag_unhighlight (widget); + +} + +static gboolean +hildon_calendar_drag_motion (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time) +{ + HildonCalendarPrivate *private_data; + GdkAtom target; + + private_data = HILDON_CALENDAR_GET_PRIVATE (widget); + + if (!private_data->drag_highlight) + { + private_data->drag_highlight = 1; + gtk_drag_highlight (widget); + } + + target = gtk_drag_dest_find_target (widget, context, NULL); + if (target == GDK_NONE) + gdk_drag_status (context, 0, time); + else { + set_status_pending (context, context->suggested_action); + gtk_drag_get_data (widget, context, target, time); + } + + return TRUE; +} + +static gboolean +hildon_calendar_drag_drop (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time) +{ + GdkAtom target; + + target = gtk_drag_dest_find_target (widget, context, NULL); + if (target != GDK_NONE) + { + gtk_drag_get_data (widget, context, + target, + time); + return TRUE; + } + + return FALSE; +} + +static void +hildon_calendar_drag_data_received (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint time) +{ + HildonCalendar *calendar = HILDON_CALENDAR (widget); + guint day, month, year; + gchar *str; + GDate *date; + GdkDragAction suggested_action; + + suggested_action = get_status_pending (context); + + if (suggested_action) + { + set_status_pending (context, 0); + + /* We are getting this data due to a request in drag_motion, + * rather than due to a request in drag_drop, so we are just + * supposed to call drag_status, not actually paste in the + * data. + */ + str = (gchar *) gtk_selection_data_get_text (selection_data); + if (str) + { + date = g_date_new (); + g_date_set_parse (date, str); + if (!g_date_valid (date)) + suggested_action = 0; + g_date_free (date); + g_free (str); + } + else + suggested_action = 0; + + gdk_drag_status (context, suggested_action, time); + + return; + } + + date = g_date_new (); + str = (gchar *) gtk_selection_data_get_text (selection_data); + if (str) + { + g_date_set_parse (date, str); + g_free (str); + } + + if (!g_date_valid (date)) + { + g_warning ("Received invalid date data\n"); + g_date_free (date); + gtk_drag_finish (context, FALSE, FALSE, time); + return; + } + + day = g_date_get_day (date); + month = g_date_get_month (date); + year = g_date_get_year (date); + g_date_free (date); + + gtk_drag_finish (context, TRUE, FALSE, time); + + + g_object_freeze_notify (G_OBJECT (calendar)); + if (!(calendar->display_flags & HILDON_CALENDAR_NO_MONTH_CHANGE) + && (calendar->display_flags & HILDON_CALENDAR_SHOW_HEADING)) + hildon_calendar_select_month (calendar, month - 1, year); + hildon_calendar_select_day (calendar, day); + g_object_thaw_notify (G_OBJECT (calendar)); +} + +/* This function return TRUE if we should mark date and FALSE + * otherwise + */ +static void +hildon_calendar_check_current_date (HildonCalendar *calendar, + gint x, + gint y) +{ + HildonCalendarPrivate *private_data; + + private_data = HILDON_CALENDAR_GET_PRIVATE (calendar); + + if (calendar->month == private_data->current_month && + calendar->year == private_data->current_year) + { + gtk_paint_box( GTK_WIDGET (calendar)->style, + private_data->main_win, + GTK_STATE_NORMAL, + GTK_SHADOW_NONE, NULL, + GTK_WIDGET (calendar), "current-day", + x, y, + HILDON_DAY_WIDTH, + HILDON_DAY_HEIGHT); + } +} + +#define __HILDON_CALENDAR_C__ diff --git a/hildon/hildon-calendar.h b/hildon/hildon-calendar.h new file mode 100644 index 0000000..8bf0d5a --- /dev/null +++ b/hildon/hildon-calendar.h @@ -0,0 +1,180 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * GTK Calendar Widget + * Copyright (C) 1998 Cesar Miquel and Shawn T. Amundson + + * HldonCalendar modifications + * Copyright (C) 2005, 2006 Nokia Corporation. + * + * Contact: Rodrigo Novo + * + * 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; either + * version 2 of the License, or (at your option) any later version. or (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#ifndef HILDON_DISABLE_DEPRECATED + +#ifndef __HILDON_CALENDAR_H__ +#define __HILDON_CALENDAR_H__ + +#include + +G_BEGIN_DECLS + +#define HILDON_TYPE_CALENDAR \ + (hildon_calendar_get_type ()) + +#define HILDON_CALENDAR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + HILDON_TYPE_CALENDAR, HildonCalendar)) + +#define HILDON_CALENDAR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + HILDON_TYPE_CALENDAR, HildonCalendarClass)) + +#define HILDON_IS_CALENDAR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_CALENDAR)) + +#define HILDON_IS_CALENDAR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_CALENDAR)) + +#define HILDON_CALENDAR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), HILDON_TYPE_CALENDAR, HildonCalendarClass)) + +typedef struct _HildonCalendar HildonCalendar; + +typedef struct _HildonCalendarClass HildonCalendarClass; + +typedef enum +{ + HILDON_CALENDAR_SHOW_HEADING = 1 << 0, + HILDON_CALENDAR_SHOW_DAY_NAMES = 1 << 1, + HILDON_CALENDAR_NO_MONTH_CHANGE = 1 << 2, + HILDON_CALENDAR_SHOW_WEEK_NUMBERS = 1 << 3, + HILDON_CALENDAR_WEEK_START_MONDAY = 1 << 4 +} HildonCalendarDisplayOptions; + +struct _HildonCalendar +{ + GtkWidget widget; + + GtkStyle *header_style; + GtkStyle *label_style; + + gint month; + gint year; + gint selected_day; + + gint day_month[6][7]; + gint day[6][7]; + + gint num_marked_dates; + gint marked_date[31]; + HildonCalendarDisplayOptions display_flags; + GdkColor marked_date_color[31]; + + GdkGC *gc; + GdkGC *xor_gc; + + gint focus_row; + gint focus_col; + + gint highlight_row; + gint highlight_col; + + gpointer private_data; + gchar grow_space [32]; + + /* Padding for future expansion */ + void (*_gtk_reserved1) (void); + void (*_gtk_reserved2) (void); + void (*_gtk_reserved3) (void); + void (*_gtk_reserved4) (void); +}; + +struct _HildonCalendarClass +{ + GtkWidgetClass parent_class; + + /* Signal handlers */ + void (* month_changed) (HildonCalendar *calendar); + void (* day_selected) (HildonCalendar *calendar); + void (* day_selected_double_click) (HildonCalendar *calendar); + void (* prev_month) (HildonCalendar *calendar); + void (* next_month) (HildonCalendar *calendar); + void (* prev_year) (HildonCalendar *calendar); + void (* next_year) (HildonCalendar *calendar); +}; + + +GType G_GNUC_CONST +hildon_calendar_get_type (void); + +GtkWidget* +hildon_calendar_new (void); + +gboolean +hildon_calendar_select_month (HildonCalendar *calendar, + guint month, + guint year); + +void +hildon_calendar_select_day (HildonCalendar *calendar, + guint day); + +gboolean +hildon_calendar_mark_day (HildonCalendar *calendar, + guint day); + +gboolean +hildon_calendar_unmark_day (HildonCalendar *calendar, + guint day); + +void +hildon_calendar_clear_marks (HildonCalendar *calendar); + +void +hildon_calendar_set_display_options (HildonCalendar *calendar, + HildonCalendarDisplayOptions flags); + +HildonCalendarDisplayOptions +hildon_calendar_get_display_options (HildonCalendar *calendar); + +void +hildon_calendar_get_date (HildonCalendar *calendar, + guint *year, + guint *month, + guint *day); + +void +hildon_calendar_freeze (HildonCalendar *calendar); + +void +hildon_calendar_thaw (HildonCalendar *calendar); + +G_END_DECLS + +#endif /* __HILDON_CALENDAR_H__ */ + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-caption-private.h b/hildon/hildon-caption-private.h new file mode 100644 index 0000000..3501d3c --- /dev/null +++ b/hildon/hildon-caption-private.h @@ -0,0 +1,53 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_PRIVATE_H__ +#define __HILDON_CAPTION_PRIVATE_H__ + +G_BEGIN_DECLS + +typedef struct _HildonCaptionPrivate HildonCaptionPrivate; + +#define HILDON_CAPTION_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_CAPTION, HildonCaptionPrivate)); + +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; +}; + +G_END_DECLS + +#endif /* __HILDON_CAPTION_PRIVATE_H__ */ diff --git a/hildon/hildon-caption.c b/hildon/hildon-caption.c new file mode 100644 index 0000000..09ab04a --- /dev/null +++ b/hildon/hildon-caption.c @@ -0,0 +1,1236 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "hildon-defines.h" +#include "hildon-caption.h" +#include "hildon-caption-private.h" + +#define _(String)\ + dgettext("hildon-libs", String) + +#define HILDON_CAPTION_SPACING 6 + +static GtkEventBox* parent_class = NULL; + +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_grab_focus (GtkWidget *widget); + +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 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, + gboolean markup); + +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); + +enum +{ + PROP_0, + PROP_LABEL, + PROP_MARKUP, + PROP_ICON, + PROP_STATUS, + PROP_SEPARATOR, + PROP_SIZE_GROUP, + PROP_ICON_POSITION, +}; + +enum +{ + CHILD_PROP_NONE, + CHILD_PROP_EXPAND +}; + +/** + * hildon_caption_get_type: + * + * Initializes and returns the type of a hildon caption. + * + * Returns: GType of #HildonCaption + */ +GType G_GNUC_CONST +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 = (gpointer) 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->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; + widget_class->grab_focus = hildon_caption_grab_focus; + + /* 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, + g_cclosure_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:markup: + * + * Caption markup. Mutually exclusive with label. + */ + g_object_class_install_property (gobject_class, PROP_MARKUP, + g_param_spec_string ("markup", + "Current markup", "Caption markup", + NULL, 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. + */ + 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 && priv->caption_area) + { + gtk_widget_unparent (priv->caption_area); + priv->caption_area = NULL; + } + + /* Free user provided strings */ + if (priv && priv->text) + { + g_free (priv->text); + priv->text = NULL; + } + + if (priv && 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); +} + +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, FALSE); + break; + + case PROP_MARKUP: + /* 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, TRUE); + 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, FALSE); + 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) +{ + gtk_widget_grab_focus (GTK_BIN (widget)->child); + + /* we'll update our focused state in set-focus when/if the child receives + * focus */ + + 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; + + 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 child_alloc; + GtkAllocation caption_alloc; + GtkRequisition req, child_req = {0}; + GtkWidget *child = NULL; + HildonCaptionPrivate *priv = NULL; + gboolean rtl; + + g_assert (HILDON_IS_CAPTION (widget)); + priv = HILDON_CAPTION_GET_PRIVATE (widget); + + /* Get the rtl status */ + rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL); + + /* 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; + if (child) + gtk_widget_get_child_requisition (child, &child_req); + + widget->allocation = *allocation; + gtk_widget_get_child_requisition (priv->caption_area, &req); + + child_alloc.height = caption_alloc.height = allocation->height; + child_alloc.width = caption_alloc.width = allocation->width; + child_alloc.x = caption_alloc.x = caption_alloc.y = child_alloc.y = 0; + + /* Center the captioned widget */ + if (rtl) + { + if (caption_alloc.width > child_req.width + HILDON_CAPTION_SPACING) + { + caption_alloc.x = caption_alloc.width - req.width; + child_alloc.width = child_req.width; + } + caption_alloc.width -= child_req.width + HILDON_CAPTION_SPACING * 2; + } + else + { + if (child_alloc.width > req.width + HILDON_CAPTION_SPACING) + { + child_alloc.x += req.width + HILDON_CAPTION_SPACING * 2; + caption_alloc.width = req.width; + } + /* Leave at least the space of the HILDON_CAPTION_SPACING in the left */ + caption_alloc.x = HILDON_CAPTION_SPACING; + + /* Leave room for the other drawable parts of the caption control */ + child_alloc.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)) + { + child_alloc.width = MIN (child_alloc.width, child_req.width); + child_alloc.height = MIN (child_alloc.height, child_req.height); + /* Center the child */ + child_alloc.y = (allocation->height - child_alloc.height - + 2 * GTK_CONTAINER (widget)->border_width)/2; + } + + /* Ensure there are no negative dimensions */ + if (child_alloc.width < 0) + { + caption_alloc.width = req.width + child_alloc.width; + child_alloc.width = 0; + caption_alloc.width = MAX (caption_alloc.width, 0); + } + + if (rtl) + child_alloc.x = caption_alloc.x - child_req.width - HILDON_CAPTION_SPACING * 2; + + child_alloc.height = MAX (child_alloc.height, 0); + caption_alloc.height = MAX (caption_alloc.height, 0); + + if (child && GTK_WIDGET_VISIBLE(child) ) + gtk_widget_size_allocate (child, &child_alloc ); + + gtk_widget_size_allocate (priv->caption_area, &caption_alloc); +} + +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_size_group: + * @caption : a #HildonCaption + * @new_group : a #GtkSizeGroup + * + * Sets a #GtkSizeGroup of a given captioned control. + * + */ +void +hildon_caption_set_size_group (const HildonCaption *self, + GtkSizeGroup *group) +{ + g_object_set (G_OBJECT(self), "size_group", group, NULL); +} + +/** + * hildon_caption_get_size_group: + * @caption : a #HildonCaption + * + * Query given captioned control for the #GtkSizeGroup assigned to it. + * + * Returns: a #GtkSizeGroup + * + */ +GtkSizeGroup* +hildon_caption_get_size_group (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", child, + "size_group", group, + "icon", icon, + "status", flag, + NULL); + + /* Do not expand GtkCheckButton by default, we want to reduce its activation area */ + if (GTK_IS_CHECK_BUTTON (child)) + hildon_caption_set_child_expand (HILDON_CAPTION (widget), FALSE); + + 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. + * + */ +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. + * + */ + +HildonCaptionIconPosition +hildon_caption_get_icon_position (const HildonCaption *caption) +{ + g_return_val_if_fail (HILDON_IS_CAPTION (caption), 0); + + 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 image widget 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 widget that is being used as the icon by the + * hildon_caption, or NULL if no icon image 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_set_label_markup: + * @caption : a #HildonCaption + * @markup : the markup text to use + * + * Sets the label markup text that appears before the control. It acts like + * #hildon_caption_set_label but is using the markup text that allows to specify + * text properties such as bold or italic. + */ +void +hildon_caption_set_label_markup (HildonCaption *caption, + const gchar *markup) +{ + g_return_if_fail (HILDON_IS_CAPTION (caption)); + + g_object_set (G_OBJECT(caption), "markup", markup, 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 (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; +} + +/* 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) +{ + GtkWidget *child = GTK_BIN (widget)->child; + gtk_widget_grab_focus (child); +} + +static void +hildon_caption_grab_focus (GtkWidget *widget) +{ + gtk_widget_grab_focus (GTK_BIN (widget)->child); +} + +/** + * hildon_caption_set_child_expand: + * @caption : a #HildonCaption + * @expand : gboolean to determine if the child is 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; +} + +static void +hildon_caption_set_label_text (HildonCaptionPrivate *priv, + gboolean markup) +{ + 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)) + { + if (markup) + gtk_label_set_markup (GTK_LABEL (priv->label), priv->text); + else + gtk_label_set_text (GTK_LABEL (priv->label), priv->text); + } + else + { + /* Append separator and set text */ + tmp = g_strconcat( priv->text, priv->separator, NULL ); + + if (markup) + gtk_label_set_markup (GTK_LABEL (priv->label), tmp); + else + gtk_label_set_text (GTK_LABEL (priv->label), tmp); + + g_free (tmp); + } + } + else + { + if (markup) + gtk_label_set_markup (GTK_LABEL (priv->label), priv->text); + else + gtk_label_set_text (GTK_LABEL (priv->label), priv->text); + } + } + else + { + /* Clear the label */ + if (markup) + gtk_label_set_markup (GTK_LABEL (priv->label), ""); + else + 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. + * + */ +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 + * + */ +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/hildon-caption.h b/hildon/hildon-caption.h new file mode 100644 index 0000000..e1851b9 --- /dev/null +++ b/hildon/hildon-caption.h @@ -0,0 +1,168 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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 "hildon-enum-types.h" + +G_BEGIN_DECLS + +typedef struct _HildonCaption HildonCaption; + +typedef struct _HildonCaptionClass HildonCaptionClass; + +#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 +{ + 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. + * + */ +typedef enum +{ + HILDON_CAPTION_POSITION_LEFT = 0, + HILDON_CAPTION_POSITION_RIGHT +} HildonCaptionIconPosition; + + +struct _HildonCaption +{ + GtkEventBox parent; +}; + + +struct _HildonCaptionClass +{ + GtkEventBoxClass parent_class; + void (*activate) (HildonCaption *widget); +}; + +GType G_GNUC_CONST +hildon_caption_get_type (void); + +GtkWidget* +hildon_caption_new (GtkSizeGroup *group, + const gchar *value, + GtkWidget *control, + GtkWidget *icon, + HildonCaptionStatus flag); + +GtkSizeGroup* +hildon_caption_get_size_group (const HildonCaption *caption); + +void +hildon_caption_set_size_group (const HildonCaption *caption, + GtkSizeGroup *new_group ); + +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); + +void +hildon_caption_set_child_expand (HildonCaption *caption, + gboolean expand); + +gboolean +hildon_caption_get_child_expand (const HildonCaption *caption); + +void +hildon_caption_set_label_markup (HildonCaption *caption, + const gchar *markup); + +G_END_DECLS + +#endif /* __HILDON_CAPTION_H__ */ diff --git a/hildon/hildon-check-button.c b/hildon/hildon-check-button.c new file mode 100644 index 0000000..1bc26ca --- /dev/null +++ b/hildon/hildon-check-button.c @@ -0,0 +1,263 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +/** + * SECTION:hildon-check-button + * @short_description: Button with a check box inside + * + * #HildonCheckButton is a button containing a label and a check box + * which will remain 'pressed-in' when clicked. Clicking again will + * make the check box toggle its state. + * + * The state of a #HildonCheckButton can be set using + * hildon_check_button_set_active(), and retrieved using + * hildon_check_button_get_active(). The label can be set using + * gtk_button_set_label() and retrieved using gtk_button_get_label(). + * + * + * + * #HildonCheckButton does NOT support an image, so don't use + * gtk_button_set_image(). + * + * + * + * + * Using a Hildon check button + * + * void + * button_toggled (HildonCheckButton *button, gpointer user_data) + * { + * gboolean active; + * + * active = hildon_check_button_get_active (button); + * if (active) + * g_debug ("Button is active"); + * else + * g_debug ("Button is not active"); + * } + * + * GtkWidget * + * create_button (void) + * { + * GtkWidget *button; + * + * button = hildon_check_button_new (HILDON_SIZE_AUTO); + * gtk_button_set_label (GTK_BUTTON (button), "Click me"); + * + * g_signal_connect (button, "toggled", G_CALLBACK (button_toggled), NULL); + * + * return button; + * } + * + * + */ + +#include "hildon-check-button.h" + +enum { + TOGGLED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +G_DEFINE_TYPE (HildonCheckButton, hildon_check_button, GTK_TYPE_BUTTON); + +#define HILDON_CHECK_BUTTON_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_CHECK_BUTTON, HildonCheckButtonPrivate)); + +struct _HildonCheckButtonPrivate +{ + GtkCellRendererToggle *toggle_renderer; +}; + +/** + * hildon_check_button_toggled: + * @button: A #HildonCheckButton + * + * Emits the #HildonCheckButton::toggled signal on the #HildonCheckButton. + * There is no good reason for an application ever to call this function. + * + * Since: 2.2 + */ +void +hildon_check_button_toggled (HildonCheckButton *button) +{ + g_return_if_fail (HILDON_IS_CHECK_BUTTON (button)); + + g_signal_emit (button, signals[TOGGLED], 0); +} + +/** + * hildon_check_button_set_active: + * @button: A #HildonCheckButton + * @is_active: new state for the button + * + * Sets the status of a #HildonCheckButton. Set to %TRUE if you want + * @button to be 'pressed-in', and %FALSE to raise it. This action + * causes the #HildonCheckButton::toggled signal to be emitted. + * + * Since: 2.2 + **/ +void +hildon_check_button_set_active (HildonCheckButton *button, + gboolean is_active) +{ + gboolean prev_is_active; + + g_return_if_fail (HILDON_IS_CHECK_BUTTON (button)); + + prev_is_active = hildon_check_button_get_active (button); + + if (prev_is_active != is_active) { + gtk_button_clicked (GTK_BUTTON (button)); + gtk_widget_queue_draw (GTK_WIDGET (button)); + } +} + +/** + * hildon_check_button_get_active: + * @button: A #HildonCheckButton + * + * Gets the current state of @button. + * + * Return value: %TRUE if @button is active, %FALSE otherwise. + * + * Since: 2.2 + **/ +gboolean +hildon_check_button_get_active (HildonCheckButton *button) +{ + g_return_val_if_fail (HILDON_IS_CHECK_BUTTON (button), FALSE); + + return gtk_cell_renderer_toggle_get_active (button->priv->toggle_renderer); +} + +/** + * hildon_check_button_new: + * @size: Flags indicating the size of the new button + * + * Creates a new #HildonCheckButton. + * + * Return value: A newly created #HildonCheckButton + * + * Since: 2.2 + **/ +GtkWidget * +hildon_check_button_new (HildonSizeType size) +{ + GtkWidget *button = g_object_new (HILDON_TYPE_CHECK_BUTTON, "xalign", 0.0, NULL); + hildon_gtk_widget_set_theme_size (button, size); + return button; +} + +static void +hildon_check_button_clicked (GtkButton *button) +{ + HildonCheckButton *checkbutton = HILDON_CHECK_BUTTON (button); + gboolean current = hildon_check_button_get_active (checkbutton); + + gtk_cell_renderer_toggle_set_active (checkbutton->priv->toggle_renderer, !current); + + hildon_check_button_toggled (checkbutton); +} + +static void +hildon_check_button_apply_style (GtkWidget *widget) +{ + guint checkbox_size; + HildonCheckButtonPrivate *priv = HILDON_CHECK_BUTTON (widget)->priv; + + gtk_widget_style_get (widget, "checkbox-size", &checkbox_size, NULL); + + g_object_set (priv->toggle_renderer, "indicator-size", checkbox_size, NULL); +} + +static void +hildon_check_button_style_set (GtkWidget *widget, + GtkStyle *previous_style) +{ + if (GTK_WIDGET_CLASS (hildon_check_button_parent_class)->style_set) + GTK_WIDGET_CLASS (hildon_check_button_parent_class)->style_set (widget, previous_style); + + hildon_check_button_apply_style (widget); +} + +static void +hildon_check_button_class_init (HildonCheckButtonClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass*) klass; + GtkWidgetClass *widget_class = (GtkWidgetClass*) klass; + GtkButtonClass *button_class = (GtkButtonClass*) klass; + + widget_class->style_set = hildon_check_button_style_set; + button_class->clicked = hildon_check_button_clicked; + + klass->toggled = NULL; + + /** + * HildonCheckButton::toggled + * + * Emitted when the #HildonCheckButton's state is changed. + * + * Since: 2.2 + */ + signals[TOGGLED] = + g_signal_new ("toggled", + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (HildonCheckButtonClass, toggled), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + gtk_widget_class_install_style_property ( + widget_class, + g_param_spec_uint ( + "checkbox-size", + "Size of the check box", + "Size of the check box", + 0, G_MAXUINT, 26, + G_PARAM_READABLE)); + + g_type_class_add_private (klass, sizeof (HildonCheckButtonPrivate)); +} + +static void +hildon_check_button_init (HildonCheckButton *button) +{ + HildonCheckButtonPrivate *priv = HILDON_CHECK_BUTTON_GET_PRIVATE (button); + GtkWidget *cell_view = gtk_cell_view_new (); + + /* Store private part */ + button->priv = priv; + + /* Make sure that the check box is always shown, no matter the value of gtk-button-images */ + g_signal_connect (cell_view, "notify::visible", G_CALLBACK (gtk_widget_show), NULL); + + /* Create toggle renderer and pack it into the cell view */ + priv->toggle_renderer = GTK_CELL_RENDERER_TOGGLE (gtk_cell_renderer_toggle_new ()); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cell_view), + GTK_CELL_RENDERER (priv->toggle_renderer), FALSE); + + /* Add cell view to the image */ + gtk_button_set_image (GTK_BUTTON (button), cell_view); + + gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE); + + hildon_check_button_apply_style (GTK_WIDGET (button)); +} diff --git a/hildon/hildon-check-button.h b/hildon/hildon-check-button.h new file mode 100644 index 0000000..6430f13 --- /dev/null +++ b/hildon/hildon-check-button.h @@ -0,0 +1,85 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +#ifndef __HILDON_CHECK_BUTTON_H__ +#define __HILDON_CHECK_BUTTON_H__ + +#include "hildon-gtk.h" + +G_BEGIN_DECLS + +#define HILDON_TYPE_CHECK_BUTTON \ + (hildon_check_button_get_type()) + +#define HILDON_CHECK_BUTTON(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + HILDON_TYPE_CHECK_BUTTON, HildonCheckButton)) + +#define HILDON_CHECK_BUTTON_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + HILDON_TYPE_CHECK_BUTTON, HildonCheckButtonClass)) + +#define HILDON_IS_CHECK_BUTTON(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_CHECK_BUTTON)) + +#define HILDON_IS_CHECK_BUTTON_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_CHECK_BUTTON)) + +#define HILDON_CHECK_BUTTON_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + HILDON_TYPE_CHECK_BUTTON, HildonCheckButtonClass)) + +typedef struct _HildonCheckButton HildonCheckButton; + +typedef struct _HildonCheckButtonClass HildonCheckButtonClass; + +typedef struct _HildonCheckButtonPrivate HildonCheckButtonPrivate; + +struct _HildonCheckButtonClass +{ + GtkButtonClass parent_class; + + /* Signal handlers */ + void (* toggled) (HildonCheckButton *button); +}; + +struct _HildonCheckButton +{ + GtkButton parent; + + /* private */ + HildonCheckButtonPrivate *priv; +}; + +GType +hildon_check_button_get_type (void) G_GNUC_CONST; + +GtkWidget * +hildon_check_button_new (HildonSizeType size); + +void +hildon_check_button_set_active (HildonCheckButton *button, + gboolean is_active); + +gboolean +hildon_check_button_get_active (HildonCheckButton *button); + +void +hildon_check_button_toggled (HildonCheckButton *button); + +G_END_DECLS + +#endif /* __HILDON_CHECK_BUTTON_H__ */ diff --git a/hildon/hildon-code-dialog-private.h b/hildon/hildon-code-dialog-private.h new file mode 100644 index 0000000..fa94638 --- /dev/null +++ b/hildon/hildon-code-dialog-private.h @@ -0,0 +1,46 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_PRIVATE_H__ +#define __HILDON_CODE_DIALOG_PRIVATE_H__ + +G_BEGIN_DECLS + +#define HILDON_CODE_DIALOG_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_CODE_DIALOG, HildonCodeDialogPrivate)); + +typedef struct _HildonCodeDialogPrivate HildonCodeDialogPrivate; + +struct _HildonCodeDialogPrivate +{ + GtkWidget *entry; + GtkWidget *buttons[5][3]; + GtkWidget *help_text; + GtkIMContext *im_context; +}; + +G_END_DECLS + +#endif /* __HILDON_CODE_DIALOG_PRIVATE_H__ */ diff --git a/hildon/hildon-code-dialog.c b/hildon/hildon-code-dialog.c new file mode 100644 index 0000000..0c8d8ae --- /dev/null +++ b/hildon/hildon-code-dialog.c @@ -0,0 +1,685 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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-code-dialog + * @short_description: A keypad-like widget used to enter pincodes. + * + * #HildonCodeDialog displays a keypad that can be used to enter + * numerical pin codes or lock codes. It emits a 'input' signal each time + * an input action is performed on the dialog. + * + */ + +/* FIXME We need property access in this widget */ + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "hildon-code-dialog.h" +#include "hildon-defines.h" +#include "hildon-banner.h" +#include "hildon-code-dialog-private.h" + +#define HEIGHT (48-HILDON_MARGIN_DEFAULT) + +#define WIDTH (100-HILDON_MARGIN_DEFAULT) + +#define BACKSPACE_ICON "general_backspace" + +#define _(String) \ + dgettext("hildon-libs", String) + +#define c_(String) \ + dgettext("hildon-common-strings", String) + +#define DEVICELOCK_OK _("wdgt_bd_done") + +#define DEVICELOCK_TITLE dgettext("osso-system-lock", "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_realize (GtkWidget *widget); + +static void +hildon_code_dialog_unrealize (GtkWidget *widget); + +static void +hildon_code_dialog_finalize (GObject *object); + +static void +hildon_code_dialog_button_clicked (GtkButton *buttonm, + gpointer user_data); + +static void +hildon_code_dialog_backspace (HildonCodeDialog *dialog); + +static void +hildon_code_dialog_im_commit (GtkIMContext *im_context, + gchar *utf8, + 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); + +static void +hildon_code_dialog_real_input (HildonCodeDialog *dialog); + +static void +hildon_code_dialog_input (HildonCodeDialog *dialog); + +static GtkDialogClass* parent_class = NULL; + +static guint input_signal; + +/** + * hildon_code_dialog_get_type: + * + * Initializes and returns the type of a hildon code dialog. + * + * Returns: GType of #HildonCodeDialog + */ +GType G_GNUC_CONST +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) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (cd_class); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (cd_class); + + parent_class = GTK_DIALOG_CLASS (g_type_class_peek_parent (cd_class)); + g_type_class_add_private (cd_class, sizeof (HildonCodeDialogPrivate)); + + gobject_class->finalize = hildon_code_dialog_finalize; + + widget_class->realize = hildon_code_dialog_realize; + widget_class->unrealize = hildon_code_dialog_unrealize; + + cd_class->input = hildon_code_dialog_real_input; + + /* FIXME Document this signal! */ + input_signal = g_signal_new("input", + HILDON_TYPE_CODE_DIALOG, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (HildonCodeDialogClass, input), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); +} + +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; + + priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); + g_assert (priv); + + 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); + gtk_dialog_set_has_separator ((GtkDialog *) dialog, FALSE); + + 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), +#if GTK_CHECK_VERSION(2,11,0) || defined(MAEMO_GTK) + GTK_BUTTONBOX_CENTER); +#else + GTK_BUTTONBOX_DEFAULT_STYLE); +#endif + + okButton = gtk_dialog_add_button (GTK_DIALOG (dialog) ,DEVICELOCK_OK, + GTK_RESPONSE_OK); + + gtk_widget_set_sensitive (okButton, FALSE); + + priv->buttons[4][0] = priv->buttons[4][1] = okButton; + + priv->im_context = gtk_im_multicontext_new(); +#ifdef MAEMO_GTK + g_object_set (G_OBJECT (priv->im_context), "hildon-input-mode", + HILDON_GTK_INPUT_MODE_NUMERIC, NULL); +#endif + + /* + Connect signals. + */ + g_signal_connect (G_OBJECT (priv->im_context), "commit", + G_CALLBACK (hildon_code_dialog_im_commit), dialog); + + 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); + + gtk_widget_show_all (GTK_WIDGET (GTK_DIALOG (dialog)->vbox)); +} + +static void +hildon_code_dialog_realize (GtkWidget *widget) +{ + HildonCodeDialog *dialog = HILDON_CODE_DIALOG (widget); + HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); + + if (GTK_WIDGET_CLASS (parent_class)->realize) + (* GTK_WIDGET_CLASS (parent_class)->realize) (widget); + + gtk_im_context_set_client_window (GTK_IM_CONTEXT (priv->im_context), + GTK_WIDGET (dialog)->window); + gtk_im_context_focus_in (priv->im_context); +} + +static void +hildon_code_dialog_unrealize (GtkWidget *widget) +{ + HildonCodeDialog *dialog = HILDON_CODE_DIALOG (widget); + HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); + + gtk_im_context_set_client_window (GTK_IM_CONTEXT (priv->im_context), NULL); + + if (GTK_WIDGET_CLASS (parent_class)->unrealize) + (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); +} + +static void +hildon_code_dialog_finalize (GObject *object) +{ + HildonCodeDialog *dialog = HILDON_CODE_DIALOG (object); + HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); + + g_object_unref (priv->im_context); + + G_OBJECT_CLASS(parent_class)->finalize(object); +} + +static void +hildon_code_dialog_backspace (HildonCodeDialog *dialog) +{ + HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); + gchar *text, *pos; + + g_assert (priv); + + text = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->entry))); + + 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); + } + + gtk_editable_set_position (GTK_EDITABLE (priv->entry), -1); + + g_free (text); +} + +static void +hildon_code_dialog_button_clicked (GtkButton *button, + gpointer user_data) +{ + HildonCodeDialog *dialog = HILDON_CODE_DIALOG (user_data); + HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); + g_assert (priv); + + const char *number = gtk_button_get_label (button); + + if (number && *number ) + { + gtk_editable_set_editable (GTK_EDITABLE (priv->entry), TRUE); + + g_signal_emit_by_name (GTK_ENTRY (priv->entry)->im_context, "commit", + number); + + gtk_editable_set_editable (GTK_EDITABLE (priv->entry), FALSE); + + gtk_editable_set_position (GTK_EDITABLE (priv->entry), -1); + } + else + { + hildon_code_dialog_backspace (dialog); + } +} + +static void +hildon_code_dialog_im_commit (GtkIMContext *im_context, + gchar *utf8, + gpointer user_data) +{ + HildonCodeDialog *dialog = HILDON_CODE_DIALOG (user_data); + HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); + gint digit; + + g_assert (priv); + + digit = g_ascii_strtod(utf8, NULL); + + if (g_ascii_isdigit(*utf8)) + { + gtk_editable_set_editable (GTK_EDITABLE (priv->entry), TRUE); + + g_signal_emit_by_name (GTK_ENTRY (priv->entry)->im_context, "commit", + utf8); + + gtk_editable_set_editable (GTK_EDITABLE (priv->entry), FALSE); + + gtk_editable_set_position (GTK_EDITABLE (priv->entry), -1); + } +} + +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 = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); + gchar *text = g_strdup(gtk_entry_get_text (GTK_ENTRY (priv->entry))); + glong length = g_utf8_strlen (text, -1); + g_free (text); + g_assert (priv); + + if (length == MAX_PINCODE_LEN) + { + hildon_banner_show_information (GTK_WIDGET (dialog), + NULL, + DEVICELOCK_MAX_CHAR_REACHED); + } + + else if (! length) + { + /* make the Ok button sensitive */ + gtk_widget_set_sensitive (priv->buttons[4][0], TRUE); + } + + hildon_code_dialog_input (dialog); +} + +static gboolean +hildon_code_dialog_key_press_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data) +{ + HildonCodeDialog *dialog = HILDON_CODE_DIALOG (user_data); + HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); + GtkWidget *new_widget = widget; + gint x, y; + + g_assert (priv); + + if (gtk_im_context_filter_keypress (priv->im_context, event)) + return TRUE; + + if (event->keyval == GDK_BackSpace) + { + hildon_code_dialog_backspace (dialog); + return TRUE; + } + + 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; +} + +/** + * hildon_code_dialog_new: + * + * Use this function to create a new HildonCodeDialog. + * + * Return value: A @HildonCodeDialog. + **/ +GtkWidget* +hildon_code_dialog_new (void) +{ + 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); + + HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); + g_assert (priv); + + return gtk_entry_get_text (GTK_ENTRY (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)); + + HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); + g_assert (priv); + + gtk_entry_set_text (GTK_ENTRY (priv->entry), ""); + gtk_widget_set_sensitive (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)); + + HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); + g_assert (priv); + + gtk_label_set_text (GTK_LABEL (priv->help_text), text); +} + +static void +hildon_code_dialog_real_input (HildonCodeDialog *dialog) +{ +} + +static void +hildon_code_dialog_input (HildonCodeDialog *dialog) +{ + /* Emit the signal */ + g_signal_emit (dialog, input_signal, 0); +} + +/** + * hildon_code_dialog_set_input_sensitive + * @dialog: The #HildonCodeDialog whose state is to be changed + * @sensitive: The new state + * + * This function will block or enable the input on the code dialog by + * making the input button sensitive (or not). + **/ +void +hildon_code_dialog_set_input_sensitive (HildonCodeDialog *dialog, + gboolean sensitive) +{ + int i; + int k; + + g_return_if_fail (HILDON_IS_CODE_DIALOG (dialog)); + + HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); + g_assert (priv); + + for (i = 0; i < 5; i++) + for (k = 0; k < 3; k++) + if (i != 4 && (k != 0 || k != 2)) + gtk_widget_set_sensitive (priv->buttons [i][k], sensitive); + + gtk_widget_set_sensitive (priv->help_text, sensitive); + gtk_widget_set_sensitive (priv->entry, sensitive); +} diff --git a/hildon/hildon-code-dialog.h b/hildon/hildon-code-dialog.h new file mode 100644 index 0000000..577fd85 --- /dev/null +++ b/hildon/hildon-code-dialog.h @@ -0,0 +1,92 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#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)) + +#define HILDON_CODE_DIALOG_GET_CLASS(obj) \ + ((HildonCodeDialogClass *) G_OBJECT_GET_CLASS(obj)) + +typedef struct _HildonCodeDialog HildonCodeDialog; + +typedef struct _HildonCodeDialogClass HildonCodeDialogClass; + +struct _HildonCodeDialog +{ + GtkDialog parent; +}; + +struct _HildonCodeDialogClass +{ + GtkDialogClass parent_class; + void (*input) (HildonCodeDialog *dialog); +}; + +GType G_GNUC_CONST +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); + +void +hildon_code_dialog_set_input_sensitive (HildonCodeDialog *dialog, + gboolean sensitive); + +G_END_DECLS + +#endif /* __HILDON_CODE_DIALOG_H__ */ + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-color-button-private.h b/hildon/hildon-color-button-private.h new file mode 100644 index 0000000..10e7741 --- /dev/null +++ b/hildon/hildon-color-button-private.h @@ -0,0 +1,43 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_PRIVATE_H__ +#define __HILDON_COLOR_BUTTON_PRIVATE_H__ + +typedef struct _HildonColorButtonPrivate HildonColorButtonPrivate; + +#define HILDON_COLOR_BUTTON_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ + HILDON_TYPE_COLOR_BUTTON, HildonColorButtonPrivate)); + +struct _HildonColorButtonPrivate +{ + GtkWidget *dialog; + gboolean popped; + + GdkColor color; + GdkGC *gc; +}; + +#endif /* __HILDON_COLOR_BUTTON_PRIVATE_H__ */ diff --git a/hildon/hildon-color-button.c b/hildon/hildon-color-button.c new file mode 100644 index 0000000..49c0dfe --- /dev/null +++ b/hildon/hildon-color-button.c @@ -0,0 +1,648 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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. + * + * + * HildonColorButton example + * + * HildonColorButton *cbutton; + * GtkColor *color; + * + * cbutton = hildon_color_button_new(); + * gtk_object_get( GTK_OBJECT(cbutton), "color", color ); + * + * + * + */ + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "hildon-color-button.h" +#include "hildon-defines.h" +#include "hildon-color-chooser-dialog.h" +#include "hildon-color-button-private.h" + +#define COLOR_FILLED_HEIGHT 22 + +#define COLOR_FILLED_WIDTH 22 + +#define COLOR_BUTTON_WIDTH 52 + +#define COLOR_BUTTON_HEIGHT 48 + +#define OUTER_BORDER_RED 0 + +#define OUTER_BORDER_BLUE 0 + +#define OUTER_BORDER_GREEN 0 + +#define OUTER_BORDER_THICKNESS 1 + +#define INNER_BORDER_RED 65535 + +#define INNER_BORDER_BLUE 65535 + +#define INNER_BORDER_GREEN 65535 + +#define INNER_BORDER_THICKNESS 2 + +enum +{ + SETUP_DIALOG, + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_COLOR, + PROP_POPUP_SHOWN +}; + +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; +static guint signals [LAST_SIGNAL] = { 0, }; + +/** + * hildon_color_button_get_type: + * + * Initializes and returns the type of a hildon color button. + * + * Returns: GType of #HildonColorButton. + */ +GType G_GNUC_CONST +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; + + signals[SETUP_DIALOG] = + g_signal_new ("setup-dialog", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + HILDON_TYPE_COLOR_CHOOSER_DIALOG); + + /** + * HildonColorButton:color: + * + * The currently 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)); + + /** + * HildonColorButton:popup-shown: + * + * If the color selection dialog is currently popped-up (visible) + */ + g_object_class_install_property (gobject_class, PROP_POPUP_SHOWN, + g_param_spec_boolean ("popup-shown", + "IsPopped", + "If the color selection dialog is popped up", + FALSE, + G_PARAM_READABLE)); + + g_type_class_add_private (gobject_class, sizeof (HildonColorButtonPrivate)); +} + +/* FIXME 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) +{ + HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (cb); + GdkColor outer_border, inner_border; + + g_assert (priv); + + /* 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 (priv->gc, &outer_border); + /* draw the outer border as a filled rectangle */ + gdk_draw_rectangle (widget->window, + (GTK_WIDGET_IS_SENSITIVE (widget)) ? 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 (priv->gc, &inner_border); + + /* draw the inner border as a filled rectangle */ + gdk_draw_rectangle (widget->window, + 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(priv->gc, &priv->color); + + /* draw the actual rectangle */ + gdk_draw_rectangle(widget->window, + 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; + HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (cb); + + priv->dialog = NULL; + priv->gc = NULL; + priv->popped = FALSE; + + 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) +{ + HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (object); + g_assert (priv); + + if (priv->dialog) + { + gtk_widget_destroy (priv->dialog); + 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) +{ + HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (widget); + g_assert (priv); + + GTK_WIDGET_CLASS (parent_class)->realize (widget); + + priv->gc = gdk_gc_new (widget->window); +} + +static void +hildon_color_button_unrealize (GtkWidget *widget) +{ + HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (widget); + g_assert (priv); + + if (priv->gc != NULL) { + g_object_unref (priv->gc); + 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); + HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (button); + HildonColorChooserDialog *cs_dialog; + + g_assert (priv); + + cs_dialog = (HildonColorChooserDialog *) 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)); + priv->dialog = hildon_color_chooser_dialog_new (); + cs_dialog = HILDON_COLOR_CHOOSER_DIALOG (priv->dialog); + if (parent) + gtk_window_set_transient_for (GTK_WINDOW (cs_dialog), GTK_WINDOW (parent)); + + g_signal_emit (button, signals[SETUP_DIALOG], 0, priv->dialog); + } + + /* Set the initial color for the color selector dialog */ + hildon_color_chooser_dialog_set_color (cs_dialog, &priv->color); + + /* Update the color for color button if selection was made */ + priv->popped = TRUE; + if (gtk_dialog_run (GTK_DIALOG (cs_dialog)) == GTK_RESPONSE_OK) + { + hildon_color_chooser_dialog_get_color (cs_dialog, &priv->color); + hildon_color_button_set_color (HILDON_COLOR_BUTTON (button), &priv->color); + // FIXME A queue-draw should be enough here (not set needed) + } + + gtk_widget_hide (GTK_WIDGET(cs_dialog)); + priv->popped = FALSE; +} + +/* Popup a color selector dialog on hardkey Select press. + * FIXME This is a bit hacky, should work without thi. Check. */ +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; +} + +static void +hildon_color_button_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + HildonColorButton *cb = HILDON_COLOR_BUTTON (object); + HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (cb); + g_assert (priv); + + switch (param_id) + { + + case PROP_COLOR: + 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; + } +} + +static void +hildon_color_button_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + HildonColorButton *cb = HILDON_COLOR_BUTTON (object); + HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (cb); + g_assert (priv); + + switch (param_id) + { + + case PROP_COLOR: + g_value_set_boxed (value, &priv->color); + break; + + case PROP_POPUP_SHOWN: + g_value_set_boolean (value, priv->popped); + 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_return_if_fail (HILDON_IS_COLOR_BUTTON (button)); + + g_object_set (G_OBJECT (button), "color", color, NULL); +} + +/** + * hildon_color_button_get_popup_shown + * @button: a #HildonColorButton + * + * This function checks if the color button has the color + * selection dialog currently popped-up. + * + * Returns: TRUE if the dialog is popped-up (visible to user). + * + */ +gboolean +hildon_color_button_get_popup_shown (HildonColorButton *button) +{ + HildonColorButtonPrivate *priv = NULL; + g_return_val_if_fail (HILDON_IS_COLOR_BUTTON (button), FALSE); + + priv = HILDON_COLOR_BUTTON_GET_PRIVATE (button); + g_assert (priv); + + return priv->popped; +} + +/** + * hildon_color_button_popdown + * @button: a #HildonColorButton + * + * If the color selection dialog is currently popped-up (visible) + * it will be popped-down (hidden). + * + */ +void +hildon_color_button_popdown (HildonColorButton *button) +{ + HildonColorButtonPrivate *priv = NULL; + g_return_if_fail (HILDON_IS_COLOR_BUTTON (button)); + + priv = HILDON_COLOR_BUTTON_GET_PRIVATE (button); + g_assert (priv); + + if (priv->popped && priv->dialog) { + gtk_dialog_response (GTK_DIALOG (priv->dialog), GTK_RESPONSE_CANCEL); + } +} + +/** + * hildon_color_button_get_color: + * @button: a #HildonColorButton + * @color: a color #GdkColor to be fillled with the current color + * + */ +void +hildon_color_button_get_color (HildonColorButton *button, + GdkColor *color) +{ + HildonColorButtonPrivate *priv = NULL; + g_return_if_fail (HILDON_IS_COLOR_BUTTON (button)); + g_return_if_fail (color != NULL); + + priv = HILDON_COLOR_BUTTON_GET_PRIVATE (button); + g_assert (priv); + + color->red = priv->color.red; + color->green = priv->color.green; + color->blue = priv->color.blue; + color->pixel = priv->color.pixel; +} + diff --git a/hildon/hildon-color-button.h b/hildon/hildon-color-button.h new file mode 100644 index 0000000..cd131ea --- /dev/null +++ b/hildon/hildon-color-button.h @@ -0,0 +1,97 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#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; + +struct _HildonColorButton +{ + GtkButton parent; +}; + +struct _HildonColorButtonClass +{ + GtkButtonClass parent_class; +}; + +GType G_GNUC_CONST +hildon_color_button_get_type (void); + +GtkWidget* +hildon_color_button_new (void); + +GtkWidget* +hildon_color_button_new_with_color (const GdkColor *color); + +void +hildon_color_button_get_color (HildonColorButton *button, + GdkColor *color); + +void +hildon_color_button_set_color (HildonColorButton *button, + GdkColor *color); + +gboolean +hildon_color_button_get_popup_shown (HildonColorButton *button); + +void +hildon_color_button_popdown (HildonColorButton *button); + +G_END_DECLS + +#endif /* __HILDON_COLOR_BUTTON_H__ */ + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-color-chooser-dialog-private.h b/hildon/hildon-color-chooser-dialog-private.h new file mode 100644 index 0000000..4ebf42f --- /dev/null +++ b/hildon/hildon-color-chooser-dialog-private.h @@ -0,0 +1,73 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Author: Kuisma Salonen + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_PRIVATE_H__ +#define __HILDON_COLOR_CHOOSER_DIALOG_PRIVATE_H__ + +#include + +typedef struct _HildonColorChooserDialogPrivate HildonColorChooserDialogPrivate; + +#define HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ + HILDON_TYPE_COLOR_CHOOSER_DIALOG, HildonColorChooserDialogPrivate)); + +typedef struct +{ + GtkBorder radio_sizes; + GtkBorder cont_sizes; + GtkBorder num_buttons; + GtkBorder last_num_buttons; + + GdkColor default_color; +} HildonColorChooserStyleInfo; + +struct _HildonColorChooserDialogPrivate +{ + GtkWidget *hbox; + GtkWidget *vbox; + + GtkWidget *align_custom, *align_defined; + GtkWidget *area_custom, *area_defined; + GtkWidget *separator; + + GtkWidget *chooser; + + GdkColor *colors_custom, *colors_defined; + GdkColor color; + GdkGC **gc_array; + + gint selected; + + HildonColorChooserStyleInfo style_info; + + gint has_style; + + GdkColor pending_color; + + GConfClient *gconf_client; +}; + +#endif /* __HILDON_COLOR_CHOOSER_DIALOG_PRIVATE_H__ */ diff --git a/hildon/hildon-color-chooser-dialog.c b/hildon/hildon-color-chooser-dialog.c new file mode 100644 index 0000000..10676e4 --- /dev/null +++ b/hildon/hildon-color-chooser-dialog.c @@ -0,0 +1,1148 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Author: Kuisma Salonen + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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 used to select a color from HSV colorspace. + * @see_also: #HildonColorButton + * + * HildonColorChooserDialog enables the user to + * select an arbitrary color from a HSV colorspace. + * The color is stored in one of the predefined color + * slots and can be reselected later on. + * + * Additionally the user can choose one of the standard "factory" + * colors. + * + */ + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "hildon-color-chooser-dialog.h" +#include "hildon-color-chooser.h" +#include "hildon-defines.h" +#include "hildon-banner.h" +#include "hildon-color-chooser-dialog-private.h" + +#define _(String) dgettext("hildon-libs", String) + +static HildonColorChooserDialogClass* parent_class = 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}}; + +static void +hildon_color_chooser_dialog_init (HildonColorChooserDialog *object); + +static void +hildon_color_chooser_dialog_class_init (HildonColorChooserDialogClass *klass); + +static void +hildon_color_chooser_dialog_size_request (GtkWidget *widget, + GtkRequisition *req); + +static void +hildon_color_chooser_dialog_size_allocate (GtkWidget *widget, + GtkAllocation *alloc); + +static void +hildon_color_chooser_dialog_realize (GtkWidget *widget); + +static void +hildon_color_chooser_dialog_unrealize (GtkWidget *widget); + +static void +hildon_color_chooser_dialog_style_set (GtkWidget *widget, + GtkStyle *previous_style); + +static void +hildon_color_chooser_dialog_show (GtkWidget *widget); + +static void +hildon_color_chooser_dialog_show_all (GtkWidget *widget); + +static gboolean +hildon_color_chooser_dialog_key_press_event (GtkWidget *widget, + GdkEventKey *event); + +static gboolean +hildon_color_chooser_dialog_key_release_event (GtkWidget *widget, + GdkEventKey *event); + +static void +hildon_color_chooser_dialog_destroy (GtkObject *object); + +static gboolean +hildon_color_chooser_dialog_area_expose (GtkWidget *widget, + GdkEventExpose *event, + gpointer data); + +static gboolean +hildon_color_chooser_dialog_area_button_press (GtkWidget *widget, + GdkEventButton *event, + gpointer data); + +static void +hildon_color_chooser_dialog_color_changed (HildonColorChooser *chooser, + gpointer data); + +static void +hildon_color_chooser_dialog_insensitive_press (GtkWidget *widget, + gpointer data); + +static void +hildon_color_chooser_dialog_refresh_style_info (HildonColorChooserDialog *dialog); + +static void +hildon_color_chooser_dialog_set_color_num (HildonColorChooserDialog *dialog, + gint num); + +static void +hildon_color_chooser_dialog_ascii_hex_to_color (gchar *s, + GdkColor *color); + +static void +hildon_color_chooser_dialog_color_to_ascii_hex (gchar *s, + GdkColor *color); + +GType G_GNUC_CONST +hildon_color_chooser_dialog_get_type (void) +{ + static GType dialog_type = 0; + + if (!dialog_type) { + static const GTypeInfo dialog_info = + { + sizeof (HildonColorChooserDialogClass), + NULL, + NULL, + (GClassInitFunc) hildon_color_chooser_dialog_class_init, + NULL, + NULL, + sizeof (HildonColorChooserDialog), + 0, + (GInstanceInitFunc) hildon_color_chooser_dialog_init, + NULL + }; + + dialog_type = g_type_register_static (GTK_TYPE_DIALOG, + "HildonColorChooserDialog", &dialog_info, 0); + } + + return dialog_type; +} + +static void +hildon_color_chooser_dialog_init (HildonColorChooserDialog *object) +{ + HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (object); + + gtk_dialog_set_has_separator (GTK_DIALOG (object), FALSE); + gtk_window_set_title (GTK_WINDOW (object), _("ecdg_ti_colour_selector")); + + g_assert (priv); + + priv->hbox = gtk_hbox_new (FALSE, 0); + priv->vbox = gtk_vbox_new (FALSE, 0); + priv->chooser = hildon_color_chooser_new (); + + gtk_box_pack_start (GTK_BOX (priv->hbox), priv->chooser, TRUE, TRUE, 0); + gtk_box_pack_end (GTK_BOX (priv->hbox), priv->vbox, FALSE, FALSE, 0); + + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (object)->vbox), priv->hbox, TRUE, TRUE, 0); + + + priv->align_custom = gtk_alignment_new (0.5, 1.0, 0.0, 0.0); + priv->align_defined = gtk_alignment_new (0.5, 1.0, 0.0, 0.0); + + priv->area_custom = gtk_drawing_area_new (); + priv->area_defined = gtk_drawing_area_new (); + + gtk_container_add (GTK_CONTAINER (priv->align_custom), priv->area_custom); + gtk_container_add (GTK_CONTAINER (priv->align_defined), priv->area_defined); + + priv->separator = gtk_hseparator_new (); + + gtk_box_pack_start (GTK_BOX (priv->vbox), priv->align_defined, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (priv->vbox), priv->separator, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (priv->vbox), priv->align_custom, FALSE, FALSE, 0); + + gtk_dialog_add_button (GTK_DIALOG (object), _("wdgt_bd_done"), GTK_RESPONSE_OK); + gtk_dialog_set_default_response (GTK_DIALOG (object), GTK_RESPONSE_OK); + + g_signal_connect (G_OBJECT (priv->chooser), + "query-tooltip", G_CALLBACK (hildon_color_chooser_dialog_insensitive_press), object); + + g_signal_connect (G_OBJECT (priv->area_custom), + "expose-event", G_CALLBACK (hildon_color_chooser_dialog_area_expose), object); + + g_signal_connect (G_OBJECT (priv->area_defined), + "expose-event", G_CALLBACK (hildon_color_chooser_dialog_area_expose), object); + + g_signal_connect (G_OBJECT (priv->area_custom), + "button-press-event", G_CALLBACK (hildon_color_chooser_dialog_area_button_press), object); + + g_signal_connect (G_OBJECT (priv->area_defined), + "button-press-event", G_CALLBACK (hildon_color_chooser_dialog_area_button_press), object); + + g_signal_connect (G_OBJECT (priv->chooser), + "color-changed", G_CALLBACK (hildon_color_chooser_dialog_color_changed), object); + + gtk_widget_add_events (priv->area_custom, GDK_BUTTON_PRESS_MASK); + gtk_widget_add_events (priv->area_defined, GDK_BUTTON_PRESS_MASK); + + priv->selected = 0; + priv->gconf_client = gconf_client_get_default (); + + memset (&priv->style_info, 0, sizeof (HildonColorChooserStyleInfo)); + + priv->colors_custom = NULL; + priv->colors_defined = NULL; + priv->gc_array = NULL; + + priv->has_style = 0; +} + +static void +hildon_color_chooser_dialog_class_init (HildonColorChooserDialogClass *klass) +{ + GtkWidgetClass *widget_klass = GTK_WIDGET_CLASS (klass); + GtkObjectClass *object_klass = GTK_OBJECT_CLASS (klass); + gchar tmp[32]; + gint i; + + widget_klass->size_request = hildon_color_chooser_dialog_size_request; + widget_klass->size_allocate = hildon_color_chooser_dialog_size_allocate; + widget_klass->realize = hildon_color_chooser_dialog_realize; + widget_klass->unrealize = hildon_color_chooser_dialog_unrealize; + widget_klass->style_set = hildon_color_chooser_dialog_style_set; + widget_klass->show = hildon_color_chooser_dialog_show; + widget_klass->show_all = hildon_color_chooser_dialog_show_all; + widget_klass->key_press_event = hildon_color_chooser_dialog_key_press_event; + widget_klass->key_release_event = hildon_color_chooser_dialog_key_release_event; + + + object_klass->destroy = hildon_color_chooser_dialog_destroy; + + parent_class = 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)); + } + + g_type_class_add_private (object_klass, sizeof (HildonColorChooserDialogPrivate)); +} + +static void +hildon_color_chooser_dialog_size_request (GtkWidget *widget, + GtkRequisition *req) +{ + HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget); + + g_assert (priv); + + gtk_container_set_border_width (GTK_CONTAINER (priv->hbox), priv->style_info.cont_sizes.left); + + gtk_box_set_spacing (GTK_BOX (priv->hbox), priv->style_info.cont_sizes.right); + gtk_box_set_spacing (GTK_BOX (priv->vbox), priv->style_info.cont_sizes.top); + gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (widget)->vbox), priv->style_info.cont_sizes.bottom); + + gtk_widget_set_size_request (priv->area_custom, + (priv->style_info.radio_sizes.left + + 2 * priv->style_info.radio_sizes.bottom) * + (priv->style_info.num_buttons.top) + + (priv->style_info.num_buttons.top-1) * + priv->style_info.radio_sizes.top, + (priv->style_info.radio_sizes.right + + 2 * priv->style_info.radio_sizes.bottom) * + (priv->style_info.num_buttons.bottom) + + (priv->style_info.num_buttons.bottom-1) * + priv->style_info.radio_sizes.top); + + gtk_widget_set_size_request (priv->area_defined, + (priv->style_info.radio_sizes.left + + 2 * priv->style_info.radio_sizes.bottom) * + (priv->style_info.num_buttons.left) + + (priv->style_info.num_buttons.left-1) * + priv->style_info.radio_sizes.top, + (priv->style_info.radio_sizes.right + + 2 * priv->style_info.radio_sizes.bottom) * + (priv->style_info.num_buttons.right) + + (priv->style_info.num_buttons.right-1) * + priv->style_info.radio_sizes.top); + + GTK_WIDGET_CLASS (parent_class)->size_request (widget, req); +} + +static void +hildon_color_chooser_dialog_size_allocate (GtkWidget *widget, + GtkAllocation *alloc) +{ + HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget); + + GdkRectangle rect; + int i, tmp, tmp2; + + g_assert (priv); + + GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, alloc); + + if (GTK_WIDGET_REALIZED (widget)) { + tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right); + tmp2 = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); + + for (i = 0; i < tmp; i++) { + rect.x = ((i % priv->style_info.num_buttons.left) * + (priv->style_info.radio_sizes.left + + priv->style_info.radio_sizes.top + + 2 * priv->style_info.radio_sizes.bottom)) + + priv->style_info.radio_sizes.bottom; + + rect.y = ((i / priv->style_info.num_buttons.left) * + (priv->style_info.radio_sizes.right + + priv->style_info.radio_sizes.top + + 2 * priv->style_info.radio_sizes.bottom)) + + priv->style_info.radio_sizes.bottom; + + rect.width = priv->style_info.radio_sizes.left; + rect.height = priv->style_info.radio_sizes.right; + + gdk_gc_set_clip_rectangle (priv->gc_array[i], &rect); + } + + for (i = 0; i < tmp2; i++) { + rect.x = ((i % priv->style_info.num_buttons.top) * + (priv->style_info.radio_sizes.left + + priv->style_info.radio_sizes.top + + 2 * priv->style_info.radio_sizes.bottom)) + + priv->style_info.radio_sizes.bottom; + + rect.y = ((i / priv->style_info.num_buttons.top) * + (priv->style_info.radio_sizes.right + + priv->style_info.radio_sizes.top + + 2 * priv->style_info.radio_sizes.bottom)) + priv->style_info.radio_sizes.bottom; + + rect.width = priv->style_info.radio_sizes.left; + rect.height = priv->style_info.radio_sizes.right; + + gdk_gc_set_clip_rectangle (priv->gc_array[i + tmp], &rect); + } + } +} + +static void +hildon_color_chooser_dialog_realize (GtkWidget *widget) +{ + HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget); + + GdkRectangle rect; + int i, tmp, tmp2; + + g_assert (priv); + + GTK_WIDGET_CLASS(parent_class)->realize (widget); + + tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right) + + (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); + + for (i = 0; i < tmp; i++) { + priv->gc_array[i] = gdk_gc_new (widget->window); + } + + tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right); + tmp2 = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); + + for (i = 0; i < tmp; i++) { + gdk_gc_set_rgb_fg_color (priv->gc_array[i], &priv->colors_defined[i]); + + rect.x = ((i % priv->style_info.num_buttons.left) * + (priv->style_info.radio_sizes.left + + priv->style_info.radio_sizes.top + + 2 * priv->style_info.radio_sizes.bottom)) + + priv->style_info.radio_sizes.bottom; + + rect.y = ((i / priv->style_info.num_buttons.left) * + (priv->style_info.radio_sizes.right + + priv->style_info.radio_sizes.top + + 2 * priv->style_info.radio_sizes.bottom)) + + priv->style_info.radio_sizes.bottom; + + rect.width = priv->style_info.radio_sizes.left; + rect.height = priv->style_info.radio_sizes.right; + + gdk_gc_set_clip_rectangle (priv->gc_array[i], &rect); + } + + for (i = 0; i < tmp2; i++) { + gdk_gc_set_rgb_fg_color (priv->gc_array[i + tmp], &priv->colors_custom[i]); + + rect.x = ((i % priv->style_info.num_buttons.top) * + (priv->style_info.radio_sizes.left + + priv->style_info.radio_sizes.top + + 2 * priv->style_info.radio_sizes.bottom)) + + priv->style_info.radio_sizes.bottom; + + rect.y = ((i / priv->style_info.num_buttons.top) * + (priv->style_info.radio_sizes.right + + priv->style_info.radio_sizes.top + + 2 * priv->style_info.radio_sizes.bottom)) + + priv->style_info.radio_sizes.bottom; + + rect.width = priv->style_info.radio_sizes.left; + rect.height = priv->style_info.radio_sizes.right; + + gdk_gc_set_clip_rectangle (priv->gc_array[i + tmp], &rect); + } +} + +static void +hildon_color_chooser_dialog_unrealize (GtkWidget *widget) +{ + HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget); + + int i, tmp; + + tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right) + + (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); + + for (i = 0; i < tmp; i++) { + g_object_unref (priv->gc_array[i]); + priv->gc_array[i] = NULL; + } + + GTK_WIDGET_CLASS (parent_class)->unrealize (widget); +} + +static void +hildon_color_chooser_dialog_style_set (GtkWidget *widget, + GtkStyle *previous_style) +{ + HildonColorChooserDialog *dialog = HILDON_COLOR_CHOOSER_DIALOG (widget); + HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget); + + GdkColor *tmpcolor; + gchar tmp[32], key[128], *val; + int i, tmpn, setcolor = 0; + + g_assert (priv); + + if (! priv->has_style) + setcolor = 1; + + priv->has_style = 1; + + gtk_widget_style_get (widget, "default_color", &tmpcolor, NULL); + + if (tmpcolor) { + priv->style_info.default_color = *tmpcolor; + gdk_color_free (tmpcolor); + } else { + priv->style_info.default_color.red = 0x0000; + priv->style_info.default_color.green = 0x0000; + priv->style_info.default_color.blue = 0x0000; + priv->style_info.default_color.pixel = 0x00000000; + } + + hildon_color_chooser_dialog_refresh_style_info (dialog); + + if (memcmp (&priv->style_info.num_buttons, &priv->style_info.last_num_buttons, sizeof (GtkBorder))) { + if (priv->colors_custom) { + g_free (priv->colors_custom); + } if (priv->colors_defined) { + g_free (priv->colors_defined); + } if (priv->gc_array) { + if (GTK_WIDGET_REALIZED (widget)) { + tmpn = (priv->style_info.last_num_buttons.left * priv->style_info.last_num_buttons.right) + + (priv->style_info.last_num_buttons.top * priv->style_info.last_num_buttons.bottom); + + for (i = 0; i < tmpn; i++) { + g_object_unref (priv->gc_array[i]); + priv->gc_array[i] = NULL; + } + } + + g_free (priv->gc_array); + } + + priv->colors_custom = (GdkColor *) + g_malloc0 (sizeof (GdkColor) * (priv->style_info.num_buttons.top * + priv->style_info.num_buttons.bottom)); + + priv->colors_defined = (GdkColor *) + g_malloc0 (sizeof(GdkColor) * (priv->style_info.num_buttons.left * + priv->style_info.num_buttons.right)); + + tmpn = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right) + + (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); + + priv->gc_array = (GdkGC **) g_malloc0 (sizeof (GdkGC *) * tmpn); + if (GTK_WIDGET_REALIZED (widget)) { + for (i = 0; i < tmpn; i++) { + priv->gc_array[i] = gdk_gc_new (widget->window); + } + } + + if (priv->gconf_client) { + + for (i = 0; i < (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); i++) { + memset (key, 0, 128); + /* FIXME Extremally bad hardcoding */ + g_snprintf (key, 128, "/system/osso/af/color_chooser/custom_color%d", i); + val = gconf_client_get_string (priv->gconf_client, key, NULL); + + if (val) { + hildon_color_chooser_dialog_ascii_hex_to_color (val, &priv->colors_custom[i]); + g_free (val); + } else { + priv->colors_custom[i] = priv->style_info.default_color; + } + } + } else { + for (i = 0; i < (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); i++) { + priv->colors_custom[i] = priv->style_info.default_color; + } + } + } + + tmpn = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right); + + hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (priv->chooser), + (priv->selected < tmpn) ? + &priv->colors_defined[priv->selected] : + &priv->colors_custom[priv->selected - tmpn]); + + for (i = 0; i < (priv->style_info.num_buttons.left * priv->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) { + priv->colors_defined[i] = *tmpcolor; + gdk_color_free (tmpcolor); + } else { + if(i < 16) { + priv->colors_defined[i] = hardcoded_colors[i]; + } else { /* fallback to prevent segfault */ + priv->colors_defined[i].red = 0x0000; + priv->colors_defined[i].green = 0x0000; + priv->colors_defined[i].blue = 0x0000; + priv->colors_defined[i].pixel = 0x00000000; + } + } + } + + if (GTK_WIDGET_REALIZED (widget)) { + for (i = 0; i < (priv->style_info.num_buttons.left * + priv->style_info.num_buttons.right); i++) { + gdk_gc_set_rgb_fg_color (priv->gc_array[i], &priv->colors_defined[i]); + } + } + + if (setcolor) + hildon_color_chooser_dialog_set_color (HILDON_COLOR_CHOOSER_DIALOG (dialog), + &priv->pending_color); + + gtk_widget_queue_resize (widget); + + GTK_WIDGET_CLASS (parent_class)->style_set (widget, previous_style); +} + +static void +hildon_color_chooser_dialog_show (GtkWidget *widget) +{ + HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget); + + g_assert (priv); + + gtk_widget_show (priv->hbox); + gtk_widget_show (priv->vbox); + + gtk_widget_show (priv->chooser); + + gtk_widget_show (priv->align_custom); + gtk_widget_show (priv->align_defined); + + gtk_widget_show (priv->separator); + + gtk_widget_show (priv->area_custom); + gtk_widget_show (priv->area_defined); + + GTK_WIDGET_CLASS (parent_class)->show (widget); +} + +/* FIXME WTF this function is even needed here? */ +static void +hildon_color_chooser_dialog_show_all (GtkWidget *widget) +{ + hildon_color_chooser_dialog_show (widget); +} + +static gboolean +hildon_color_chooser_dialog_key_press_event (GtkWidget *widget, + GdkEventKey *event) +{ + HildonColorChooserDialog *dialog = HILDON_COLOR_CHOOSER_DIALOG (widget); + HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget); + int tmp, tot, sel; + + g_assert (priv); + + if (event->keyval == HILDON_HARDKEY_UP || event->keyval == HILDON_HARDKEY_DOWN || + event->keyval == HILDON_HARDKEY_LEFT || event->keyval == HILDON_HARDKEY_RIGHT) { + tmp = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); + tot = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right) + tmp; + + switch (event->keyval) { + + case HILDON_HARDKEY_UP: + if(priv->selected >= priv->style_info.num_buttons.top) { + if(priv->selected - priv->style_info.num_buttons.left >= tmp) { + sel = priv->selected - priv->style_info.num_buttons.left; + } else { + sel = priv->selected - priv->style_info.num_buttons.top; + } + + hildon_color_chooser_dialog_set_color_num (dialog, sel); + } + break; + + case HILDON_HARDKEY_DOWN: + if(priv->selected < tot - priv->style_info.num_buttons.left) { + if(priv->selected < tmp) { + sel = priv->selected + priv->style_info.num_buttons.top; + } else { + sel = priv->selected + priv->style_info.num_buttons.left; + } + + hildon_color_chooser_dialog_set_color_num (dialog, sel); + } + break; + + case HILDON_HARDKEY_LEFT: + if ((priv->selected < tmp ? + (priv->selected % priv->style_info.num_buttons.top) : + ((priv->selected - tmp) % priv->style_info.num_buttons.left)) > 0) { + sel = priv->selected - 1; + + hildon_color_chooser_dialog_set_color_num (dialog, sel); + } + break; + + case HILDON_HARDKEY_RIGHT: + if ((priv->selected < tmp) ? + (priv->selected % priv->style_info.num_buttons.top < priv->style_info.num_buttons.top - 1) : + ((priv->selected - tmp) % priv->style_info.num_buttons.left < priv->style_info.num_buttons.left - 1)) { + sel = priv->selected + 1; + + hildon_color_chooser_dialog_set_color_num (dialog, sel); + } + break; + + default: + break; + } + + return FALSE; + } + + return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event); +} + +static gboolean +hildon_color_chooser_dialog_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_class)->key_press_event (widget, event); +} + +static void +hildon_color_chooser_dialog_destroy (GtkObject *object) +{ + HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (object); + + gchar key[128], color[13]; + int i, tmp; + + g_assert (priv); + + if (priv->gconf_client) { + memset (color, 0, 13); + + tmp = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); + + for (i = 0; i < tmp; i++) { + memset (key, 0, 128); + /* FIXME Extremally bad hardcoding */ + g_snprintf (key, 128, "/system/osso/af/color_chooser/custom_color%d", i); + hildon_color_chooser_dialog_color_to_ascii_hex (color, &priv->colors_custom[i]); + gconf_client_set_string (priv->gconf_client, key, color, NULL); + } + + g_object_unref (priv->gconf_client); + priv->gconf_client = NULL; + } + + if (priv->gc_array) { + g_free (priv->gc_array); + priv->gc_array = NULL; + } if (priv->colors_defined) { + g_free (priv->colors_defined); + priv->colors_defined = NULL; + } if (priv->colors_custom) { + g_free (priv->colors_custom); + priv->colors_custom = NULL; + } + + GTK_OBJECT_CLASS (parent_class)->destroy (object); +} + +/** + * hildon_color_chooser_dialog_set_color: + * @dialog: a #HildonColorChooserDialog + * @color: a color to set on the #HildonColorChooserDialog + * + * Sets the dialog to point at the given color. It'll first try to + * search the palette of the existing colors to match the passed color. + * If the color is not found in the pallette, the color in the currently + * selected box will be modified. + * + */ +void +hildon_color_chooser_dialog_set_color (HildonColorChooserDialog *dialog, + GdkColor *color) +{ + HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (dialog); + + int i, found = -1, tmp, tmp2; + + g_assert (priv); + + if (! priv->has_style) { + priv->pending_color = *color; + return; + } + + tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right); + tmp2 = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); + + for (i = 0; i < tmp; i++) { + if (priv->colors_defined[i].red == color->red && + priv->colors_defined[i].green == color->green && + priv->colors_defined[i].blue == color->blue) { + found = i; + break; + } + } + + if (found == -1) { + for (i = 0; i < tmp2; i++) { + if (priv->colors_custom[i].red == color->red && + priv->colors_custom[i].green == color->green && + priv->colors_custom[i].blue == color->blue) { + found = i + tmp; + break; + } + } + } + + if (found == -1) { + priv->colors_custom[tmp2-1] = *color; + if (GTK_WIDGET_REALIZED (GTK_WIDGET (dialog))) { + gdk_gc_set_rgb_fg_color (priv->gc_array[tmp2-1], color); + } + hildon_color_chooser_dialog_set_color_num (dialog, tmp2 - 1); + } else { + hildon_color_chooser_dialog_set_color_num (dialog, found); + } +} + +static gboolean +hildon_color_chooser_dialog_area_expose (GtkWidget *widget, + GdkEventExpose *event, + gpointer data) +{ + HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (data); + + int i, num_selected, tot_w, tot_h, spacing, brd, x, y; + GdkGC **start_gc; + int tmp, w, h; + + g_assert (priv); + + tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right); + + if (widget == priv->area_custom) { + num_selected = priv->selected - tmp; + start_gc = priv->gc_array + tmp; + tmp = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); + w = priv->style_info.num_buttons.top; + h = priv->style_info.num_buttons.bottom; + } else { /* widget == dialog->area_defined */ + num_selected = priv->selected; + start_gc = priv->gc_array; + w = priv->style_info.num_buttons.left; + h = priv->style_info.num_buttons.right; + } + + spacing = priv->style_info.radio_sizes.top; + brd = priv->style_info.radio_sizes.bottom; + tot_w = priv->style_info.radio_sizes.left + 2 * brd; + tot_h = priv->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, + (i == num_selected) ? widget->style->bg_gc[GTK_STATE_SELECTED] : widget->style->bg_gc[GTK_STATE_NORMAL], + 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, + (i == num_selected) ? widget->style->bg_gc[GTK_STATE_NORMAL] : 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); + } + + return FALSE; +} + +static gboolean +hildon_color_chooser_dialog_area_button_press (GtkWidget *widget, + GdkEventButton *event, + gpointer data) +{ + HildonColorChooserDialog *dialog = HILDON_COLOR_CHOOSER_DIALOG (data); + HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (data); + + int i, hskip, vskip, brd, selection = -1; + int x, y, tmp, tmp2, w; + + g_assert (priv); + + x = event->x; + y = event->y; + + brd = priv->style_info.radio_sizes.bottom; + hskip = priv->style_info.radio_sizes.left + + priv->style_info.radio_sizes.top + 2 * brd; + vskip = priv->style_info.radio_sizes.right + + priv->style_info.radio_sizes.top + 2 * brd; + + tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right); + tmp2 = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); + + if (widget == priv->area_defined) { + w = priv->style_info.num_buttons.left; + + for (i = 0; i < tmp; i++) { + if (x >= hskip * (i % w) + brd && x < hskip * (i % w) + brd + priv->style_info.radio_sizes.left && + y >= vskip * (i / w) + brd && y < hskip * (i / w) + brd + priv->style_info.radio_sizes.right) { + selection = i; + break; + } + } + } else { + w = priv->style_info.num_buttons.top; + for (i = 0; i < tmp2; i++) { + if (x >= hskip * (i % w) + brd && x < hskip * (i % w) + brd + priv->style_info.radio_sizes.left && + y >= vskip * (i / w) + brd && y < hskip * (i / w) + brd + priv->style_info.radio_sizes.right) { + selection = i + tmp; + break; + } + } + } + + if (selection != -1) { + hildon_color_chooser_dialog_set_color_num (dialog, selection); + } + + return FALSE; +} + +static void +hildon_color_chooser_dialog_color_changed (HildonColorChooser *chooser, + gpointer data) +{ + HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (data); + char key[128], color_str[13]; + int tmp; + GdkColor color; + + g_assert (priv); + + hildon_color_chooser_get_color (chooser, &color); + + tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right); + + if (priv->selected >= tmp) { + priv->colors_custom[priv->selected - tmp] = color; + + gdk_gc_set_rgb_fg_color (priv->gc_array[priv->selected], &priv->colors_custom[priv->selected - tmp]); + gtk_widget_queue_draw (priv->area_custom); + + if (priv->gconf_client) { + memset (key, 0, 128); + memset (color_str, 0, 13); + /* FIXME Ugly hardcoded stuff! */ + g_snprintf (key, 128, "/system/osso/af/color_chooser/custom_color%d", priv->selected - tmp); + hildon_color_chooser_dialog_color_to_ascii_hex (color_str, &priv->colors_custom[priv->selected - tmp]); + gconf_client_set_string (priv->gconf_client, key, color_str, NULL); + } + } +} + +static void +hildon_color_chooser_dialog_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_refresh_style_info (HildonColorChooserDialog *dialog) +{ + GtkBorder *tmp1, *tmp2, *tmp3; + HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (dialog); + + g_assert (priv); + + gtk_widget_style_get (GTK_WIDGET (dialog), "container_sizes", &tmp1, + "radio_sizes", &tmp2, "num_buttons", &tmp3, NULL); + + priv->style_info.last_num_buttons = priv->style_info.num_buttons; + + if (tmp1) { + priv->style_info.cont_sizes = *tmp1; + gtk_border_free (tmp1); + } else { + priv->style_info.cont_sizes.left = 0; + priv->style_info.cont_sizes.right = 8; + priv->style_info.cont_sizes.top = 4; + priv->style_info.cont_sizes.bottom = 0; + } + + if (tmp2) { + priv->style_info.radio_sizes = *tmp2; + gtk_border_free (tmp2); + } else { + priv->style_info.radio_sizes.left = 16; + priv->style_info.radio_sizes.right = 16; + priv->style_info.radio_sizes.top = 4; + priv->style_info.radio_sizes.bottom = 2; + } + + if (tmp3) { + priv->style_info.num_buttons = *tmp3; + gtk_border_free (tmp3); + } else { + priv->style_info.num_buttons.left = 8; + priv->style_info.num_buttons.right = 2; + priv->style_info.num_buttons.top = 8; + priv->style_info.num_buttons.bottom = 2; + } +} + +static void +hildon_color_chooser_dialog_set_color_num (HildonColorChooserDialog *dialog, + gint num) +{ + HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (dialog); + + int tmp; + + g_assert (priv); + + tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right); + + if (num < tmp) { + gtk_widget_set_sensitive (priv->chooser, FALSE); + } else { + gtk_widget_set_sensitive (priv->chooser, TRUE); + } + + priv->selected = num; + + gtk_widget_queue_draw (priv->area_custom); + gtk_widget_queue_draw (priv->area_defined); + + priv->color = (num < tmp) ? priv->colors_defined[num] : priv->colors_custom[num - tmp]; + + hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (priv->chooser), + (num < tmp) ? &priv->colors_defined[num] : &priv->colors_custom[num - tmp]); +} + +static void +hildon_color_chooser_dialog_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_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); +} + +/** + * hildon_color_chooser_dialog_new: + * + * Creates a new color chooser dialog. + * + * Returns: a new color chooser dialog. + */ +GtkWidget* +hildon_color_chooser_dialog_new (void) +{ + return g_object_new (HILDON_TYPE_COLOR_CHOOSER_DIALOG, NULL); +} + +/** + * hildon_color_chooser_dialog_get_color: + * @dialog: a #HildonColorChooserDialog + * @color: a color structure to fill with the currently selected color + * + * Retrives the currently selected color in the color chooser dialog. + * + */ +void +hildon_color_chooser_dialog_get_color (HildonColorChooserDialog *dialog, + GdkColor *color) +{ + /* FIXME Should return pending color? */ + HildonColorChooserDialogPrivate *priv; + + g_return_if_fail (HILDON_IS_COLOR_CHOOSER_DIALOG (dialog)); + priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (dialog); + g_assert (priv); + + hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER (priv->chooser), color); +} + diff --git a/hildon/hildon-color-chooser-dialog.h b/hildon/hildon-color-chooser-dialog.h new file mode 100644 index 0000000..cb51d00 --- /dev/null +++ b/hildon/hildon-color-chooser-dialog.h @@ -0,0 +1,84 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Author: Kuisma Salonen + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#ifndef __HILDON_COLOR_CHOOSER_DIALOG_H__ +#define __HILDON_COLOR_CHOOSER_DIALOG_H__ + +#include + +G_BEGIN_DECLS + +#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; +}; + +struct _HildonColorChooserDialogClass +{ + GtkDialogClass parent_class; +}; + +GType G_GNUC_CONST +hildon_color_chooser_dialog_get_type (void); + +GtkWidget* +hildon_color_chooser_dialog_new (void); + +void +hildon_color_chooser_dialog_set_color (HildonColorChooserDialog *dialog, + GdkColor *color); + +void +hildon_color_chooser_dialog_get_color (HildonColorChooserDialog *dialog, + GdkColor *color); + +G_END_DECLS + +#endif /* __HILDON_COLOR_CHOOSER_DIALOG_H__ */ + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-color-chooser-private.h b/hildon/hildon-color-chooser-private.h new file mode 100644 index 0000000..80f04fb --- /dev/null +++ b/hildon/hildon-color-chooser-private.h @@ -0,0 +1,63 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Author: Kuisma Salonen + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_PRIVATE_H__ +#define __HILDON_COLOR_CHOOSER_PRIVATE_H__ + +typedef struct _HildonColorChooserPrivate HildonColorChooserPrivate; + +#define HILDON_COLOR_CHOOSER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ + HILDON_TYPE_COLOR_CHOOSER, HildonColorChooserPrivate)); + +struct _HildonColorChooserPrivate +{ + 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; +}; + +#endif /* __HILDON_COLOR_CHOOSER_H__ */ diff --git a/hildon/hildon-color-chooser.c b/hildon/hildon-color-chooser.c new file mode 100644 index 0000000..81f8704 --- /dev/null +++ b/hildon/hildon-color-chooser.c @@ -0,0 +1,1365 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Author: Kuisma Salonen + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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 used to select a color from an HSV colorspace. + * @see_also: #HildonColorChooserDialog + * + * HildonColorChooser is a widget that displays an HSV colorspace. + * The user can manipulate the colorspace and easily select and shade of any color + * he wants. + * + * Normally you should not need to use this widget directly. Using #HildonColorButton or + * #HildonColorChooserDialog is much more handy. + * + */ + +#undef HILDON_DISABLE_DEPRECATED + +#include "hildon-color-chooser.h" +#include "hildon-color-chooser-private.h" + +static GtkWidgetClass* 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_init (HildonColorChooser *self); + +static void +hildon_color_chooser_class_init (HildonColorChooserClass *klass); + +static void +hildon_color_chooser_dispose (HildonColorChooser *self); + +static void +hildon_color_chooser_size_request (GtkWidget *widget, + GtkRequisition *req); + +static void +hildon_color_chooser_size_allocate (GtkWidget *widget, + GtkAllocation *alloc); + +static void +hildon_color_chooser_realize (GtkWidget *widget); + +static void +hildon_color_chooser_unrealize (GtkWidget *widget); + +static void +hildon_color_chooser_map (GtkWidget *widget); + +static void +hildon_color_chooser_unmap (GtkWidget *widget); + +static gboolean +hildon_color_chooser_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 +get_border (GtkWidget *w, + char *name, + GtkBorder *b); + +static void +init_borders (GtkWidget *w, + GtkBorder *inner, + GtkBorder *outer); + +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 (HildonColorChooser *self); + +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 (HildonColorChooser *self, + int x, + int y, + int w, + int h); + +inline void +inline_draw_sv_plane_dimmed (HildonColorChooser *self, + 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_expose_timer (gpointer data); + +static void +hildon_color_chooser_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec); + +static void +hildon_color_chooser_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec); + +#define EXPOSE_INTERVAL 50000 + +#define FULL_COLOR8 0xff + +#define FULL_COLOR 0x00ffffff + +enum +{ + COLOR_CHANGED, + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_COLOR +}; + +static guint color_chooser_signals [LAST_SIGNAL] = { 0 }; + +GType G_GNUC_CONST +hildon_color_chooser_get_type (void) +{ + static GType chooser_type = 0; + + if (!chooser_type) { + static const GTypeInfo chooser_info = + { + sizeof (HildonColorChooserClass), + NULL, + NULL, + (GClassInitFunc) hildon_color_chooser_class_init, + NULL, + NULL, + sizeof (HildonColorChooser), + 0, + (GInstanceInitFunc) hildon_color_chooser_init, + NULL + }; + + chooser_type = g_type_register_static (GTK_TYPE_WIDGET, + "HildonColorChooser", + &chooser_info, 0); + } + + return chooser_type; +} + +static void +hildon_color_chooser_init (HildonColorChooser *sel) +{ + + GTK_WIDGET_SET_FLAGS (sel, GTK_NO_WINDOW); + HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (sel); + g_assert (priv); + + priv->currhue = 0; + priv->currsat = 0; + priv->currval = 0; + + priv->mousestate = 0; + priv->mousein = FALSE; + + g_get_current_time (&priv->expose_info.last_expose_time); + + priv->expose_info.last_expose_hue = priv->currhue; + priv->expose_info.expose_queued = 0; + + priv->dimmed_plane = NULL; + priv->dimmed_bar = NULL; +} + +static void +hildon_color_chooser_class_init (HildonColorChooserClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->dispose = (gpointer) hildon_color_chooser_dispose; + object_class->get_property = hildon_color_chooser_get_property; + object_class->set_property = hildon_color_chooser_set_property; + + widget_class->size_request = hildon_color_chooser_size_request; + widget_class->size_allocate = hildon_color_chooser_size_allocate; + widget_class->realize = hildon_color_chooser_realize; + widget_class->unrealize = hildon_color_chooser_unrealize; + widget_class->map = hildon_color_chooser_map; + widget_class->unmap = hildon_color_chooser_unmap; + widget_class->expose_event = hildon_color_chooser_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; + + 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 ("outer_border", + "Outer border", + "The outer border for the chooser", + 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)); + + /** + * HildonColorChooser:color: + * + * The currently selected color. + */ + g_object_class_install_property (object_class, PROP_COLOR, + g_param_spec_boxed ("color", + "Current Color", + "The selected color", + GDK_TYPE_COLOR, + G_PARAM_READWRITE)); + + 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__VOID, + G_TYPE_NONE, + 0); + + g_type_class_add_private (klass, sizeof (HildonColorChooserPrivate)); +} + +static void +hildon_color_chooser_dispose (HildonColorChooser *sel) +{ + HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (sel); + g_assert (priv); + + if (priv->dimmed_bar != NULL) { + g_object_unref (priv->dimmed_bar); + priv->dimmed_bar = NULL; + } + + if (priv->dimmed_plane != NULL) { + g_object_unref (priv->dimmed_plane); + priv->dimmed_plane = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose (G_OBJECT (sel)); +} + +static void +hildon_color_chooser_size_request (GtkWidget *widget, + GtkRequisition *req) +{ + GtkBorder inner, outer; + + 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_size_allocate (GtkWidget *widget, + GtkAllocation *alloc) +{ + HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget); + GtkBorder outer, inner; + + g_assert (priv); + + widget->allocation = *alloc; + + init_borders(widget, &inner, &outer); + + priv->hba.height = alloc->height - outer.top - outer.bottom; + priv->hba.y = alloc->y + outer.top; + priv->hba.width = inner.top; + priv->hba.x = alloc->x + alloc->width - outer.right - inner.top; + + priv->spa.x = alloc->x + outer.left; + priv->spa.y = alloc->y + outer.top; + priv->spa.height = alloc->height - outer.top - outer.bottom; + priv->spa.width = alloc->width - outer.left - outer.right - inner.top - inner.bottom; + + if (GTK_WIDGET_REALIZED (widget)) { + gdk_window_move_resize (priv->event_window, + widget->allocation.x, + widget->allocation.y, + widget->allocation.width, + widget->allocation.height); + } +} + +static void +hildon_color_chooser_realize (GtkWidget *widget) +{ + HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget); + + g_assert (priv); + 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; + priv->event_window = gdk_window_new (widget->parent->window, &attributes, attributes_mask); + + + gdk_window_set_user_data (priv->event_window, widget); + + GTK_WIDGET_CLASS (parent_class)->realize (widget); +} + +static void +hildon_color_chooser_unrealize (GtkWidget *widget) +{ + HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget); + + g_assert (priv); + + 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_color_chooser_map (GtkWidget *widget) +{ + HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget); + + g_assert (priv); + GTK_WIDGET_CLASS(parent_class)->map(widget); + + if (priv->event_window) { + gdk_window_show (priv->event_window); + } +} + +static void +hildon_color_chooser_unmap (GtkWidget *widget) +{ + HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget); + + g_assert (priv); + + if (priv->event_window) { + gdk_window_hide (priv->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_expose (GtkWidget *widget, + GdkEventExpose *event) +{ + HildonColorChooser *sel = HILDON_COLOR_CHOOSER (widget); + HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget); + + g_assert (priv); + + GtkBorder graphical_border; + + struct { + int x, y, w, h; + } area; + + + if(! GTK_WIDGET_REALIZED (widget)) { + return FALSE; + } + + get_border (widget, "graphic_border", &graphical_border); + + if (event->area.width || event->area.height) { + + gdk_draw_rectangle (widget->window, + widget->style->black_gc, + FALSE, + priv->hba.x - 2, + priv->hba.y - 2, + priv->hba.width + 3, + priv->hba.height + 3); + + gdk_draw_rectangle (widget->window, + widget->style->black_gc, + FALSE, + priv->spa.x - 2, + priv->spa.y - 2, + priv->spa.width + 3, + priv->spa.height + 3); + } + + if (priv->expose_info.expose_queued) { + if (GTK_WIDGET_SENSITIVE (widget)) { + inline_draw_hue_bar (widget, priv->hba.x, priv->hba.y, priv->hba.width, priv->hba.height, priv->hba.y, priv->hba.height); + + inline_draw_sv_plane (sel, priv->spa.x, priv->spa.y, priv->spa.width, priv->spa.height); + } else { + inline_draw_hue_bar_dimmed (widget, priv->hba.x, priv->hba.y, priv->hba.width, priv->hba.height, priv->hba.y, priv->hba.height); + + inline_draw_sv_plane_dimmed (sel, priv->spa.x, priv->spa.y, priv->spa.width, priv->spa.height); + } + + priv->expose_info.expose_queued = 0; + + g_get_current_time (&priv->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, &priv->hba); + + if(GTK_WIDGET_SENSITIVE (widget)) { + inline_draw_hue_bar (widget, area.x, area.y, area.w, area.h, priv->hba.y, priv->hba.height); + } else { + inline_draw_hue_bar_dimmed (widget, area.x, area.y, area.w, area.h, priv->hba.y, priv->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, &priv->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; + } +} + +inline void +inline_limited_expose (HildonColorChooser *sel) +{ + GTimeVal curr_time, result; + GdkEventExpose event; + HildonColorChooserPrivate *priv; + + if (! GTK_WIDGET_REALIZED (GTK_WIDGET (sel))) { + return; + } + + priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (sel); + g_assert (priv); + + if(priv->currhue == priv->expose_info.last_expose_hue) { + return; /* no need to redraw */ + } + + priv->expose_info.last_expose_hue = priv->currhue; + + g_get_current_time (&curr_time); + + inline_sub_times (&result, &curr_time, &priv->expose_info.last_expose_time); + + if(result.tv_sec != 0 || result.tv_usec >= EXPOSE_INTERVAL) { + + priv->expose_info.expose_queued = 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 if(! priv->expose_info.expose_queued) { + priv->expose_info.expose_queued = 1; + g_timeout_add ((EXPOSE_INTERVAL - result.tv_usec) / 1000, hildon_color_chooser_expose_timer, sel); + } +} + +static gboolean +hildon_color_chooser_button_press (GtkWidget *widget, + GdkEventButton *event) +{ + HildonColorChooser *sel = HILDON_COLOR_CHOOSER (widget); + HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget); + + g_assert (priv); + int x, y, tmp; + + x = (int) event->x + widget->allocation.x; + y = (int) event->y + widget->allocation.y; + + if (x >= priv->spa.x && x <= priv->spa.x + priv->spa.width && + y >= priv->spa.y && y <= priv->spa.y + priv->spa.height) { + + tmp = y - priv->spa.y; + priv->currsat = tmp * 0xffff / priv->spa.height; + tmp = x - priv->spa.x; + priv->currval = tmp * 0xffff / priv->spa.width; + + g_signal_emit (sel, color_chooser_signals[COLOR_CHANGED], 0); + gtk_widget_queue_draw (widget); + + priv->mousestate = 1; + priv->mousein = TRUE; + + gtk_grab_add(widget); + + } else if (x >= priv->hba.x && x <= priv->hba.x + priv->hba.width && + y >= priv->hba.y && y <= priv->hba.y + priv->hba.height) { + + tmp = y - priv->hba.y; + priv->currhue = tmp * 0xffff / priv->hba.height; + + g_signal_emit (sel, color_chooser_signals[COLOR_CHANGED], 0); + inline_limited_expose (sel); + + priv->mousestate = 2; + priv->mousein = TRUE; + + gtk_grab_add (widget); + } + + return FALSE; +} + +static gboolean +hildon_color_chooser_button_release (GtkWidget *widget, + GdkEventButton *event) +{ + HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget); + + g_assert (priv); + + if (priv->mousestate) { + gtk_grab_remove (widget); + } + + priv->mousestate = 0; + priv->mousein = FALSE; + + return FALSE; +} + +static gboolean +hildon_color_chooser_pointer_motion (GtkWidget *widget, + GdkEventMotion *event) +{ + HildonColorChooser *sel = HILDON_COLOR_CHOOSER (widget); + HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget); + + gint x, y, tmp; + + g_assert (priv); + + x = (gint) event->x; + y = (gint) event->y; + + if (priv->mousestate == 1) { + if (x >= priv->spa.x && x <= priv->spa.x + priv->spa.width && + y >= priv->spa.y && y <= priv->spa.y + priv->spa.height) { + + priv->currsat = (((long)(y - priv->spa.y)) * 0xffff) / priv->spa.height; + priv->currval = (((long)(x - priv->spa.x)) * 0xffff) / priv->spa.width; + + g_signal_emit (sel, color_chooser_signals[COLOR_CHANGED], 0); + gtk_widget_queue_draw(widget); + + } else if (priv->mousein == TRUE) { + } + + } else if (priv->mousestate == 2) { + if (x >= priv->hba.x && x <= priv->hba.x + priv->hba.width && + y >= priv->hba.y && y <= priv->hba.y + priv->hba.height) { + tmp = y - priv->hba.y; + tmp *= 0xffff; + tmp /= priv->hba.height; + + if(tmp != priv->currhue) { + priv->currhue = tmp; + + g_signal_emit (sel, color_chooser_signals[COLOR_CHANGED], 0); + inline_limited_expose (sel); + } + + } else if (priv->mousein == TRUE) { + } + } + + gdk_event_request_motions (event); + + return FALSE; +} + +static void +get_border (GtkWidget *w, + char *name, + GtkBorder *b) +{ + GtkBorder *tb = NULL; + + gtk_widget_style_get (w, name, &tb, NULL); + + if (tb) { + *b = *tb; + gtk_border_free (tb); + } else { + b->left = 0; + b->right = 0; + b->top = 0; + b->bottom = 0; + } +} + +static void +init_borders (GtkWidget *w, + GtkBorder *inner, + GtkBorder *outer) +{ + GtkBorder *tb; + + get_border (w, "outer_border", outer); + + gtk_widget_style_get (w, "inner_size", &tb, NULL); + + if (tb) { + *inner = *tb; + gtk_border_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; +} + +/** + * hildon_color_chooser_set_color: + * @chooser: a #HildonColorChooser + * @color: a color to be set + * + * Sets the color selected in the widget. + * Will move the crosshair pointer to indicate the passed color. + */ +void +hildon_color_chooser_set_color (HildonColorChooser *chooser, + GdkColor *color) +{ + unsigned short hue, sat, val; + unsigned long min, max; + signed long tmp, diff; + HildonColorChooserPrivate *priv; + + g_return_if_fail (HILDON_IS_COLOR_CHOOSER (chooser)); + g_return_if_fail (color != NULL); + + priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (chooser); + g_assert (priv); + + /* 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; + } + + priv->currhue = hue; + priv->currsat = sat; + priv->currval = val; + + inline_limited_expose (chooser); + g_signal_emit (chooser, color_chooser_signals[COLOR_CHANGED], 0); +} + +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; + } +} + +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) +{ + HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget); + + unsigned short hvec, hcurr; + unsigned char *buf, *ptr, tmp[3]; + int i, j, tmpy; + g_assert (priv); + + 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 = priv->hba.y + (priv->currhue * priv->hba.height / 0xffff); + gdk_draw_line (widget->parent->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], priv->hba.x, tmpy, priv->hba.x + priv->hba.width - 1, tmpy); + + if ((((priv->currhue * priv->hba.height) & 0xffff) > 0x8000) && (tmpy < (priv->hba.y + priv->hba.height))) { + gdk_draw_line (widget->parent->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], + priv->hba.x, tmpy+1, priv->hba.x + priv->hba.width - 1, tmpy+1); + } else if (tmpy > priv->hba.y) { + gdk_draw_line(widget->parent->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], priv->hba.x, + tmpy-1, priv->hba.x + priv->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) +{ + HildonColorChooser *sel = HILDON_COLOR_CHOOSER (widget); + HildonColorChooserPrivate *priv; + + if (w <= 0 || h <= 0) { + return; + } + + priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (sel); + g_assert (priv); + + /* We need to create (and cache) the pixbuf if we don't + * have it yet */ + if (priv->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; + } + + priv->dimmed_bar = gdk_pixbuf_new_from_data (buf, GDK_COLORSPACE_RGB, FALSE, 8, w, h, w * 3, (gpointer) g_free, buf); + } + + gdk_draw_pixbuf (widget->parent->window, widget->style->fg_gc [0], priv->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 (HildonColorChooser *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]; + HildonColorChooserPrivate *priv; + int i, j; + int tmp; + + if (w <= 0 || h <= 0) { + return; + } + + priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (sel); + g_assert (priv); + tmp = priv->spa.width * priv->spa.height; + + buf = (unsigned char *) g_malloc (w * h * 3); + ptr = buf; + + inline_h2rgb (priv->currhue, rgbtmp); + + rgby[0] = rgbtmp[0] - rgbx[0]; + rgby[1] = rgbtmp[1] - rgbx[1]; + rgby[2] = rgbtmp[2] - rgbx[2]; + + rgbx[0] /= priv->spa.width; + rgbx[1] /= priv->spa.width; + rgbx[2] /= priv->spa.width; + + rgby[0] /= tmp; + rgby[1] /= tmp; + rgby[2] /= tmp; + + rgbx[0] += (y - priv->spa.y) * rgby[0]; + rgbx[1] += (y - priv->spa.y) * rgby[1]; + rgbx[2] += (y - priv->spa.y) * rgby[2]; + + for(i = 0; i < h; i++) { + rgbtmp[0] = rgbx[0] * (x - priv->spa.x); + rgbtmp[1] = rgbx[1] * (x - priv->spa.x); + rgbtmp[2] = rgbx[2] * (x - priv->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, + (priv->spa.width * priv->currval / 0xffff) - x + priv->spa.x - 4, + (priv->spa.height * priv->currsat / 0xffff) - y + priv->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 (HildonColorChooser *sel, + int x, + int y, + int w, + int h) +{ + GtkWidget *widget = GTK_WIDGET (sel); + HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (sel); + + g_assert (priv); + + if (w <= 0 || h <= 0) { + return; + } + + /* We need to create (and cache) the pixbuf if we don't + * have it yet */ + if (priv->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 = priv->spa.width * priv->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] /= priv->spa.width; + rgbx[1] /= priv->spa.width; + rgbx[2] /= priv->spa.width; + + rgby[0] /= tmp; + rgby[1] /= tmp; + rgby[2] /= tmp; + + rgbx[0] += (y - priv->spa.y) * rgby[0]; + rgbx[1] += (y - priv->spa.y) * rgby[1]; + rgbx[2] += (y - priv->spa.y) * rgby[2]; + + for(i = 0; i < h; i++) { + rgbtmp[0] = rgbx[0] * (x - priv->spa.x); + rgbtmp[1] = rgbx[1] * (x - priv->spa.x); + rgbtmp[2] = rgbx[2] * (x - priv->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]; + } + + priv->dimmed_plane = gdk_pixbuf_new_from_data (buf, GDK_COLORSPACE_RGB, FALSE, 8, w, h, w * 3, (gpointer) g_free, buf); + } + + gdk_draw_pixbuf (widget->parent->window, widget->style->fg_gc [0], priv->dimmed_plane, 0, 0, x, y, w, h, GDK_RGB_DITHER_NONE, 0, 0); +} + + +static gboolean +hildon_color_chooser_expose_timer (gpointer data) +{ + HildonColorChooser *sel = HILDON_COLOR_CHOOSER (data); + HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (sel); + + g_assert (priv); + + if (priv->expose_info.expose_queued) { + gtk_widget_queue_draw (GTK_WIDGET (data)); + } + + return FALSE; +} + +/** + * hildon_color_chooser_get_color: + * @chooser: a #HildonColorChooser + * @color: a color structure to fill with the currently selected color + * + * Retrives the currently selected color in the chooser. + * + */ +void +hildon_color_chooser_get_color (HildonColorChooser *chooser, + GdkColor *color) +{ + HildonColorChooserPrivate *priv; + GdkVisual *system_visual = gdk_visual_get_system (); + unsigned long rgb[3], rgb2[3]; + + g_return_if_fail (HILDON_IS_COLOR_CHOOSER (chooser)); + g_return_if_fail (color != NULL); + + priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (chooser); + g_assert (priv); + + inline_h2rgb (priv->currhue, rgb); + + rgb2[0] = 0xffffff - rgb[0]; + rgb2[1] = 0xffffff - rgb[1]; + rgb2[2] = 0xffffff - rgb[2]; + + color->red = ((rgb[0] >> 8) + ((rgb2[0] >> 8) * (0xffff - priv->currsat) / 0xffff)) * priv->currval / 0xffff; + color->green = ((rgb[1] >> 8) + ((rgb2[1] >> 8) * (0xffff - priv->currsat) / 0xffff)) * priv->currval / 0xffff; + color->blue = ((rgb[2] >> 8) + ((rgb2[2] >> 8) * (0xffff - priv->currsat) / 0xffff)) * priv->currval / 0xffff; + + color->pixel = ((color->red >> (16 - system_visual->red_prec)) << system_visual->red_shift) | + ((color->green >> (16 - system_visual->green_prec)) << system_visual->green_shift) | + ((color->blue >> (16 - system_visual->blue_prec)) << system_visual->blue_shift); +} + +GtkWidget* +hildon_color_chooser_new (void) +{ + return (GtkWidget *) g_object_new (HILDON_TYPE_COLOR_CHOOSER, NULL); +} + +static void +hildon_color_chooser_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + g_return_if_fail (HILDON_IS_COLOR_CHOOSER (object)); + + switch (param_id) + { + + case PROP_COLOR: { + GdkColor *color = g_value_get_boxed (value); + hildon_color_chooser_set_color ((HildonColorChooser *) object, color); + } break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +hildon_color_chooser_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + g_return_if_fail (HILDON_IS_COLOR_CHOOSER (object)); + + switch (param_id) + { + + case PROP_COLOR: { + GdkColor color; + hildon_color_chooser_get_color ((HildonColorChooser *) object, &color); + g_value_set_boxed (value, &color); + } break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + + diff --git a/hildon/hildon-color-chooser.h b/hildon/hildon-color-chooser.h new file mode 100644 index 0000000..bcc8e4d --- /dev/null +++ b/hildon/hildon-color-chooser.h @@ -0,0 +1,87 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Author: Kuisma Salonen + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#ifndef __HILDON_COLOR_CHOOSER_H__ +#define __HILDON_COLOR_CHOOSER_H__ + +#include + +G_BEGIN_DECLS + +#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; +}; + +struct _HildonColorChooserClass +{ + GtkWidgetClass parent; + + void (*color_changed) (HildonColorChooser *selection, GdkColor *color); + void (*set_color) (HildonColorChooser *, GdkColor *); +}; + +GType G_GNUC_CONST +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); + +G_END_DECLS + +#endif /* __HILDON_COLOR_CHOOSER_H__ */ + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-controlbar-private.h b/hildon/hildon-controlbar-private.h new file mode 100644 index 0000000..49983af --- /dev/null +++ b/hildon/hildon-controlbar-private.h @@ -0,0 +1,44 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_PRIVATE_H__ +#define __HILDON_CONTROLBAR_PRIVATE_H__ + +G_BEGIN_DECLS + +typedef struct _HildonControlbarPrivate HildonControlbarPrivate; + +#define HILDON_CONTROLBAR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ + HILDON_TYPE_CONTROLBAR, HildonControlbarPrivate)); + +struct _HildonControlbarPrivate +{ + gboolean button_press; + gint old_value; +}; + +G_END_DECLS + +#endif /* __HILDON_CONTROLBAR_PRIVATE_H__ */ diff --git a/hildon/hildon-controlbar.c b/hildon/hildon-controlbar.c new file mode 100644 index 0000000..e9b4d8e --- /dev/null +++ b/hildon/hildon-controlbar.c @@ -0,0 +1,893 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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. + * + * + * + * #HildonControlbar has been deprecated since Hildon 2.2 + * See Migrating Control Bars + * section to know how to migrate this deprecated widget. + * + * + * + * + * HildonControlbar example + * + * GtkWidget *cbar = hildon_controlbar_new(); + * hildon_controlbar_set_max (HILDON_CONTROLBAR (cbar), 12); + * hildon_controlbar_set_value (HILDON_CONTROLBAR (cbar), 6); + * + * + * + */ + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "hildon-controlbar.h" +#include "hildon-controlbar-private.h" + +#define _(string)\ + dgettext("hildon-libs", string) + +#define DEFAULT_WIDTH 234 + +#define DEFAULT_HEIGHT 60 + +#define DEFAULT_BORDER_WIDTH 0 + +#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; + +enum +{ + PROP_0, + 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); + +static gboolean +hildon_controlbar_change_value (GtkRange *range, + GtkScrollType scroll, + gdouble new_value, + gpointer data); + +/** + * hildon_controlbar_get_type: + * + * Initializes and returns the type of a hildon control bar. + * + * Returns: GType of #HildonControlbar + */ +GType G_GNUC_CONST +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; +} + +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; + gobject_class->constructor = hildon_controlbar_constructor; + 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; + 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 current 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); + g_assert (priv); + + priv->button_press = FALSE; + priv->old_value = 0; + range = GTK_RANGE (controlbar); + + 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); + g_assert (priv); + + /* 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 + * + * Set 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 highlights + * 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); + g_assert (priv); + + 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; + gdouble vv = adj->upper - adj->lower; + gint calc = ((new_value - adj->lower) / vv) * (vv + 1.0) + adj->lower; + + priv = HILDON_CONTROLBAR_GET_PRIVATE(range); + g_assert (priv); + + /* 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; + } + + GTK_RANGE_CLASS (parent_class)->change_value (range, scroll, calc); + + return TRUE; +} + +/* + * 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); + g_assert (priv); + + 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 (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); + g_assert (priv); + + 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); + + block_area = (w - 2 * stepper_size - 2 * stepper_spacing - 2 * inner_border_width); + + if (block_area <= 0) + return; + + block_min = 1; + 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; + + if (block_count == 0) + block_count = 1; + /* 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/hildon-controlbar.h b/hildon/hildon-controlbar.h new file mode 100644 index 0000000..f3aaf34 --- /dev/null +++ b/hildon/hildon-controlbar.h @@ -0,0 +1,105 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#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)) + +#define HILDON_CONTROLBAR_GET_CLASS(obj) \ + ((HildonControlBarClass *) G_OBJECT_GET_CLASS(obj)) + +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 G_GNUC_CONST +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__ */ + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-date-button.c b/hildon/hildon-date-button.c new file mode 100644 index 0000000..a27b996 --- /dev/null +++ b/hildon/hildon-date-button.c @@ -0,0 +1,221 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +#include + +#include "hildon-date-button.h" +#include "hildon-date-selector.h" +#include "hildon-touch-selector.h" +#include "hildon-picker-button-private.h" + +#define _(String) \ + dgettext("hildon-libs", String) + +#define c_(String) \ + dgettext("hildon-common-strings", String) + +/** + * SECTION:hildon-date-button + * @Short_Description: Button displaying and allowing selection of a date. + * @See_Also: #HildonPickerButton, #HildonTimeButton + * + * #HildonDateButton is a widget that shows a text label and a date, and allows + * the user to select a different date. Visually, it's a button that, once clicked, + * presents a #HildonPickerDialog containing a #HildonDateSelector. Once the user selects + * a different date from the selector, this will be shown in the button. + */ + +G_DEFINE_TYPE (HildonDateButton, hildon_date_button, HILDON_TYPE_PICKER_BUTTON) + +#if 0 +#define GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), HILDON_TYPE_DATE_BUTTON, HildonDateButtonPrivate)) + +typedef struct _HildonDateButtonPrivate HildonDateButtonPrivate; + +struct _HildonDateButtonPrivate +{ +}; +#endif + +#if 0 +static void +hildon_date_button_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +hildon_date_button_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} +#endif + +static void +hildon_date_button_class_init (HildonDateButtonClass * klass) +{ +#if 0 + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (HildonDateButtonPrivate)); + + object_class->get_property = hildon_date_button_get_property; + object_class->set_property = hildon_date_button_set_property; +#endif +} + +static void +hildon_date_button_init (HildonDateButton * self) +{ + GtkWidget *date_selector; + + date_selector = hildon_date_selector_new (); + + hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (self), + HILDON_TOUCH_SELECTOR (date_selector)); +} + +static GtkWidget * +hildon_date_button_new_full (HildonSizeType size, + HildonButtonArrangement arrangement, + GtkWidget *selector) +{ + return g_object_new (HILDON_TYPE_DATE_BUTTON, + "title", _("wdgt_ti_date"), + "arrangement", arrangement, + "size", size, + "touch-selector", selector, + NULL); +} + +/** + * hildon_date_button_new: + * @size: One of #HildonSizeType + * @arrangement: one of #HildonButtonArrangement + * + * Creates a new #HildonDateButton. See hildon_button_new() for details on the + * parameters. + * + * Returns: a new #HildonDateButton + * + * Since: 2.2 + **/ +GtkWidget * +hildon_date_button_new (HildonSizeType size, + HildonButtonArrangement arrangement) +{ + GtkWidget *selector = hildon_date_selector_new (); + return hildon_date_button_new_full (size, arrangement, selector); +} + +/** + * hildon_date_button_new_with_year_range: + * @size: One of #HildonSizeType + * @arrangement: one of #HildonButtonArrangement + * @min_year: the minimum available year or -1 to ignore + * @max_year: the maximum available year or -1 to ignore + * + * Creates a new #HildonDateButton with a specific valid range of years. + * See hildon_date_selector_new_with_year_range() for details on the range. + * + * Returns: a new #HildonDateButton + * + * Since: 2.2 + **/ +GtkWidget * +hildon_date_button_new_with_year_range (HildonSizeType size, + HildonButtonArrangement arrangement, + gint min_year, + gint max_year) +{ + GtkWidget *selector; + selector = hildon_date_selector_new_with_year_range (min_year, max_year); + return hildon_date_button_new_full (size, arrangement, selector); +} + +/** + * hildon_date_button_get_date: + * @button: a #HildonDateButton + * @year: return location for the selected year + * @month: return location for the selected month + * @day: return location for the selected day + * + * Retrieves currently selected date from @button. + * + * Since: 2.2 + **/ +void +hildon_date_button_get_date (HildonDateButton * button, + guint * year, guint * month, guint * day) +{ + HildonTouchSelector *selector; + + g_return_if_fail (HILDON_IS_DATE_BUTTON (button)); + + selector = hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (button)); + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); + + hildon_date_selector_get_date (HILDON_DATE_SELECTOR (selector), year, month, day); +} + +/** + * hildon_date_button_set_date: + * @button: a #HildonDateButton + * @year: the year to set. + * @month: the month number to set. + * @day: the day of the month to set. + * + * Sets the date in @button. The date set will be displayed + * and will be the default selected option on the shown #HildonDateSelector. + * + * Since: 2.2 + **/ +void +hildon_date_button_set_date (HildonDateButton * button, + guint year, guint month, guint day) +{ + HildonTouchSelector *selector; + gchar *date; + + g_return_if_fail (HILDON_IS_DATE_BUTTON (button)); + + selector = hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (button)); + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); + + hildon_picker_button_disable_value_changed (HILDON_PICKER_BUTTON (button), TRUE); + hildon_date_selector_select_current_date (HILDON_DATE_SELECTOR (selector), + year, month, day); + hildon_picker_button_disable_value_changed (HILDON_PICKER_BUTTON (button), FALSE); + + date = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector)); + + hildon_button_set_value (HILDON_BUTTON (button), date); + + g_free (date); + + hildon_picker_button_value_changed (HILDON_PICKER_BUTTON (button)); +} diff --git a/hildon/hildon-date-button.h b/hildon/hildon-date-button.h new file mode 100644 index 0000000..5c8e1ca --- /dev/null +++ b/hildon/hildon-date-button.h @@ -0,0 +1,87 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +#ifndef __HILDON_DATE_BUTTON__ +#define __HILDON_DATE_BUTTON__ + +#include + +#include "hildon-picker-button.h" + +G_BEGIN_DECLS + +#define HILDON_TYPE_DATE_BUTTON \ + hildon_date_button_get_type() + +#define HILDON_DATE_BUTTON(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj),\ + HILDON_TYPE_DATE_BUTTON, HildonDateButton)) + +#define HILDON_DATE_BUTTON_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + HILDON_TYPE_DATE_BUTTON, HildonDateButtonClass)) + +#define HILDON_IS_DATE_BUTTON(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_DATE_BUTTON)) + +#define HILDON_IS_DATE_BUTTON_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_DATE_BUTTON)) + +#define HILDON_DATE_BUTTON_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + HILDON_TYPE_DATE_BUTTON, HildonDateButtonClass)) + + +typedef struct _HildonDateButton HildonDateButton; +typedef struct _HildonDateButtonClass HildonDateButtonClass; + +struct _HildonDateButton +{ + HildonPickerButton parent; +}; + +struct _HildonDateButtonClass +{ + HildonPickerButtonClass parent_class; +}; + +GType +hildon_date_button_get_type (void); + +GtkWidget* +hildon_date_button_new (HildonSizeType size, + HildonButtonArrangement arrangement); + +GtkWidget * +hildon_date_button_new_with_year_range (HildonSizeType size, + HildonButtonArrangement arrangement, + gint min_year, + gint max_year); + +void +hildon_date_button_get_date (HildonDateButton *button, + guint *year, + guint *month, + guint *day); +void +hildon_date_button_set_date (HildonDateButton * button, + guint year, + guint month, + guint day); + +G_END_DECLS + +#endif /* __HILDON_DATE_BUTTON__ */ diff --git a/hildon/hildon-date-editor-private.h b/hildon/hildon-date-editor-private.h new file mode 100644 index 0000000..3206172 --- /dev/null +++ b/hildon/hildon-date-editor-private.h @@ -0,0 +1,65 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_PRIVATE_H__ +#define __HILDON_DATE_EDITOR_PRIVATE_H__ + +G_BEGIN_DECLS + +#define HILDON_DATE_EDITOR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE((obj),\ + HILDON_TYPE_DATE_EDITOR, HildonDateEditorPrivate)); + +typedef struct _HildonDateEditorPrivate HildonDateEditorPrivate; + +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 */ +}; + +G_END_DECLS + +#endif /* __HILDON_DATE_EDITOR_PRIVATE_H__ */ diff --git a/hildon/hildon-date-editor.c b/hildon/hildon-date-editor.c new file mode 100644 index 0000000..eb8dee4 --- /dev/null +++ b/hildon/hildon-date-editor.c @@ -0,0 +1,1570 @@ +/* vim:set sw=4 expandtab cino=(0: + * + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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. + * + * + * + * + * #HildonDateEditor has been deprecated since Hildon 2.2 and should + * not be used in newly written code. Use #HildonDateSelector instead. See + * Migrating Date Widgets + * section to know how to migrate this deprecated widget. + * + * + * + * + * + * guint y, m, d; + * GtkDialog *dialog; + * GtkWidget *date_editor; + * + * dialog = GTK_DIALOG (gtk_dialog_new ()); + * date_editor = hildon_date_editor_new (); + * + * gtk_box_pack_start (GTK_BOX (dialog->vbox), gtk_label_new ("Choose a date"), FALSE, FALSE, 10); + * gtk_box_pack_start (GTK_BOX (dialog->vbox), date_editor, FALSE, FALSE, 10); + * gtk_dialog_add_button (dialog, "Close", GTK_RESPONSE_CANCEL); + * + * gtk_widget_show_all (GTK_WIDGET (dialog)); + * gtk_dialog_run (dialog); + * + * hildon_date_editor_get_date (HILDON_DATE_EDITOR (date_editor), &y, &m, &d); + * g_debug ("Date: %u-%u-%u", y, m, d); + * + * + * + * + */ + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include "hildon-date-editor.h" +#include "hildon-calendar-popup.h" +#include "hildon-defines.h" +#include "hildon-marshalers.h" +#include "hildon-enum-types.h" +#include "hildon-time-editor.h" +#include "hildon-banner.h" +#include "hildon-date-editor-private.h" +#include "hildon-private.h" + +#define _(string) dgettext("hildon-libs", string) + +#define c_(string) dgettext("hildon-common-strings", 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 + +static GtkContainerClass* parent_class; + +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, + HildonDateTimeError type); + +static gboolean +hildon_date_editor_entry_focus_in (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_focus (GtkWidget *widget, + GtkDirectionType direction); +static gboolean +hildon_date_editor_entry_select_all (GtkWidget *widget); + +/* Property indices */ +enum +{ + PROP_0, + PROP_DAY, + PROP_MONTH, + PROP_YEAR, + PROP_MIN_YEAR, + PROP_MAX_YEAR +}; + +enum +{ + DATE_ERROR, + LAST_SIGNAL +}; + +static guint date_editor_signals[LAST_SIGNAL] = { 0 }; + +/** + * hildon_date_editor_get_type: + * + * Initializes and returns the type of a hildon date editor. + * + * Returns: GType of #HildonDateEditor + */ +GType G_GNUC_CONST +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_date_editor_focus; + + container_class->forall = hildon_child_forall; + GTK_OBJECT_CLASS(editor_class)->destroy = hildon_date_editor_destroy; + + editor_class->date_error = (gpointer) 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_TIME_ERROR); + + /** + * HildonDateEditor:year: + * + * Current year. + */ + g_object_class_install_property (gobject_class, PROP_YEAR, + g_param_spec_uint ("year", + "Current year", + "Current year", + 1, 10000, + 2007, + 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, 10000, + 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, 10000, + 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) +{ + g_assert (priv); + + gtk_image_set_from_icon_name (GTK_IMAGE (priv->calendar_icon), + "widgets_date_editor", HILDON_ICON_SIZE_SMALL); + + 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); + g_assert (priv); + + 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); + g_assert (priv); + + 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 (); + +#ifdef MAEMO_GTK + g_object_set (G_OBJECT(priv->d_entry), "hildon-input-mode", + HILDON_GTK_INPUT_MODE_NUMERIC, NULL); + g_object_set (G_OBJECT(priv->m_entry), "hildon-input-mode", + HILDON_GTK_INPUT_MODE_NUMERIC, NULL); + g_object_set (G_OBJECT(priv->y_entry), "hildon-input-mode", + HILDON_GTK_INPUT_MODE_NUMERIC, NULL); +#endif + + /* 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_focus_in), editor); + + g_signal_connect (GTK_OBJECT (priv->m_entry), "focus-in-event", + G_CALLBACK (hildon_date_editor_entry_focus_in), editor); + + g_signal_connect (GTK_OBJECT (priv->y_entry), "focus-in-event", + G_CALLBACK (hildon_date_editor_entry_focus_in), 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; + + g_assert (priv); + + 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); + 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); + break; + + case PROP_MAX_YEAR: + val = g_value_get_uint (value); + 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); + 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); + g_assert (priv); + + 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); + g_assert (priv); + + 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 (GtkWidget *) 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. */ + + priv = HILDON_DATE_EDITOR_GET_PRIVATE (editor); + g_assert (priv); + + 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 + * + * Gets the date represented by the date editor. + * You can pass NULL to any of the pointers if + * you're not interested in obtaining it. + * + */ +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)); + + 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. */ + + if (year != NULL) + *year = /*priv->year;*/ + (guint) atoi (gtk_entry_get_text (GTK_ENTRY (priv->y_entry))); + if (month != NULL) + *month = /*priv->month;*/ + (guint) atoi (gtk_entry_get_text (GTK_ENTRY (priv->m_entry))); + if (day != NULL) + *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_focus_in (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 = HILDON_DATE_TIME_ERROR_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); + g_assert (priv); + + 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, HILDON_DATE_TIME_ERROR_EMPTY_DAY, &r); + else if(widget == priv->m_entry) + g_signal_emit (ed, date_editor_signals[DATE_ERROR], 0, HILDON_DATE_TIME_ERROR_EMPTY_MONTH, &r); + else + g_signal_emit (ed, date_editor_signals[DATE_ERROR], 0, HILDON_DATE_TIME_ERROR_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 = HILDON_DATE_TIME_ERROR_MIN_MONTH; + m = 1; + } + else if (m > 12) { + error_code = HILDON_DATE_TIME_ERROR_MAX_MONTH; + m = 12; + } + } + + /* Validate year */ + if(widget == priv->y_entry) { + if (y < priv->min_year) { + error_code = HILDON_DATE_TIME_ERROR_MIN_YEAR; + y = priv->min_year; + } + else if (y > priv->max_year) { + error_code = HILDON_DATE_TIME_ERROR_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 = HILDON_DATE_TIME_ERROR_MIN_DAY; + d = 1; + } + else if (d > max_days) { + if (d > 31) { + error_code = HILDON_DATE_TIME_ERROR_MAX_DAY; + d = max_days; + } + else { /* the date does not exist (is invalid) */ + error_code = HILDON_DATE_TIME_ERROR_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 != HILDON_DATE_TIME_ERROR_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; +} + +/* 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; +} + +/* 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; + priv = HILDON_DATE_EDITOR_GET_PRIVATE (HILDON_DATE_EDITOR (data)); + + g_assert (GTK_IS_ENTRY (ed)); + g_assert (HILDON_IS_DATE_EDITOR (data)); + g_assert (priv); + + 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 == HILDON_DATE_TIME_ERROR_NO_ERROR) + { + priv->skip_validation = TRUE; + gtk_widget_child_focus (GTK_WIDGET (data), GTK_DIR_RIGHT); + } + } else { + priv->skip_validation = FALSE; + } +} + +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; + + g_assert (HILDON_IS_DATE_EDITOR (data)); + g_assert (GTK_IS_ENTRY (widget)); + + ed = HILDON_DATE_EDITOR (data); + + switch (event->keyval) { + 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. */ + hildon_date_editor_set_calendar_icon_state (ed, TRUE); + return TRUE; + case GDK_Escape: + priv = HILDON_DATE_EDITOR_GET_PRIVATE (ed); + 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); + g_assert (priv); + + hildon_date_editor_entry_validate (widget, data); + priv->skip_validation = FALSE; + + return FALSE; +} + +static gboolean +hildon_date_editor_date_error (HildonDateEditor *editor, + HildonDateTimeError type) +{ + HildonDateEditorPrivate *priv = HILDON_DATE_EDITOR_GET_PRIVATE (editor); + g_assert (priv); + + switch (type) + { + case HILDON_DATE_TIME_ERROR_MAX_DAY: + hildon_banner_show_informationf (GTK_WIDGET (editor), NULL, _("ckct_ib_maximum_value"), 31); + break; + + case HILDON_DATE_TIME_ERROR_MAX_MONTH: + hildon_banner_show_informationf (GTK_WIDGET (editor), NULL, _("ckct_ib_maximum_value"), 12); + break; + + case HILDON_DATE_TIME_ERROR_MAX_YEAR: + hildon_banner_show_informationf (GTK_WIDGET (editor), NULL, _("ckct_ib_maximum_value"), priv->max_year); + break; + + case HILDON_DATE_TIME_ERROR_MIN_DAY: + case HILDON_DATE_TIME_ERROR_MIN_MONTH: + hildon_banner_show_informationf (GTK_WIDGET (editor), NULL, _("ckct_ib_minimum_value"), 1); + break; + + case HILDON_DATE_TIME_ERROR_MIN_YEAR: + hildon_banner_show_informationf (GTK_WIDGET (editor), NULL, _("ckct_ib_minimum_value"), priv->min_year); + break; + + case HILDON_DATE_TIME_ERROR_EMPTY_DAY: + hildon_banner_show_informationf (GTK_WIDGET (editor), NULL, _("ckct_ib_set_a_value_within_range"), 1, 31); + break; + + case HILDON_DATE_TIME_ERROR_EMPTY_MONTH: + hildon_banner_show_informationf (GTK_WIDGET (editor), NULL, _("ckct_ib_set_a_value_within_range"), 1, 12); + break; + + case HILDON_DATE_TIME_ERROR_EMPTY_YEAR: + hildon_banner_show_informationf (GTK_WIDGET (editor), NULL, _("ckct_ib_set_a_value_within_range"), + priv->min_year, priv->max_year); + break; + + case HILDON_DATE_TIME_ERROR_INVALID_CHAR: + hildon_banner_show_information (GTK_WIDGET (editor), NULL, c_("ckct_ib_illegal_character")); + break; + + case HILDON_DATE_TIME_ERROR_INVALID_DATE: + hildon_banner_show_information (GTK_WIDGET (editor), 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); + g_assert (priv); + + /* 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; + gboolean rtl; + + g_assert (GTK_IS_WIDGET (widget)); + g_assert (allocation != NULL); + + ed = HILDON_DATE_EDITOR (widget); + priv = HILDON_DATE_EDITOR_GET_PRIVATE (ed); + + rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL); + 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; + + /* calculate allocations */ + if (GTK_WIDGET_VISIBLE (widget)) { + /* allocate frame */ + gtk_widget_get_child_requisition (priv->frame, &req); + + f_alloc.width = req.width; + f_alloc.height = max_req.height; + + /* allocate icon */ + 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; + + if (rtl) + { + img_alloc.x = f_alloc.x; + f_alloc.x += img_alloc.width + HILDON_MARGIN_DEFAULT; + } + + if (GTK_WIDGET_VISIBLE (priv->d_button_image)) { + gtk_widget_size_allocate (priv->d_button_image, &img_alloc); + } + + if (GTK_WIDGET_VISIBLE (priv->frame)) { + gtk_widget_size_allocate (priv->frame, &f_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); + } +} + +static gboolean +hildon_date_editor_focus (GtkWidget *widget, + GtkDirectionType direction) +{ + gboolean retval; + GtkDirectionType effective_direction; + + g_assert (HILDON_IS_DATE_EDITOR (widget)); + + retval = hildon_private_composite_focus (widget, direction, &effective_direction); + + if (retval == TRUE) + return GTK_WIDGET_CLASS (parent_class)->focus (widget, effective_direction); + else + return FALSE; +} + +/** + * 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 and has been set. + */ +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); + g_assert (priv); + + 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 and has been set. + */ +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); + g_assert (priv); + + 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 and has been set. + */ +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); + g_assert (priv); + + 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); + g_assert (priv); + + 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); + g_assert (priv); + + 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); + g_assert (priv); + + return (guint) atoi (gtk_entry_get_text (GTK_ENTRY (priv->d_entry))); +} + diff --git a/hildon/hildon-date-editor.h b/hildon/hildon-date-editor.h new file mode 100644 index 0000000..02c91db --- /dev/null +++ b/hildon/hildon-date-editor.h @@ -0,0 +1,114 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#ifndef __HILDON_DATE_EDITOR_H__ +#define __HILDON_DATE_EDITOR_H__ + +#include + +#include "hildon-time-editor.h" + +G_BEGIN_DECLS + +#define HILDON_TYPE_DATE_EDITOR \ + (hildon_date_editor_get_type()) + +#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)) + +typedef struct _HildonDateEditor HildonDateEditor; + +typedef struct _HildonDateEditorClass HildonDateEditorClass; + + +struct _HildonDateEditor +{ + GtkContainer parent; +}; + +struct _HildonDateEditorClass +{ + GtkContainerClass parent_class; + + gboolean (*date_error) (HildonDateEditor *editor, HildonDateTimeError type); +}; + +GType G_GNUC_CONST +hildon_date_editor_get_type (void); + +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__ */ + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-date-selector.c b/hildon/hildon-date-selector.c new file mode 100644 index 0000000..c2e0f96 --- /dev/null +++ b/hildon/hildon-date-selector.c @@ -0,0 +1,904 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2008 Nokia Corporation. + * + * 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; either + * version 2 of the License, or (at your option) any later version. or (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/** + * SECTION:hildon-date-selector + * @short_description: A widget to select the current date. + * + * #HildonDateSelector is a date widget with multiple columns. Users + * can choose a date by selecting values in the day, month and year + * columns. + * + * The currently selected month and year can be altered with + * hildon_date_selector_select_month(). The day can be selected from + * the active month using hildon_date_selector_select_day(). + */ + +#define _GNU_SOURCE /* needed for GNU nl_langinfo_l */ +#define __USE_GNU /* needed for locale */ + +#include + +#ifdef HAVE_SYS_TIME_H +#include +#endif + +#include +#include + +#include +#include +#include + +#include "hildon-date-selector.h" + +#define HILDON_DATE_SELECTOR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_DATE_SELECTOR, HildonDateSelectorPrivate)) + +G_DEFINE_TYPE (HildonDateSelector, hildon_date_selector, HILDON_TYPE_TOUCH_SELECTOR) + +#define INIT_YEAR 100 +#define LAST_YEAR 50 /* since current year */ + +#define _(String) dgettext("hildon-libs", String) + +/* #define _(String) "%A %e. %B %Y" debug purposes */ + +enum +{ + COLUMN_STRING, + COLUMN_INT, + N_COLUMNS +}; + +enum +{ + DAY, + MONTH, + YEAR +}; + +struct _HildonDateSelectorPrivate +{ + GtkTreeModel *year_model; + GtkTreeModel *month_model; + GtkTreeModel *day_model; + + GSList *column_order; + gint day_column; + gint month_column; + gint year_column; /* it depends on the locale */ + + gchar *format; /* day/month/year format, depends on locale */ + + gint creation_day; + gint creation_month; + gint creation_year; /* date at creation time */ + + gint current_num_days; + + gint min_year; + gint max_year; +}; + +enum { + PROP_MIN_YEAR = 1, + PROP_MAX_YEAR, +}; + +static GObject * hildon_date_selector_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_properties); +static void hildon_date_selector_finalize (GObject * object); + +/* private functions */ +static GtkTreeModel *_create_day_model (HildonDateSelector * selector); +static GtkTreeModel *_create_year_model (HildonDateSelector * selector); +static GtkTreeModel *_create_month_model (HildonDateSelector * selector); + +static void _get_real_date (gint * year, gint * month, gint * day); +static void _locales_init (HildonDateSelectorPrivate * priv); + +static void _manage_selector_change_cb (HildonTouchSelector * selector, + gint num_column, gpointer data); + +static GtkTreeModel *_update_day_model (HildonDateSelector * selector); + +static gint _month_days (gint month, gint year); +static void _init_column_order (HildonDateSelector * selector); + +static gchar *_custom_print_func (HildonTouchSelector * selector, + gpointer user_data); + +/***************************************************************************/ +/* The following date routines are taken from the lib_date package. Keep + * them separate in case we want to update them if a newer lib_date comes + * out with fixes. */ + +typedef unsigned int N_int; + +typedef unsigned long N_long; + +typedef signed long Z_long; + +typedef enum +{ false = FALSE, true = TRUE } boolean; + +#define and && /* logical (boolean) operators: lower case */ + +#define or || + +static const N_int month_length[2][13] = { + {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, + {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} +}; + +static const N_int days_in_months[2][14] = { + {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}, + {0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366} +}; + +static Z_long _calc_days (N_int year, N_int mm, N_int dd); + +static N_int _day_of_week (N_int year, N_int mm, N_int dd); + +static boolean _leap (N_int year); + + +static boolean +_leap (N_int year) +{ + return ((((year % 4) == 0) and ((year % 100) != 0)) or ((year % 400) == 0)); +} + +static N_int +_day_of_week (N_int year, N_int mm, N_int dd) +{ + Z_long days; + + days = _calc_days (year, mm, dd); + if (days > 0L) { + days--; + days %= 7L; + days++; + } + return ((N_int) days); +} + +static Z_long +_year_to_days (N_int year) +{ + return (year * 365L + (year / 4) - (year / 100) + (year / 400)); +} + +static Z_long +_calc_days (N_int year, N_int mm, N_int dd) +{ + boolean lp; + + if (year < 1) + return (0L); + if ((mm < 1) or (mm > 12)) + return (0L); + if ((dd < 1) or (dd > month_length[(lp = _leap (year))][mm])) + return (0L); + return (_year_to_days (--year) + days_in_months[lp][mm] + dd); +} + +static void +hildon_date_selector_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + HildonDateSelectorPrivate *priv = HILDON_DATE_SELECTOR (object)->priv; + + switch (prop_id) + { + case PROP_MIN_YEAR: + priv->min_year = g_value_get_int (value); + break; + case PROP_MAX_YEAR: + priv->max_year = g_value_get_int (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +hildon_date_selector_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + HildonDateSelectorPrivate *priv = HILDON_DATE_SELECTOR (object)->priv; + + switch (prop_id) + { + case PROP_MIN_YEAR: + g_value_set_int (value, priv->min_year); + break; + case PROP_MAX_YEAR: + g_value_set_int (value, priv->max_year); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +hildon_date_selector_class_init (HildonDateSelectorClass * class) +{ + GObjectClass *gobject_class; + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + GtkContainerClass *container_class; + + gobject_class = (GObjectClass *) class; + object_class = (GtkObjectClass *) class; + widget_class = (GtkWidgetClass *) class; + container_class = (GtkContainerClass *) class; + + /* GObject */ + gobject_class->finalize = hildon_date_selector_finalize; + gobject_class->get_property = hildon_date_selector_get_property; + gobject_class->set_property = hildon_date_selector_set_property; + gobject_class->constructor = hildon_date_selector_constructor; + + /* GtkWidget */ + + /* GtkContainer */ + + /* properties */ + + g_object_class_install_property ( + gobject_class, + PROP_MIN_YEAR, + g_param_spec_int ( + "min-year", + "Minimum year", + "The minimum available year in the selector", + 1900, + 2100, + 1970, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); + + g_object_class_install_property ( + gobject_class, + PROP_MAX_YEAR, + g_param_spec_int ( + "max-year", + "Maximum year", + "The maximum available year in the selector", + 1900, + 2100, + 2037, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); + + /* signals */ + + g_type_class_add_private (object_class, sizeof (HildonDateSelectorPrivate)); +} + +static void +hildon_date_selector_construct_ui (HildonDateSelector *selector) +{ + GSList *iter = NULL; + gint current_item = 0; + HildonTouchSelectorColumn *column = NULL; + + selector->priv->year_model = _create_year_model (selector); + selector->priv->month_model = _create_month_model (selector); + selector->priv->day_model = _create_day_model (selector); + + /* We add the columns, checking the locale order */ + iter = selector->priv->column_order; + for (iter = selector->priv->column_order; iter; iter = g_slist_next (iter)) { + current_item = GPOINTER_TO_INT (iter->data); + + switch (current_item) { + case DAY: + column = hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), + selector->priv->day_model, TRUE); + g_object_set (G_OBJECT (column), "text-column", 0, NULL); + break; + case MONTH: + column = hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), + selector->priv->month_model, TRUE); + g_object_set (G_OBJECT (column), "text-column", 0, NULL); + break; + case YEAR: + column = hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), + selector->priv->year_model, TRUE); + g_object_set (G_OBJECT (column), "text-column", 0, NULL); + break; + default: + g_error ("Current column order incorrect"); + break; + } + } +} + +static GObject * +hildon_date_selector_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_properties) +{ + GObject *object; + HildonDateSelector *selector; + + object = G_OBJECT_CLASS (hildon_date_selector_parent_class)->constructor + (type, n_construct_properties, construct_properties); + + selector = HILDON_DATE_SELECTOR (object); + + hildon_date_selector_construct_ui (selector); + + g_signal_connect (object, "changed", G_CALLBACK (_manage_selector_change_cb), NULL); + + /* By default we should select the current day */ + hildon_date_selector_select_current_date (selector, selector->priv->creation_year, + selector->priv->creation_month, + selector->priv->creation_day); + + return object; +} + +static void +hildon_date_selector_init (HildonDateSelector * selector) +{ + selector->priv = HILDON_DATE_SELECTOR_GET_PRIVATE (selector); + + GTK_WIDGET_SET_FLAGS (GTK_WIDGET (selector), GTK_NO_WINDOW); + gtk_widget_set_redraw_on_allocate (GTK_WIDGET (selector), FALSE); + + hildon_touch_selector_set_print_func (HILDON_TOUCH_SELECTOR (selector), + _custom_print_func); + + _locales_init (selector->priv); + + _init_column_order (selector); + + _get_real_date (&selector->priv->creation_year, + &selector->priv->creation_month, &selector->priv->creation_day); + selector->priv->current_num_days = 31; +} + +static void +hildon_date_selector_finalize (GObject * object) +{ + HildonDateSelector *selector = NULL; + + selector = HILDON_DATE_SELECTOR (object); + + g_slist_free (selector->priv->column_order); + g_free (selector->priv->format); + + (*G_OBJECT_CLASS (hildon_date_selector_parent_class)->finalize) (object); +} + +/* ------------------------------ PRIVATE METHODS ---------------------------- */ +static gchar * +_custom_print_func (HildonTouchSelector * touch_selector, gpointer user_data) +{ + HildonDateSelector *selector = NULL; + gchar *result = NULL; + guint year, month, day; + gint day_of_week = 0; + static gchar string[255]; + struct tm tm = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + selector = HILDON_DATE_SELECTOR (touch_selector); + + hildon_date_selector_get_date (selector, &year, &month, &day); + day_of_week = _day_of_week (year, month + 1, day) % 7; + + tm.tm_mday = day; + tm.tm_mon = month; + tm.tm_year = year - 1900; + tm.tm_wday = day_of_week; + + strftime (string, 255, _("wdgt_va_date_long"), &tm); + + result = g_strdup (string); + + return result; +} + +/* This was copied from hildon-calendar */ +static void +_locales_init (HildonDateSelectorPrivate * priv) +{ + /* Hildon: This is not exactly portable, see + * http://bugzilla.gnome.org/show_bug.cgi?id=343415 + * The labels need to be instance variables as the startup wizard changes + * locale on runtime. + */ + locale_t l; + + l = newlocale (LC_TIME_MASK, setlocale (LC_MESSAGES, NULL), NULL); + + priv->format = g_locale_to_utf8 (nl_langinfo_l (D_FMT, l), + -1, NULL, NULL, NULL); + + freelocale (l); +} + +static void +_init_column_order (HildonDateSelector * selector) +{ + gchar *current_order[3] = { NULL, NULL, NULL }; + gchar *day_pos = NULL; + gchar *month_pos = NULL; + gchar *year_pos = NULL; + gint i, c; + gchar *aux = NULL; + + g_debug ("Current format: %s", selector->priv->format); + + /* search each token on the format */ + day_pos = g_strrstr (selector->priv->format, "%d"); + + month_pos = g_strrstr (selector->priv->format, "%m"); + year_pos = g_strrstr (selector->priv->format, "%y"); + if (year_pos == NULL) { + year_pos = g_strrstr (selector->priv->format, "%Y"); + } + + + if ((day_pos == NULL) || (month_pos == NULL) || (year_pos == NULL)) { + g_error ("Wrong date format"); /* so default values */ + + selector->priv->day_column = 0; + selector->priv->month_column = 1; + selector->priv->year_column = 2; + selector->priv->column_order = g_slist_append (NULL, GINT_TO_POINTER (DAY)); + selector->priv->column_order = + g_slist_append (selector->priv->column_order, GINT_TO_POINTER (MONTH)); + selector->priv->column_order = + g_slist_append (selector->priv->column_order, GINT_TO_POINTER (YEAR)); + } + + /* sort current_order with this values (bubble sort) */ + current_order[0] = day_pos; + current_order[1] = month_pos; + current_order[2] = year_pos; + + for (c = 1; c <= 2; c++) { + for (i = 0; i < 3 - c; i++) { + if (current_order[i] > current_order[i + 1]) { + aux = current_order[i]; + current_order[i] = current_order[i + 1]; + current_order[i + 1] = aux; + } + } + } + + /* fill the column positions */ + selector->priv->column_order = NULL; + c = 0; + for (i = 0; i < 3; i++) { + if (current_order[i] == day_pos) { + selector->priv->column_order = + g_slist_append (selector->priv->column_order, GINT_TO_POINTER (DAY)); + selector->priv->day_column = c++; + } + if (current_order[i] == month_pos) { + selector->priv->column_order = + g_slist_append (selector->priv->column_order, GINT_TO_POINTER (MONTH)); + selector->priv->month_column = c++; + } + if (current_order[i] == year_pos) { + selector->priv->column_order = + g_slist_append (selector->priv->column_order, GINT_TO_POINTER (YEAR)); + selector->priv->year_column = c++; + } + } +} + + +static GtkTreeModel * +_create_day_model (HildonDateSelector * selector) +{ + GtkListStore *store_days = NULL; + gint i = 0; + gchar label[255]; + struct tm tm = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + GtkTreeIter iter; + + store_days = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT); + for (i = 1; i < 32; i++) { + tm.tm_mday = i; + strftime (label, 255, _("wdgt_va_day_numeric"), &tm); + + gtk_list_store_append (store_days, &iter); + gtk_list_store_set (store_days, &iter, + COLUMN_STRING, label, COLUMN_INT, i, -1); + } + + return GTK_TREE_MODEL (store_days); +} + +static GtkTreeModel * +_create_year_model (HildonDateSelector * selector) +{ + GtkListStore *store_years = NULL; + gint real_year = 0; + gint i = 0; + static gchar label[255]; + struct tm tm = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + GtkTreeIter iter; + + real_year = selector->priv->creation_year; + + store_years = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT); + for (i = selector->priv->min_year; i < selector->priv->max_year + 1; i++) { + tm.tm_year = i - 1900; + strftime (label, 255, _("wdgt_va_year"), &tm); + + gtk_list_store_append (store_years, &iter); + gtk_list_store_set (store_years, &iter, + COLUMN_STRING, label, COLUMN_INT, i, -1); + } + + return GTK_TREE_MODEL (store_years); +} + +static GtkTreeModel * +_create_month_model (HildonDateSelector * selector) +{ + GtkTreeIter iter; + gint i = 0; + GtkListStore *store_months = NULL; + static gchar label[255]; + struct tm tm = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + store_months = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT); + for (i = 0; i < 12; i++) { + tm.tm_mon = i; + strftime (label, 255, _("wdgt_va_month"), &tm); + + gtk_list_store_append (store_months, &iter); + gtk_list_store_set (store_months, &iter, COLUMN_STRING, label, + COLUMN_INT, i, + -1); + } + + return GTK_TREE_MODEL (store_months); +} + +static GtkTreeModel * +_update_day_model (HildonDateSelector * selector) +{ + GtkListStore *store_days = NULL; + GtkTreePath *path = NULL; + gint i = 0; + GtkTreeIter iter; + static gchar label[255]; + struct tm tm = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + guint current_day = 0; + guint current_year = 0; + guint current_month = 0; + gint num_days = 31; + + hildon_date_selector_get_date (selector, ¤t_year, ¤t_month, + ¤t_day); + + num_days = _month_days (current_month, current_year); + store_days = GTK_LIST_STORE (selector->priv->day_model); + + if (num_days == selector->priv->current_num_days) { + return GTK_TREE_MODEL (store_days); + } + + if (num_days > selector->priv->current_num_days) { + for (i = selector->priv->current_num_days + 1; i <= num_days; i++) { + tm.tm_mday = i; + strftime (label, 255, _("wdgt_va_day_numeric"), &tm); + + gtk_list_store_append (store_days, &iter); + gtk_list_store_set (store_days, &iter, + COLUMN_STRING, label, COLUMN_INT, i, -1); + } + } else { + path = gtk_tree_path_new_from_indices (num_days, + -1); + gtk_tree_model_get_iter (GTK_TREE_MODEL (store_days), &iter, path); + do { + }while (gtk_list_store_remove (store_days, &iter)); + + gtk_tree_path_free (path); + } + + + selector->priv->current_num_days = num_days; + + /* now we select a day */ + if (current_day >= num_days) { + current_day = num_days; + } + + hildon_date_selector_select_day (selector, current_day); + + return GTK_TREE_MODEL (store_days); +} + + +static void +_get_real_date (gint * year, gint * month, gint * day) +{ + time_t secs; + struct tm *tm = NULL; + + secs = time (NULL); + tm = localtime (&secs); + + if (year != NULL) { + *year = 1900 + tm->tm_year; + } + + if (month != NULL) { + *month = tm->tm_mon; + } + + if (day != NULL) { + *day = tm->tm_mday; + } +} + + +static void +_manage_selector_change_cb (HildonTouchSelector * touch_selector, + gint num_column, gpointer data) +{ + HildonDateSelector *selector = NULL; + + g_return_if_fail (HILDON_IS_DATE_SELECTOR (touch_selector)); + selector = HILDON_DATE_SELECTOR (touch_selector); + + if ((num_column == selector->priv->month_column) || + (num_column == selector->priv->year_column)) /* it is required to check that with + * the years too,remember: leap years + * update_day_model will check if + * the number of days is different + */ + { + _update_day_model (selector); + } +} + +static gint +_month_days (gint month, gint year) +{ + gint month_days[2][12] = { + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, + {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} + }; + + g_return_val_if_fail (month >= 0 && month < 12, -1); + + return month_days[_leap (year)][month]; +} + + +/* ------------------------------ PUBLIC METHODS ---------------------------- */ + +/** + * hildon_date_selector_new: + * + * Creates a new #HildonDateSelector + * + * Returns: a new #HildonDateSelector + * + * Since: 2.2 + **/ +GtkWidget * +hildon_date_selector_new () +{ + return g_object_new (HILDON_TYPE_DATE_SELECTOR, NULL); +} + +/** + * hildon_date_selector_new_with_year_range: + * @min_year: the minimum available year or -1 to ignore + * @max_year: the maximum available year or -1 to ignore + * + * Creates a new #HildonDateSelector with a specific year range. + * If @min_year or @max_year are set to -1, then the default + * upper or lower bound will be used, respectively. + * + * Returns: a new #HildonDateSelector + * + * Since: 2.2 + **/ +GtkWidget * +hildon_date_selector_new_with_year_range (gint min_year, + gint max_year) +{ + GtkWidget *selector; + + g_return_val_if_fail (min_year <= max_year, NULL); + + if (min_year == -1 && min_year == -1) { + selector = g_object_new (HILDON_TYPE_DATE_SELECTOR, + NULL); + } else if (min_year == -1) { + selector = g_object_new (HILDON_TYPE_DATE_SELECTOR, + "max-year", max_year, + NULL); + } else if (max_year == -1) { + selector = g_object_new (HILDON_TYPE_DATE_SELECTOR, + "min-year", min_year, + NULL); + } else { + selector = g_object_new (HILDON_TYPE_DATE_SELECTOR, + "min-year", min_year, + "max-year", max_year, + NULL); + } + + return selector; +} +/** + * hildon_date_selector_select_current_date: + * @selector: the #HildonDateSelector + * @year: the current year + * @month: the current month (0-11) + * @day: the current day (1-31, 1-30, 1-29, 1-28) depends on the month + * + * Sets the current active date on the #HildonDateSelector widget + * + * Since: 2.2 + * + * Returns: %TRUE on success, %FALSE otherwise + **/ +gboolean +hildon_date_selector_select_current_date (HildonDateSelector * selector, + guint year, guint month, guint day) +{ + GtkTreeIter iter; + gint min_year = 0; + gint max_year = 0; + gint num_days = 0; + + min_year = selector->priv->min_year; + max_year = selector->priv->max_year; + + g_return_val_if_fail (min_year <= year && year <= max_year, FALSE); + g_return_val_if_fail (month < 12, FALSE); + + num_days = _month_days (month, year); + g_return_val_if_fail (day > 0 && day <= num_days, FALSE); + + + gtk_tree_model_iter_nth_child (selector->priv->year_model, &iter, NULL, + year - min_year); + hildon_touch_selector_select_iter (HILDON_TOUCH_SELECTOR (selector), + selector->priv->year_column, &iter, + FALSE); + + gtk_tree_model_iter_nth_child (selector->priv->month_model, &iter, NULL, + month); + hildon_touch_selector_select_iter (HILDON_TOUCH_SELECTOR (selector), + selector->priv->month_column, &iter, + FALSE); + + gtk_tree_model_iter_nth_child (selector->priv->day_model, &iter, NULL, + day - 1); + hildon_touch_selector_select_iter (HILDON_TOUCH_SELECTOR (selector), + selector->priv->day_column, &iter, + FALSE); + + return TRUE; +} + + +/** + * hildon_date_selector_get_date: + * @selector: the #HildonDateSelector + * @year: to set the current year + * @month: to set the current month (0-11) + * @day: to the current day (1-31, 1-30, 1-29, 1-28) depends on the month + * + * Gets the current active date on the #HildonDateSelector widget + * + * Since: 2.2 + **/ +void +hildon_date_selector_get_date (HildonDateSelector * selector, + guint * year, guint * month, guint * day) +{ + GtkTreeIter iter; + + if (year != NULL) { + if (hildon_touch_selector_get_selected (HILDON_TOUCH_SELECTOR (selector), + selector->priv->year_column, &iter)) + gtk_tree_model_get (selector->priv->year_model, + &iter, COLUMN_INT, year, -1); + } + + if (month != NULL) { + if (hildon_touch_selector_get_selected (HILDON_TOUCH_SELECTOR (selector), + selector->priv->month_column, &iter)) + gtk_tree_model_get (selector->priv->month_model, + &iter, COLUMN_INT, month, -1); + } + + if (day != NULL) { + if (hildon_touch_selector_get_selected (HILDON_TOUCH_SELECTOR (selector), + selector->priv->day_column, &iter)) + { + gtk_tree_model_get (selector->priv->day_model, + &iter, COLUMN_INT, day, -1); + } +/* *day = *day - 1; */ + } + +} + + +/** + * hildon_date_selector_select_month: + * @selector: the #HildonDateSelector + * @month: the current month (0-11) + * @year: the current year + * + * Modify the current month and year on the current active date + * + * Utility function to keep this API similar to the previously + * existing #HildonCalendar widget. + * + * Since: 2.2 + * + * Returns: %TRUE on success, %FALSE otherwise + **/ +gboolean hildon_date_selector_select_month (HildonDateSelector *selector, + guint month, guint year) +{ + guint day = 0; + + hildon_date_selector_get_date (selector, NULL, NULL, &day); + + return hildon_date_selector_select_current_date (selector, year, month, day); +} + +/** + * hildon_date_selector_select_day: + * @selector: the #HildonDateSelector + * @day: the current day (1-31, 1-30, 1-29, 1-28) depends on the month + * + * Modify the current day on the current active date + * + * Utility function to keep this API similar to the previously + * existing #HildonCalendar widget. + * + * Since: 2.2 + **/ +void +hildon_date_selector_select_day (HildonDateSelector *selector, guint day) +{ + guint month = 0; + guint year = 0; + + hildon_date_selector_get_date (selector, &year, &month, NULL); + + hildon_date_selector_select_current_date (selector, year, month, day); +} diff --git a/hildon/hildon-date-selector.h b/hildon/hildon-date-selector.h new file mode 100644 index 0000000..0a775e8 --- /dev/null +++ b/hildon/hildon-date-selector.h @@ -0,0 +1,103 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2008 Nokia Corporation. + * + * 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; either + * version 2 of the License, or (at your option) any later version. or (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __HILDON_DATE_SELECTOR_H__ +#define __HILDON_DATE_SELECTOR_H__ + +#include "hildon-touch-selector.h" + +G_BEGIN_DECLS +#define HILDON_TYPE_DATE_SELECTOR \ + (hildon_date_selector_get_type ()) + +#define HILDON_DATE_SELECTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + HILDON_TYPE_DATE_SELECTOR, HildonDateSelector)) + +#define HILDON_DATE_SELECTOR_CLASS(vtable) \ + (G_TYPE_CHECK_CLASS_CAST ((vtable), \ + HILDON_TYPE_DATE_SELECTOR, HildonDateSelectorClass)) + +#define HILDON_IS_DATE_SELECTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_DATE_SELECTOR)) + +#define HILDON_IS_DATE_SELECTOR_CLASS(vtable) \ + (G_TYPE_CHECK_CLASS_TYPE ((vtable), HILDON_TYPE_DATE_SELECTOR)) + +#define HILDON_DATE_SELECTOR_GET_CLASS(inst) \ + (G_TYPE_INSTANCE_GET_CLASS ((inst), \ + HILDON_TYPE_DATE_SELECTOR, HildonDateSelectorClass)) + +typedef struct _HildonDateSelector HildonDateSelector; +typedef struct _HildonDateSelectorClass HildonDateSelectorClass; +typedef struct _HildonDateSelectorPrivate HildonDateSelectorPrivate; + +struct _HildonDateSelector +{ + HildonTouchSelector parent_instance; + + /*< private > */ + HildonDateSelectorPrivate *priv; +}; + +struct _HildonDateSelectorClass +{ + HildonTouchSelectorClass parent_class; + + /* signals */ +}; + + +/* construction */ +GType +hildon_date_selector_get_type (void) G_GNUC_CONST; + +GtkWidget* +hildon_date_selector_new (void); + +GtkWidget * +hildon_date_selector_new_with_year_range (gint min_year, + gint max_year); + +/* date management */ +gboolean +hildon_date_selector_select_month (HildonDateSelector *selector, + guint month, + guint year); + +void +hildon_date_selector_select_day (HildonDateSelector *selector, + guint day); + +gboolean +hildon_date_selector_select_current_date (HildonDateSelector *selector, + guint year, + guint month, + guint day); + +void +hildon_date_selector_get_date (HildonDateSelector *selector, + guint *year, + guint *month, + guint *day); + +G_END_DECLS + +#endif /* __HILDON_DATE_SELECTOR_H__ */ diff --git a/hildon/hildon-defines.c b/hildon/hildon-defines.c new file mode 100644 index 0000000..1321185 --- /dev/null +++ b/hildon/hildon-defines.c @@ -0,0 +1,58 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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: A collection of useful defines. + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "hildon-defines.h" + +/** + * hildon_get_icon_pixel_size: + * @size: the icon size to get pixel size for + * + * Returns the icon size (height) for the given, named icon. + * In most cases it's much more convienient to call one of the + * predefined macros instead of this function directly. + * + * Returns: the height/width of icon to use. O if icon could not be found. + */ +gint +hildon_get_icon_pixel_size (GtkIconSize size) +{ + gint w, h; + + if (gtk_icon_size_lookup (size, &w, &h)) + return h; + else + return 0; +} + + diff --git a/hildon/hildon-defines.h b/hildon/hildon-defines.h new file mode 100644 index 0000000..bcfec6b --- /dev/null +++ b/hildon/hildon-defines.h @@ -0,0 +1,124 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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 + * + */ + +/* FIXME: Add documentation for the macros here */ + +#ifndef __HILDON_DEFINES_H__ +#define __HILDON_DEFINES_H__ + +#include +#include + +G_BEGIN_DECLS + +/* New hildon icon sizes. */ + +#define HILDON_ICON_SIZE_XSMALL gtk_icon_size_from_name ("hildon-xsmall") + +#define HILDON_ICON_SIZE_SMALL gtk_icon_size_from_name ("hildon-small") + +#define HILDON_ICON_SIZE_STYLUS gtk_icon_size_from_name ("hildon-stylus") + +#define HILDON_ICON_SIZE_FINGER gtk_icon_size_from_name ("hildon-finger") + +#define HILDON_ICON_SIZE_THUMB gtk_icon_size_from_name ("hildon-thumb") + +#define HILDON_ICON_SIZE_LARGE gtk_icon_size_from_name ("hildon-large") + +#define HILDON_ICON_SIZE_XLARGE gtk_icon_size_from_name ("hildon-xlarge") + +/* legacy hildon icon sizes, updated for new hildon */ + +#define HILDON_ICON_SIZE_TOOLBAR \ + gtk_icon_size_from_name ("hildon-finger") +/* Actual icon sizes */ + +/* New sizes */ +#define HILDON_ICON_PIXEL_SIZE_XSMALL \ + hildon_get_icon_pixel_size (HILDON_ICON_SIZE_XSMALL) + +#define HILDON_ICON_PIXEL_SIZE_SMALL \ + hildon_get_icon_pixel_size (HILDON_ICON_SIZE_SMALL) + +#define HILDON_ICON_PIXEL_SIZE_STYLUS \ + hildon_get_icon_pixel_size (HILDON_ICON_SIZE_STYLUS) + +#define HILDON_ICON_PIXEL_SIZE_FINGER \ + hildon_get_icon_pixel_size (HILDON_ICON_SIZE_FINGER) + +#define HILDON_ICON_PIXEL_SIZE_THUMB \ + hildon_get_icon_pixel_size (HILDON_ICON_SIZE_THUMB) + +#define HILDON_ICON_PIXEL_SIZE_LARGE \ + hildon_get_icon_pixel_size (HILDON_ICON_SIZE_LARGE) + +#define HILDON_ICON_PIXEL_SIZE_XLARGE \ + hildon_get_icon_pixel_size (HILDON_ICON_SIZE_XLARGE) + +/* legacy sizes */ +#define HILDON_ICON_PIXEL_SIZE_TOOLBAR \ + hildon_get_icon_pixel_size (HILDON_ICON_SIZE_TOOLBAR) + +/* Margins */ + +#define HILDON_MARGIN_HALF 4 + +#define HILDON_MARGIN_DEFAULT 8 + +#define HILDON_MARGIN_DOUBLE 16 + +#define HILDON_MARGIN_TRIPLE 24 + +#define HILDON_WINDOW_TITLEBAR_HEIGHT 56 + +/* Hard keys */ + +#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 + +gint +hildon_get_icon_pixel_size (GtkIconSize size); + +G_END_DECLS + +#endif /* HILDON_DEFINES_H */ diff --git a/hildon/hildon-dialog.c b/hildon/hildon-dialog.c new file mode 100644 index 0000000..5b5653e --- /dev/null +++ b/hildon/hildon-dialog.c @@ -0,0 +1,231 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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-dialog + * @short_description: Widget representing a popup window in the Hildon framework. + * @see_also: #HildonCodeDialog, #HildonColorChooserDialog, #HildonFontSelectionDialog, #HildonGetPasswordDialog, #HildonLoginDialog, #HildonSetPasswordDialog, #HildonSortDialog, #HildonWizardDialog + * + * #HildonDialog is a GTK widget which represent a popup window in the + * Hildon framework. It is derived from #GtkDialog and provides additional + * commodities specific to the Hildon framework. + * + * As of hildon 2.2, #HildonDialog has been deprecated in favor of #GtkDialog. + * + * + * + * #HildonDialog has been deprecated since Hildon 2.2 and should not + * be used in newly written code. See + * Migrating Hildon Dialogs + * section to know how to migrate this deprecated widget. + * + * + * + * + * Simple <structname>HildonDialog</structname> usage + * + * void quick_message (gchar *message) + * { + * + * GtkWidget *dialog, *label; + * + * dialog = hildon_dialog_new (); + * label = gtk_label_new (message); + * + * g_signal_connect_swapped (dialog, + * "response", + * G_CALLBACK (gtk_widget_destroy), + * dialog); + * + * gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), + * label); + * gtk_widget_show_all (dialog); + * + * } + * + * + */ + +#undef HILDON_DISABLE_DEPRECATED + +#include "hildon-dialog.h" +#include "hildon-gtk.h" + +G_DEFINE_TYPE (HildonDialog, hildon_dialog, GTK_TYPE_DIALOG); + +static void +hildon_dialog_class_init (HildonDialogClass *dialog_class) +{ +} + +static void +hildon_dialog_init (HildonDialog *self) +{ +} + +/** + * hildon_dialog_new: + * + * Creates a new #HildonDialog widget + * + * Returns: the newly created #HildonDialog + * + * Since: 2.2 + */ +GtkWidget* +hildon_dialog_new (void) +{ + GtkWidget *self = g_object_new (HILDON_TYPE_DIALOG, NULL); + + return self; +} + +/** + * hildon_dialog_new_with_buttons: + * @title: Title of the dialog, or %NULL + * @parent: Transient parent of the dialog, or %NULL + * @flags: from #GtkDialogFlags + * @first_button_text: stock ID or text to go in first button, or %NULL + * @Varargs: response ID for first button, then additional buttons, ending with %NULL + * + * Creates a new #HildonDialog. See gtk_dialog_new_with_buttons() for + * more information. + * + * Return value: a new #HildonDialog + * + * Since: 2.2 + */ +GtkWidget* +hildon_dialog_new_with_buttons (const gchar *title, + GtkWindow *parent, + GtkDialogFlags flags, + const gchar *first_button_text, + ...) +{ + GtkWidget *dialog; + + dialog = g_object_new (HILDON_TYPE_DIALOG, NULL); + + /* This code is copied from gtk_dialog_new_empty(), as it's a + * private function that we cannot use here */ + if (title) + gtk_window_set_title (GTK_WINDOW (dialog), title); + + if (parent) + gtk_window_set_transient_for (GTK_WINDOW (dialog), parent); + + if (flags & GTK_DIALOG_MODAL) + gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); + + if (flags & GTK_DIALOG_DESTROY_WITH_PARENT) + gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE); + + if (flags & GTK_DIALOG_NO_SEPARATOR) + gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE); + + /* This is almost copied from gtk_dialog_add_buttons_valist() */ + if (first_button_text != NULL) { + va_list args; + const gchar *text; + gint response_id; + + va_start (args, first_button_text); + text = first_button_text; + response_id = va_arg (args, gint); + + while (text != NULL) { + hildon_dialog_add_button (HILDON_DIALOG (dialog), text, response_id); + + text = va_arg (args, gchar*); + if (text == NULL) + break; + response_id = va_arg (args, int); + } + va_end (args); + } + + return dialog; +} + +/** + * hildon_dialog_add_button: + * @dialog: a #HildonDialog + * @button_text: text of the button, or stock ID + * @response_id: response ID for the button. + * + * Adds a button to the dialog. Works exactly like + * gtk_dialog_add_button(), the only difference being that the button + * has finger size. + * + * Returns: the button widget that was added + * + * Since: 2.2 + */ +GtkWidget * +hildon_dialog_add_button (HildonDialog *dialog, + const gchar *button_text, + gint response_id) +{ + GtkWidget *button; + button = gtk_dialog_add_button (GTK_DIALOG (dialog), button_text, response_id); + return button; +} + +/** + * hildon_dialog_add_buttons: + * @dialog: a #HildonDialog + * @first_button_text: text of the button, or stock ID + * @Varargs: response ID for first button, then more text-response_id pairs + * + * Adds several buttons to the dialog. Works exactly like + * gtk_dialog_add_buttons(), the only difference being that the + * buttons have finger size. + * + * Since: 2.2 + */ +void +hildon_dialog_add_buttons (HildonDialog *dialog, + const gchar *first_button_text, + ...) +{ + va_list args; + const gchar *text; + gint response_id; + + va_start (args, first_button_text); + text = first_button_text; + response_id = va_arg (args, gint); + + while (text != NULL) { + hildon_dialog_add_button (HILDON_DIALOG (dialog), text, response_id); + + text = va_arg (args, gchar*); + if (text == NULL) + break; + response_id = va_arg (args, int); + } + + va_end (args); +} + diff --git a/hildon/hildon-dialog.h b/hildon/hildon-dialog.h new file mode 100644 index 0000000..37ebd07 --- /dev/null +++ b/hildon/hildon-dialog.h @@ -0,0 +1,101 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#ifndef __HILDON_DIALOG_H__ +#define __HILDON_DIALOG_H__ + +#include + +#include "hildon-defines.h" + +G_BEGIN_DECLS + +#define HILDON_TYPE_DIALOG \ + (hildon_dialog_get_type ()) + +#define HILDON_DIALOG(obj) \ + (GTK_CHECK_CAST (obj, HILDON_TYPE_DIALOG, HildonDialog)) + +#define HILDON_DIALOG_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST ((klass),\ + HILDON_TYPE_DIALOG, HildonDialogClass)) + +#define HILDON_IS_DIALOG(obj) \ + (GTK_CHECK_TYPE (obj, HILDON_TYPE_DIALOG)) + +#define HILDON_IS_DIALOG_CLASS(klass) \ + (GTK_CHECH_CLASS_TYPE ((klass), HILDON_TYPE_DIALOG)) + +#define HILDON_DIALOG_GET_CLASS(obj) \ + ((HildonDialogClass *) G_OBJECT_GET_CLASS (obj)) + +typedef struct _HildonDialog HildonDialog; + +typedef struct _HildonDialogClass HildonDialogClass; + +struct _HildonDialog +{ + GtkDialog parent; +}; + +struct _HildonDialogClass +{ + GtkDialogClass parent_class; + + /* Padding for future extension */ + void (*_hildon_reserved1)(void); + void (*_hildon_reserved2)(void); + void (*_hildon_reserved3)(void); +}; + +GType G_GNUC_CONST +hildon_dialog_get_type (void); + +GtkWidget* +hildon_dialog_new (void); + +GtkWidget* +hildon_dialog_new_with_buttons (const gchar *title, + GtkWindow *parent, + GtkDialogFlags flags, + const gchar *first_button_text, + ...); + +GtkWidget * +hildon_dialog_add_button (HildonDialog *dialog, + const gchar *button_text, + gint response_id); + +void +hildon_dialog_add_buttons (HildonDialog *dialog, + const gchar *first_button_text, + ...); + +G_END_DECLS + +#endif /* __HILDON_DIALOG_H__ */ + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-edit-toolbar.c b/hildon/hildon-edit-toolbar.c new file mode 100644 index 0000000..daf38b3 --- /dev/null +++ b/hildon/hildon-edit-toolbar.c @@ -0,0 +1,324 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +/** + * SECTION:hildon-edit-toolbar + * @short_description: Widget representing a toolbar for editing. + * + * The #HildonEditToolbar is a toolbar which contains a label and two + * buttons, one of them being an arrow pointing backwards. + * + * The label is a description of the action that the user is supposed + * to do. The button is to be pressed when the user completes the + * action. The arrow is used to go back to the previous view + * discarding any changes. + * + * Note that those widgets don't do anything themselves by default. To + * actually peform actions the developer must provide callbacks for + * them. + * + * To add a #HildonEditToolbar to a window use + * hildon_window_set_edit_toolbar(). + * + * + * HildonEditToolbar example + * + * GtkWidget *window; + * GtkWidget *toolbar; + * // Declare more widgets here ... + * + * window = hildon_stackable_window_new (); + * toolbar = hildon_edit_toolbar_new_with_text ("Choose items to delete", "Delete"); + * // Create more widgets here ... + * + * // Add toolbar to window + * hildon_window_set_edit_toolbar (HILDON_WINDOW (window), HILDON_EDIT_TOOLBAR (toolbar)); + * + * // Add other widgets ... + * + * g_signal_connect (toolbar, "button-clicked", G_CALLBACK (delete_button_clicked), someparameter); + * g_signal_connect_swapped (toolbar, "arrow-clicked", G_CALLBACK (gtk_widget_destroy), window); + * + * gtk_widget_show_all (window); + * gtk_window_fullscreen (GTK_WINDOW (window)); + * + * + */ + +#include "hildon-edit-toolbar.h" +#include "hildon-gtk.h" + +G_DEFINE_TYPE (HildonEditToolbar, hildon_edit_toolbar, GTK_TYPE_HBOX); + +#define TOOLBAR_LEFT_PADDING 24 +#define TOOLBAR_RIGHT_PADDING 8 + +#define HILDON_EDIT_TOOLBAR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_EDIT_TOOLBAR, HildonEditToolbarPrivate)); + +typedef struct _HildonEditToolbarPrivate HildonEditToolbarPrivate; + +struct _HildonEditToolbarPrivate +{ + GtkLabel *label; + GtkButton *button; + GtkButton *arrow; +}; + +enum { + BUTTON_CLICKED, + ARROW_CLICKED, + N_SIGNALS +}; + +static guint toolbar_signals [N_SIGNALS] = { 0 }; + +static void +hildon_edit_toolbar_style_set (GtkWidget *widget, + GtkStyle *previous_style) +{ + guint width, height; + HildonEditToolbarPrivate *priv = HILDON_EDIT_TOOLBAR_GET_PRIVATE (widget); + + if (GTK_WIDGET_CLASS (hildon_edit_toolbar_parent_class)->style_set) + GTK_WIDGET_CLASS (hildon_edit_toolbar_parent_class)->style_set (widget, previous_style); + + gtk_widget_style_get (widget, + "arrow-width", &width, + "arrow-height", &height, + NULL); + + gtk_widget_set_size_request (GTK_WIDGET (priv->arrow), width, height); +} + +static gboolean +hildon_edit_toolbar_expose (GtkWidget *widget, + GdkEventExpose *event) +{ + if (GTK_WIDGET_DRAWABLE (widget)) { + gtk_paint_flat_box (widget->style, + widget->window, + GTK_STATE_NORMAL, + GTK_SHADOW_NONE, + &event->area, widget, "edit-toolbar", + widget->allocation.x, widget->allocation.y, + widget->allocation.width, widget->allocation.height); + } + + if (GTK_WIDGET_CLASS (hildon_edit_toolbar_parent_class)->expose_event) + return GTK_WIDGET_CLASS (hildon_edit_toolbar_parent_class)->expose_event (widget, event); + + return FALSE; +} + +static void +hildon_edit_toolbar_class_init (HildonEditToolbarClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; + + widget_class->style_set = hildon_edit_toolbar_style_set; + widget_class->expose_event = hildon_edit_toolbar_expose; + + g_type_class_add_private (klass, sizeof (HildonEditToolbarPrivate)); + + gtk_widget_class_install_style_property ( + widget_class, + g_param_spec_uint ( + "arrow-width", + "Width of the arrow button", + "Width of the arrow button", + 0, G_MAXUINT, 112, + G_PARAM_READABLE)); + + gtk_widget_class_install_style_property ( + widget_class, + g_param_spec_uint ( + "arrow-height", + "Height of the arrow button", + "Height of the arrow button", + 0, G_MAXUINT, 56, + G_PARAM_READABLE)); + + /** + * HildonEditToolbar::button-clicked: + * @widget: the object which received the signal. + * + * Emitted when the toolbar button has been activated (pressed and released). + * + * Since: 2.2 + */ + toolbar_signals[BUTTON_CLICKED] = + g_signal_new ("button_clicked", + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * HildonEditToolbar::arrow-clicked: + * @widget: the object which received the signal. + * + * Emitted when the toolbar back button (arrow) has been activated + * (pressed and released). + * + * Since: 2.2 + */ + toolbar_signals[ARROW_CLICKED] = + g_signal_new ("arrow_clicked", + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +button_clicked_cb (GtkButton *self, + HildonEditToolbar *toolbar) +{ + g_signal_emit (toolbar, toolbar_signals[BUTTON_CLICKED], 0); +} + +static void +arrow_clicked_cb (GtkButton *self, + HildonEditToolbar *toolbar) +{ + g_signal_emit (toolbar, toolbar_signals[ARROW_CLICKED], 0); +} + +static void +hildon_edit_toolbar_init (HildonEditToolbar *self) +{ + HildonEditToolbarPrivate *priv = HILDON_EDIT_TOOLBAR_GET_PRIVATE (self); + GtkWidget *separator; + GtkAlignment *align; + GtkBox *hbox = GTK_BOX (self); + GtkBox *hbox2; + + hbox2 = GTK_BOX (gtk_hbox_new (FALSE, 0)); + align = GTK_ALIGNMENT (gtk_alignment_new (0, 0.5, 1, 1)); + priv->label = GTK_LABEL (gtk_label_new (NULL)); + priv->button = GTK_BUTTON (hildon_gtk_button_new (HILDON_SIZE_AUTO)); + separator = gtk_vseparator_new (); + priv->arrow = GTK_BUTTON (gtk_button_new ()); + + gtk_button_set_focus_on_click (priv->arrow, FALSE); + + g_signal_connect (priv->button, "clicked", G_CALLBACK (button_clicked_cb), self); + g_signal_connect (priv->arrow, "clicked", G_CALLBACK (arrow_clicked_cb), self); + + gtk_box_set_spacing (hbox, 0); + gtk_alignment_set_padding (align, 0, 0, TOOLBAR_LEFT_PADDING, TOOLBAR_RIGHT_PADDING); + + gtk_widget_set_name (GTK_WIDGET (self), "toolbar-edit-mode"); + gtk_widget_set_name (GTK_WIDGET (priv->arrow), "hildon-edit-toolbar-arrow"); + + gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET (hbox2)); + gtk_box_pack_start (hbox2, GTK_WIDGET (priv->label), TRUE, TRUE, 0); + gtk_box_pack_start (hbox2, GTK_WIDGET (priv->button), FALSE, FALSE, 0); + + gtk_box_pack_start (hbox, GTK_WIDGET (align), TRUE, TRUE, 0); + gtk_box_pack_start (hbox, separator, FALSE, FALSE, 0); + gtk_box_pack_start (hbox, GTK_WIDGET (priv->arrow), FALSE, FALSE, 0); + + gtk_misc_set_alignment (GTK_MISC (priv->label), 0, 0.5); + + gtk_widget_show_all (GTK_WIDGET (align)); + gtk_widget_show_all (separator); + gtk_widget_show_all (GTK_WIDGET (priv->arrow)); +} + +/** + * hildon_edit_toolbar_set_label: + * @toolbar: a #HildonEditToolbar + * @label: a new text for the toolbar label + * + * Sets the label of @toolbar to @label. This will clear any + * previously set value. + * + * Since: 2.2 + */ +void +hildon_edit_toolbar_set_label (HildonEditToolbar *toolbar, + const gchar *label) +{ + HildonEditToolbarPrivate *priv; + g_return_if_fail (HILDON_IS_EDIT_TOOLBAR (toolbar)); + priv = HILDON_EDIT_TOOLBAR_GET_PRIVATE (toolbar); + gtk_label_set_text (priv->label, label); +} + +/** + * hildon_edit_toolbar_set_button_label: + * @toolbar: a #HildonEditToolbar + * @label: a new text for the label of the toolbar button + * + * Sets the label of the toolbar button to @label. This will clear any + * previously set value. + * + * Since: 2.2 + */ +void +hildon_edit_toolbar_set_button_label (HildonEditToolbar *toolbar, + const gchar *label) +{ + HildonEditToolbarPrivate *priv; + g_return_if_fail (HILDON_IS_EDIT_TOOLBAR (toolbar)); + priv = HILDON_EDIT_TOOLBAR_GET_PRIVATE (toolbar); + gtk_button_set_label (priv->button, label); +} + +/** + * hildon_edit_toolbar_new: + * + * Creates a new #HildonEditToolbar. + * + * Returns: a new #HildonEditToolbar + * + * Since: 2.2 + */ +GtkWidget * +hildon_edit_toolbar_new (void) +{ + return g_object_new (HILDON_TYPE_EDIT_TOOLBAR, NULL); +} + +/** + * hildon_edit_toolbar_new_with_text: + * @label: Text for the toolbar label. + * @button: Text for the toolbar button. + * + * Creates a new #HildonEditToolbar, with the toolbar label set to + * @label and the button label set to @button. + * + * Returns: a new #HildonEditToolbar + * + * Since: 2.2 + */ +GtkWidget * +hildon_edit_toolbar_new_with_text (const gchar *label, + const gchar *button) +{ + GtkWidget *toolbar = g_object_new (HILDON_TYPE_EDIT_TOOLBAR, NULL); + + hildon_edit_toolbar_set_label (HILDON_EDIT_TOOLBAR (toolbar), label); + hildon_edit_toolbar_set_button_label (HILDON_EDIT_TOOLBAR (toolbar), button); + + return toolbar; +} diff --git a/hildon/hildon-edit-toolbar.h b/hildon/hildon-edit-toolbar.h new file mode 100644 index 0000000..a93e7e1 --- /dev/null +++ b/hildon/hildon-edit-toolbar.h @@ -0,0 +1,79 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +#ifndef __HILDON_EDIT_TOOLBAR_H__ +#define __HILDON_EDIT_TOOLBAR_H__ + +#include + +G_BEGIN_DECLS + +#define HILDON_TYPE_EDIT_TOOLBAR \ + (hildon_edit_toolbar_get_type()) + +#define HILDON_EDIT_TOOLBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + HILDON_TYPE_EDIT_TOOLBAR, HildonEditToolbar)) + +#define HILDON_EDIT_TOOLBAR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + HILDON_TYPE_EDIT_TOOLBAR, HildonEditToolbarClass)) + +#define HILDON_IS_EDIT_TOOLBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_EDIT_TOOLBAR)) + +#define HILDON_IS_EDIT_TOOLBAR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_EDIT_TOOLBAR)) + +#define HILDON_EDIT_TOOLBAR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + HILDON_TYPE_EDIT_TOOLBAR, HildonEditToolbarClass)) + +typedef struct _HildonEditToolbar HildonEditToolbar; + +typedef struct _HildonEditToolbarClass HildonEditToolbarClass; + +struct _HildonEditToolbarClass +{ + GtkHBoxClass parent_class; +}; + +struct _HildonEditToolbar +{ + GtkHBox parent; +}; + +GType +hildon_edit_toolbar_get_type (void) G_GNUC_CONST; + +GtkWidget * +hildon_edit_toolbar_new (void); + +GtkWidget * +hildon_edit_toolbar_new_with_text (const gchar *label, + const gchar *button); + +void +hildon_edit_toolbar_set_label (HildonEditToolbar *toolbar, + const gchar *label); + +void +hildon_edit_toolbar_set_button_label (HildonEditToolbar *toolbar, + const gchar *label); + +G_END_DECLS + +#endif /* __HILDON_EDIT_TOOLBAR_H__ */ diff --git a/hildon/hildon-entry.c b/hildon/hildon-entry.c new file mode 100644 index 0000000..fad2382 --- /dev/null +++ b/hildon/hildon-entry.c @@ -0,0 +1,250 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +/** + * SECTION:hildon-entry + * @short_description: Widget representing a text entry in the Hildon framework. + * + * The #HildonEntry is a GTK widget which represents a text entry. It + * is derived from the #GtkEntry widget and provides additional + * commodities specific to the Hildon framework. + * + * Besides all the features inherited from #GtkEntry, a #HildonEntry + * can also have a placeholder text. This text will be shown if the + * entry is empty and doesn't have the input focus, but it's otherwise + * ignored. Thus, calls to hildon_entry_get_text() will never return + * the placeholder text, not even when it's being displayed. + * + * Although #HildonEntry is derived from #GtkEntry, + * gtk_entry_get_text() and gtk_entry_set_text() must never be used to + * get/set the text in this widget. hildon_entry_get_text() and + * hildon_entry_set_text() must be used instead. + * + * + * Creating a HildonEntry with a placeholder + * + * GtkWidget * + * create_entry (void) + * { + * GtkWidget *entry; + * + * entry = hildon_entry_new (HILDON_SIZE_AUTO); + * hildon_entry_set_placeholder (HILDON_ENTRY (entry), "First name"); + * + * return entry; + * } + * + * + */ + +#include "hildon-entry.h" +#include "hildon-helper.h" + +G_DEFINE_TYPE (HildonEntry, hildon_entry, GTK_TYPE_ENTRY); + +#define HILDON_ENTRY_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_ENTRY, HildonEntryPrivate)); + +struct _HildonEntryPrivate +{ + gchar *placeholder; + gboolean showing_placeholder; +}; + +static void +hildon_entry_show_placeholder (HildonEntry *entry) +{ + HildonEntryPrivate *priv = HILDON_ENTRY (entry)->priv; + + priv->showing_placeholder = TRUE; + gtk_entry_set_text (GTK_ENTRY (entry), priv->placeholder); + hildon_helper_set_logical_color (GTK_WIDGET (entry), + GTK_RC_TEXT, GTK_STATE_NORMAL, "ReversedSecondaryTextColor"); +} + +static void +hildon_entry_hide_placeholder (HildonEntry *entry, const gchar *text) +{ + HildonEntryPrivate *priv = HILDON_ENTRY (entry)->priv; + + priv->showing_placeholder = FALSE; + gtk_entry_set_text (GTK_ENTRY (entry), text); + hildon_helper_set_logical_color (GTK_WIDGET (entry), + GTK_RC_TEXT, GTK_STATE_NORMAL, "ReversedTextColor"); +} + +/** + * hildon_entry_set_text: + * @entry: a #HildonEntry + * @text: the new text + * + * Sets the text in @entry to @text, replacing its current contents. + * + * Note that you must never use gtk_entry_set_text() to set the text + * of a #HildonEntry. + * + * Since: 2.2 + */ +void +hildon_entry_set_text (HildonEntry *entry, + const gchar *text) +{ + g_return_if_fail (HILDON_IS_ENTRY (entry) && text != NULL); + + if (text[0] == '\0' && !GTK_WIDGET_HAS_FOCUS (entry)) { + hildon_entry_show_placeholder (entry); + } else { + hildon_entry_hide_placeholder (entry, text); + } +} + +/** + * hildon_entry_get_text: + * @entry: a #HildonEntry + * + * Gets the current text in @entry. + * + * Note that you must never use gtk_entry_get_text() to get the text + * from a #HildonEntry. + * + * Also note that placeholder text (set using + * hildon_entry_set_placeholder()) is never returned. Only text set by + * hildon_entry_set_text() or typed by the user is considered. + * + * Returns: the text in @entry. This text must not be modified or + * freed. + * + * Since: 2.2 + */ +const gchar * +hildon_entry_get_text (HildonEntry *entry) +{ + g_return_val_if_fail (HILDON_IS_ENTRY (entry), NULL); + + if (entry->priv->showing_placeholder) { + return ""; + } + + return gtk_entry_get_text (GTK_ENTRY (entry)); +} + +/** + * hildon_entry_set_placeholder: + * @entry: a #HildonEntry + * @text: the new text + * + * Sets the placeholder text in @entry to @text. + * + * Since: 2.2 + */ +void +hildon_entry_set_placeholder (HildonEntry *entry, + const gchar *text) +{ + g_return_if_fail (HILDON_IS_ENTRY (entry) && text != NULL); + + g_free (entry->priv->placeholder); + entry->priv->placeholder = g_strdup (text); + + /* Show the placeholder if it needs to be updated or if should be shown now. */ + if (entry->priv->showing_placeholder || + (!GTK_WIDGET_HAS_FOCUS (entry) && gtk_entry_get_text (GTK_ENTRY (entry)) [0] == '\0')) { + hildon_entry_show_placeholder (entry); + } +} + +/** + * hildon_entry_new: + * @size: The size of the entry + * + * Creates a new entry. + * + * Returns: a new #HildonEntry + * + * Since: 2.2 + */ +GtkWidget * +hildon_entry_new (HildonSizeType size) +{ + GtkWidget *entry = g_object_new (HILDON_TYPE_ENTRY, NULL); + + hildon_gtk_widget_set_theme_size (entry, size); + + return entry; +} + +static gboolean +hildon_entry_focus_in_event (GtkWidget *widget, + GdkEventFocus *event) +{ + if (HILDON_ENTRY (widget)->priv->showing_placeholder) { + hildon_entry_hide_placeholder (HILDON_ENTRY (widget), ""); + } + + if (GTK_WIDGET_CLASS (hildon_entry_parent_class)->focus_in_event) { + return GTK_WIDGET_CLASS (hildon_entry_parent_class)->focus_in_event (widget, event); + } else { + return FALSE; + } +} + +static gboolean +hildon_entry_focus_out_event (GtkWidget *widget, + GdkEventFocus *event) +{ + if (gtk_entry_get_text (GTK_ENTRY (widget)) [0] == '\0') { + hildon_entry_show_placeholder (HILDON_ENTRY (widget)); + } + + if (GTK_WIDGET_CLASS (hildon_entry_parent_class)->focus_out_event) { + return GTK_WIDGET_CLASS (hildon_entry_parent_class)->focus_out_event (widget, event); + } else { + return FALSE; + } +} + +static void +hildon_entry_finalize (GObject *object) +{ + HildonEntryPrivate *priv = HILDON_ENTRY (object)->priv; + + g_free (priv->placeholder); + + if (G_OBJECT_CLASS (hildon_entry_parent_class)->finalize) + G_OBJECT_CLASS (hildon_entry_parent_class)->finalize (object); +} + +static void +hildon_entry_class_init (HildonEntryClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass *)klass; + GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; + + gobject_class->finalize = hildon_entry_finalize; + widget_class->focus_in_event = hildon_entry_focus_in_event; + widget_class->focus_out_event = hildon_entry_focus_out_event; + + g_type_class_add_private (klass, sizeof (HildonEntryPrivate)); +} + +static void +hildon_entry_init (HildonEntry *self) +{ + self->priv = HILDON_ENTRY_GET_PRIVATE (self); + self->priv->placeholder = g_strdup (""); + self->priv->showing_placeholder = FALSE; +} diff --git a/hildon/hildon-entry.h b/hildon/hildon-entry.h new file mode 100644 index 0000000..eb2ab71 --- /dev/null +++ b/hildon/hildon-entry.h @@ -0,0 +1,84 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +#ifndef __HILDON_ENTRY_H__ +#define __HILDON_ENTRY_H__ + +#include "hildon-gtk.h" + +G_BEGIN_DECLS + +#define HILDON_TYPE_ENTRY \ + (hildon_entry_get_type()) + +#define HILDON_ENTRY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + HILDON_TYPE_ENTRY, HildonEntry)) + +#define HILDON_ENTRY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + HILDON_TYPE_ENTRY, HildonEntryClass)) + +#define HILDON_IS_ENTRY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_ENTRY)) + +#define HILDON_IS_ENTRY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_ENTRY)) + +#define HILDON_ENTRY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + HILDON_TYPE_ENTRY, HildonEntryClass)) + +typedef struct _HildonEntry HildonEntry; + +typedef struct _HildonEntryClass HildonEntryClass; + +typedef struct _HildonEntryPrivate HildonEntryPrivate; + +struct _HildonEntryClass +{ + GtkEntryClass parent_class; +}; + +struct _HildonEntry +{ + GtkEntry parent; + + /* private */ + HildonEntryPrivate *priv; +}; + + +GType +hildon_entry_get_type (void) G_GNUC_CONST; + +GtkWidget * +hildon_entry_new (HildonSizeType size); + +void +hildon_entry_set_text (HildonEntry *entry, + const gchar *text); + +const gchar * +hildon_entry_get_text (HildonEntry *entry); + +void +hildon_entry_set_placeholder (HildonEntry *entry, + const gchar *text); + +G_END_DECLS + +#endif /* __HILDON_ENTRY_H__ */ diff --git a/hildon/hildon-find-toolbar-private.h b/hildon/hildon-find-toolbar-private.h new file mode 100644 index 0000000..0a49845 --- /dev/null +++ b/hildon/hildon-find-toolbar-private.h @@ -0,0 +1,49 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_PRIVATE_H__ +#define __HILDON_FIND_TOOLBAR_PRIVATE_H__ + +G_BEGIN_DECLS + +typedef struct _HildonFindToolbarPrivate HildonFindToolbarPrivate; + +struct _HildonFindToolbarPrivate +{ + GtkWidget* label; + GtkComboBoxEntry* entry_combo_box; + GtkToolItem* separator; + GtkToolItem* close_button; + + gint history_limit; +}; + +#define HILDON_FIND_TOOLBAR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ + HILDON_TYPE_FIND_TOOLBAR, HildonFindToolbarPrivate)) + + +G_END_DECLS + +#endif /* __HILDON_FIND_TOOLBAR_PRIVATE_H_ */ diff --git a/hildon/hildon-find-toolbar.c b/hildon/hildon-find-toolbar.c new file mode 100644 index 0000000..01ccb63 --- /dev/null +++ b/hildon/hildon-find-toolbar.c @@ -0,0 +1,924 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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 toolbar with a search field. + * @see_also: #HildonWindow + * + * HildonFindToolbar is a toolbar that contains a search entry and a dropdown + * list with previously searched strings. The list is represented using a + * #GtkListStore and can be accesed using a property 'list'. Entries are added + * automatically to the list when the search button is pressed. + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "hildon-find-toolbar.h" +#include "hildon-defines.h" +#include "hildon-find-toolbar-private.h" +#include "hildon-marshalers.h" + +#define _(String) \ + dgettext("hildon-libs", 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 + +static GtkTreeModel* +hildon_find_toolbar_get_list_model (HildonFindToolbarPrivate *priv); + +static GtkEntry* +hildon_find_toolbar_get_entry (HildonFindToolbarPrivate *priv); + +static gboolean +hildon_find_toolbar_filter (GtkTreeModel *model, + GtkTreeIter *iter, + gpointer self); + +static void +hildon_find_toolbar_apply_filter (HildonFindToolbar *self, + GtkTreeModel *model); + +static void +hildon_find_toolbar_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +static void +hildon_find_toolbar_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); + +static gboolean +hildon_find_toolbar_find_string (HildonFindToolbar *self, + GtkTreeIter *iter, + gint column, + const gchar *string); + +static gboolean +hildon_find_toolbar_history_append (HildonFindToolbar *self, + gpointer data); + +static void +hildon_find_toolbar_emit_close (GtkButton *button, + gpointer self); + +#ifdef MAEMO_GTK +static void +hildon_find_toolbar_emit_invalid_input (GtkEntry *entry, + GtkInvalidInputType type, + gpointer self); +#endif + +static void +hildon_find_toolbar_entry_activate (GtkWidget *widget, + gpointer user_data); + +static void +hildon_find_toolbar_class_init (HildonFindToolbarClass *klass); + +static void +hildon_find_toolbar_init (HildonFindToolbar *self); + +enum +{ + SEARCH = 0, + CLOSE, + INVALID_INPUT, + HISTORY_APPEND, + + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_LABEL = 1, + PROP_PREFIX, + PROP_LIST, + PROP_COLUMN, + PROP_MAX, + PROP_HISTORY_LIMIT +}; + +static guint HildonFindToolbar_signal [LAST_SIGNAL] = {0}; + +/** + * hildon_find_toolbar_get_type: + * + * Initializes and returns the type of a hildon fond toolbar. + * + * Returns: GType of #HildonFindToolbar + */ +GType G_GNUC_CONST +hildon_find_toolbar_get_type (void) +{ + static GType find_toolbar_type = 0; + + if (! find_toolbar_type) { + static const GTypeInfo find_toolbar_info = { + sizeof(HildonFindToolbarClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_find_toolbar_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonFindToolbar), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_find_toolbar_init, + }; + find_toolbar_type = g_type_register_static (GTK_TYPE_TOOLBAR, + "HildonFindToolbar", + &find_toolbar_info, 0); + } + + return find_toolbar_type; +} + +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 = HILDON_FIND_TOOLBAR_GET_PRIVATE (self); + g_assert (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_GET_PRIVATE (object); + g_assert (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 = HILDON_FIND_TOOLBAR_GET_PRIVATE (object); + g_assert (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; + HildonFindToolbarPrivate *priv = HILDON_FIND_TOOLBAR_GET_PRIVATE (self); + g_assert (priv); + + model = hildon_find_toolbar_get_list_model (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_GET_PRIVATE (self); + g_assert (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 FALSE; +} + +static void +hildon_find_toolbar_emit_close (GtkButton *button, + gpointer self) +{ +#ifdef MAEMO_GTK + HildonFindToolbarPrivate *priv = HILDON_FIND_TOOLBAR_GET_PRIVATE (self); + g_assert (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); + } +#endif + + /* Clicked close button */ + g_signal_emit (self, HildonFindToolbar_signal [CLOSE], 0); +} + +#ifdef MAEMO_GTK +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 (self, HildonFindToolbar_signal [INVALID_INPUT], 0); +} +#endif + +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 (find_toolbar, HildonFindToolbar_signal [SEARCH], 0); + g_signal_emit (find_toolbar, HildonFindToolbar_signal [HISTORY_APPEND], 0, &rb); +} + +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 = (gpointer) hildon_find_toolbar_history_append; + + /** + * HildonFindToolbar:label: + * + * The label to display before the search box. + * + */ + 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)); + + /** + * HildonFindToolbar:label: + * + * The label to display before the search box. + * + */ + g_object_class_install_property (object_class, PROP_PREFIX, + g_param_spec_string ("prefix", + "Prefix", "Search string", NULL, + G_PARAM_READWRITE)); + + /** + * HildonFindToolbar:list: + * + * A #GtkListStore where the search history is kept. + * + */ + 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)); + + /** + * HildonFindToolbar:column: + * + * The column number in GtkListStore where strings of + * search history are kept. + * + */ + 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)); + + /** + * HildonFindToolbar:label: + * + * The label to display before the search box. + * + */ + 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)); + + /** + * HildonFindToolbar:history-limit: + * + * Maximum number of history items in the combobox. + * + */ + 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, g_cclosure_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, g_cclosure_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, g_cclosure_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, + _hildon_marshal_BOOLEAN__VOID, + G_TYPE_BOOLEAN, 0); +} + +static void +hildon_find_toolbar_init (HildonFindToolbar *self) +{ + GtkToolItem *label_container; + GtkToolItem *entry_combo_box_container; + GtkAlignment *alignment; + + HildonFindToolbarPrivate *priv = HILDON_FIND_TOOLBAR_GET_PRIVATE (self); + g_assert (priv); + + /* Create the label */ + priv->label = gtk_label_new (_("ecdg_ti_find_toolbar_label")); + + gtk_misc_set_padding (GTK_MISC (priv->label), FIND_LABEL_XPADDING, + FIND_LABEL_YPADDING); + + label_container = gtk_tool_item_new (); + gtk_container_add (GTK_CONTAINER (label_container), + 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 */ + priv->entry_combo_box = GTK_COMBO_BOX_ENTRY (gtk_combo_box_entry_new ()); + +#ifdef MAEMO_GTK + g_signal_connect (hildon_find_toolbar_get_entry(priv), + "invalid_input", + G_CALLBACK(hildon_find_toolbar_emit_invalid_input), self); +#endif + + entry_combo_box_container = gtk_tool_item_new (); + alignment = GTK_ALIGNMENT (gtk_alignment_new (0, 0.5, 1, 0)); + + gtk_tool_item_set_expand (entry_combo_box_container, TRUE); + gtk_container_add (GTK_CONTAINER (alignment), + GTK_WIDGET (priv->entry_combo_box)); + gtk_container_add (GTK_CONTAINER (entry_combo_box_container), + GTK_WIDGET (alignment)); + 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 (priv), + "activate", + G_CALLBACK(hildon_find_toolbar_entry_activate), self); + + /* Separator */ + priv->separator = gtk_separator_tool_item_new(); + gtk_widget_set_size_request (GTK_WIDGET (priv->separator), 72, -1); + gtk_widget_show(GTK_WIDGET(priv->separator)); + gtk_toolbar_insert (GTK_TOOLBAR(self), priv->separator, -1); + + /* Close button */ + priv->close_button = gtk_tool_button_new ( + gtk_image_new_from_icon_name ("general_close", + HILDON_ICON_SIZE_TOOLBAR), + "Close"); + g_signal_connect(priv->close_button, "clicked", + G_CALLBACK(hildon_find_toolbar_emit_close), self); + gtk_widget_show_all(GTK_WIDGET(priv->close_button)); + gtk_toolbar_insert (GTK_TOOLBAR(self), priv->close_button, -1); + if ( GTK_WIDGET_CAN_FOCUS( GTK_BIN(priv->close_button)->child) ) + GTK_WIDGET_UNSET_FLAGS( + GTK_BIN(priv->close_button)->child, GTK_CAN_FOCUS); +} + +/** + * hildon_find_toolbar_new: + * @label: label for the find_toolbar, NULL to set the label to + * default "Find" + * + * Creates 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 + * + * Creates 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. + * + * Highlights the current entry in the find toolbar. + * + */ +void +hildon_find_toolbar_highlight_entry (HildonFindToolbar *self, + gboolean get_focus) +{ + GtkEntry *entry = NULL; + HildonFindToolbarPrivate *priv; + + g_return_if_fail (HILDON_IS_FIND_TOOLBAR (self)); + priv = HILDON_FIND_TOOLBAR_GET_PRIVATE (self); + g_assert (priv); + + entry = hildon_find_toolbar_get_entry (priv); + + gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1); + + if (get_focus) + gtk_widget_grab_focus (GTK_WIDGET (entry)); +} + +/** + * hildon_find_toolbar_set_active: + * @toolbar: A find toolbar to operate on + * @index: An index in the model passed during construction, or -1 to have no active item + * + * Sets the active item on the toolbar's combo-box. Simply calls gtk_combo_box_set_active on + * the HildonFindToolbar's combo. + * + */ +void +hildon_find_toolbar_set_active (HildonFindToolbar *toolbar, + gint index) +{ + HildonFindToolbarPrivate *priv; + + g_return_if_fail (HILDON_IS_FIND_TOOLBAR (toolbar)); + priv = HILDON_FIND_TOOLBAR_GET_PRIVATE (toolbar); + + gtk_combo_box_set_active (GTK_COMBO_BOX (priv->entry_combo_box), index); +} + +/** + * hildon_find_toolbar_get_active: + * @toolbar: A find toolbar to query + * + * Gets the index of the currently active item, or -1 if there's no active item. Simply + * calls gtk_combo_box_get_active on the HildonFindToolbar's combo. + * + * Returns: An integer which is the index of the currently active item, or -1 if there's no active item. + * + */ +gint +hildon_find_toolbar_get_active (HildonFindToolbar *toolbar) +{ + HildonFindToolbarPrivate *priv; + + g_return_val_if_fail (HILDON_IS_FIND_TOOLBAR (toolbar), -1); + priv = HILDON_FIND_TOOLBAR_GET_PRIVATE (toolbar); + + return gtk_combo_box_get_active (GTK_COMBO_BOX (priv->entry_combo_box)); +} + +/** + * hildon_find_toolbar_set_active_iter: + * @toolbar: A find toolbar to operate on + * @iter: An iter to make active + * + * Sets the current active item to be the one referenced by iter. Simply calls + * gtk_combo_box_set_active_iter on the HildonFindToolbar's combo. + * + */ +void +hildon_find_toolbar_set_active_iter (HildonFindToolbar *toolbar, + GtkTreeIter *iter) +{ + HildonFindToolbarPrivate *priv; + + g_return_if_fail (HILDON_IS_FIND_TOOLBAR (toolbar)); + priv = HILDON_FIND_TOOLBAR_GET_PRIVATE (toolbar); + + gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->entry_combo_box), iter); +} + +/** + * hildon_find_toolbar_get_active_iter: + * @toolbar: A find toolbar to query + * @iter: The uninitialized GtkTreeIter + * + * Sets iter to point to the current active item, if it exists. Simply calls + * gtk_combo_box_get_active_iter on the HildonFindToolbar's combo. + * + * Returns: TRUE, if iter was set + * + */ +gboolean +hildon_find_toolbar_get_active_iter (HildonFindToolbar *toolbar, + GtkTreeIter *iter) +{ + HildonFindToolbarPrivate *priv; + + g_return_val_if_fail (HILDON_IS_FIND_TOOLBAR (toolbar), FALSE); + priv = HILDON_FIND_TOOLBAR_GET_PRIVATE (toolbar); + + return gtk_combo_box_get_active_iter (GTK_COMBO_BOX (priv->entry_combo_box), iter); +} + +/** + * hildon_find_toolbar_get_last_index + * @toolbar: A find toolbar to query + * + * Returns the index of the last (most recently added) item in the toolbar. + * Can be used to set this item active in the history-append signal. + * + * + * Returns: Index of the last entry + * + */ +gint32 +hildon_find_toolbar_get_last_index (HildonFindToolbar *toolbar) +{ + HildonFindToolbarPrivate *priv; + GtkTreeModel *filter_model; + + g_return_val_if_fail (HILDON_IS_FIND_TOOLBAR (toolbar), FALSE); + priv = HILDON_FIND_TOOLBAR_GET_PRIVATE (toolbar); + + filter_model = gtk_combo_box_get_model (GTK_COMBO_BOX (priv->entry_combo_box)); + + if (filter_model == NULL) + return 0; + + gint i = 0; + GtkTreeIter iter; + + gtk_tree_model_get_iter_first (filter_model, &iter); + + while (gtk_tree_model_iter_next (filter_model, &iter)) + i++; + + return i; +} + diff --git a/hildon/hildon-find-toolbar.h b/hildon/hildon-find-toolbar.h new file mode 100644 index 0000000..00ce8e8 --- /dev/null +++ b/hildon/hildon-find-toolbar.h @@ -0,0 +1,111 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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 + +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_TOOLBAR_CLASS(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; + +struct _HildonFindToolbar +{ + GtkToolbar parent; +}; + +struct _HildonFindToolbarClass +{ + GtkToolbarClass parent_class; + + void (*search) (HildonFindToolbar *toolbar); + void (*close) (HildonFindToolbar *toolbar); + void (*invalid_input) (HildonFindToolbar *toolbar); + gboolean (*history_append) (HildonFindToolbar *tooblar); +}; + +GType G_GNUC_CONST +hildon_find_toolbar_get_type (void); + +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); + +void +hildon_find_toolbar_set_active (HildonFindToolbar *toolbar, + gint index); + +gint +hildon_find_toolbar_get_active (HildonFindToolbar *toolbar); + +void +hildon_find_toolbar_set_active_iter (HildonFindToolbar *toolbar, + GtkTreeIter *iter); + +gboolean +hildon_find_toolbar_get_active_iter (HildonFindToolbar *toolbar, + GtkTreeIter *iter); + +gint32 +hildon_find_toolbar_get_last_index (HildonFindToolbar *toolbar); + +G_END_DECLS + +#endif /* __HILDON_FIND_TOOLBAR_H__ */ + diff --git a/hildon/hildon-font-selection-dialog-private.h b/hildon/hildon-font-selection-dialog-private.h new file mode 100644 index 0000000..bb0628c --- /dev/null +++ b/hildon/hildon-font-selection-dialog-private.h @@ -0,0 +1,75 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_PRIVATE_H__ +#define __HILDON_FONT_SELECTION_DIALOG_PRIVATE_H__ + +G_BEGIN_DECLS + +#define HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_FONT_SELECTION_DIALOG, \ + HildonFontSelectionDialogPrivate)) + +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; +}; + +G_END_DECLS + +#endif /* __HILDON_FONT_SELECTION_DIALOG_PRIVATE_H__ */ diff --git a/hildon/hildon-font-selection-dialog.c b/hildon/hildon-font-selection-dialog.c new file mode 100644 index 0000000..175edc2 --- /dev/null +++ b/hildon/hildon-font-selection-dialog.c @@ -0,0 +1,1417 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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. Since hildon 2.2, the previously available preview dialog + * has been removed. + */ + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include + +#include "hildon-font-selection-dialog.h" +#include "hildon-caption.h" +#include "hildon-color-button.h" +#include "hildon-font-selection-dialog-private.h" + +/* 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 +}; + +enum +{ + PROP_0, + PROP_FAMILY, + 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 +}; + +/* 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; + +#if 0 +static gboolean +hildon_font_selection_dialog_preview_key_press (GtkWidget *widget, + GdkEventKey *event, + gpointer unused); +#endif + +static int +cmp_families (const void *a, + const void *b); +#if 0 +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); +#endif + +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); + +#if 0 +static void +add_preview_text_attr (PangoAttrList *list, + PangoAttribute *attr, + guint start, + guint len); +#endif + +static void +toggle_clicked (GtkButton *button, + gpointer unused); + +static GtkDialogClass* parent_class = NULL; + +#define _(String) dgettext("hildon-libs", String) + +#define SUPERSCRIPT_RISE 3333 + +#define SUBSCRIPT_LOW -3333 + +#define ON_BIT 0x01 + +#define OFF_BIT 0x02 + +/** + * hildon_font_selection_dialog_get_type: + * + * Initializes and returns the type of a hildon font selection dialog + * + * Returns: GType of #HildonFontSelectionDialog + */ +GType G_GNUC_CONST +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; + + HildonFontSelectionDialogPrivate *priv = + HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(object); + + g_assert (priv); + + 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"); + /* FIXME Bad hardcoding here */ + 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: + hildon_color_button_get_color + (HILDON_COLOR_BUTTON (priv->font_color_button), &color); + g_value_set_boxed (value, (gconstpointer) &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 *family; + gboolean b; + GdkColor *color = NULL; + GdkColor black; + + HildonFontSelectionDialogPrivate *priv = HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE (object); + g_assert (priv); + + black.red = black.green = black.blue = 0; + + switch (prop_id) + { + case PROP_FAMILY: + family = g_value_get_string (value); + g_return_if_fail (family != NULL); + for(i = 0; i < priv->n_families; i++) + { + if (strcmp (family, 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; + + 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 properties to the class */ + + /** + * HildonFontSelectionDialog:family: + * + * Font family used. + */ + 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)); + + /** + * HildonFontSelectionDialog:family-set: + * + * Is font family set or inconsistent. + */ + 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)); + + /** + * HildonFontSelectionDialog:size: + * + * Font size. + */ + 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)); + + /** + * HildonFontSelectionDialog:size-set: + * + * Is font size set or inconsistent. + */ + 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)); + + /** + * HildonFontSelectionDialog:color: + * + * GdkColor for the text. + */ + 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)); + + /** + * HildonFontSelectionDialog:color-set: + * + * Is font color set or inconsistent. + */ + 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)); + + /** + * HildonFontSelectionDialog:color-set: + * + * Is font set as bold. + */ + 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)); + + /** + * HildonFontSelectionDialog:color-set: + * + * Is font bold status set or inconsistent. + */ + 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)); + + /** + * HildonFontSelectionDialog:italic: + * + * Is font set as italic. + */ + 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)); + + /** + * HildonFontSelectionDialog:italic-set: + * + * Is font italic status set or inconsistent. + */ + 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)); + + /** + * HildonFontSelectionDialog:underline: + * + * Is the font underlined. + */ + 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)); + + /** + * HildonFontSelectionDialog:underline: + * + * Is font underline status set or inconsistent. + */ + 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)); + + /** + * HildonFontSelectionDialog:strikethrough: + * + * Is the font striken-through. + */ + 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)); + + /** + * HildonFontSelectionDialog:strikethrough-set: + * + * Is the font strikenthrough status set. + */ + 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)); + + /** + * HildonFontSelectionDialog:position: + * + * The font positioning versus baseline. + */ + 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)); + + /** + * HildonFontSelectionDialog:position-set: + * + * Is the font positioning set. + */ + 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)); + + /** + * HildonFontSelectionDialog:font-scaling: + * + * The font scaling factor applied to the preview dialog. + */ + 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)); + + /** + * HildonFontSelectionDialog:preview-text: + * + * The text used for the preview dialog. + * + * Deprecated: this property is unused since hildon 2.2 + */ + 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; */ + + g_assert (priv); + 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), + _("wdgt_bd_done"), + GTK_RESPONSE_OK); + +#if 0 + 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); +#endif + + /*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); + g_assert (priv); + + 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); + + g_object_unref (group); + + 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; + g_assert (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_assert (priv); + + if (priv->preview_text != NULL) { + g_free (priv->preview_text); + priv->preview_text = NULL; + } + + if (priv->families != NULL) { + g_free (priv->families); + priv->families = NULL; + } + + if (G_OBJECT_CLASS (parent_class)->finalize) + G_OBJECT_CLASS (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); +} + +#if 0 +/* Exits the preview dialog with GTK_RESPONSE_CANCEL if Esc key + * was pressed + * FIXME This should be handled automatically */ +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_assert (priv); + + 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, + _("wdgt_bd_done"), + 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); + + if (str) + g_free (str); + + str = NULL; + + /* 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); + + /* A smallish hack to add scrollbar when font size is really big */ + + if (size_set && size > 24) { + GtkScrolledWindow *scrolled = GTK_SCROLLED_WINDOW (gtk_scrolled_window_new (NULL, NULL)); + gtk_scrolled_window_set_policy (scrolled, GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_add_with_viewport (scrolled, GTK_WIDGET (preview_label)); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG(preview_dialog)->vbox), GTK_WIDGET (scrolled)); + gtk_widget_set_size_request (GTK_WIDGET (scrolled), -1, 400); + } else + gtk_container_add (GTK_CONTAINER (GTK_DIALOG(preview_dialog)->vbox), GTK_WIDGET (preview_label)); + + /* 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"))); + } + if (str != NULL) + g_free (str); + + str = NULL; + + /* 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_set_default_response (GTK_DIALOG (preview_dialog), GTK_RESPONSE_OK); + + GtkBox *action_area = (GtkBox *) GTK_DIALOG (preview_dialog)->action_area; + GtkWidget *button = ((GtkBoxChild *) ((GSList *) action_area->children)->data)->widget; + gtk_widget_grab_focus (button); + + gtk_dialog_run (GTK_DIALOG (preview_dialog)); + gtk_widget_destroy (preview_dialog); +} +#endif + +static gboolean +is_internal_font (const gchar * name) +{ + /* FIXME Extremally BAD BAD BAD way of doing things */ + + 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); + g_assert (priv); + + 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; + + g_assert (priv); + + 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); + } +} + +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); + } +} + +/** + * 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. + * Please note that since hildon 2.2, the preview has been discontinued, + * so this setting has no effect. + * + * Returns: a string pointer + */ +gchar* +hildon_font_selection_dialog_get_preview_text (HildonFontSelectionDialog * fsd) +{ + /* FIXME Return a const pointer? */ + HildonFontSelectionDialogPrivate *priv; + + g_return_val_if_fail (HILDON_IS_FONT_SELECTION_DIALOG (fsd), NULL); + + priv = HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE (fsd); + g_assert (priv); + + 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". Please note that since + * hildon 2.2, the preview has been discontinued, so this setting has no effect. + * + */ +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_assert (priv); + + g_free (priv->preview_text); + priv->preview_text = g_strdup (text); + g_object_notify (G_OBJECT (fsd), "preview-text"); +} + diff --git a/hildon/hildon-font-selection-dialog.h b/hildon/hildon-font-selection-dialog.h new file mode 100644 index 0000000..558f660 --- /dev/null +++ b/hildon/hildon-font-selection-dialog.h @@ -0,0 +1,91 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#ifndef __HILDON_FONT_SELECTION_DIALOG_H__ +#define __HILDON_FONT_SELECTION_DIALOG_H__ + +#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; +}; + +GType G_GNUC_CONST +hildon_font_selection_dialog_get_type (void); + +GtkWidget* +hildon_font_selection_dialog_new (GtkWindow *parent, + const gchar *title); + +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__ */ + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-get-password-dialog-private.h b/hildon/hildon-get-password-dialog-private.h new file mode 100644 index 0000000..a6bdf6e --- /dev/null +++ b/hildon/hildon-get-password-dialog-private.h @@ -0,0 +1,45 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_PRIVATE_H__ +#define __HILDON_GET_PASSWORD_DIALOG_PRIVATE_H__ + +G_BEGIN_DECLS + +#define HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_GET_PASSWORD_DIALOG, HildonGetPasswordDialogPrivate)); + +typedef struct _HildonGetPasswordDialogPrivate HildonGetPasswordDialogPrivate; + +struct _HildonGetPasswordDialogPrivate +{ + GtkLabel *message_label; + HildonCaption *password_entry; + gboolean get_old; +}; + +G_END_DECLS + +#endif /* __HILDON_GET_PASSWORD_DIALOG_PRIVATE_H__ */ diff --git a/hildon/hildon-get-password-dialog.c b/hildon/hildon-get-password-dialog.c new file mode 100644 index 0000000..c7d993f --- /dev/null +++ b/hildon/hildon-get-password-dialog.c @@ -0,0 +1,672 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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 a custom message. The maximum length of the password can be set. + * + * + * HildonGetPassword example + * + * get_dialog = HILDON_GET_PASSWORD_DIALOG (hildon_get_password_dialog_new (parent, FALSE)); + * + * gtk_widget_show (GTK_WIDGET (get_dialog)); + * + * i = gtk_dialog_run (GTK_DIALOG (get_dialog)); + * + * pass = hildon_get_password_dialog_get_password (get_dialog); + * + * if (i == GTK_RESPONSE_OK && (strcmp (pass, dialog.current_password) != 0)) + * { + * gtk_infoprint (GTK_WINDOW (parent), STR_PASSWORD_INCORRECT); + * gtk_widget_set_sensitive (GTK_WIDGET (dialog.button2), FALSE); + * gtk_widget_set_sensitive (GTK_WIDGET (dialog.button3), FALSE); + * gtk_widget_set_sensitive (GTK_WIDGET (dialog.button4), FALSE); + * } + * + * else if (i == GTK_RESPONSE_OK) + * { + * gtk_widget_set_sensitive( GTK_WIDGET( dialog.button2 ), TRUE); + * } + * + * else + * { + * gtk_widget_set_sensitive (GTK_WIDGET (dialog.button2), FALSE); + * gtk_widget_set_sensitive (GTK_WIDGET (dialog.button3), FALSE); + * gtk_widget_set_sensitive (GTK_WIDGET (dialog.button4), FALSE); + * } + * gtk_widget_destroy (GTK_WIDGET (get_dialog)); + * } + * + * + */ + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include "hildon-get-password-dialog.h" +#include "hildon-caption.h" +#include "hildon-banner.h" +#include "hildon-get-password-dialog-private.h" +#include "hildon-entry.h" + +#define _(String) dgettext("hildon-libs", String) + +#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 "wdgt_bd_done" + +#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 "wdgt_bd_done" + +#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" + +static GtkDialogClass* parent_class; + +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); + +#ifdef MAEMO_GTK +static void +invalid_input (GtkWidget *widget, + GtkInvalidInputType reason, + gpointer unused); +#endif + +enum +{ + PROP_0, + PROP_MESSAGE, + 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 (object); + g_assert (priv); + + switch (prop_id) { + + case PROP_MESSAGE: + /* Set label text representing password domain */ + gtk_label_set_text (priv->message_label, g_value_get_string (value)); + break; + + case PROP_PASSWORD: + hildon_entry_set_text(HILDON_ENTRY (gtk_bin_get_child (GTK_BIN (priv->password_entry))), + g_value_get_string(value)); + break; + + case PROP_NUMBERS_ONLY: +#ifdef MAEMO_GTK + /* Set input mode for the password entry */ + g_object_set(G_OBJECT (gtk_bin_get_child GTK_BIN ((priv->password_entry))), + "hildon-input-mode", + (g_value_get_boolean (value) + ? HILDON_GTK_INPUT_MODE_NUMERIC + : HILDON_GTK_INPUT_MODE_FULL), + NULL); +#endif + 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; +#ifdef MAEMO_GTK + gint input_mode; +#endif + + priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE (dialog); + g_assert (priv); + + switch (prop_id) { + + case PROP_MESSAGE: + string = gtk_label_get_text (priv->message_label); + g_value_set_string (value, string); + break; + + case PROP_PASSWORD: + string = hildon_entry_get_text (HILDON_ENTRY (gtk_bin_get_child (GTK_BIN (priv->password_entry)))); + g_value_set_string (value, string); + break; + + case PROP_NUMBERS_ONLY: +#ifdef MAEMO_GTK + /* 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 (gtk_bin_get_child (GTK_BIN (priv->password_entry))), + "hildon-input-mode", &input_mode, NULL); + g_value_set_boolean (value, + (input_mode == HILDON_GTK_INPUT_MODE_NUMERIC)); +#else + g_value_set_boolean (value, FALSE); +#endif + break; + + case PROP_CAPTION_LABEL: + string = hildon_caption_get_label (priv->password_entry); + g_value_set_string (value, string); + break; + + case PROP_MAX_CHARS: + max_length = gtk_entry_get_max_length + (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->password_entry)))); + 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 */ + + /** + * HildonGetPasswordDialog:message: + * + * Optional message displayed to the user. + */ + g_object_class_install_property + (object_class, + PROP_MESSAGE, + g_param_spec_string ("message", + "Message", + "Set optional message", + NULL, + G_PARAM_READWRITE)); + + /** + * HildonGetPasswordDialog:password: + * + * Password field contents. + */ + g_object_class_install_property + (object_class, + PROP_PASSWORD, + g_param_spec_string ("password", + "Password", + "Password field", + "DEFAULT", + G_PARAM_READWRITE)); + + /** + * HildonGetPasswordDialog:numbers-only: + * + * If the password entry field is operating in numbers-only mode. + */ + 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)); + + /** + * HildonGetPasswordDialog:caption-label: + * + * Caption label. + */ + 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)); + + /** + * HildonGetPasswordDialog:max-characters: + * + * Maximum characters than can be entered. + */ + 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)); + + /** + * HildonGetPasswordDialog:get-old: + * + * If the dialog is used to retrieve an old password or set a new one. + */ + 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; + AtkObject *atk_aux = NULL; + + /* Cache private pointer for faster member access */ + priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE (dialog); + g_assert (priv); + + /* 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->message_label = GTK_LABEL (gtk_label_new (NULL)); + + /* Create buttons */ + gtk_dialog_add_button (GTK_DIALOG (dialog), + (priv->get_old + ? _(HILDON_GET_PASSWORD_DIALOG_OK) + : _(HILDON_GET_PASSWORD_VERIFY_DIALOG_OK)), + GTK_RESPONSE_OK); + + 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 = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH); + if ((atk_aux = gtk_widget_get_accessible(control))) + { + atk_object_set_name(atk_aux, "Passwd"); + } + + gtk_entry_set_width_chars (GTK_ENTRY (control), 20); + +#ifdef MAEMO_GTK + g_object_set (control, "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL); +#endif + + gtk_entry_set_visibility (GTK_ENTRY(control), FALSE); + priv->password_entry = 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->password_entry), ""); + + /* Do the basic layout */ + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), + GTK_WIDGET (priv->message_label), FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), + GTK_WIDGET (priv->password_entry), 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); +} + +/** + * hildon_get_password_dialog_get_type: + * + * Returns GType for HildonGetPasswordDialog as produced by + * g_type_register_static(). + * + * Returns: HildonGetPasswordDialog type + */ +GType G_GNUC_CONST +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 (GtkWidget *) 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 entered password. The string should not be freed. + * + * Returns: current password entered by the user. + */ +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); + g_assert (priv); + + /* Retrieve the password entry widget */ + entry1 = GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->password_entry))); + text1 = GTK_ENTRY (entry1)->text; + + return text1; +} + +/** + * hildon_get_password_dialog_set_message + * @dialog: the dialog + * @message: a custom message or some other descriptive text to be set + * + * Sets the optional descriptive text displayed at the top of the dialog. + */ +void +hildon_get_password_dialog_set_message (HildonGetPasswordDialog *dialog, + const gchar *message) +{ + HildonGetPasswordDialogPrivate *priv; + + g_return_if_fail (HILDON_IS_GET_PASSWORD_DIALOG (dialog)); + + priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE (dialog); + g_assert (priv); + + gtk_label_set_text (priv->message_label, message); + +} + +/** + * 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); + g_assert (priv); + + hildon_caption_set_label (priv->password_entry, new_caption); +} + +/** + * hildon_get_password_dialog_set_max_characters: + * @dialog: the dialog + * @max_characters: the maximum number of characters the password dialog + * accepts + * + * 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); + g_assert (priv); + + /* Apply the given length to password entry */ + gtk_entry_set_max_length (GTK_ENTRY + (gtk_bin_get_child + GTK_BIN ((priv->password_entry))), + max_characters); + + /* FIXME There is a bug here -- the prev. signal needs to be + * disconnected before connecting the new signal. Besides, this + * should go into the constructor */ + +#ifdef MAEMO_GTK + /* Connect callback to show error banner if the limit is exceeded */ + g_signal_connect (GTK_ENTRY + (gtk_bin_get_child + GTK_BIN ((priv->password_entry))), + "invalid_input", + G_CALLBACK (invalid_input), + NULL + ); +#endif +} + +#ifdef MAEMO_GTK +/* Callback that gets called when maximum chars is reached in the entry */ +static void +invalid_input (GtkWidget *widget, + GtkInvalidInputType reason, + gpointer unused) +{ + if (reason == GTK_INVALID_INPUT_MAX_CHARS_REACHED) + { + hildon_banner_show_information (widget, NULL, _(HILDON_GET_PASSWORD_DIALOG_MAX_CHARS)); + } +} +#endif diff --git a/hildon/hildon-get-password-dialog.h b/hildon/hildon-get-password-dialog.h new file mode 100644 index 0000000..46999cb --- /dev/null +++ b/hildon/hildon-get-password-dialog.h @@ -0,0 +1,96 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#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)) + +typedef struct _HildonGetPasswordDialog HildonGetPasswordDialog; + +typedef struct _HildonGetPasswordDialogClass HildonGetPasswordDialogClass; + +struct _HildonGetPasswordDialog +{ + GtkDialog parent; +}; + +struct _HildonGetPasswordDialogClass +{ + GtkDialogClass parent_class; +}; + +GType G_GNUC_CONST +hildon_get_password_dialog_get_type (void); + +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_message (HildonGetPasswordDialog *dialog, + const gchar *message); + +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); + +G_END_DECLS + +#endif /* __HILDON_GET_PASSWORD_DIALOG_H__ */ + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-gtk.c b/hildon/hildon-gtk.c new file mode 100644 index 0000000..fd1f9f4 --- /dev/null +++ b/hildon/hildon-gtk.c @@ -0,0 +1,500 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +/** + * SECTION:hildon-gtk + * @short_description: Additional functions for Gtk widgets + * @see_also: #HildonButton, #HildonCheckButton + * + * Hildon provides some functions to extend the functionality of + * existing Gtk widgets. This also includes convenience functions to + * easily perform frequent tasks. + */ + +#include +#include + +#include "hildon-gtk.h" + +typedef void (*HildonFlagFunc) (GtkWindow *window, gpointer userdata); + +static void +image_visible_changed_cb (GtkWidget *image, + GParamSpec *arg1, + gpointer oldparent) +{ + if (!GTK_WIDGET_VISIBLE (image)) + gtk_widget_show (image); +} + +static void +parent_changed_cb (GtkWidget *image, + GParamSpec *arg1, + gpointer oldparent) +{ + /* If the parent has really changed, remove the old signal handlers */ + if (image->parent != oldparent) { + g_signal_handlers_disconnect_by_func (image, parent_changed_cb, oldparent); + g_signal_handlers_disconnect_by_func (image, image_visible_changed_cb, NULL); + } +} + +static void +image_changed_cb (GtkButton *button, + GParamSpec *arg1, + gpointer user_data) +{ + GtkWidget *image = gtk_button_get_image (button); + + g_return_if_fail (image == NULL || GTK_IS_WIDGET (image)); + + if (image != NULL) { + /* If the button has a new image, show it */ + gtk_widget_show (image); + /* Show the image no matter the value of gtk-button-images */ + g_signal_connect (image, "notify::visible", G_CALLBACK (image_visible_changed_cb), NULL); + /* If the image is removed from the button, disconnect these handlers */ + g_signal_connect (image, "notify::parent", G_CALLBACK (parent_changed_cb), image->parent); + } +} + +static void +button_common_init (GtkWidget *button, + HildonSizeType size) +{ + /* Set requested size */ + hildon_gtk_widget_set_theme_size (button, size); + + /* Set focus-on-click to FALSE by default */ + gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE); + + /* Make sure that all images in this button are always shown */ + g_signal_connect (button, "notify::image", G_CALLBACK (image_changed_cb), NULL); +} + +/** + * hildon_gtk_menu_new: + * + * This is a convenience function to create a #GtkMenu setting its + * widget name to allow Hildon specific styling. + * + * Return value: A newly created #GtkMenu widget. + * + * Since: 2.2 + **/ +GtkWidget * +hildon_gtk_menu_new (void) +{ + GtkWidget *menu = gtk_menu_new (); + gtk_widget_set_name (menu, "hildon-context-sensitive-menu"); + return menu; +} + +/** + * hildon_gtk_button_new: + * @size: Flags indicating the size of the new button + * + * This is a convenience function to create a #GtkButton setting its + * size to one of the pre-defined Hildon sizes. + * + * Buttons created with this function also override the + * "gtk-button-images" setting. Images set using + * gtk_button_set_image() are always shown. + * + * Buttons created using this function have #GtkButton:focus-on-click + * set to %FALSE by default. + * + * Return value: A newly created #GtkButton widget. + * + * Since: 2.2 + **/ +GtkWidget * +hildon_gtk_button_new (HildonSizeType size) +{ + GtkWidget *button = gtk_button_new (); + button_common_init (button, size); + return button; +} + +/** + * hildon_gtk_toggle_button_new: + * @size: Flags indicating the size of the new button + * + * This is a convenience function to create a #GtkToggleButton setting + * its size to one of the pre-defined Hildon sizes. + * + * Buttons created with this function also override the + * "gtk-button-images" setting. Images set using + * gtk_button_set_image() are always shown. + * + * Buttons created using this function have #GtkButton:focus-on-click + * set to %FALSE by default. + * + * Return value: A newly created #GtkToggleButton widget. + * + * Since: 2.2 + **/ +GtkWidget * +hildon_gtk_toggle_button_new (HildonSizeType size) +{ + GtkWidget *button = gtk_toggle_button_new (); + button_common_init (button, size); + return button; +} + +/** + * hildon_gtk_radio_button_new: + * @size: Flags indicating the size of the new button + * @group: An existing radio button group, or %NULL if you are + * creating a new group + * + * This is a convenience function to create a #GtkRadioButton setting + * its size to one of the pre-defined Hildon sizes. + * + * Buttons created with this function also override the + * "gtk-button-images" setting. Images set using + * gtk_button_set_image() are always shown. + * + * Buttons created using this function have #GtkButton:focus-on-click + * set to %FALSE by default. + * + * Return value: A newly created #GtkRadioButton widget. + * + * Since: 2.2 + **/ +GtkWidget * +hildon_gtk_radio_button_new (HildonSizeType size, + GSList *group) +{ + GtkWidget *button = gtk_radio_button_new (group); + button_common_init (button, size); + return button; +} + +/** + * hildon_gtk_radio_button_new_from_widget: + * @size: Flags indicating the size of the new button + * @radio_group_member: widget to get radio group from or %NULL + * + * This is a convenience function to create a #GtkRadioButton setting + * its size to one of the pre-defined Hildon sizes. + * + * Buttons created with this function also override the + * "gtk-button-images" setting. Images set using + * gtk_button_set_image() are always shown. + * + * Buttons created using this function have #GtkButton:focus-on-click + * set to %FALSE by default. + * + * Return value: A newly created #GtkRadioButton widget. + * + * Since: 2.2 + **/ +GtkWidget * +hildon_gtk_radio_button_new_from_widget (HildonSizeType size, + GtkRadioButton *radio_group_member) +{ + GtkWidget *button = gtk_radio_button_new_from_widget (radio_group_member); + button_common_init (button, size); + return button; +} + +#ifdef MAEMO_GTK +/** + * hildon_gtk_tree_view_new: + * @mode: the Hildon UI mode + * + * Creates a new #GtkTreeView widget with the Hildon UI mode set to + * @mode + * + * Return value: A newly created #GtkTreeView widget. + * + * Since: 2.2 + **/ +GtkWidget * +hildon_gtk_tree_view_new (HildonUIMode mode) +{ + return g_object_new (GTK_TYPE_TREE_VIEW, "hildon-ui-mode", mode, + "enable-search", FALSE, NULL); +} + +/** + * hildon_gtk_tree_view_new_with_model: + * @mode: the Hildon UI mode + * @model: the model. + * + * Creates a new #GtkTreeView widget with the Hildon UI mode set to + * @mode and the model initialized to @model. + * + * Return value: A newly created #GtkTreeView widget. + * + * Since: 2.2 + **/ +GtkWidget * +hildon_gtk_tree_view_new_with_model (HildonUIMode mode, + GtkTreeModel *model) +{ + return g_object_new (GTK_TYPE_TREE_VIEW, "hildon-ui-mode", mode, "model", model, NULL); +} + +/** + * hildon_gtk_tree_view_set_ui_mode: + * @treeview: A #GtkTreeView + * @mode: The new #HildonUIMode + * + * Sets the UI mode of @treeview to @mode. + * + * Since: 2.2 + **/ +void +hildon_gtk_tree_view_set_ui_mode (GtkTreeView *treeview, + HildonUIMode mode) +{ + g_return_if_fail (GTK_IS_TREE_VIEW (treeview)); + g_object_set (treeview, "hildon-ui-mode", mode, NULL); +} + +/** + * hildon_gtk_icon_view_new: + * @mode: the Hildon UI mode + * + * Creates a new #GtkIconView widget with the Hildon UI mode set to + * @mode + * + * Return value: A newly created #GtkIconView widget + * + * Since: 2.2 + **/ +GtkWidget * +hildon_gtk_icon_view_new (HildonUIMode mode) +{ + return g_object_new (GTK_TYPE_ICON_VIEW, "hildon-ui-mode", mode, NULL); +} + +/** + * hildon_gtk_icon_view_new_with_model: + * @mode: the Hildon UI mode + * @model: The model. + * + * Creates a new #GtkIconView widget with the Hildon UI mode set to + * @mode and the model intitialized to @model. + * + * Return value: A newly created #GtkIconView widget. + * + * Since: 2.2 + **/ +GtkWidget * +hildon_gtk_icon_view_new_with_model (HildonUIMode mode, + GtkTreeModel *model) +{ + return g_object_new (GTK_TYPE_ICON_VIEW, "hildon-ui-mode", mode, "model", model, NULL); +} + +/** + * hildon_gtk_icon_view_set_ui_mode: + * @iconview: A #GtkIconView + * @mode: The new #HildonUIMode + * + * Sets the UI mode of @iconview to @mode. + * + * Since: 2.2 + **/ +void +hildon_gtk_icon_view_set_ui_mode (GtkIconView *iconview, + HildonUIMode mode) +{ + g_return_if_fail (GTK_IS_ICON_VIEW (iconview)); + g_object_set (iconview, "hildon-ui-mode", mode, NULL); +} +#endif /* MAEMO_GTK */ + +static void +set_clear_window_flag (GtkWindow *window, + const gchar *atomname, + Atom xatom, + gboolean flag) +{ + GdkWindow *gdkwin = GTK_WIDGET (window)->window; + GdkAtom atom = gdk_atom_intern (atomname, FALSE); + + if (flag) { + guint32 set = 1; + gdk_property_change (gdkwin, atom, gdk_x11_xatom_to_atom (xatom), + 32, GDK_PROP_MODE_REPLACE, (const guchar *) &set, 1); + } else { + gdk_property_delete (gdkwin, atom); + } +} + +static void +do_set_progress_indicator (GtkWindow *window, + gpointer stateptr) +{ + guint state = GPOINTER_TO_UINT (stateptr); + set_clear_window_flag (window, "_HILDON_WM_WINDOW_PROGRESS_INDICATOR", XA_INTEGER, state); + g_signal_handlers_disconnect_matched (window, G_SIGNAL_MATCH_FUNC, + 0, 0, NULL, do_set_progress_indicator, NULL); +} + +static void +do_set_do_not_disturb (GtkWindow *window, + gpointer dndptr) +{ + gboolean dndflag = GPOINTER_TO_INT (dndptr); + set_clear_window_flag (window, "_HILDON_DO_NOT_DISTURB", XA_INTEGER, dndflag); + g_signal_handlers_disconnect_matched (window, G_SIGNAL_MATCH_FUNC, + 0, 0, NULL, do_set_do_not_disturb, NULL); +} + +static void +do_set_portrait_flags (GtkWindow *window, + gpointer flagsptr) +{ + HildonPortraitFlags flags = GPOINTER_TO_INT (flagsptr); + + set_clear_window_flag (window, "_HILDON_PORTRAIT_MODE_REQUEST", XA_CARDINAL, + flags & HILDON_PORTRAIT_MODE_REQUEST); + set_clear_window_flag (window, "_HILDON_PORTRAIT_MODE_SUPPORT", XA_CARDINAL, + flags & HILDON_PORTRAIT_MODE_SUPPORT); + + g_signal_handlers_disconnect_matched (window, G_SIGNAL_MATCH_FUNC, + 0, 0, NULL, do_set_portrait_flags, NULL); +} + +static void +set_flag (GtkWindow *window, + HildonFlagFunc func, + gpointer userdata) +{ + g_return_if_fail (GTK_IS_WINDOW (window)); + if (GTK_WIDGET_REALIZED (window)) { + (*func) (window, userdata); + } else { + g_signal_handlers_disconnect_matched (window, G_SIGNAL_MATCH_FUNC, + 0, 0, NULL, func, NULL); + g_signal_connect (window, "realize", G_CALLBACK (func), userdata); + } +} + +/** + * hildon_gtk_window_set_progress_indicator: + * @window: a #GtkWindow. + * @state: The state we want to set: 1 -> show progress indicator, 0 + * -> hide progress indicator. + * + * This functions tells the window manager to show/hide a progress + * indicator in the window title. It applies to #HildonDialog and + * #HildonWindow (including subclasses). + * + * Since: 2.2 + **/ +void +hildon_gtk_window_set_progress_indicator (GtkWindow *window, + guint state) +{ + set_flag (window, (HildonFlagFunc) do_set_progress_indicator, GUINT_TO_POINTER (state)); +} + +/** + * hildon_gtk_window_set_do_not_disturb: + * @window: a #GtkWindow + * @dndflag: %TRUE to set the "do-not-disturb" flag, %FALSE to clear it + * + * This function tells the window manager to set (or clear) the + * "do-not-disturb" flag on @window. + * + * Since: 2.2 + **/ +void +hildon_gtk_window_set_do_not_disturb (GtkWindow *window, + gboolean dndflag) +{ + set_flag (window, (HildonFlagFunc) do_set_do_not_disturb, GUINT_TO_POINTER (dndflag)); +} + +/** + * hildon_gtk_window_set_portrait_flags: + * @window: a #GtkWindow + * @portrait_flags: a combination of #HildonPortraitFlags + * + * Sets the portrait flags for @window. + * + * Since: 2.2 + **/ +void +hildon_gtk_window_set_portrait_flags (GtkWindow *window, + HildonPortraitFlags portrait_flags) +{ + set_flag (window, (HildonFlagFunc) do_set_portrait_flags, GUINT_TO_POINTER (portrait_flags)); +} + +/** + * hildon_gtk_hscale_new: + * + * Creates a new horizontal scale widget that lets the user select + * a value. The value is technically a double between 0.0 and 1.0. + * See gtk_adjustment_configure() for reconfiguring the adjustment. + * + * The scale is hildonized, which means that a click or tap immediately + * jumps to the desired position, see gtk_range_set_jump_to_position(). + * Further more the value is not displayed, see gtk_scale_set_draw_value(). + * + * Returns: a new hildonized #GtkHScale + * + * Since: 2.2 + **/ +GtkWidget* +hildon_gtk_hscale_new (void) +{ + GtkWidget *scale = gtk_hscale_new_with_range (0.0, 1.0, 0.1); + g_object_set (scale, + "draw-value", FALSE, +#ifdef MAEMO_GTK + "jump-to-position", TRUE, +#endif + NULL); + + return scale; +} + +/** + * hildon_gtk_vscale_new: + * + * Creates a new vertical scale widget that lets the user select + * a value. The value is technically a double between 0.0 and 1.0. + * See gtk_adjustment_configure() for reconfiguring the adjustment. + * + * The scale is hildonized, which means that a click or tap immediately + * jumps to the desired position, see gtk_range_set_jump_to_position(). + * Further more the value is not displayed, see gtk_scale_set_draw_value(). + * + * Returns: a new hildonized #GtkVScale + * + * Since: 2.2 + **/ +GtkWidget* +hildon_gtk_vscale_new (void) +{ + GtkWidget *scale = gtk_vscale_new_with_range (0.0, 1.0, 0.1); + g_object_set (scale, + "draw-value", FALSE, +#ifdef MAEMO_GTK + "jump-to-position", TRUE, +#endif + NULL); + + return scale; +} diff --git a/hildon/hildon-gtk.h b/hildon/hildon-gtk.h new file mode 100644 index 0000000..7d7e9eb --- /dev/null +++ b/hildon/hildon-gtk.h @@ -0,0 +1,90 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +#ifndef __HILDON_GTK_H__ +#define __HILDON_GTK_H__ + +#include + +G_BEGIN_DECLS + +GtkWidget * +hildon_gtk_menu_new (void); + +GtkWidget * +hildon_gtk_button_new (HildonSizeType size); + +GtkWidget * +hildon_gtk_toggle_button_new (HildonSizeType size); + +GtkWidget * +hildon_gtk_radio_button_new (HildonSizeType size, + GSList *group); + +GtkWidget * +hildon_gtk_radio_button_new_from_widget (HildonSizeType size, + GtkRadioButton *radio_group_member); + +#ifdef MAEMO_GTK +GtkWidget * +hildon_gtk_tree_view_new (HildonUIMode mode); + +GtkWidget * +hildon_gtk_tree_view_new_with_model (HildonUIMode mode, + GtkTreeModel *model); + +void +hildon_gtk_tree_view_set_ui_mode (GtkTreeView *treeview, + HildonUIMode mode); + +GtkWidget * +hildon_gtk_icon_view_new (HildonUIMode mode); + +GtkWidget * +hildon_gtk_icon_view_new_with_model (HildonUIMode mode, + GtkTreeModel *model); + +void +hildon_gtk_icon_view_set_ui_mode (GtkIconView *iconview, + HildonUIMode mode); +#endif /* MAEMO_GTK */ + +void +hildon_gtk_window_set_progress_indicator (GtkWindow *window, + guint state); + +void +hildon_gtk_window_set_do_not_disturb (GtkWindow *window, + gboolean dndflag); + +typedef enum { + HILDON_PORTRAIT_MODE_REQUEST = 1 << 0, + HILDON_PORTRAIT_MODE_SUPPORT = 1 << 1 +} HildonPortraitFlags; + +void +hildon_gtk_window_set_portrait_flags (GtkWindow *window, + HildonPortraitFlags portrait_flags); + +GtkWidget* +hildon_gtk_hscale_new (void); + +GtkWidget* +hildon_gtk_vscale_new (void); + +G_END_DECLS + +#endif /* __HILDON_GTK_H__ */ diff --git a/hildon/hildon-helper.c b/hildon/hildon-helper.c new file mode 100644 index 0000000..cd3026d --- /dev/null +++ b/hildon/hildon-helper.c @@ -0,0 +1,508 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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-helper + * @short_description: A collection of useful utilities and functions. + * + * Hildon provides some helper functions that can be used for commonly + * performed tasks and functionality blocks. This includes operations + * on widget styles and probing functions for touch events. + */ + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "hildon-helper.h" +#include "hildon-banner.h" + +#define HILDON_FINGER_PRESSURE_THRESHOLD 0.4 + +#define HILDON_FINGER_BUTTON 8 + +#define HILDON_FINGER_ALT_BUTTON 1 + +#define HILDON_FINGER_ALT_MASK GDK_MOD4_MASK + +#define HILDON_FINGER_SIMULATE_BUTTON 2 + +struct _HildonLogicalElement +{ + gboolean is_color; /* If FALSE, it's a logical font def */ + GtkRcFlags rc_flags; + GtkStateType state; + gchar *logical_color_name; + gchar *logical_font_name; +} typedef HildonLogicalElement; + +static void +hildon_logical_element_list_free (GSList *list) +{ + GSList *iterator = list; + + while (iterator) { + HildonLogicalElement *element = (HildonLogicalElement *) iterator->data; + + g_free (element->logical_color_name); + g_free (element->logical_font_name); + g_slice_free (HildonLogicalElement, element); + + iterator = iterator->next; + } + + /* Free the list itself */ + g_slist_free (list); +} + +static GQuark +hildon_helper_logical_data_quark (void) +{ + static GQuark quark = 0; + + if (G_UNLIKELY (quark == 0)) + quark = g_quark_from_static_string ("hildon-logical-data"); + + return quark; +} + +static HildonLogicalElement* +attach_blank_element (GtkWidget *widget, + GSList **style_list) +{ + gboolean first = (*style_list == NULL) ? TRUE : FALSE; + + HildonLogicalElement *element = g_slice_new (HildonLogicalElement); + + element->is_color = FALSE; + element->rc_flags = 0; + element->state = 0; + element->logical_color_name = NULL; + element->logical_font_name = NULL; + + *style_list = g_slist_append (*style_list, element); + + if (first) + g_object_set_qdata_full (G_OBJECT (widget), hildon_helper_logical_data_quark (), *style_list, (GDestroyNotify) hildon_logical_element_list_free); + + return element; +} + +static GSList* +attach_new_font_element (GtkWidget *widget, + const gchar *font_name) +{ + GSList *style_list = g_object_get_qdata (G_OBJECT (widget), hildon_helper_logical_data_quark ()); + HildonLogicalElement *element = NULL; + + /* Try to find an element that already sets a font */ + GSList *iterator = style_list; + while (iterator) { + element = (HildonLogicalElement *) iterator->data; + + if (element->is_color == FALSE) { + /* Reusing ... */ + g_free (element->logical_font_name); + element->logical_font_name = g_strdup (font_name); + return style_list; + } + + iterator = iterator->next; + } + + /* It was not found so we need to create a new one and attach it */ + element = attach_blank_element (widget, &style_list); + element->is_color = FALSE; + element->logical_font_name = g_strdup (font_name); + return style_list; +} + +static GSList* +attach_new_color_element (GtkWidget *widget, + GtkRcFlags flags, + GtkStateType state, + const gchar *color_name) +{ + GSList *style_list = g_object_get_qdata (G_OBJECT (widget), hildon_helper_logical_data_quark ()); + HildonLogicalElement *element = NULL; + + /* Try to find an element that has same flags and state */ + GSList *iterator = style_list; + while (iterator) { + element = (HildonLogicalElement *) iterator->data; + + if (element->rc_flags == flags && + element->state == state && + element->is_color == TRUE) { + /* Reusing ... */ + g_free (element->logical_color_name); + element->logical_color_name = g_strdup (color_name); + return style_list; + } + + iterator = iterator->next; + } + + /* It was not found so we need to create a new one and attach it */ + element = attach_blank_element (widget, &style_list); + element->is_color = TRUE; + element->state = state; + element->rc_flags = flags; + element->logical_color_name = g_strdup (color_name); + return style_list; +} + +static void +hildon_change_style_recursive_from_list (GtkWidget *widget, + GtkStyle *prev_style, + GSList *list) +{ + g_assert (GTK_IS_WIDGET (widget)); + + /* Change the style for child widgets */ + if (GTK_IS_CONTAINER (widget)) { + GList *iterator, *children; + children = gtk_container_get_children (GTK_CONTAINER (widget)); + for (iterator = children; iterator != NULL; iterator = g_list_next (iterator)) + hildon_change_style_recursive_from_list (GTK_WIDGET (iterator->data), prev_style, list); + g_list_free (children); + } + + /* 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_list, + NULL); + + /* We iterate over all list elements and apply each style + * specification. */ + + GSList *iterator = list; + while (iterator) { + + HildonLogicalElement *element = (HildonLogicalElement *) iterator->data; + + if (element->is_color == TRUE) { + + /* Changing logical color */ + GdkColor color; + gtk_widget_ensure_style (widget); + if (gtk_style_lookup_color (widget->style, element->logical_color_name, &color) == TRUE) { + + switch (element->rc_flags) + { + case GTK_RC_FG: + gtk_widget_modify_fg (widget, element->state, &color); + break; + + case GTK_RC_BG: + gtk_widget_modify_bg (widget, element->state, &color); + break; + + case GTK_RC_TEXT: + gtk_widget_modify_text (widget, element->state, &color); + break; + + case GTK_RC_BASE: + gtk_widget_modify_base (widget, element->state, &color); + break; + } + } + } else { + + /* Changing logical font */ + GtkStyle *font_style = gtk_rc_get_style_by_paths (gtk_settings_get_default (), element->logical_font_name, NULL, G_TYPE_NONE); + if (font_style != NULL) { + PangoFontDescription *font_desc = font_style->font_desc; + + if (font_desc != NULL) + gtk_widget_modify_font (widget, font_desc); + } + } + + iterator = iterator->next; + } + + /* 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_list, + NULL); +} + +/** + * hildon_helper_event_button_is_finger: + * @event: A #GtkEventButton to check + * + * Checks if the given button event is a finger event. + * + * Return value: TRUE if the event is a finger event. + **/ +gboolean +hildon_helper_event_button_is_finger (GdkEventButton *event) +{ + gdouble pressure; + + if (gdk_event_get_axis ((GdkEvent*) event, GDK_AXIS_PRESSURE, &pressure) && + pressure > HILDON_FINGER_PRESSURE_THRESHOLD) + return TRUE; + + if (event->button == HILDON_FINGER_BUTTON) + return TRUE; + + if (event->button == HILDON_FINGER_ALT_BUTTON && + event->state & HILDON_FINGER_ALT_MASK) + return TRUE; + + if (event->button == HILDON_FINGER_SIMULATE_BUTTON) + return TRUE; + + return FALSE; +} + +/** + * hildon_helper_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. + * + * 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. + * When calling multiple times 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_helper_set_logical_font (GtkWidget *widget, + const gchar *logicalfontname) +{ + gulong signum = 0; + GSList *list; + + g_return_val_if_fail (GTK_IS_WIDGET (widget), 0); + g_return_val_if_fail (logicalfontname != NULL, 0); + + list = attach_new_font_element (widget, 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, 0, NULL, + G_CALLBACK (hildon_change_style_recursive_from_list), NULL); + + /* Change the font now */ + hildon_change_style_recursive_from_list (widget, NULL, list); + + /* 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_list), + list, NULL, 0); + + return signum; +} + +static GQuark +hildon_helper_insensitive_message_quark (void) +{ + static GQuark quark = 0; + + if (G_UNLIKELY (quark == 0)) + quark = g_quark_from_static_string ("hildon-insensitive-message"); + + return quark; +} + +static void +show_insensitive_message (GtkWidget *widget, + gpointer user_data) +{ + gchar *message = NULL; + + g_assert (GTK_IS_WIDGET (widget)); + + message = (gchar*) g_object_get_qdata (G_OBJECT (widget), + hildon_helper_insensitive_message_quark ()); + + if (message) + hildon_banner_show_information (widget, NULL, message); +} + + +/** + * hildon_helper_set_insensitive_message: + * @widget: A #GtkWidget to assign a banner to + * @message: A message to display to the user + * + * This function assigns an insensitive message to a @widget. When the @widget is + * in an insensitive state and the user activates it, the @message will be displayed + * using a standard #HildonBanner. + * + * Deprecated: As of hildon 2.2, it is strongly discouraged to use insensitive messages. + **/ +void +hildon_helper_set_insensitive_message (GtkWidget *widget, + const gchar *message) +{ + g_return_if_fail (GTK_IS_WIDGET (widget)); + + /* Clean up any previous instance of the insensitive message */ + g_signal_handlers_disconnect_matched (G_OBJECT (widget), G_SIGNAL_MATCH_FUNC, + 0, 0, NULL, + G_CALLBACK (show_insensitive_message), NULL); + + /* We need to dup the string because the pointer might not be valid when the + insensitive-press signal callback is executed */ + g_object_set_qdata_full (G_OBJECT (widget), hildon_helper_insensitive_message_quark (), + (gpointer)g_strdup (message), + g_free); + + if (message != NULL) { + g_signal_connect (G_OBJECT (widget), "insensitive-press", + G_CALLBACK (show_insensitive_message), NULL); + } +} + +/** + * hildon_helper_set_insensitive_messagef: + * @widget: A #GtkWidget to assign a banner to + * @format: a printf-like format string + * @Varargs: arguments for the format string + * + * A version of hildon_helper_set_insensitive_message with string formatting. + * + * Deprecated: As of hildon 2.2, it is strongly discouraged to use insensitive messages. + **/ +void +hildon_helper_set_insensitive_messagef (GtkWidget *widget, + const gchar *format, + ...) +{ + g_return_if_fail (GTK_IS_WIDGET (widget)); + + gchar *message; + va_list args; + + va_start (args, format); + message = g_strdup_vprintf (format, args); + va_end (args); + + hildon_helper_set_insensitive_message (widget, message); + + g_free (message); +} + +/** + * hildon_helper_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. + * When calling multiple times 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_helper_set_logical_color (GtkWidget *widget, + GtkRcFlags rcflags, + GtkStateType state, + const gchar *logicalcolorname) +{ + gulong signum = 0; + GSList *list = NULL; + + g_return_val_if_fail (GTK_IS_WIDGET (widget), 0); + g_return_val_if_fail (logicalcolorname != NULL, 0); + + list = attach_new_color_element (widget, rcflags, state, logicalcolorname); + + /* Disconnects the previously connected signals. */ + g_signal_handlers_disconnect_matched (G_OBJECT (widget), G_SIGNAL_MATCH_FUNC, + 0, 0, NULL, + G_CALLBACK (hildon_change_style_recursive_from_list), NULL); + + /* Change the colors now */ + hildon_change_style_recursive_from_list (widget, NULL, list); + + /* 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_list), + list, NULL, 0); + + return signum; +} + + +/** + * hildon_helper_set_thumb_scrollbar: + * @win: A #GtkScrolledWindow to use as target + * @thumb: TRUE to enable the thumb scrollbar, FALSE to disable + * + * This function enables a thumb scrollbar on a given scrolled window. It'll convert the + * existing normal scrollbar into a larger, finger-usable scrollbar that works without a stylus. + * As fingerable list rows are fairly high, consider using the whole available vertical space + * of your application for the content in order to have as many rows as possible + * visible on the screen at once. + * + * Finger-Sized scrollbar should always be used together with finger-sized content. + **/ +void +hildon_helper_set_thumb_scrollbar (GtkScrolledWindow *win, + gboolean thumb) +{ + g_return_if_fail (GTK_IS_SCROLLED_WINDOW (win)); + + if (win->vscrollbar) + gtk_widget_set_name (win->vscrollbar, (thumb) ? "hildon-thumb-scrollbar" : NULL); +} + + + + diff --git a/hildon/hildon-helper.h b/hildon/hildon-helper.h new file mode 100644 index 0000000..879d55f --- /dev/null +++ b/hildon/hildon-helper.h @@ -0,0 +1,65 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_HELPER_H__ +#define __HILDON_HELPER_H__ + +#include +#include + +#include "hildon-defines.h" + +G_BEGIN_DECLS + +gulong +hildon_helper_set_logical_font (GtkWidget *widget, + const gchar *logicalfontname); + +gulong +hildon_helper_set_logical_color (GtkWidget *widget, + GtkRcFlags rcflags, + GtkStateType state, + const gchar *logicalcolorname); +gboolean +hildon_helper_event_button_is_finger (GdkEventButton *event); + +#ifndef HILDON_DISABLE_DEPRECATED +void +hildon_helper_set_insensitive_message (GtkWidget *widget, + const gchar *message); + +void +hildon_helper_set_insensitive_messagef (GtkWidget *widget, + const gchar *format, + ...); +#endif + +void +hildon_helper_set_thumb_scrollbar (GtkScrolledWindow *win, + gboolean thumb); + +G_END_DECLS + +#endif /* __HILDON_HELPER_H__ */ + diff --git a/hildon/hildon-hvolumebar.c b/hildon/hildon-hvolumebar.c new file mode 100644 index 0000000..3e1ff0e --- /dev/null +++ b/hildon/hildon-hvolumebar.c @@ -0,0 +1,377 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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. + * + * + * + * #HildonHVolumeBar has been deprecated since Hildon 2.2 + * See Migrating Volume Bars + * section to know how to migrate this deprecated widget. + * + * + * + * + * + * GtkWidget *volbar = hildon_hvolumebar_new (); + * g_signal_connect (G_OBJECT(volbar), "mute_toggled", G_CALLBACK(mute_toggle), NULL); + * g_signal_connect (G_OBJECT(volbar), "level_changed", G_CALLBACK(level_change), NULL); + * + * + * + */ + +#undef HILDON_DISABLE_DEPRECATED + +#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 60 + +#define DEFAULT_TBUTTON_HEIGHT 60 + +/* Volume bar */ +#define MINIMUM_BAR_WIDTH 147 + +#define DEFAULT_BAR_HEIGHT 60 + +#define DEFAULT_ENDING_SIZE 20 + +/* Gap to leave for mute button */ +#define VERTICAL_MUTE_GAP 0 + +#define HORIZONTAL_MUTE_GAP 0 + +/* 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); + +/** + * hildon_hvolumebar_get_type: + * + * Returns GType for HildonHVolumebar. + * + * Returns: HildonHVolumebar type + */ +GType G_GNUC_CONST +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_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; + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget); + g_assert (priv); + + 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; + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(HILDON_VOLUMEBAR(widget)); + g_assert (priv); + + 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 */ + /* FIXME Not sure if this is even needed here */ + (*GTK_WIDGET_CLASS(parent_class)->expose_event) (widget, event); + } + + return FALSE; +} + +static void +hildon_hvolumebar_size_request (GtkWidget * widget, + GtkRequisition * requisition) +{ + HildonVolumebarPrivate *priv; + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(HILDON_VOLUMEBAR(widget)); + g_assert (priv); + + /* 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; + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget); + g_assert (priv); + + 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/hildon-hvolumebar.h b/hildon/hildon-hvolumebar.h new file mode 100644 index 0000000..cd19e67 --- /dev/null +++ b/hildon/hildon-hvolumebar.h @@ -0,0 +1,76 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#ifndef __HILDON_HVOLUMEBAR_H__ +#define __HILDON_HVOLUMEBAR_H__ + +#include "hildon-volumebar.h" + +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)) + +#define HILDON_HVOLUMEBAR_GET_CLASS(obj) \ + ((HildonHVolumebarClass *) G_OBJECT_GET_CLASS(obj)) + +typedef struct _HildonHVolumebar HildonHVolumebar; + +typedef struct _HildonHVolumebarClass HildonHVolumebarClass; + +struct _HildonHVolumebar +{ + HildonVolumebar parent; +}; + +struct _HildonHVolumebarClass +{ + HildonVolumebarClass parent_class; +}; + +GType G_GNUC_CONST +hildon_hvolumebar_get_type (void); + +GtkWidget* +hildon_hvolumebar_new (void); + +G_END_DECLS + +#endif /* __HILDON_HVOLUMEBAR_H__ */ + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-login-dialog-private.h b/hildon/hildon-login-dialog-private.h new file mode 100644 index 0000000..76e559c --- /dev/null +++ b/hildon/hildon-login-dialog-private.h @@ -0,0 +1,46 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_PRIVATE_H__ +#define __HILDON_NAME_PASSWORD_DIALOG_PRIVATE_H__ + +G_BEGIN_DECLS + +#define HILDON_LOGIN_DIALOG_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ + HILDON_TYPE_LOGIN_DIALOG,\ + HildonLoginDialogPrivate)) + +typedef struct _HildonLoginDialogPrivate HildonLoginDialogPrivate; + +struct _HildonLoginDialogPrivate +{ + GtkLabel *message_label; + GtkWidget *username_entry; + GtkWidget *password_entry; +}; + +G_END_DECLS + +#endif /* __HILDON_NAME_PASSWORD_DIALOG_PRIVATE_H__ */ diff --git a/hildon/hildon-login-dialog.c b/hildon/hildon-login-dialog.c new file mode 100644 index 0000000..0a76f9d --- /dev/null +++ b/hildon/hildon-login-dialog.c @@ -0,0 +1,430 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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-login-dialog + * @short_description: A widget which allows a user to enter an username + * and a password. + * @see_also: #HildonGetPasswordDialog, #HildonSetPasswordDialog + * + * #HildonLoginDialog is used to enter a username and password + * when accessing a password protected area. The widget performs no + * input checking and is used only for retrieving the username and a + * password. + */ + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "hildon-login-dialog.h" +#include "hildon-caption.h" +#include "hildon-login-dialog-private.h" +#include "hildon-entry.h" + +enum +{ + PROP_0, + PROP_MESSAGE, + PROP_USERNAME, + PROP_PASSWORD +}; + +static void +hildon_login_dialog_class_init (HildonLoginDialogClass *class); + +static void +hildon_login_dialog_init (HildonLoginDialog *widget); + +static void +hildon_login_dialog_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); + +static void +hildon_login_dialog_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +#define HILDON_LOGIN_DIALOG_TITLE "frw_ti_get_user_name_and_pwd" + +#define HILDON_LOGIN_DIALOG_USERNAME "frw_ti_get_user_name_and_pwd_enter_user_name" + +#define HILDON_LOGIN_DIALOG_PASSWORD "frw_ti_get_user_name_and_pwd_enter_pwd" + +#define HILDON_LOGIN_DIALOG_OK "wdgt_bd_done" + +#define _(String) dgettext("hildon-libs", String) + +static GtkDialogClass* parent_class; + +/** + * hildon_login_dialog_get_type: + * + * Returns GType for HildonLoginDialog. + * + * Returns: HildonLoginDialog type + */ +GType G_GNUC_CONST +hildon_login_dialog_get_type (void) +{ + static GType dialog_type = 0; + + if (! dialog_type) { + static const GTypeInfo dialog_info = { + sizeof (HildonLoginDialogClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_login_dialog_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(HildonLoginDialog), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_login_dialog_init + }; + dialog_type = g_type_register_static (GTK_TYPE_DIALOG, + "HildonLoginDialog", + &dialog_info, 0); + } + + return dialog_type; +} + +static void +hildon_login_dialog_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + HildonLoginDialog *dialog = NULL; + HildonLoginDialogPrivate *priv = NULL; + + dialog = HILDON_LOGIN_DIALOG (object); + priv = HILDON_LOGIN_DIALOG_GET_PRIVATE(dialog); + g_assert (priv); + + switch (prop_id) { + + case PROP_MESSAGE: + /* Set the password message text */ + hildon_login_dialog_set_message (dialog, g_value_get_string (value)); + break; + + case PROP_USERNAME: + /* Set the current username displayed in the dialog */ + hildon_entry_set_text (HILDON_ENTRY (priv->username_entry), g_value_get_string (value)); + break; + + case PROP_PASSWORD: + /* Set the currently entered password */ + hildon_entry_set_text (HILDON_ENTRY (priv->password_entry), g_value_get_string (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +hildon_login_dialog_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + HildonLoginDialog *dialog = NULL; + HildonLoginDialogPrivate *priv = NULL; + + dialog = HILDON_LOGIN_DIALOG (object); + priv = HILDON_LOGIN_DIALOG_GET_PRIVATE (dialog); + g_assert (priv); + + switch (prop_id) { + + case PROP_MESSAGE: + g_value_set_string (value, gtk_label_get_text (priv->message_label)); + break; + + case PROP_USERNAME: + g_value_set_string (value, hildon_login_dialog_get_username (dialog)); + break; + + case PROP_PASSWORD: + g_value_set_string (value, hildon_login_dialog_get_password (dialog)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +hildon_login_dialog_class_init (HildonLoginDialogClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + parent_class = g_type_class_peek_parent (class); + + /* Override virtual functions */ + object_class->set_property = hildon_login_dialog_set_property; + object_class->get_property = hildon_login_dialog_get_property; + + /* Install new properties */ + + /** + * HildonLoginDialog:message: + * + * Optional message displayed to the user. + */ + g_object_class_install_property (object_class, + PROP_MESSAGE, + g_param_spec_string ("message", + "Message", + "Message displayed by the dialog", + NULL, + G_PARAM_READWRITE)); + + /** + * HildonLoginDialog:username: + * + * Contents of the username field. + */ + g_object_class_install_property (object_class, + PROP_USERNAME, + g_param_spec_string ("username", + "Username", + "Username field", + "DEFAULT", + G_PARAM_READWRITE)); + + /** + * HildonLoginDialog:password: + * + * Contents of the password field. + */ + g_object_class_install_property (object_class, + PROP_PASSWORD, + g_param_spec_string ("password", + "Password", + "Password field", + "DEFAULT", + G_PARAM_READWRITE)); + + /* Install private data structure */ + g_type_class_add_private (class, sizeof (HildonLoginDialogPrivate)); +} + +static void +hildon_login_dialog_init (HildonLoginDialog *dialog) +{ + /* Access private structure */ + HildonLoginDialogPrivate *priv = HILDON_LOGIN_DIALOG_GET_PRIVATE (dialog); + g_assert (priv); + + /* 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_LOGIN_DIALOG_TITLE)); + + /* Optional message label */ + /* FIXME Set the warpping for the message label */ + priv->message_label = GTK_LABEL (gtk_label_new (NULL)); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), + GTK_WIDGET (priv->message_label), FALSE, FALSE, 0); + + /* Create buttons */ + gtk_dialog_add_button (GTK_DIALOG (dialog), _(HILDON_LOGIN_DIALOG_OK), GTK_RESPONSE_OK); + + /* Setup username entry */ + priv->username_entry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH); + +#ifdef MAEMO_GTK + g_object_set (priv->username_entry, "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL); +#endif + + caption = HILDON_CAPTION (hildon_caption_new + (group, + _(HILDON_LOGIN_DIALOG_USERNAME), + GTK_WIDGET (priv->username_entry), 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->password_entry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH); + +#ifdef MAEMO_GTK + g_object_set (priv->password_entry, "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL); +#endif + + gtk_entry_set_visibility (GTK_ENTRY (priv->password_entry), FALSE); + + caption = HILDON_CAPTION (hildon_caption_new (group, + _(HILDON_LOGIN_DIALOG_PASSWORD), + GTK_WIDGET (priv->password_entry), + 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); +} + +/** + * hildon_login_dialog_new: + * @parent: the parent window of the dialog + * + * Creates a new #HildonLoginDialog widget with Ok and Close + * buttons. + * + * Returns: the newly created #HildonLoginDialog + */ +GtkWidget* +hildon_login_dialog_new (GtkWindow *parent) +{ + GtkWidget *self = g_object_new (HILDON_TYPE_LOGIN_DIALOG, NULL); + + if (parent) + gtk_window_set_transient_for (GTK_WINDOW (self), parent); + + return self; +} + +/** + * hildon_login_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_login_dialog_new but with a + * default username and password. + * + * Returns: the newly created #HildonLoginDialog + */ +GtkWidget* +hildon_login_dialog_new_with_default (GtkWindow *parent, + const gchar *name, + const gchar *password) +{ + GtkWidget *self = hildon_login_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_login_dialog_get_username: + * @dialog: the dialog + * + * Gets the text that's in the username entry. + * + * Returns: a pointer to the name string. You should not modify it. + */ +const gchar* +hildon_login_dialog_get_username (HildonLoginDialog *dialog) +{ + HildonLoginDialogPrivate *priv; + + g_return_val_if_fail (HILDON_IS_LOGIN_DIALOG (dialog), NULL); + + priv = HILDON_LOGIN_DIALOG_GET_PRIVATE (dialog); + g_assert (priv); + + return hildon_entry_get_text (HILDON_ENTRY (priv->username_entry)); +} + +/** + * hildon_login_dialog_get_password: + * @dialog: the dialog + * + * Gets the text that's in the password entry. + * + * Returns: a pointer to the password string. You should not modify it. + */ +const gchar* +hildon_login_dialog_get_password (HildonLoginDialog *dialog) +{ + HildonLoginDialogPrivate *priv; + + g_return_val_if_fail (HILDON_IS_LOGIN_DIALOG (dialog), NULL); + + priv = HILDON_LOGIN_DIALOG_GET_PRIVATE (dialog); + g_assert (priv); + + return hildon_entry_get_text (HILDON_ENTRY (priv->password_entry)); +} + +/** + * hildon_login_dialog_set_message: + * @dialog: the dialog + * @msg: the message or some other descriptive text to be set + * + * Sets the optional descriptive text that is displayed on the top + * of the dialog. + */ +void +hildon_login_dialog_set_message (HildonLoginDialog *dialog, + const gchar *msg) +{ + HildonLoginDialogPrivate *priv; + + g_return_if_fail (HILDON_IS_LOGIN_DIALOG (dialog)); + + priv = HILDON_LOGIN_DIALOG_GET_PRIVATE (dialog); + g_assert (priv); + + gtk_label_set_text (priv->message_label, msg); +} + + diff --git a/hildon/hildon-login-dialog.h b/hildon/hildon-login-dialog.h new file mode 100644 index 0000000..93b78e6 --- /dev/null +++ b/hildon/hildon-login-dialog.h @@ -0,0 +1,91 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#ifndef __HILDON_NAME_PASSWORD_DIALOG_H__ +#define __HILDON_NAME_PASSWORD_DIALOG_H__ + +#include + +G_BEGIN_DECLS + +#define HILDON_TYPE_LOGIN_DIALOG \ + (hildon_login_dialog_get_type ()) + +#define HILDON_LOGIN_DIALOG(obj) \ + (GTK_CHECK_CAST (obj, HILDON_TYPE_LOGIN_DIALOG, \ + HildonLoginDialog)) + +#define HILDON_LOGIN_DIALOG_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST ((klass), HILDON_TYPE_LOGIN_DIALOG, \ + HildonLoginDialogClass)) + +#define HILDON_IS_LOGIN_DIALOG(obj) \ + (GTK_CHECK_TYPE (obj, HILDON_TYPE_LOGIN_DIALOG)) + +#define HILDON_IS_LOGIN_DIALOG_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE ((klass), \ + HILDON_TYPE_LOGIN_DIALOG)) + +typedef struct _HildonLoginDialog HildonLoginDialog; + +typedef struct _HildonLoginDialogClass HildonLoginDialogClass; + +struct _HildonLoginDialog +{ + GtkDialog parent; +}; + +struct _HildonLoginDialogClass +{ + GtkDialogClass parent_class; +}; + +GType G_GNUC_CONST +hildon_login_dialog_get_type (void); + +GtkWidget* +hildon_login_dialog_new (GtkWindow *parent); + +GtkWidget* +hildon_login_dialog_new_with_default (GtkWindow *parent, + const gchar *name, + const gchar *password); + +const gchar* +hildon_login_dialog_get_username (HildonLoginDialog *dialog); + +const gchar* +hildon_login_dialog_get_password (HildonLoginDialog *dialog); + +void +hildon_login_dialog_set_message (HildonLoginDialog *dialog, + const gchar *msg); + +G_END_DECLS + +#endif /* __HILDON_LOGIN_DIALOG_H__ */ + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-main.c b/hildon/hildon-main.c new file mode 100644 index 0000000..4713af9 --- /dev/null +++ b/hildon/hildon-main.c @@ -0,0 +1,121 @@ +/* + * This file is part of the hildon library + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * 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, or (at your option) any later version. + * + * 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-main + * @Short_Description: Library initialization. + * + * Before using Hildon, you need to initialize it; initialization connects + * to the window system display, and parses some standard command line + * arguments. See also gtk_init () to know more details on this topic. + * + * Hildon should be initialized by using hildon_gtk_init (). Notice this function + * also initialize gtk by calling gtk_init (). In case you need a customized + * initialization of GTK+ library you could use hildon_init () after the + * customized GTK+ initialization. + * + * + * Typical <function>main</function> function for a Hildon application + * + * int + * main (int argc, char **argv) + * { + * /* Initialize i18n support */ + * gtk_set_locale (); + * + * /* Initialize the widget set */ + * hildon_gtk_init (&argc, &argv); + * + * /* Create the main window */ + * mainwin = hildon_stackable_window_new(); + * + * /* Set up our GUI elements */ + * ... + * + * /* Show the application window */ + * gtk_widget_show_all (mainwin); + * + * /* Enter the main event loop, and wait for user interaction */ + * gtk_main (); + * + * /* The user lost interest */ + * return 0; + *} + * + * + */ + + +#include +#include "hildon-main.h" + +/** + * hildon_init: + * + * Initializes the hildon library. Call this function after calling gtk_init() + * and before using any hildon or GTK+ functions in your program. + * + * Since: 2.2 + **/ +void +hildon_init (void) +{ + static gboolean initialized = FALSE; + + if (initialized) { + g_critical ("Tried to initialized Hildon more than once."); + return; + } else { + initialized = TRUE; + } + + /* Register icon sizes */ + gtk_icon_size_register ("hildon-xsmall", 16, 16); + gtk_icon_size_register ("hildon-small", 24, 24); + gtk_icon_size_register ("hildon-stylus", 32, 32); + gtk_icon_size_register ("hildon-finger", 48, 48); + gtk_icon_size_register ("hildon-thumb", 64, 64); + gtk_icon_size_register ("hildon-large", 96, 96); + gtk_icon_size_register ("hildon-xlarge", 128, 128); +} + +/** + * hildon_gtk_init: + * @argc: Address of the argc + * parameter of your main() function. Changed if any arguments were + * handled. + * @argv: Address of the argv + * parameter of main(). Any parameters understood by gtk_init() + * are stripped before return. + * + * Convenience function to initialize the GTK+ and hildon + * libraries. Use this function to replace a call to gtk_init() and also + * initialize the hildon library. See hildon_init() and gtk_init() for details. + * + * Since: 2.2 + **/ +void +hildon_gtk_init (int *argc, char ***argv) +{ + gtk_init (argc, argv); + hildon_init (); +} diff --git a/hildon/hildon-main.h b/hildon/hildon-main.h new file mode 100644 index 0000000..88b1694 --- /dev/null +++ b/hildon/hildon-main.h @@ -0,0 +1,28 @@ +/* + * This file is part of the hildon library + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * 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, or (at your option) any later version. + * + * 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 + * + */ + +G_BEGIN_DECLS + +void hildon_init (void); +void hildon_gtk_init (int *argc, char ***argv); + +G_END_DECLS diff --git a/hildon/hildon-marshalers.list b/hildon/hildon-marshalers.list new file mode 100644 index 0000000..af8dfb1 --- /dev/null +++ b/hildon/hildon-marshalers.list @@ -0,0 +1,32 @@ +# 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 +BOOLEAN:POINTER +BOOLEAN:VOID +VOID:OBJECT +VOID:VOID +VOID:INT,DOUBLE,DOUBLE diff --git a/hildon/hildon-note-private.h b/hildon/hildon-note-private.h new file mode 100644 index 0000000..f5ae60b --- /dev/null +++ b/hildon/hildon-note-private.h @@ -0,0 +1,59 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_PRIVATE_H__ +#define __HILDON_NOTE_PRIVATE_H__ + +G_BEGIN_DECLS + +typedef struct _HildonNotePrivate HildonNotePrivate; + +#define HILDON_NOTE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_NOTE, HildonNotePrivate)); + +struct _HildonNotePrivate +{ + GtkWidget *okButton; + GtkWidget *cancelButton; + GtkWidget *label; + GtkWidget *box; + GtkWidget *event_box; + GdkWindow *transfer_window; + + HildonNoteType note_n; + GtkWidget *progressbar; + gulong sound_signal_handler; + gint button_width; + + gchar *original_description; + + /* These strings stored for backwards compatibility */ + gchar *icon; + gchar *stock_icon; +}; + +G_END_DECLS + +#endif /* __HILDON_NOTE_PRIVATE_H__ */ diff --git a/hildon/hildon-note.c b/hildon/hildon-note.c new file mode 100644 index 0000000..814e456 --- /dev/null +++ b/hildon/hildon-note.c @@ -0,0 +1,1053 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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. + * + * #HildonNote is a convenient way to prompt users for a small amount of + * input. A simple note contains an information text and, in case of + * confirmation notes, it shows buttons to confirm or cancel. It also can + * include a progress bar. + * + * This widget provides convenient functions to create either + * information notes, confirmation notes or cancel notes, which are + * useful to show the progress of a requested task allowing the user + * to cancel it. + * + * To create information notes you can use + * hildon_note_new_information(). hildon_note_new_confirmation() + * creates a note with a text and two buttons to confirm or + * cancel. Note that it is possible to create a confirmation note with + * customized buttons by using + * hildon_note_new_confirmation_add_buttons(). + * + * To create a note with a text, a progress bar and cancel button, + * hildon_note_new_cancel_with_progress_bar() can be used. + * + * + * HildonNote example + * + * + * gboolean + * show_confirmation_note (GtkWindow *parent) + * { + * gint retcode; + * GtkWidget *note; + * note = hildon_note_new_confirmation (parent, "Confirmation message..."); + * + * retcode = gtk_dialog_run (GTK_DIALOG (note)); + * gtk_widget_destroy (note); + * + * if (retcode == GTK_RESPONSE_OK) { + * g_debug ("User pressed 'OK' button'"); + * return TRUE; + * } else { + * g_debug ("User pressed 'Cancel' button"); + * return FALSE; + * } + * } + * + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#undef HILDON_DISABLE_DEPRECATED + +#include "hildon-note.h" +#include "hildon-defines.h" +#include "hildon-sound.h" +#include "hildon-banner.h" +#include "hildon-enum-types.h" +#include "hildon-note-private.h" + +#define HILDON_INFORMATION_NOTE_MIN_HEIGHT 140 + +#define HILDON_INFORMATION_NOTE_MARGIN 100 + +#define CONFIRMATION_SOUND_PATH \ + "/usr/share/sounds/ui-confirmation_note.wav" + +#define INFORMATION_SOUND_PATH \ + "/usr/share/sounds/ui-information_note.wav" + +#define _(String) dgettext("hildon-libs", String) + +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_rename (HildonNote *note); + +static void +hildon_note_finalize (GObject *obj_self); + +static void +hildon_note_realize (GtkWidget *widget); + +static void +hildon_note_unrealize (GtkWidget *widget); + +static void +label_size_request (GtkWidget *label, + GtkRequisition *req, + GtkWidget *note); + +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); +static void +unpack_widget (GtkWidget *widget); + +enum +{ + PROP_0, + PROP_HILDON_NOTE_TYPE, + PROP_HILDON_NOTE_DESCRIPTION, + PROP_HILDON_NOTE_ICON, + PROP_HILDON_NOTE_PROGRESSBAR, + PROP_HILDON_NOTE_STOCK_ICON +}; + +static GtkDialogClass* parent_class; + +static gboolean +event_box_press_event (GtkEventBox *event_box, + GdkEventButton *event, + GtkDialog *note) +{ + HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (note); + + if (priv->note_n == HILDON_NOTE_TYPE_INFORMATION || + priv->note_n == HILDON_NOTE_TYPE_INFORMATION_THEME) { + gtk_dialog_response (note, GTK_RESPONSE_DELETE_EVENT); + return TRUE; + } else { + return FALSE; + } +} + +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); + g_assert (priv); + + switch (prop_id) { + + case PROP_HILDON_NOTE_TYPE: + priv->note_n = g_value_get_enum (value); + hildon_note_rename (note); + hildon_note_rebuild (note); + break; + + case PROP_HILDON_NOTE_DESCRIPTION: + if (priv->original_description) + g_free (priv->original_description); + priv->original_description = g_value_dup_string (value); + + gtk_label_set_text (GTK_LABEL (priv->label), priv->original_description); + /* FIXME Is the "original_description" used anywhere? */ + + break; + + case PROP_HILDON_NOTE_ICON: + if (priv->icon) { + g_free (priv->icon); + } + priv->icon = g_value_dup_string (value); + break; + + case PROP_HILDON_NOTE_STOCK_ICON: + if (priv->stock_icon) { + g_free (priv->stock_icon); + } + priv->stock_icon = g_value_dup_string (value); + 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_value_set_string (value, priv->icon); + break; + + case PROP_HILDON_NOTE_STOCK_ICON: + g_value_set_string (value, priv->stock_icon); + 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; + } +} + +/** + * hildon_note_get_type: + * + * Returns GType for HildonNote. + * + * Returns: HildonNote type + */ +GType G_GNUC_CONST +hildon_note_get_type (void) +{ + 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; + widget_class->unrealize = hildon_note_unrealize; + + 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_TYPE_CONFIRMATION, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + /** + * HildonNote:description: + * + * Description for the 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 the note. + * + * Deprecated: Since 2.2 + */ + 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 name for the note. + * + * Deprecated: Since 2.2 + */ + 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 the note (if any). + */ + 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); + g_assert (priv); + + priv->label = gtk_label_new (NULL); + gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE); + gtk_label_set_justify (GTK_LABEL (priv->label), GTK_JUSTIFY_LEFT); + + priv->event_box = gtk_event_box_new (); + priv->icon = NULL; + priv->stock_icon = NULL; + + gtk_event_box_set_visible_window (GTK_EVENT_BOX (priv->event_box), FALSE); + gtk_event_box_set_above_child (GTK_EVENT_BOX (priv->event_box), TRUE); + g_signal_connect (priv->event_box, "button-press-event", + G_CALLBACK (event_box_press_event), dialog); + + /* Acquire real references to our internal children, since + they are not nessecarily packed into container in each + layout */ + g_object_ref_sink (priv->event_box); + g_object_ref_sink (priv->label); + + gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE); + gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); + + /* We use special hint to turn the note into information notification. */ + gtk_window_set_type_hint (GTK_WINDOW (dialog), GDK_WINDOW_TYPE_HINT_NOTIFICATION); +} + + +static void +hildon_note_finalize (GObject *obj_self) +{ + HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (obj_self); + g_assert (priv); + + /* FIXME Some of this stuff should be moved to dispose */ + + /* Free internal data */ + if (priv->event_box) + g_object_unref (priv->event_box); + + if (priv->label) + g_object_unref (priv->label); + + if (priv->icon) { + g_free (priv->icon); + priv->icon = NULL; + } + if (priv->stock_icon) { + g_free (priv->stock_icon); + priv->stock_icon = NULL; + } + + if (priv->progressbar) + g_object_unref (priv->progressbar); + + if (priv->original_description) + g_free (priv->original_description); + + G_OBJECT_CLASS (parent_class)->finalize (obj_self); +} + +static void +label_size_request (GtkWidget *label, + GtkRequisition *req, + GtkWidget *note) +{ + gint note_height = MAX (HILDON_INFORMATION_NOTE_MIN_HEIGHT, req->height); + g_object_set (note, "height-request", note_height, NULL); +} + +static void +resize_button (GtkWidget *button, gpointer *data) +{ + gint width = GPOINTER_TO_INT (data); + g_object_set (button, "width-request", width, NULL); +} + +static void +hildon_note_orientation_update (HildonNote *note, GdkScreen *screen) +{ + GtkDialog *dialog = GTK_DIALOG (note); + HildonNotePrivate* priv = HILDON_NOTE_GET_PRIVATE (note); + GtkWidget *parent; + gint button_width, padding; + gboolean portrait = gdk_screen_get_width (screen) < gdk_screen_get_height (screen); + + g_object_ref (dialog->action_area); + unpack_widget (dialog->action_area); + + if (portrait) { + parent = dialog->vbox; + button_width = gdk_screen_get_width (screen) - HILDON_MARGIN_DOUBLE * 2; + padding = HILDON_MARGIN_DOUBLE; + } else { + parent = gtk_widget_get_parent (dialog->vbox); + button_width = priv->button_width; + padding = 0; + } + + gtk_box_pack_end (GTK_BOX (parent), dialog->action_area, + portrait, TRUE, 0); + gtk_box_reorder_child (GTK_BOX (parent), dialog->action_area, 0); + gtk_container_foreach (GTK_CONTAINER (dialog->action_area), + (GtkCallback) resize_button, + GINT_TO_POINTER (button_width)); + g_object_unref (dialog->action_area); + gtk_container_child_set (GTK_CONTAINER (priv->box), priv->label, + "padding", padding, NULL); +} + +static void +screen_size_changed (GdkScreen *screen, + GtkWidget *note) +{ + HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (note); + gint screen_width = gdk_screen_get_width (screen); + gint text_width = screen_width - HILDON_INFORMATION_NOTE_MARGIN * 2; + + if (priv->note_n == HILDON_NOTE_TYPE_INFORMATION || + priv->note_n == HILDON_NOTE_TYPE_INFORMATION_THEME) { + g_object_set (note, "width-request", screen_width, NULL); + g_object_set (priv->label, "width-request", text_width, NULL); + + return; + } else if (priv->note_n == HILDON_NOTE_TYPE_CONFIRMATION) { + hildon_note_orientation_update (HILDON_NOTE (note), screen); + } +} + +static void +hildon_note_realize (GtkWidget *widget) +{ + GdkDisplay *display; + gboolean is_info_note = FALSE; + Atom atom; + const gchar *notification_type; + HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (widget); + g_assert (priv); + + /* 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); + + /* Set the _HILDON_NOTIFICATION_TYPE property so Matchbox places the window correctly */ + display = gdk_drawable_get_display (widget->window); + atom = gdk_x11_get_xatom_by_name_for_display (display, "_HILDON_NOTIFICATION_TYPE"); + + if (priv->note_n == HILDON_NOTE_TYPE_INFORMATION || + priv->note_n == HILDON_NOTE_TYPE_INFORMATION_THEME) { + notification_type = "_HILDON_NOTIFICATION_TYPE_INFO"; + is_info_note = TRUE; + } else { + notification_type = "_HILDON_NOTIFICATION_TYPE_CONFIRMATION"; + } + + XChangeProperty (GDK_WINDOW_XDISPLAY (widget->window), GDK_WINDOW_XID (widget->window), + atom, XA_STRING, 8, PropModeReplace, (guchar *) notification_type, + strlen (notification_type)); + + if (is_info_note) { + g_signal_connect (priv->label, "size-request", G_CALLBACK (label_size_request), widget); + } + + GdkScreen *screen = gtk_widget_get_screen (widget); + g_signal_connect (screen, "size-changed", G_CALLBACK (screen_size_changed), widget); + screen_size_changed (screen, widget); +} + +static void +hildon_note_unrealize (GtkWidget *widget) +{ + HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (widget); + GdkScreen *screen = gtk_widget_get_screen (widget); + + g_signal_handlers_disconnect_by_func (screen, G_CALLBACK (screen_size_changed), widget); + g_signal_handlers_disconnect_by_func (priv->label, G_CALLBACK (label_size_request), widget); + + GTK_WIDGET_CLASS (parent_class)->unrealize (widget); +} + + +/* 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); +} + +/* + Name the widget and text label based on the note type. This is used + by the theme to give proper backgrounds depending on the note type. +*/ +static void +hildon_note_rename (HildonNote *note) +{ + GEnumValue *value; + GEnumClass *enum_class; + gchar *name; + + HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (note); + + enum_class = g_type_class_ref (HILDON_TYPE_NOTE_TYPE); + value = g_enum_get_value (enum_class, priv->note_n); + + name = g_strconcat ("HildonNote-", value->value_nick, NULL); + gtk_widget_set_name (GTK_WIDGET (note), name); + g_free (name); + + name = g_strconcat ("HildonNoteLabel-", value->value_nick, NULL); + gtk_widget_set_name (priv->label, name); + g_free (name); + + g_type_class_unref (enum_class); +} + +static void +hildon_note_rebuild (HildonNote *note) +{ + GtkDialog *dialog; + HildonNotePrivate *priv; + gboolean is_info_note = FALSE; + + g_assert (HILDON_IS_NOTE (note)); + + priv = HILDON_NOTE_GET_PRIVATE (note); + g_assert (priv); + + dialog = GTK_DIALOG (note); + + /* Reuse exiting content widgets for new layout */ + unpack_widget (priv->label); + unpack_widget (priv->progressbar); + unpack_widget (priv->event_box); + + /* 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_TYPE_CONFIRMATION: + priv->okButton = gtk_dialog_add_button (dialog, + _("wdgt_bd_yes"), GTK_RESPONSE_OK); + priv->cancelButton = gtk_dialog_add_button (dialog, + _("wdgt_bd_no"), GTK_RESPONSE_CANCEL); + gtk_widget_show (priv->cancelButton); + g_object_get (priv->okButton, "width-request", + &priv->button_width, NULL); + gtk_widget_set_no_show_all (priv->cancelButton, FALSE); + break; + + case HILDON_NOTE_TYPE_PROGRESSBAR: + priv->cancelButton = gtk_dialog_add_button (dialog, + _("wdgt_bd_stop"), GTK_RESPONSE_CANCEL); + gtk_widget_show (priv->cancelButton); + gtk_widget_set_no_show_all (priv->cancelButton, FALSE); + break; + + case HILDON_NOTE_TYPE_INFORMATION_THEME: + case HILDON_NOTE_TYPE_INFORMATION: + is_info_note = TRUE; + break; + + case HILDON_NOTE_TYPE_CONFIRMATION_BUTTON: + default: + break; + } + + /* Don't display the action area if this is just an information + * note. This prevents text from being slightly aligned to the + * left + */ + if (is_info_note) { + gtk_widget_hide (dialog->action_area); + } else { + gtk_widget_show (dialog->action_area); + } + gtk_widget_set_no_show_all (dialog->action_area, is_info_note); + + /* Pack label vertically. Spacing is only necessary for the progressbar note. */ + priv->box = gtk_vbox_new (FALSE, priv->progressbar ? HILDON_MARGIN_DOUBLE : 0); + gtk_container_add (GTK_CONTAINER (priv->event_box), 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_container_add (GTK_CONTAINER (dialog->vbox), priv->event_box); + + gtk_widget_show_all (priv->event_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; + GtkWidget *button; + + g_return_val_if_fail (description != NULL, NULL); + + GtkWidget *conf_note = + g_object_new (HILDON_TYPE_NOTE, + "note-type", HILDON_NOTE_TYPE_CONFIRMATION_BUTTON, + "description", description, + 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); + + button = gtk_dialog_add_button (GTK_DIALOG (conf_note), message, value); + /* maemo-gtk is going to set the "no-show-all" property all + cancel/close-like buttons to TRUE, so that they are not shown. On + the other hand, this confirmation note with custom buttons should + not obey this rule, so we need to make sure they are shown. */ + gtk_widget_show (button); + gtk_widget_set_no_show_all (button, FALSE); + } + + 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 a text (description) + * that you specify and two buttons. + * + * Returns: a #GtkWidget pointer of the note + */ +GtkWidget* +hildon_note_new_confirmation (GtkWindow *parent, + const gchar *description) +{ + GtkWidget *dialog = NULL; + + g_return_val_if_fail (description != NULL, NULL); + + dialog = g_object_new (HILDON_TYPE_NOTE, + "note-type", + HILDON_NOTE_TYPE_CONFIRMATION, + "description", description, 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 a text (description) + * that you specify and two buttons. + * + * Deprecated: Since 2.2, icons are not shown in confirmation notes. Icons set + * with this function will be ignored. Use hildon_note_new_confirmation() instead. + * + * 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; + + dialog = hildon_note_new_confirmation (parent, description); + g_object_set (dialog, "icon", icon_name); + + 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 and an OK button. + * + * Returns: a #GtkWidget pointer of the note + */ +GtkWidget* +hildon_note_new_information (GtkWindow *parent, + const gchar *description) +{ + GtkWidget *dialog = NULL; + + g_return_val_if_fail (description != NULL, NULL); + + dialog = g_object_new (HILDON_TYPE_NOTE, + "note-type", + HILDON_NOTE_TYPE_INFORMATION_THEME, + "description", description, 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. + * + * Deprecated: Since 2.2, icons are not shown in confirmation notes. Icons set + * with this function will be ignored. Use hildon_note_new_information() instead. + * + * 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; + + dialog = hildon_note_new_information (parent, description); + g_object_set (dialog, "icon", icon_name); + + return dialog; +} + +/* FIXME This documentation string LIES! */ + +/** + * 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 (description != NULL, NULL); + + dialog = g_object_new (HILDON_TYPE_NOTE, + "note-type", + HILDON_NOTE_TYPE_PROGRESSBAR, + "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)); + g_assert (priv); + + if (priv->okButton) { + gtk_button_set_label (GTK_BUTTON (priv->okButton), text); + gtk_button_set_label (GTK_BUTTON (priv->cancelButton), + _("wdgt_bd_no")); + } else { + gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text); + } +} + +/** + * hildon_note_set_button_texts: + * @note: a #HildonNote + * @text_ok: the new text of the default OK button + * @text_cancel: 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 *text_ok, + const gchar *text_cancel) +{ + HildonNotePrivate *priv; + + g_return_if_fail (HILDON_IS_NOTE (note)); + + priv = HILDON_NOTE_GET_PRIVATE (HILDON_NOTE (note)); + g_assert (priv); + + if (priv->okButton) { + gtk_button_set_label (GTK_BUTTON (priv->okButton), text_ok); + gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text_cancel); + } else { + gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text_cancel); + } +} + +/* 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_assert (priv); + + g_signal_handler_disconnect (widget, priv->sound_signal_handler); + + priv->sound_signal_handler = 0; + + switch (priv->note_n) + { + case HILDON_NOTE_TYPE_INFORMATION: + case HILDON_NOTE_TYPE_INFORMATION_THEME: + hildon_play_system_sound (INFORMATION_SOUND_PATH); + break; + + case HILDON_NOTE_TYPE_CONFIRMATION: + case HILDON_NOTE_TYPE_CONFIRMATION_BUTTON: + hildon_play_system_sound (CONFIRMATION_SOUND_PATH); + break; + + default: + break; + }; + + return FALSE; +} diff --git a/hildon/hildon-note.h b/hildon/hildon-note.h new file mode 100644 index 0000000..8e67cfd --- /dev/null +++ b/hildon/hildon-note.h @@ -0,0 +1,116 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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 + +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; + +struct _HildonNote +{ + GtkDialog parent; +}; + +struct _HildonNoteClass +{ + GtkDialogClass parent_class; +}; + +GType G_GNUC_CONST +hildon_note_get_type (void); + +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_name (GtkWindow *parent, + const gchar *description, + const gchar *icon_name); +#endif + +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); +#ifndef HILDON_DISABLE_DEPRECATED +GtkWidget* +hildon_note_new_information_with_icon_name (GtkWindow *parent, + const gchar *description, + const gchar *icon_name); +#endif + +void +hildon_note_set_button_text (HildonNote *note, + const gchar *text); + +void +hildon_note_set_button_texts (HildonNote *note, + const gchar *text_ok, + const gchar *text_cancel); + +typedef enum +{ + HILDON_NOTE_TYPE_CONFIRMATION = 0, + HILDON_NOTE_TYPE_CONFIRMATION_BUTTON, + HILDON_NOTE_TYPE_INFORMATION, + HILDON_NOTE_TYPE_INFORMATION_THEME, + HILDON_NOTE_TYPE_PROGRESSBAR +} HildonNoteType; + +G_END_DECLS + +#endif /* __HILDON_NOTE_H__ */ diff --git a/hildon/hildon-number-editor-private.h b/hildon/hildon-number-editor-private.h new file mode 100644 index 0000000..cabec13 --- /dev/null +++ b/hildon/hildon-number-editor-private.h @@ -0,0 +1,56 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_PRIVATE_H__ +#define __HILDON_NUMBER_EDITOR_PRIVATE_H__ + +G_BEGIN_DECLS + +typedef struct _HildonNumberEditorPrivate HildonNumberEditorPrivate; + +#define HILDON_NUMBER_EDITOR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_NUMBER_EDITOR, \ + HildonNumberEditorPrivate)); + +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 */ +}; + +G_END_DECLS + +#endif /* __HILDON_NUMBER_EDITOR_PRIVATE_H__ */ diff --git a/hildon/hildon-number-editor.c b/hildon/hildon-number-editor.c new file mode 100644 index 0000000..994918e --- /dev/null +++ b/hildon/hildon-number-editor.c @@ -0,0 +1,1053 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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. + * + * + * + * #HildonNumberEditor has been deprecated since Hildon 2.2 + * See Migrating Number Widgets + * section to know how to migrate this deprecated widget. + * + * + * + * + * HildonNumberEditor example + * + * number_editor = hildon_number_editor_new (-250, 500); + * hildon_number_editor_set_range (number_editor, 0, 100); + * + * + */ + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include "hildon-number-editor.h" +#include "hildon-marshalers.h" +#include "hildon-defines.h" +#include "hildon-enum-types.h" +#include "hildon-banner.h" +#include "hildon-number-editor-private.h" +#include "hildon-private.h" + +#define _(String) dgettext("hildon-libs", String) + +/*Pixel spec defines*/ +#define NUMBER_EDITOR_HEIGHT 30 + +/* Size of plus and minus buttons */ +#define BUTTON_HEIGHT 30 + +#define BUTTON_WIDTH 30 + +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_focus (GtkWidget *widget, + GtkDirectionType direction); + +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); + +enum +{ + RANGE_ERROR, + LAST_SIGNAL +}; + +enum { + PROP_0, + PROP_VALUE +}; + +static GtkContainerClass* parent_class; + +static guint HildonNumberEditor_signal[LAST_SIGNAL] = {0}; + +/** + * hildon_number_editor_get_type: + * + * Returns GType for HildonNumberEditor. + * + * Returns: HildonNumberEditor type + */ +GType G_GNUC_CONST +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_number_editor_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; + + /** + * HildonNumberEditor:value: + * + * The current value of the number editor. + */ + 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); + g_assert (priv); + + 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); + g_assert (priv); + + /* 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) +{ + g_assert (priv != NULL); + + 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); + g_assert (priv); + + /* 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); + g_assert (priv); + + 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); + +#ifdef MAEMO_GTK + g_object_set (G_OBJECT (priv->num_entry), + "hildon-input-mode", HILDON_GTK_INPUT_MODE_NUMERIC, NULL); +#endif + + 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); + g_assert (priv); + + 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; + + /* Update text in entry to new value */ + buffer = g_strdup_printf ("%d", value); + gtk_entry_set_text (GTK_ENTRY (priv->num_entry), buffer); + g_free (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); + g_assert (priv); + + settings = gtk_settings_get_default (); + g_object_get (settings, "gtk-timeout-initial", &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) + { + change_numbers (editor, priv->button_type); + 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-timeout-repeat", &timeout, NULL); + timeout *= 8; + + priv->button_event_id = g_timeout_add (timeout, + (GSourceFunc) do_mouse_timeout, + editor); + + return FALSE; +} + +static gboolean +do_mouse_timeout (HildonNumberEditor *editor) +{ + HildonNumberEditorPrivate *priv; + g_assert (HILDON_IS_NUMBER_EDITOR (editor)); + + priv = HILDON_NUMBER_EDITOR_GET_PRIVATE (editor); + g_assert (priv); + + GDK_THREADS_ENTER (); + + /* Update value based on button held */ + 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); + g_assert (priv); + + 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) +{ + g_assert (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); + g_assert (priv); + + 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 = HILDON_NUMBER_EDITOR_ERROR_MAXIMUM_VALUE_EXCEED; + fixup_value = priv->end; + } + else if (value < priv->start && (priv->start < 0 || (priv->start >= 0 && value <= 0))) + { + error_code = HILDON_NUMBER_EDITOR_ERROR_MINIMUM_VALUE_EXCEED; + fixup_value = priv->start; + } + } + else + { + if (value > priv->end) { + error_code = HILDON_NUMBER_EDITOR_ERROR_MAXIMUM_VALUE_EXCEED; + fixup_value = priv->end; + } + else if (value < priv->start) { + error_code = HILDON_NUMBER_EDITOR_ERROR_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 = HILDON_NUMBER_EDITOR_ERROR_ERRONEOUS_VALUE; + } + else if (! allow_intermediate) + error_code = HILDON_NUMBER_EDITOR_ERROR_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); + g_assert (priv); + + /* 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); + g_assert (priv); + + 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_focus (GtkWidget *widget, + GtkDirectionType direction) +{ + gboolean retval; + GtkDirectionType effective_direction; + + g_assert (HILDON_IS_NUMBER_EDITOR (widget)); + + retval = hildon_private_composite_focus (widget, direction, &effective_direction); + + if (retval == TRUE) + return GTK_WIDGET_CLASS (parent_class)->focus (widget, effective_direction); + else + return FALSE; +} + +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); + g_assert (priv); + + min = priv->start; + max = priv->end; + + /* Construct error message */ + switch (type) + { + case HILDON_NUMBER_EDITOR_ERROR_MAXIMUM_VALUE_EXCEED: + err_msg = g_strdup_printf (_("ckct_ib_maximum_value"), max, max); + break; + + case HILDON_NUMBER_EDITOR_ERROR_MINIMUM_VALUE_EXCEED: + err_msg = g_strdup_printf (_("ckct_ib_minimum_value"), min, min); + break; + + case HILDON_NUMBER_EDITOR_ERROR_ERRONEOUS_VALUE: + err_msg = + g_strdup_printf (_("ckct_ib_set_a_value_within_range"), min, max); + break; + } + + /* Infoprint error */ + if (err_msg) + { + hildon_banner_show_information (GTK_WIDGET (GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET(editor), + GTK_TYPE_WINDOW))), NULL, 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); + g_assert (priv); + + /* 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); + g_assert (priv); + + 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_assert (priv); + + 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/hildon-number-editor.h b/hildon/hildon-number-editor.h new file mode 100644 index 0000000..7f46590 --- /dev/null +++ b/hildon/hildon-number-editor.h @@ -0,0 +1,98 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#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)) + +#define HILDON_NUMBER_EDITOR_GET_CLASS(obj) \ + ((HildonNumberEditorClass *) G_OBJECT_GET_CLASS(obj)) + +typedef struct _HildonNumberEditor HildonNumberEditor; + +typedef struct _HildonNumberEditorClass HildonNumberEditorClass; + +struct _HildonNumberEditor +{ + GtkContainer parent; +}; + +typedef enum +{ + HILDON_NUMBER_EDITOR_ERROR_MAXIMUM_VALUE_EXCEED, + HILDON_NUMBER_EDITOR_ERROR_MINIMUM_VALUE_EXCEED, + HILDON_NUMBER_EDITOR_ERROR_ERRONEOUS_VALUE +} HildonNumberEditorErrorType; + +struct _HildonNumberEditorClass +{ + GtkContainerClass parent_class; + + gboolean (*range_error) (HildonNumberEditor *editor, HildonNumberEditorErrorType type); +}; + +GType G_GNUC_CONST +hildon_number_editor_get_type (void); + +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__ */ + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-pannable-area.c b/hildon/hildon-pannable-area.c new file mode 100644 index 0000000..717d5ae --- /dev/null +++ b/hildon/hildon-pannable-area.c @@ -0,0 +1,3278 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * This widget is based on MokoFingerScroll from libmokoui + * OpenMoko Application Framework UI Library + * Authored by Chris Lord + * Copyright (C) 2006-2007 OpenMoko Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +/** + * SECTION: hildon-pannable-area + * @short_description: A scrolling widget designed for touch screens + * @see_also: #GtkScrolledWindow + * + * #HildonPannableArea is a container widget that can be "panned" (scrolled) + * up and down using the touchscreen with fingers. The widget has no scrollbars, + * but it rather shows small scroll indicators to give an idea of the part of the + * content that is visible at a time. The scroll indicators appear when a dragging + * motion is started on the pannable area. + * + * The scrolling is "kinetic", meaning the motion can be "flicked" and it will + * continue from the initial motion by gradually slowing down to an eventual stop. + * The motion can also be stopped immediately by pressing the touchscreen over the + * pannable area. + */ + +#undef HILDON_DISABLE_DEPRECATED + +#include +#if USE_CAIRO_SCROLLBARS == 1 +#include +#endif +#include + +#include "hildon-pannable-area.h" +#include "hildon-marshalers.h" +#include "hildon-enum-types.h" + +#define USE_CAIRO_SCROLLBARS 0 + +#define SCROLL_BAR_MIN_SIZE 5 +#define RATIO_TOLERANCE 0.000001 +#define SCROLL_FADE_TIMEOUT 100 +#define MOTION_EVENTS_PER_SECOND 25 +#define CURSOR_STOPPED_TIMEOUT 80 +#define PANNABLE_MAX_WIDTH 788 +#define PANNABLE_MAX_HEIGHT 378 + +G_DEFINE_TYPE (HildonPannableArea, hildon_pannable_area, GTK_TYPE_BIN) + +#define PANNABLE_AREA_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), HILDON_TYPE_PANNABLE_AREA, \ + HildonPannableAreaPrivate)) + +struct _HildonPannableAreaPrivate { + HildonPannableAreaMode mode; + HildonMovementMode mov_mode; + GdkWindow *event_window; + gdouble x; /* Used to store mouse co-ordinates of the first or */ + gdouble y; /* previous events in a press-motion pair */ + gdouble ex; /* Used to store mouse co-ordinates of the last */ + gdouble ey; /* motion event in acceleration mode */ + gboolean enabled; + gboolean clicked; + guint32 last_time; /* Last event time, to stop infinite loops */ + gint last_type; + gboolean last_in; + gboolean moved; + gdouble vmin; + gdouble vmax; + gdouble vmax_overshooting; + gdouble vfast_factor; + gdouble decel; + gdouble drag_inertia; + gdouble scroll_time; + gdouble vel_factor; + guint sps; + guint panning_threshold; + guint scrollbar_fade_delay; + guint bounce_steps; + guint force; + guint direction_error_margin; + gdouble vel_x; + gdouble vel_y; + GdkWindow *child; + gint child_width; + gint child_height; + gint ix; /* Initial click mouse co-ordinates */ + gint iy; + gint cx; /* Initial click child window mouse co-ordinates */ + gint cy; + guint idle_id; + gdouble scroll_to_x; + gdouble scroll_to_y; + gdouble motion_x; + gdouble motion_y; + gint overshot_dist_x; + gint overshot_dist_y; + gint overshooting_y; + gint overshooting_x; + gdouble scroll_indicator_alpha; + gint motion_event_scroll_timeout; + gint scroll_indicator_timeout; + gint scroll_indicator_event_interrupt; + gint scroll_delay_counter; + gint vovershoot_max; + gint hovershoot_max; + gboolean initial_hint; + gboolean initial_effect; + gboolean low_friction_mode; + gboolean first_drag; + + gboolean size_request_policy; + gboolean hscroll_visible; + gboolean vscroll_visible; + GdkRectangle hscroll_rect; + GdkRectangle vscroll_rect; + guint indicator_width; + + GtkAdjustment *hadjust; + GtkAdjustment *vadjust; + + GtkPolicyType vscrollbar_policy; + GtkPolicyType hscrollbar_policy; + + GdkGC *scrollbars_gc; +}; + +/*signals*/ +enum { + HORIZONTAL_MOVEMENT, + VERTICAL_MOVEMENT, + LAST_SIGNAL +}; + +static guint pannable_area_signals [LAST_SIGNAL] = { 0 }; + +enum { + PROP_ENABLED = 1, + PROP_MODE, + PROP_MOVEMENT_MODE, + PROP_VELOCITY_MIN, + PROP_VELOCITY_MAX, + PROP_VEL_MAX_OVERSHOOTING, + PROP_VELOCITY_FAST_FACTOR, + PROP_DECELERATION, + PROP_DRAG_INERTIA, + PROP_SPS, + PROP_PANNING_THRESHOLD, + PROP_SCROLLBAR_FADE_DELAY, + PROP_BOUNCE_STEPS, + PROP_FORCE, + PROP_DIRECTION_ERROR_MARGIN, + PROP_VSCROLLBAR_POLICY, + PROP_HSCROLLBAR_POLICY, + PROP_VOVERSHOOT_MAX, + PROP_HOVERSHOOT_MAX, + PROP_SCROLL_TIME, + PROP_INITIAL_HINT, + PROP_LOW_FRICTION_MODE, + PROP_SIZE_REQUEST_POLICY, + PROP_HADJUSTMENT, + PROP_VADJUSTMENT, + PROP_LAST +}; + +static void hildon_pannable_area_class_init (HildonPannableAreaClass * klass); +static void hildon_pannable_area_init (HildonPannableArea * area); +static void hildon_pannable_area_get_property (GObject * object, + guint property_id, + GValue * value, + GParamSpec * pspec); +static void hildon_pannable_area_set_property (GObject * object, + guint property_id, + const GValue * value, + GParamSpec * pspec); +static void hildon_pannable_area_dispose (GObject * object); +static void hildon_pannable_area_realize (GtkWidget * widget); +static void hildon_pannable_area_unrealize (GtkWidget * widget); +static void hildon_pannable_area_size_request (GtkWidget * widget, + GtkRequisition * requisition); +static void hildon_pannable_area_size_allocate (GtkWidget * widget, + GtkAllocation * allocation); +static void hildon_pannable_area_child_allocate_calculate (GtkWidget * widget, + GtkAllocation * allocation, + GtkAllocation * child_allocation); +static void hildon_pannable_area_style_set (GtkWidget * widget, + GtkStyle * previous_style); +static void hildon_pannable_area_map (GtkWidget * widget); +static void hildon_pannable_area_unmap (GtkWidget * widget); +static void hildon_pannable_area_grab_notify (GtkWidget *widget, + gboolean was_grabbed, + gpointer user_data); +#if USE_CAIRO_SCROLLBARS == 1 +static void rgb_from_gdkcolor (GdkColor *color, gdouble *r, gdouble *g, gdouble *b); +#else /* USE_CAIRO_SCROLLBARS */ +static void tranparency_color (GdkColor *color, + GdkColor colora, + GdkColor colorb, + gdouble transparency); +#endif /* USE_CAIRO_SCROLLBARS */ +static void hildon_pannable_draw_vscroll (GtkWidget * widget, + GdkColor *back_color, + GdkColor *scroll_color); +static void hildon_pannable_draw_hscroll (GtkWidget * widget, + GdkColor *back_color, + GdkColor *scroll_color); +static void hildon_pannable_area_initial_effect (GtkWidget * widget); +static void hildon_pannable_area_redraw (HildonPannableArea * area); +static void hildon_pannable_area_launch_fade_timeout (HildonPannableArea * area, + gdouble alpha); +static void hildon_pannable_area_adjust_value_changed (HildonPannableArea * area, + gpointer data); +static void hildon_pannable_area_adjust_changed (HildonPannableArea * area, + gpointer data); +static gboolean hildon_pannable_area_scroll_indicator_fade(HildonPannableArea * area); +static gboolean hildon_pannable_area_expose_event (GtkWidget * widget, + GdkEventExpose * event); +static GdkWindow * hildon_pannable_area_get_topmost (GdkWindow * window, + gint x, gint y, + gint * tx, gint * ty, + GdkEventMask mask); +static void synth_crossing (GdkWindow * child, + gint x, gint y, + gint x_root, gint y_root, + guint32 time, gboolean in); +static gboolean hildon_pannable_area_button_press_cb (GtkWidget * widget, + GdkEventButton * event); +static void hildon_pannable_area_refresh (HildonPannableArea * area); +static gboolean hildon_pannable_area_check_scrollbars (HildonPannableArea * area); +static void hildon_pannable_axis_scroll (HildonPannableArea *area, + GtkAdjustment *adjust, + gdouble *vel, + gdouble inc, + gint *overshooting, + gint *overshot_dist, + gdouble *scroll_to, + gint overshoot_max, + gboolean *s); +static void hildon_pannable_area_scroll (HildonPannableArea *area, + gdouble x, gdouble y); +static gboolean hildon_pannable_area_timeout (HildonPannableArea * area); +static void hildon_pannable_area_calculate_velocity (gdouble *vel, + gdouble delta, + gdouble dist, + gdouble vmax, + gdouble drag_inertia, + gdouble force, + guint sps); +static gboolean hildon_pannable_area_motion_event_scroll_timeout (HildonPannableArea *area); +static void hildon_pannable_area_motion_event_scroll (HildonPannableArea *area, + gdouble x, gdouble y); +static gboolean hildon_pannable_area_motion_notify_cb (GtkWidget * widget, + GdkEventMotion * event); +static gboolean hildon_pannable_leave_notify_event (GtkWidget *widget, + GdkEventCrossing *event); +static gboolean hildon_pannable_area_button_release_cb (GtkWidget * widget, + GdkEventButton * event); +static gboolean hildon_pannable_area_scroll_cb (GtkWidget *widget, + GdkEventScroll *event); +static void hildon_pannable_area_child_mapped (GtkWidget *widget, + GdkEvent *event, + gpointer user_data); +static void hildon_pannable_area_add (GtkContainer *container, GtkWidget *child); +static void hildon_pannable_area_remove (GtkContainer *container, GtkWidget *child); +static void hildon_pannable_calculate_vel_factor (HildonPannableArea * self); + + +static void +hildon_pannable_area_class_init (HildonPannableAreaClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass); + + + g_type_class_add_private (klass, sizeof (HildonPannableAreaPrivate)); + + object_class->get_property = hildon_pannable_area_get_property; + object_class->set_property = hildon_pannable_area_set_property; + object_class->dispose = hildon_pannable_area_dispose; + + widget_class->realize = hildon_pannable_area_realize; + widget_class->unrealize = hildon_pannable_area_unrealize; + widget_class->map = hildon_pannable_area_map; + widget_class->unmap = hildon_pannable_area_unmap; + widget_class->size_request = hildon_pannable_area_size_request; + widget_class->size_allocate = hildon_pannable_area_size_allocate; + widget_class->expose_event = hildon_pannable_area_expose_event; + widget_class->style_set = hildon_pannable_area_style_set; + widget_class->button_press_event = hildon_pannable_area_button_press_cb; + widget_class->button_release_event = hildon_pannable_area_button_release_cb; + widget_class->motion_notify_event = hildon_pannable_area_motion_notify_cb; + widget_class->leave_notify_event = hildon_pannable_leave_notify_event; + widget_class->scroll_event = hildon_pannable_area_scroll_cb; + + container_class->add = hildon_pannable_area_add; + container_class->remove = hildon_pannable_area_remove; + + klass->horizontal_movement = NULL; + klass->vertical_movement = NULL; + + g_object_class_install_property (object_class, + PROP_ENABLED, + g_param_spec_boolean ("enabled", + "Enabled", + "Enable or disable finger-scroll.", + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, + PROP_VSCROLLBAR_POLICY, + g_param_spec_enum ("vscrollbar_policy", + "vscrollbar policy", + "Visual policy of the vertical scrollbar", + GTK_TYPE_POLICY_TYPE, + GTK_POLICY_AUTOMATIC, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, + PROP_HSCROLLBAR_POLICY, + g_param_spec_enum ("hscrollbar_policy", + "hscrollbar policy", + "Visual policy of the horizontal scrollbar", + GTK_TYPE_POLICY_TYPE, + GTK_POLICY_AUTOMATIC, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, + PROP_MODE, + g_param_spec_enum ("mode", + "Scroll mode", + "Change the finger-scrolling mode.", + HILDON_TYPE_PANNABLE_AREA_MODE, + HILDON_PANNABLE_AREA_MODE_AUTO, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, + PROP_MOVEMENT_MODE, + g_param_spec_flags ("mov_mode", + "Scroll movement mode", + "Controls if the widget can scroll vertically, horizontally or both", + HILDON_TYPE_MOVEMENT_MODE, + HILDON_MOVEMENT_MODE_VERT, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, + PROP_VELOCITY_MIN, + g_param_spec_double ("velocity_min", + "Minimum scroll velocity", + "Minimum distance the child widget should scroll " + "per 'frame', in pixels per frame.", + 0, G_MAXDOUBLE, 20, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, + PROP_VELOCITY_MAX, + g_param_spec_double ("velocity_max", + "Maximum scroll velocity", + "Maximum distance the child widget should scroll " + "per 'frame', in pixels per frame.", + 0, G_MAXDOUBLE, 500, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, + PROP_VEL_MAX_OVERSHOOTING, + g_param_spec_double ("velocity_overshooting_max", + "Maximum scroll velocity when overshooting", + "Maximum distance the child widget should scroll " + "per 'frame', in pixels per frame when it overshoots after hitting the edge.", + 0, G_MAXDOUBLE, 20, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, + PROP_VELOCITY_FAST_FACTOR, + g_param_spec_double ("velocity_fast_factor", + "Fast velocity factor", + "Minimum velocity that is considered 'fast': " + "children widgets won't receive button presses. " + "Expressed as a fraction of the maximum velocity.", + 0, 1, 0.02, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, + PROP_DECELERATION, + g_param_spec_double ("deceleration", + "Deceleration multiplier", + "The multiplier used when decelerating when in " + "acceleration scrolling mode.", + 0, 1.0, 0.93, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, + PROP_DRAG_INERTIA, + g_param_spec_double ("drag_inertia", + "Inertia of the cursor dragging", + "Percentage of the calculated speed in each moment we are are going to use" + "to calculate the launch speed, the other part would be the speed" + "calculated previously", + 0, 1.0, 0.85, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, + PROP_SPS, + g_param_spec_uint ("sps", + "Scrolls per second", + "Amount of scroll events to generate per second.", + 0, G_MAXUINT, 20, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, + PROP_PANNING_THRESHOLD, + g_param_spec_uint ("panning_threshold", + "Threshold to consider a motion event an scroll", + "Amount of pixels to consider a motion event an scroll, if it is less" + "it is a click detected incorrectly by the touch screen.", + 0, G_MAXUINT, 6, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, + PROP_SCROLLBAR_FADE_DELAY, + g_param_spec_uint ("scrollbar_fade_delay", + "Time before starting to fade the scrollbar", + "Time the scrollbar is going to be visible if the widget is not in" + "action in miliseconds", + 0, G_MAXUINT, 3000, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, + PROP_BOUNCE_STEPS, + g_param_spec_uint ("bounce_steps", + "Bounce steps", + "Number of steps that is going to be used to bounce when hitting the" + "edge, the rubberband effect depends on it", + 0, G_MAXUINT, 3, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, + PROP_FORCE, + g_param_spec_uint ("force", + "Multiplier of the calculated speed", + "Force applied to the movement, multiplies the calculated speed of the" + "user movement the cursor in the screen", + 0, G_MAXUINT, 120, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, + PROP_DIRECTION_ERROR_MARGIN, + g_param_spec_uint ("direction_error_margin", + "Margin in the direction detection", + "After detecting the direction of the movement (horizontal or" + "vertical), we can add this margin of error to allow the movement in" + "the other direction even apparently it is not", + 0, G_MAXUINT, 10, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, + PROP_VOVERSHOOT_MAX, + g_param_spec_int ("vovershoot_max", + "Vertical overshoot distance", + "Space we allow the widget to pass over its vertical limits when" + "hitting the edges, set 0 in order to deactivate overshooting.", + 0, G_MAXINT, 150, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, + PROP_HOVERSHOOT_MAX, + g_param_spec_int ("hovershoot_max", + "Horizontal overshoot distance", + "Space we allow the widget to pass over its horizontal limits when" + "hitting the edges, set 0 in order to deactivate overshooting.", + 0, G_MAXINT, 150, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, + PROP_SCROLL_TIME, + g_param_spec_double ("scroll_time", + "Time to scroll to a position", + "The time to scroll to a position when calling the hildon_pannable_scroll_to function", + 1.0, 20.0, 10.0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, + PROP_INITIAL_HINT, + g_param_spec_boolean ("initial-hint", + "Initial hint", + "Whether to hint the user about the pannability of the container.", + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, + PROP_LOW_FRICTION_MODE, + g_param_spec_boolean ("low-friction-mode", + "Do not decelerate the initial velocity", + "Avoid decelerating the panning movement, like no friction, the widget" + "will stop in the edges or if the user clicks.", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, + PROP_SIZE_REQUEST_POLICY, + g_param_spec_enum ("size-request-policy", + "Size Requisition policy", + "Controls the size request policy of the widget", + HILDON_TYPE_SIZE_REQUEST_POLICY, + HILDON_SIZE_REQUEST_MINIMUM, + G_PARAM_READWRITE| + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, + PROP_HADJUSTMENT, + g_param_spec_object ("hadjustment", + "Horizontal Adjustment", + "The GtkAdjustment for the horizontal position", + GTK_TYPE_ADJUSTMENT, + G_PARAM_READABLE)); + g_object_class_install_property (object_class, + PROP_VADJUSTMENT, + g_param_spec_object ("vadjustment", + "Vertical Adjustment", + "The GtkAdjustment for the vertical position", + GTK_TYPE_ADJUSTMENT, + G_PARAM_READABLE)); + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_uint + ("indicator-width", + "Width of the scroll indicators", + "Pixel width used to draw the scroll indicators.", + 0, G_MAXUINT, 8, + G_PARAM_READWRITE)); + /** + * HildonPannableArea::horizontal-movement: + * @hildonpannable: the object which received the signal + * @direction: the direction of the movement #HILDON_MOVEMENT_UP or #HILDON_MOVEMENT_DOWN + * @initial_x: the x value of the touched point in the area when the motion started + * @initial_y: the y value of the touched point in the area when the motion started + * + * The horizontal-movement signal is emitted when the pannable area + * starts a horizontal movement. + * + * Since: 2.2 + */ + pannable_area_signals[HORIZONTAL_MOVEMENT] = + g_signal_new ("horizontal_movement", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (HildonPannableAreaClass, horizontal_movement), + NULL, NULL, + _hildon_marshal_VOID__INT_DOUBLE_DOUBLE, + G_TYPE_NONE, 3, + G_TYPE_INT, + G_TYPE_DOUBLE, + G_TYPE_DOUBLE); + + /** + * HildonPannableArea::vertical-movement: + * @hildonpannable: the object which received the signal + * @direction: the direction of the movement #HILDON_MOVEMENT_LEFT or #HILDON_MOVEMENT_RIGHT + * @initial_x: the x value when the motion started + * @initial_y: the y value when the motion started + * + * The vertical-movement signal is emitted when the pannable area + * starts a vertical movement. + * + * Since: 2.2 + */ + pannable_area_signals[VERTICAL_MOVEMENT] = + g_signal_new ("vertical_movement", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (HildonPannableAreaClass, vertical_movement), + NULL, NULL, + _hildon_marshal_VOID__INT_DOUBLE_DOUBLE, + G_TYPE_NONE, 3, + G_TYPE_INT, + G_TYPE_DOUBLE, + G_TYPE_DOUBLE); + + +} + +static void +hildon_pannable_area_init (HildonPannableArea * area) +{ + HildonPannableAreaPrivate *priv = PANNABLE_AREA_PRIVATE (area); + + GTK_WIDGET_UNSET_FLAGS (area, GTK_NO_WINDOW); + + area->priv = priv; + + priv->moved = FALSE; + priv->clicked = FALSE; + priv->last_time = 0; + priv->last_type = 0; + priv->vscroll_visible = TRUE; + priv->hscroll_visible = TRUE; + priv->indicator_width = 6; + priv->overshot_dist_x = 0; + priv->overshot_dist_y = 0; + priv->overshooting_y = 0; + priv->overshooting_x = 0; + priv->idle_id = 0; + priv->vel_x = 0; + priv->vel_y = 0; + priv->scroll_indicator_alpha = 0.0; + priv->scroll_indicator_timeout = 0; + priv->motion_event_scroll_timeout = 0; + priv->scroll_indicator_event_interrupt = 0; + priv->scroll_delay_counter = priv->scrollbar_fade_delay; + priv->scroll_to_x = -1; + priv->scroll_to_y = -1; + priv->first_drag = TRUE; + priv->initial_effect = TRUE; + priv->child_width = 0; + priv->child_height = 0; + priv->last_in = TRUE; + + hildon_pannable_calculate_vel_factor (area); + + gtk_widget_add_events (GTK_WIDGET (area), GDK_POINTER_MOTION_HINT_MASK); + + priv->hadjust = + GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); + priv->vadjust = + GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); + + g_object_ref_sink (G_OBJECT (priv->hadjust)); + g_object_ref_sink (G_OBJECT (priv->vadjust)); + + g_signal_connect_swapped (priv->hadjust, "value-changed", + G_CALLBACK (hildon_pannable_area_adjust_value_changed), area); + g_signal_connect_swapped (priv->vadjust, "value-changed", + G_CALLBACK (hildon_pannable_area_adjust_value_changed), area); + g_signal_connect_swapped (priv->hadjust, "changed", + G_CALLBACK (hildon_pannable_area_adjust_changed), area); + g_signal_connect_swapped (priv->vadjust, "changed", + G_CALLBACK (hildon_pannable_area_adjust_changed), area); + g_signal_connect (area, "grab-notify", + G_CALLBACK (hildon_pannable_area_grab_notify), NULL); +} + +static void +hildon_pannable_area_get_property (GObject * object, + guint property_id, + GValue * value, + GParamSpec * pspec) +{ + HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (object)->priv; + + switch (property_id) { + case PROP_ENABLED: + g_value_set_boolean (value, priv->enabled); + break; + case PROP_MODE: + g_value_set_enum (value, priv->mode); + break; + case PROP_MOVEMENT_MODE: + g_value_set_flags (value, priv->mov_mode); + break; + case PROP_VELOCITY_MIN: + g_value_set_double (value, priv->vmin); + break; + case PROP_VELOCITY_MAX: + g_value_set_double (value, priv->vmax); + break; + case PROP_VEL_MAX_OVERSHOOTING: + g_value_set_double (value, priv->vmax_overshooting); + break; + case PROP_VELOCITY_FAST_FACTOR: + g_value_set_double (value, priv->vfast_factor); + break; + case PROP_DECELERATION: + g_value_set_double (value, priv->decel); + break; + case PROP_DRAG_INERTIA: + g_value_set_double (value, priv->drag_inertia); + break; + case PROP_SPS: + g_value_set_uint (value, priv->sps); + break; + case PROP_PANNING_THRESHOLD: + g_value_set_uint (value, priv->panning_threshold); + break; + case PROP_SCROLLBAR_FADE_DELAY: + /* convert to miliseconds */ + g_value_set_uint (value, priv->scrollbar_fade_delay * SCROLL_FADE_TIMEOUT); + break; + case PROP_BOUNCE_STEPS: + g_value_set_uint (value, priv->bounce_steps); + break; + case PROP_FORCE: + g_value_set_uint (value, priv->force); + break; + case PROP_DIRECTION_ERROR_MARGIN: + g_value_set_uint (value, priv->direction_error_margin); + break; + case PROP_VSCROLLBAR_POLICY: + g_value_set_enum (value, priv->vscrollbar_policy); + break; + case PROP_HSCROLLBAR_POLICY: + g_value_set_enum (value, priv->hscrollbar_policy); + break; + case PROP_VOVERSHOOT_MAX: + g_value_set_int (value, priv->vovershoot_max); + break; + case PROP_HOVERSHOOT_MAX: + g_value_set_int (value, priv->hovershoot_max); + break; + case PROP_SCROLL_TIME: + g_value_set_double (value, priv->scroll_time); + break; + case PROP_INITIAL_HINT: + g_value_set_boolean (value, priv->initial_hint); + break; + case PROP_LOW_FRICTION_MODE: + g_value_set_boolean (value, priv->low_friction_mode); + break; + case PROP_SIZE_REQUEST_POLICY: + g_value_set_enum (value, priv->size_request_policy); + break; + case PROP_HADJUSTMENT: + g_value_set_object (value, + hildon_pannable_area_get_hadjustment + (HILDON_PANNABLE_AREA (object))); + break; + case PROP_VADJUSTMENT: + g_value_set_object (value, + hildon_pannable_area_get_vadjustment + (HILDON_PANNABLE_AREA (object))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +hildon_pannable_area_set_property (GObject * object, + guint property_id, + const GValue * value, + GParamSpec * pspec) +{ + HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (object)->priv; + gboolean enabled; + + switch (property_id) { + case PROP_ENABLED: + enabled = g_value_get_boolean (value); + + if ((priv->enabled != enabled) && (GTK_WIDGET_REALIZED (object))) { + if (enabled) + gdk_window_raise (priv->event_window); + else + gdk_window_lower (priv->event_window); + } + + priv->enabled = enabled; + break; + case PROP_MODE: + priv->mode = g_value_get_enum (value); + break; + case PROP_MOVEMENT_MODE: + priv->mov_mode = g_value_get_flags (value); + break; + case PROP_VELOCITY_MIN: + priv->vmin = g_value_get_double (value); + break; + case PROP_VELOCITY_MAX: + priv->vmax = g_value_get_double (value); + break; + case PROP_VEL_MAX_OVERSHOOTING: + priv->vmax_overshooting = g_value_get_double (value); + break; + case PROP_VELOCITY_FAST_FACTOR: + priv->vfast_factor = g_value_get_double (value); + break; + case PROP_DECELERATION: + hildon_pannable_calculate_vel_factor (HILDON_PANNABLE_AREA (object)); + + priv->decel = g_value_get_double (value); + break; + case PROP_DRAG_INERTIA: + priv->drag_inertia = g_value_get_double (value); + break; + case PROP_SPS: + priv->sps = g_value_get_uint (value); + break; + case PROP_PANNING_THRESHOLD: + priv->panning_threshold = g_value_get_uint (value); + break; + case PROP_SCROLLBAR_FADE_DELAY: + /* convert to miliseconds */ + priv->scrollbar_fade_delay = g_value_get_uint (value)/(SCROLL_FADE_TIMEOUT); + break; + case PROP_BOUNCE_STEPS: + priv->bounce_steps = g_value_get_uint (value); + break; + case PROP_FORCE: + priv->force = g_value_get_uint (value); + break; + case PROP_DIRECTION_ERROR_MARGIN: + priv->direction_error_margin = g_value_get_uint (value); + break; + case PROP_VSCROLLBAR_POLICY: + priv->vscrollbar_policy = g_value_get_enum (value); + + gtk_widget_queue_resize (GTK_WIDGET (object)); + break; + case PROP_HSCROLLBAR_POLICY: + priv->hscrollbar_policy = g_value_get_enum (value); + + gtk_widget_queue_resize (GTK_WIDGET (object)); + break; + case PROP_VOVERSHOOT_MAX: + priv->vovershoot_max = g_value_get_int (value); + break; + case PROP_HOVERSHOOT_MAX: + priv->hovershoot_max = g_value_get_int (value); + break; + case PROP_SCROLL_TIME: + priv->scroll_time = g_value_get_double (value); + + hildon_pannable_calculate_vel_factor (HILDON_PANNABLE_AREA (object)); + break; + case PROP_INITIAL_HINT: + priv->initial_hint = g_value_get_boolean (value); + break; + case PROP_LOW_FRICTION_MODE: + priv->low_friction_mode = g_value_get_boolean (value); + break; + case PROP_SIZE_REQUEST_POLICY: + hildon_pannable_area_set_size_request_policy (HILDON_PANNABLE_AREA (object), + g_value_get_enum (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +hildon_pannable_area_dispose (GObject * object) +{ + HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (object)->priv; + GtkWidget *child = gtk_bin_get_child (GTK_BIN (object)); + + if (priv->idle_id) { + g_source_remove (priv->idle_id); + priv->idle_id = 0; + } + + if (priv->scroll_indicator_timeout){ + g_source_remove (priv->scroll_indicator_timeout); + priv->scroll_indicator_timeout = 0; + } + + if (priv->motion_event_scroll_timeout){ + g_source_remove (priv->motion_event_scroll_timeout); + priv->motion_event_scroll_timeout = 0; + } + + if (child) { + g_signal_handlers_disconnect_by_func (child, + hildon_pannable_area_child_mapped, + object); + } + + g_signal_handlers_disconnect_by_func (object, + hildon_pannable_area_grab_notify, + NULL); + + if (priv->hadjust) { + g_signal_handlers_disconnect_by_func (priv->hadjust, + hildon_pannable_area_adjust_value_changed, + object); + g_signal_handlers_disconnect_by_func (priv->hadjust, + hildon_pannable_area_adjust_changed, + object); + g_object_unref (priv->hadjust); + priv->hadjust = NULL; + } + + if (priv->vadjust) { + g_signal_handlers_disconnect_by_func (priv->vadjust, + hildon_pannable_area_adjust_value_changed, + object); + g_signal_handlers_disconnect_by_func (priv->vadjust, + hildon_pannable_area_adjust_changed, + object); + g_object_unref (priv->vadjust); + priv->vadjust = NULL; + } + + if (G_OBJECT_CLASS (hildon_pannable_area_parent_class)->dispose) + G_OBJECT_CLASS (hildon_pannable_area_parent_class)->dispose (object); +} + +static void +hildon_pannable_area_realize (GtkWidget * widget) +{ + GdkWindowAttr attributes; + gint attributes_mask; + gint border_width; + HildonPannableAreaPrivate *priv; + + priv = HILDON_PANNABLE_AREA (widget)->priv; + + GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); + + border_width = GTK_CONTAINER (widget)->border_width; + + attributes.x = widget->allocation.x + border_width; + attributes.y = widget->allocation.y + border_width; + attributes.width = MAX (widget->allocation.width - 2 * border_width, 0); + attributes.height = MAX (widget->allocation.height - 2 * border_width, 0); + attributes.window_type = GDK_WINDOW_CHILD; + + /* avoid using the hildon_window */ + attributes.visual = gtk_widget_get_visual (widget); + attributes.colormap = gtk_widget_get_colormap (widget); + attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK; + attributes.wclass = GDK_INPUT_OUTPUT; + + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + + widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), + &attributes, attributes_mask); + gdk_window_set_user_data (widget->window, widget); + + /* create the events window */ + attributes.x = 0; + attributes.y = 0; + attributes.event_mask = gtk_widget_get_events (widget) + | GDK_BUTTON_MOTION_MASK + | GDK_BUTTON_PRESS_MASK + | GDK_BUTTON_RELEASE_MASK + | GDK_SCROLL_MASK + | GDK_EXPOSURE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK; + attributes.wclass = GDK_INPUT_ONLY; + + 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); + + widget->style = gtk_style_attach (widget->style, widget->window); + gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); + + priv->scrollbars_gc = gdk_gc_new (GDK_DRAWABLE (widget->window)); + gdk_gc_copy (priv->scrollbars_gc, widget->style->fg_gc[GTK_STATE_INSENSITIVE]); +} + +static void +hildon_pannable_area_unrealize (GtkWidget * widget) +{ + HildonPannableAreaPrivate *priv; + + priv = HILDON_PANNABLE_AREA (widget)->priv; + + if (priv->event_window != NULL) { + gdk_window_set_user_data (priv->event_window, NULL); + gdk_window_destroy (priv->event_window); + priv->event_window = NULL; + } + + gdk_gc_unref (priv->scrollbars_gc); + + if (GTK_WIDGET_CLASS (hildon_pannable_area_parent_class)->unrealize) + (*GTK_WIDGET_CLASS (hildon_pannable_area_parent_class)->unrealize)(widget); +} + +static void +hildon_pannable_area_size_request (GtkWidget * widget, + GtkRequisition * requisition) +{ + GtkRequisition child_requisition = {0}; + HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (widget)->priv; + GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget)); + + if (child && GTK_WIDGET_VISIBLE (child)) + { + gtk_widget_size_request (child, &child_requisition); + } + + if (priv->hscrollbar_policy == GTK_POLICY_NEVER) { + requisition->width = child_requisition.width; + } else { + switch (priv->size_request_policy) { + case HILDON_SIZE_REQUEST_CHILDREN: + requisition->width = MIN (PANNABLE_MAX_WIDTH, + child_requisition.width); + break; + case HILDON_SIZE_REQUEST_MINIMUM: + default: + requisition->width = priv->indicator_width; + } + } + + if (priv->vscrollbar_policy == GTK_POLICY_NEVER) { + requisition->height = child_requisition.height; + } else { + switch (priv->size_request_policy) { + case HILDON_SIZE_REQUEST_CHILDREN: + requisition->height = MIN (PANNABLE_MAX_HEIGHT, + child_requisition.height); + break; + case HILDON_SIZE_REQUEST_MINIMUM: + default: + requisition->height = priv->indicator_width; + } + } + + requisition->width += 2 * GTK_CONTAINER (widget)->border_width; + requisition->height += 2 * GTK_CONTAINER (widget)->border_width; +} + +static void +hildon_pannable_area_child_allocate_calculate (GtkWidget * widget, + GtkAllocation * allocation, + GtkAllocation * child_allocation) +{ + gint border_width; + HildonPannableAreaPrivate *priv; + + border_width = GTK_CONTAINER (widget)->border_width; + + priv = HILDON_PANNABLE_AREA (widget)->priv; + + child_allocation->x = 0; + child_allocation->y = 0; + child_allocation->width = MAX (allocation->width - 2 * border_width - + (priv->vscroll_visible ? priv->vscroll_rect.width : 0), 0); + child_allocation->height = MAX (allocation->height - 2 * border_width - + (priv->hscroll_visible ? priv->hscroll_rect.height : 0), 0); + + if (priv->overshot_dist_y > 0) { + child_allocation->y = MIN (child_allocation->y + priv->overshot_dist_y, + child_allocation->height); + child_allocation->height = MAX (child_allocation->height - priv->overshot_dist_y, 0); + } else if (priv->overshot_dist_y < 0) { + child_allocation->height = MAX (child_allocation->height + priv->overshot_dist_y, 0); + } + + if (priv->overshot_dist_x > 0) { + child_allocation->x = MIN (child_allocation->x + priv->overshot_dist_x, + child_allocation->width); + child_allocation->width = MAX (child_allocation->width - priv->overshot_dist_x, 0); + } else if (priv->overshot_dist_x < 0) { + child_allocation->width = MAX (child_allocation->width + priv->overshot_dist_x, 0); + } +} + +static void +hildon_pannable_area_size_allocate (GtkWidget * widget, + GtkAllocation * allocation) +{ + GtkAllocation child_allocation; + HildonPannableAreaPrivate *priv; + GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget)); + gint border_width; + + border_width = GTK_CONTAINER (widget)->border_width; + + widget->allocation = *allocation; + + priv = HILDON_PANNABLE_AREA (widget)->priv; + + if (GTK_WIDGET_REALIZED (widget)) { + gdk_window_move_resize (widget->window, + allocation->x + border_width, + allocation->y + border_width, + allocation->width - border_width * 2, + allocation->height - border_width * 2); + gdk_window_move_resize (priv->event_window, + 0, + 0, + allocation->width - border_width * 2, + allocation->height - border_width * 2); + } + + if (child && GTK_WIDGET_VISIBLE (child)) { + + hildon_pannable_area_child_allocate_calculate (widget, + allocation, + &child_allocation); + + gtk_widget_size_allocate (child, &child_allocation); + + if (hildon_pannable_area_check_scrollbars (HILDON_PANNABLE_AREA (widget))) { + hildon_pannable_area_child_allocate_calculate (widget, + allocation, + &child_allocation); + + gtk_widget_size_allocate (child, &child_allocation); + } + + /* we have to do this after child size_allocate because page_size is + * changed when we allocate the size of the children */ + if (priv->overshot_dist_y < 0) { + gtk_adjustment_set_value (priv->vadjust, priv->vadjust->upper - + priv->vadjust->page_size); + } + + if (priv->overshot_dist_x < 0) { + gtk_adjustment_set_value (priv->hadjust, priv->hadjust->upper - + priv->hadjust->page_size); + } + + } else { + hildon_pannable_area_check_scrollbars (HILDON_PANNABLE_AREA (widget)); + } +} + +static void +hildon_pannable_area_style_set (GtkWidget * widget, + GtkStyle * previous_style) +{ + HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (widget)->priv; + + GTK_WIDGET_CLASS (hildon_pannable_area_parent_class)-> + style_set (widget, previous_style); + + gtk_widget_style_get (widget, "indicator-width", &priv->indicator_width, NULL); +} + +static void +hildon_pannable_area_map (GtkWidget * widget) +{ + HildonPannableAreaPrivate *priv; + + priv = HILDON_PANNABLE_AREA (widget)->priv; + + gdk_window_show (widget->window); + + if (priv->event_window != NULL && !priv->enabled) + gdk_window_show (priv->event_window); + + (*GTK_WIDGET_CLASS (hildon_pannable_area_parent_class)->map) (widget); + + if (priv->event_window != NULL && priv->enabled) + gdk_window_show (priv->event_window); +} + +static void +hildon_pannable_area_unmap (GtkWidget * widget) +{ + HildonPannableAreaPrivate *priv; + + priv = HILDON_PANNABLE_AREA (widget)->priv; + + if (priv->event_window != NULL) + gdk_window_hide (priv->event_window); + + gdk_window_hide (widget->window); + + (*GTK_WIDGET_CLASS (hildon_pannable_area_parent_class)->unmap) (widget); +} + +static void +hildon_pannable_area_grab_notify (GtkWidget *widget, + gboolean was_grabbed, + gpointer user_data) +{ + /* an internal widget has grabbed the focus and now has returned it, + we have to do some release actions */ + if (was_grabbed) { + HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (widget)->priv; + + priv->scroll_indicator_event_interrupt = 0; + + if ((!priv->scroll_indicator_timeout)&&(priv->scroll_indicator_alpha)>0.1) { + priv->scroll_delay_counter = priv->scrollbar_fade_delay; + + hildon_pannable_area_launch_fade_timeout (HILDON_PANNABLE_AREA (widget), + priv->scroll_indicator_alpha); + } + + priv->last_type = 3; + priv->moved = FALSE; + } +} + +#if USE_CAIRO_SCROLLBARS == 1 + +static void +rgb_from_gdkcolor (GdkColor *color, gdouble *r, gdouble *g, gdouble *b) +{ + *r = (color->red >> 8) / 255.0; + *g = (color->green >> 8) / 255.0; + *b = (color->blue >> 8) / 255.0; +} + +static void +hildon_pannable_draw_vscroll (GtkWidget * widget, + GdkColor *back_color, + GdkColor *scroll_color) +{ + HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (widget)->priv; + gfloat y, height; + cairo_t *cr; + cairo_pattern_t *pattern; + gdouble r, g, b; + gint radius = (priv->vscroll_rect.width/2) - 1; + + cr = gdk_cairo_create(widget->window); + + /* Draw the background */ + rgb_from_gdkcolor (back_color, &r, &g, &b); + cairo_set_source_rgb (cr, r, g, b); + cairo_rectangle(cr, priv->vscroll_rect.x, priv->vscroll_rect.y, + priv->vscroll_rect.width, + priv->vscroll_rect.height); + cairo_fill_preserve (cr); + cairo_clip (cr); + + /* Calculate the scroll bar height and position */ + y = ((priv->vadjust->value - priv->vadjust->lower) / (priv->vadjust->upper - priv->vadjust->lower)) * + (widget->allocation.height - + (priv->hscroll_visible ? priv->indicator_width : 0)); + height = ((((priv->vadjust->value - priv->vadjust->lower) + + priv->vadjust->page_size) / + (priv->vadjust->upper - priv->vadjust->lower)) * + (widget->allocation.height - + (priv->hscroll_visible ? priv->indicator_width : 0))) - y; + + /* Set a minimum height */ + height = MAX (SCROLL_BAR_MIN_SIZE, height); + + /* Check the max y position */ + y = MIN (y, widget->allocation.height - + (priv->hscroll_visible ? priv->hscroll_rect.height : 0) - + height); + + /* Draw the scrollbar */ + rgb_from_gdkcolor (scroll_color, &r, &g, &b); + + pattern = cairo_pattern_create_linear(radius+1, y, radius+1,y + height); + cairo_pattern_add_color_stop_rgb(pattern, 0, r, g, b); + cairo_pattern_add_color_stop_rgb(pattern, 1, r/2, g/2, b/2); + cairo_set_source(cr, pattern); + cairo_fill(cr); + cairo_pattern_destroy(pattern); + + cairo_arc(cr, priv->vscroll_rect.x + radius + 1, y + radius + 1, radius, G_PI, 0); + cairo_line_to(cr, priv->vscroll_rect.x + (radius * 2) + 1, y + height - radius); + cairo_arc(cr, priv->vscroll_rect.x + radius + 1, y + height - radius, radius, 0, G_PI); + cairo_line_to(cr, priv->vscroll_rect.x + 1, y + height - radius); + cairo_clip (cr); + + cairo_paint_with_alpha(cr, priv->scroll_indicator_alpha); + + cairo_destroy(cr); +} + +static void +hildon_pannable_draw_hscroll (GtkWidget * widget, + GdkColor *back_color, + GdkColor *scroll_color) +{ + HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (widget)->priv; + gfloat x, width; + cairo_t *cr; + cairo_pattern_t *pattern; + gdouble r, g, b; + gint radius = (priv->hscroll_rect.height/2) - 1; + + cr = gdk_cairo_create(widget->window); + + /* Draw the background */ + rgb_from_gdkcolor (back_color, &r, &g, &b); + cairo_set_source_rgb (cr, r, g, b); + cairo_rectangle(cr, priv->hscroll_rect.x, priv->hscroll_rect.y, + priv->hscroll_rect.width, + priv->hscroll_rect.height); + cairo_fill_preserve (cr); + cairo_clip (cr); + + /* calculate the scrollbar width and position */ + x = ((priv->hadjust->value - priv->hadjust->lower) / (priv->hadjust->upper - priv->hadjust->lower)) * + (widget->allocation.width - (priv->vscroll_visible ? priv->indicator_width : 0)); + width =((((priv->hadjust->value - priv->hadjust->lower) + + priv->hadjust->page_size) / (priv->hadjust->upper - priv->hadjust->lower)) * + (widget->allocation.width - + (priv->vscroll_visible ? priv->indicator_width : 0))) - x; + + /* Set a minimum width */ + width = MAX (SCROLL_BAR_MIN_SIZE, width); + + /* Check the max x position */ + x = MIN (x, widget->allocation.width - + (priv->vscroll_visible ? priv->vscroll_rect.width : 0) - + width); + + /* Draw the scrollbar */ + rgb_from_gdkcolor (scroll_color, &r, &g, &b); + + pattern = cairo_pattern_create_linear(x, radius+1, x+width, radius+1); + cairo_pattern_add_color_stop_rgb(pattern, 0, r, g, b); + cairo_pattern_add_color_stop_rgb(pattern, 1, r/2, g/2, b/2); + cairo_set_source(cr, pattern); + cairo_fill(cr); + cairo_pattern_destroy(pattern); + + cairo_arc_negative(cr, x + radius + 1, priv->hscroll_rect.y + radius + 1, radius, 3*G_PI_2, G_PI_2); + cairo_line_to(cr, x + width - radius, priv->hscroll_rect.y + (radius * 2) + 1); + cairo_arc_negative(cr, x + width - radius, priv->hscroll_rect.y + radius + 1, radius, G_PI_2, 3*G_PI_2); + cairo_line_to(cr, x + width - radius, priv->hscroll_rect.y + 1); + cairo_clip (cr); + + cairo_paint_with_alpha(cr, priv->scroll_indicator_alpha); + + cairo_destroy(cr); +} + +#else /* USE_CAIRO_SCROLLBARS */ + +static void +tranparency_color (GdkColor *color, + GdkColor colora, + GdkColor colorb, + gdouble transparency) +{ + gdouble diff; + + diff = colora.red - colorb.red; + color->red = colora.red-diff*transparency; + + diff = colora.green - colorb.green; + color->green = colora.green-diff*transparency; + + diff = colora.blue - colorb.blue; + color->blue = colora.blue-diff*transparency; +} + +static void +hildon_pannable_draw_vscroll (GtkWidget *widget, + GdkColor *back_color, + GdkColor *scroll_color) +{ + HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (widget)->priv; + gfloat y, height; + GdkColor transp_color; + GdkGC *gc = widget->style->fg_gc[GTK_STATE_INSENSITIVE]; + + gdk_draw_rectangle (widget->window, + widget->style->bg_gc[GTK_STATE_NORMAL], + TRUE, + priv->vscroll_rect.x, priv->vscroll_rect.y, + priv->vscroll_rect.width, + priv->vscroll_rect.height); + + y = ((priv->vadjust->value - priv->vadjust->lower) / (priv->vadjust->upper - priv->vadjust->lower)) * + (widget->allocation.height - (priv->hscroll_visible ? priv->indicator_width : 0)); + height = ((((priv->vadjust->value - priv->vadjust->lower) + priv->vadjust->page_size) / + (priv->vadjust->upper - priv->vadjust->lower)) * + (widget->allocation.height - + (priv->hscroll_visible ? priv->indicator_width : 0))) - y; + + /* Set a minimum height */ + height = MAX (SCROLL_BAR_MIN_SIZE, height); + + /* Check the max y position */ + y = MIN (y, widget->allocation.height - + (priv->hscroll_visible ? priv->hscroll_rect.height : 0) - + height); + + if (priv->scroll_indicator_alpha < 1.0) { + tranparency_color (&transp_color, *back_color, *scroll_color, + priv->scroll_indicator_alpha); + + gdk_gc_set_rgb_fg_color (priv->scrollbars_gc, &transp_color); + + gc = priv->scrollbars_gc; + } + + gdk_draw_rectangle (widget->window, gc, + TRUE, priv->vscroll_rect.x, y, + priv->vscroll_rect.width, height); +} + +static void +hildon_pannable_draw_hscroll (GtkWidget *widget, + GdkColor *back_color, + GdkColor *scroll_color) +{ + HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (widget)->priv; + gfloat x, width; + GdkColor transp_color; + GdkGC *gc = widget->style->fg_gc[GTK_STATE_INSENSITIVE]; + + gdk_draw_rectangle (widget->window, + widget->style->bg_gc[GTK_STATE_INSENSITIVE], + TRUE, + priv->hscroll_rect.x, priv->hscroll_rect.y, + priv->hscroll_rect.width, + priv->hscroll_rect.height); + + /* calculate the scrollbar width and position */ + x = ((priv->hadjust->value - priv->hadjust->lower) / (priv->hadjust->upper - priv->hadjust->lower)) * + (widget->allocation.width - (priv->vscroll_visible ? priv->indicator_width : 0)); + width =((((priv->hadjust->value - priv->hadjust->lower) + + priv->hadjust->page_size) / (priv->hadjust->upper - priv->hadjust->lower)) * + (widget->allocation.width - + (priv->vscroll_visible ? priv->indicator_width : 0))) - x; + + /* Set a minimum width */ + width = MAX (SCROLL_BAR_MIN_SIZE, width); + + /* Check the max x position */ + x = MIN (x, widget->allocation.width - + (priv->vscroll_visible ? priv->vscroll_rect.width : 0) - + width); + + if (priv->scroll_indicator_alpha < 1.0) { + tranparency_color (&transp_color, *back_color, *scroll_color, + priv->scroll_indicator_alpha); + + gdk_gc_set_rgb_fg_color (priv->scrollbars_gc, &transp_color); + + gc = priv->scrollbars_gc; + } + + gdk_draw_rectangle (widget->window, gc, + TRUE, x, priv->hscroll_rect.y, width, + priv->hscroll_rect.height); +} + +#endif /* USE_CAIRO_SCROLLBARS */ + +static void +hildon_pannable_area_initial_effect (GtkWidget * widget) +{ + HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (widget)->priv; + gboolean hscroll_visible, vscroll_visible; + + if (priv->initial_hint) { + + vscroll_visible = (priv->vadjust->upper - priv->vadjust->lower > + priv->vadjust->page_size); + hscroll_visible = (priv->hadjust->upper - priv->hadjust->lower > + priv->hadjust->page_size); + + if (priv->vscroll_visible || priv->hscroll_visible) { + + priv->scroll_indicator_event_interrupt = 0; + priv->scroll_delay_counter = priv->scrollbar_fade_delay; + + hildon_pannable_area_launch_fade_timeout (HILDON_PANNABLE_AREA (widget), 1.0); + } + } +} + +static void +hildon_pannable_area_launch_fade_timeout (HildonPannableArea * area, + gdouble alpha) +{ + HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (area)->priv; + + priv->scroll_indicator_alpha = alpha; + + if (!priv->scroll_indicator_timeout) + priv->scroll_indicator_timeout = + gdk_threads_add_timeout (SCROLL_FADE_TIMEOUT, + (GSourceFunc) hildon_pannable_area_scroll_indicator_fade, + area); +} + +static void +hildon_pannable_area_adjust_changed (HildonPannableArea * area, + gpointer data) +{ + if (GTK_WIDGET_REALIZED (area)) + hildon_pannable_area_refresh (area); +} + +static void +hildon_pannable_area_adjust_value_changed (HildonPannableArea * area, + gpointer data) +{ + if (GTK_WIDGET_REALIZED (area)) { + HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (area)->priv; + + hildon_pannable_area_redraw (area); + + if ((priv->vscroll_visible) || (priv->hscroll_visible)) { + priv->scroll_indicator_event_interrupt = 0; + priv->scroll_delay_counter = priv->scrollbar_fade_delay; + + hildon_pannable_area_launch_fade_timeout (area, 1.0); + } + } +} + +static void +hildon_pannable_area_redraw (HildonPannableArea * area) +{ + HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (area)->priv; + + /* Redraw scroll indicators */ + if (GTK_WIDGET_DRAWABLE (area)) { + if (priv->hscroll_visible) { + gdk_window_invalidate_rect (GTK_WIDGET (area)->window, + &priv->hscroll_rect, FALSE); + } + + if (priv->vscroll_visible) { + gdk_window_invalidate_rect (GTK_WIDGET (area)->window, + &priv->vscroll_rect, FALSE); + } + } +} + +static gboolean +hildon_pannable_area_scroll_indicator_fade(HildonPannableArea * area) +{ + HildonPannableAreaPrivate *priv = area->priv; + + /* if moving do not fade out */ + if (((ABS (priv->vel_y)>1.0)|| + (ABS (priv->vel_x)>1.0))&&(!priv->clicked)) { + + return TRUE; + } + + if (priv->scroll_indicator_event_interrupt) { + /* Stop a fade out, and fade back in */ + if (priv->scroll_indicator_alpha > 0.9) { + priv->scroll_indicator_alpha = 1.0; + priv->scroll_indicator_timeout = 0; + + return FALSE; + } else { + priv->scroll_indicator_alpha += 0.2; + hildon_pannable_area_redraw (area); + + return TRUE; + } + } + + if ((priv->scroll_indicator_alpha > 0.9) && + (priv->scroll_delay_counter > 0)) { + priv->scroll_delay_counter--; + + return TRUE; + } + + if (!priv->scroll_indicator_event_interrupt) { + /* Continue fade out */ + if (priv->scroll_indicator_alpha < 0.1) { + priv->scroll_indicator_timeout = 0; + priv->scroll_indicator_alpha = 0.0; + + return FALSE; + } else { + priv->scroll_indicator_alpha -= 0.2; + hildon_pannable_area_redraw (area); + + return TRUE; + } + } + + return TRUE; +} + +static gboolean +hildon_pannable_area_expose_event (GtkWidget * widget, + GdkEventExpose * event) +{ + + HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (widget)->priv; +#if USE_CAIRO_SCROLLBARS == 1 + GdkColor back_color = widget->style->bg[GTK_STATE_NORMAL]; + GdkColor scroll_color = widget->style->base[GTK_STATE_SELECTED]; +#else /* USE_CAIRO_SCROLLBARS */ + GdkColor back_color = widget->style->bg[GTK_STATE_NORMAL]; + GdkColor scroll_color = widget->style->fg[GTK_STATE_INSENSITIVE]; +#endif + + if (gtk_bin_get_child (GTK_BIN (widget))) { + + if (priv->scroll_indicator_alpha > 0.1) { + if (priv->vscroll_visible) { + hildon_pannable_draw_vscroll (widget, &back_color, &scroll_color); + } + if (priv->hscroll_visible) { + hildon_pannable_draw_hscroll (widget, &back_color, &scroll_color); + } + } + + /* draw overshooting rectangles */ + if (priv->overshot_dist_y > 0) { + gint overshot_height; + + overshot_height = MIN (priv->overshot_dist_y, widget->allocation.height - + (priv->hscroll_visible ? priv->hscroll_rect.height : 0)); + + gdk_draw_rectangle (widget->window, + widget->style->bg_gc[GTK_STATE_NORMAL], + TRUE, + 0, + 0, + widget->allocation.width - + (priv->vscroll_visible ? priv->vscroll_rect.width : 0), + overshot_height); + } else if (priv->overshot_dist_y < 0) { + gint overshot_height; + gint overshot_y; + + overshot_height = + MAX (priv->overshot_dist_y, + -(widget->allocation.height - + (priv->hscroll_visible ? priv->hscroll_rect.height : 0))); + + overshot_y = MAX (widget->allocation.height + + overshot_height - + (priv->hscroll_visible ? priv->hscroll_rect.height : 0), 0); + + gdk_draw_rectangle (widget->window, + widget->style->bg_gc[GTK_STATE_NORMAL], + TRUE, + 0, + overshot_y, + widget->allocation.width - + priv->vscroll_rect.width, + -overshot_height); + } + + if (priv->overshot_dist_x > 0) { + gint overshot_width; + + overshot_width = MIN (priv->overshot_dist_x, widget->allocation.width - + (priv->vscroll_visible ? priv->vscroll_rect.width : 0)); + + gdk_draw_rectangle (widget->window, + widget->style->bg_gc[GTK_STATE_NORMAL], + TRUE, + 0, + 0, + overshot_width, + widget->allocation.height - + (priv->hscroll_visible ? priv->hscroll_rect.height : 0)); + } else if (priv->overshot_dist_x < 0) { + gint overshot_width; + gint overshot_x; + + overshot_width = + MAX (priv->overshot_dist_x, + -(widget->allocation.width - + (priv->vscroll_visible ? priv->vscroll_rect.width : 0))); + + overshot_x = MAX (widget->allocation.width + + overshot_width - + (priv->vscroll_visible ? priv->vscroll_rect.width : 0), 0); + + gdk_draw_rectangle (widget->window, + widget->style->bg_gc[GTK_STATE_NORMAL], + TRUE, + overshot_x, + 0, + -overshot_width, + widget->allocation.height - + priv->hscroll_rect.height); + } + + } + + if (G_UNLIKELY (priv->initial_effect)) { + + hildon_pannable_area_initial_effect (widget); + + priv->initial_effect = FALSE; + } + + return GTK_WIDGET_CLASS (hildon_pannable_area_parent_class)->expose_event (widget, event); +} + +static GdkWindow * +hildon_pannable_area_get_topmost (GdkWindow * window, + gint x, gint y, + gint * tx, gint * ty, + GdkEventMask mask) +{ + /* Find the GdkWindow at the given point, by recursing from a given + * parent GdkWindow. Optionally return the co-ordinates transformed + * relative to the child window. + */ + gint width, height; + GList *c, *children; + GdkWindow *selected_window = NULL; + + gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height); + if ((x < 0) || (x >= width) || (y < 0) || (y >= height)) + return NULL; + + children = gdk_window_peek_children (window); + + if (!children) { + if (tx) + *tx = x; + if (ty) + *ty = y; + selected_window = window; + } + + for (c = children; c; c = c->next) { + GdkWindow *child = (GdkWindow *) c->data; + gint wx, wy; + + gdk_drawable_get_size (GDK_DRAWABLE (child), &width, &height); + gdk_window_get_position (child, &wx, &wy); + + if ((x >= wx) && (x < (wx + width)) && (y >= wy) && (y < (wy + height)) && + (gdk_window_is_visible (child))) { + + if (gdk_window_peek_children (child)) { + selected_window = hildon_pannable_area_get_topmost (child, x-wx, y-wy, + tx, ty, mask); + if (!selected_window) { + if (tx) + *tx = x; + if (ty) + *ty = y; + selected_window = child; + } + } else { + if ((gdk_window_get_events (child)&mask)) { + if (tx) + *tx = x-wx; + if (ty) + *ty = y-wy; + selected_window = child; + } + } + } + } + + return selected_window; +} + +static void +synth_crossing (GdkWindow * child, + gint x, gint y, + gint x_root, gint y_root, + guint32 time, gboolean in) +{ + GdkEventCrossing *crossing_event; + GdkEventType type = in ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY; + + /* Send synthetic enter event */ + crossing_event = (GdkEventCrossing *) gdk_event_new (type); + ((GdkEventAny *) crossing_event)->type = type; + ((GdkEventAny *) crossing_event)->window = g_object_ref (child); + ((GdkEventAny *) crossing_event)->send_event = FALSE; + crossing_event->subwindow = g_object_ref (child); + crossing_event->time = time; + crossing_event->x = x; + crossing_event->y = y; + crossing_event->x_root = x_root; + crossing_event->y_root = y_root; + crossing_event->mode = GDK_CROSSING_NORMAL; + crossing_event->detail = GDK_NOTIFY_UNKNOWN; + crossing_event->focus = FALSE; + crossing_event->state = 0; + gdk_event_put ((GdkEvent *) crossing_event); + gdk_event_free ((GdkEvent *) crossing_event); +} + +static gboolean +hildon_pannable_area_button_press_cb (GtkWidget * widget, + GdkEventButton * event) +{ + gint x, y; + HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (widget)->priv; + + if ((!priv->enabled) || (event->button != 1) || + ((event->time == priv->last_time) && + (priv->last_type == 1)) || (gtk_bin_get_child (GTK_BIN (widget)) == NULL)) + return TRUE; + + priv->scroll_indicator_event_interrupt = 1; + + hildon_pannable_area_launch_fade_timeout (HILDON_PANNABLE_AREA (widget), + priv->scroll_indicator_alpha); + + priv->last_time = event->time; + priv->last_type = 1; + + priv->scroll_to_x = -1; + priv->scroll_to_y = -1; + + if (priv->clicked && priv->child) { + /* Widget stole focus on last click, send crossing-out event */ + synth_crossing (priv->child, 0, 0, event->x_root, event->y_root, + event->time, FALSE); + } + + priv->x = event->x; + priv->y = event->y; + priv->ix = priv->x; + priv->iy = priv->y; + + /* Don't allow a click if we're still moving fast */ + if ((ABS (priv->vel_x) <= (priv->vmax * priv->vfast_factor)) && + (ABS (priv->vel_y) <= (priv->vmax * priv->vfast_factor))) + priv->child = + hildon_pannable_area_get_topmost (gtk_bin_get_child (GTK_BIN (widget))->window, + event->x, event->y, &x, &y, GDK_BUTTON_PRESS_MASK); + else + priv->child = NULL; + + priv->clicked = TRUE; + + /* Stop scrolling on mouse-down (so you can flick, then hold to stop) */ + priv->vel_x = 0; + priv->vel_y = 0; + + if (priv->child) { + + gdk_drawable_get_size (priv->child, &priv->child_width, + &priv->child_height); + priv->last_in = TRUE; + + g_object_add_weak_pointer ((GObject *) priv->child, + (gpointer) & priv->child); + + event = (GdkEventButton *) gdk_event_copy ((GdkEvent *) event); + event->x = x; + event->y = y; + priv->cx = x; + priv->cy = y; + + synth_crossing (priv->child, x, y, event->x_root, + event->y_root, event->time, TRUE); + + /* Send synthetic click (button press/release) event */ + ((GdkEventAny *) event)->window = g_object_ref (priv->child); + + gdk_event_put ((GdkEvent *) event); + gdk_event_free ((GdkEvent *) event); + } else + priv->child = NULL; + + return TRUE; +} + +static gboolean +hildon_pannable_area_check_scrollbars (HildonPannableArea * area) +{ + HildonPannableAreaPrivate *priv = area->priv; + gboolean prev_hscroll_visible, prev_vscroll_visible; + + prev_hscroll_visible = priv->hscroll_visible; + prev_vscroll_visible = priv->vscroll_visible; + + if (!gtk_bin_get_child (GTK_BIN (area))) { + priv->vscroll_visible = FALSE; + priv->hscroll_visible = FALSE; + } else { + switch (priv->hscrollbar_policy) { + case GTK_POLICY_ALWAYS: + priv->hscroll_visible = TRUE; + break; + case GTK_POLICY_NEVER: + priv->hscroll_visible = FALSE; + break; + default: + priv->hscroll_visible = (priv->hadjust->upper - priv->hadjust->lower > + priv->hadjust->page_size); + } + + switch (priv->vscrollbar_policy) { + case GTK_POLICY_ALWAYS: + priv->vscroll_visible = TRUE; + break; + case GTK_POLICY_NEVER: + priv->vscroll_visible = FALSE; + break; + default: + priv->vscroll_visible = (priv->vadjust->upper - priv->vadjust->lower > + priv->vadjust->page_size); + } + + /* Store the vscroll/hscroll areas for redrawing */ + if (priv->vscroll_visible) { + GtkAllocation *allocation = >K_WIDGET (area)->allocation; + priv->vscroll_rect.x = allocation->width - priv->indicator_width; + priv->vscroll_rect.y = 0; + priv->vscroll_rect.width = priv->indicator_width; + priv->vscroll_rect.height = allocation->height - + (priv->hscroll_visible ? priv->indicator_width : 0); + } + if (priv->hscroll_visible) { + GtkAllocation *allocation = >K_WIDGET (area)->allocation; + priv->hscroll_rect.y = allocation->height - priv->indicator_width; + priv->hscroll_rect.x = 0; + priv->hscroll_rect.height = priv->indicator_width; + priv->hscroll_rect.width = allocation->width - + (priv->vscroll_visible ? priv->indicator_width : 0); + } + } + + return ((priv->hscroll_visible != prev_hscroll_visible) || + (priv->vscroll_visible != prev_vscroll_visible)); +} + +static void +hildon_pannable_area_refresh (HildonPannableArea * area) +{ + if (GTK_WIDGET_DRAWABLE (area) && + hildon_pannable_area_check_scrollbars (area)) { + gtk_widget_queue_resize (GTK_WIDGET (area)); + } else { + hildon_pannable_area_redraw (area); + } +} + +/* Scroll by a particular amount (in pixels). Optionally, return if + * the scroll on a particular axis was successful. + */ +static void +hildon_pannable_axis_scroll (HildonPannableArea *area, + GtkAdjustment *adjust, + gdouble *vel, + gdouble inc, + gint *overshooting, + gint *overshot_dist, + gdouble *scroll_to, + gint overshoot_max, + gboolean *s) +{ + gdouble dist; + HildonPannableAreaPrivate *priv = area->priv; + + dist = gtk_adjustment_get_value (adjust) - inc; + + /* Overshooting + * We use overshot_dist to define the distance of the current overshoot, + * and overshooting to define the direction/whether or not we are overshot + */ + if (!(*overshooting)) { + + /* Initiation of the overshoot happens when the finger is released + * and the current position of the pannable contents are out of range + */ + if (dist < adjust->lower) { + if (s) *s = FALSE; + + dist = adjust->lower; + + if (overshoot_max!=0) { + *overshooting = 1; + *scroll_to = -1; + *overshot_dist = CLAMP (*overshot_dist + *vel, 0, overshoot_max); + *vel = MIN (priv->vmax_overshooting, *vel); + gtk_widget_queue_resize (GTK_WIDGET (area)); + } else { + *vel = 0.0; + } + } else if (dist > adjust->upper - adjust->page_size) { + if (s) *s = FALSE; + + dist = adjust->upper - adjust->page_size; + + if (overshoot_max!=0) { + *overshooting = 1; + *scroll_to = -1; + *overshot_dist = CLAMP (*overshot_dist + *vel, -overshoot_max, 0); + *vel = MAX (-priv->vmax_overshooting, *vel); + gtk_widget_queue_resize (GTK_WIDGET (area)); + } else { + *vel = 0.0; + } + } else { + if ((*scroll_to) != -1) { + if (((inc < 0)&&(*scroll_to <= dist))|| + ((inc > 0)&&(*scroll_to >= dist))) { + dist = *scroll_to; + *scroll_to = -1; + *vel = 0; + } + } + } + + gtk_adjustment_set_value (adjust, dist); + } else { + if (!priv->clicked) { + + /* When the overshoot has started we continue for + * PROP_BOUNCE_STEPS more steps into the overshoot before we + * reverse direction. The deceleration factor is calculated + * based on the percentage distance from the first item with + * each iteration, therefore always returning us to the + * top/bottom most element + */ + if (*overshot_dist > 0) { + + if ((*overshooting < priv->bounce_steps) && (*vel > 0)) { + (*overshooting)++; + *vel = (((gdouble)*overshot_dist)/overshoot_max) * (*vel); + } else if ((*overshooting >= priv->bounce_steps) && (*vel > 0)) { + *vel *= -1; + } else if ((*overshooting > 1) && (*vel < 0)) { + /* we add the MIN in order to avoid very small speeds */ + *vel = MIN ((((gdouble)*overshot_dist)*0.4) * -1, -2.0); + } + + *overshot_dist = CLAMP (*overshot_dist + *vel, 0, overshoot_max); + + gtk_widget_queue_resize (GTK_WIDGET (area)); + + } else if (*overshot_dist < 0) { + + if ((*overshooting < priv->bounce_steps) && (*vel < 0)) { + (*overshooting)++; + *vel = (((gdouble)*overshot_dist)/overshoot_max) * (*vel) * -1; + } else if ((*overshooting >= priv->bounce_steps) && (*vel < 0)) { + *vel *= -1; + } else if ((*overshooting > 1) && (*vel > 0)) { + /* we add the MAX in order to avoid very small speeds */ + *vel = MAX ((((gdouble)*overshot_dist)*0.4) * -1, 2.0); + } + + *overshot_dist = CLAMP (*overshot_dist + (*vel), -overshoot_max, 0); + + gtk_widget_queue_resize (GTK_WIDGET (area)); + + } else { + *overshooting = 0; + *vel = 0; + gtk_widget_queue_resize (GTK_WIDGET (area)); + } + } else { + + gint overshot_dist_old = *overshot_dist; + + if (*overshot_dist > 0) { + *overshot_dist = CLAMP ((*overshot_dist) + inc, 0, overshoot_max); + } else if (*overshot_dist < 0) { + *overshot_dist = CLAMP ((*overshot_dist) + inc, -1 * overshoot_max, 0); + } else { + *overshooting = 0; + gtk_adjustment_set_value (adjust, dist); + } + + if (*overshot_dist != overshot_dist_old) + gtk_widget_queue_resize (GTK_WIDGET (area)); + } + } +} + +static void +hildon_pannable_area_scroll (HildonPannableArea *area, + gdouble x, gdouble y) +{ + gboolean sx, sy; + HildonPannableAreaPrivate *priv = area->priv; + gboolean hscroll_visible, vscroll_visible; + + if (gtk_bin_get_child (GTK_BIN (area)) == NULL) + return; + + vscroll_visible = (priv->vadjust->upper - priv->vadjust->lower > + priv->vadjust->page_size); + hscroll_visible = (priv->hadjust->upper - priv->hadjust->lower > + priv->hadjust->page_size); + + sx = TRUE; + sy = TRUE; + + if (vscroll_visible) { + hildon_pannable_axis_scroll (area, priv->vadjust, &priv->vel_y, y, + &priv->overshooting_y, &priv->overshot_dist_y, + &priv->scroll_to_y, priv->vovershoot_max, &sy); + } else { + priv->vel_y = 0; + } + + if (hscroll_visible) { + hildon_pannable_axis_scroll (area, priv->hadjust, &priv->vel_x, x, + &priv->overshooting_x, &priv->overshot_dist_x, + &priv->scroll_to_x, priv->hovershoot_max, &sx); + } else { + priv->vel_x = 0; + } + + /* If the scroll on a particular axis wasn't succesful, reset the + * initial scroll position to the new mouse co-ordinate. This means + * when you get to the top of the page, dragging down works immediately. + */ + if (priv->mode == HILDON_PANNABLE_AREA_MODE_ACCEL) { + if (!sx) { + priv->x = priv->ex; + } + + if (!sy) { + priv->y = priv->ey; + } + } +} + +static gboolean +hildon_pannable_area_timeout (HildonPannableArea * area) +{ + HildonPannableAreaPrivate *priv = area->priv; + + if ((!priv->enabled) || (priv->mode == HILDON_PANNABLE_AREA_MODE_PUSH)) { + priv->idle_id = 0; + + return FALSE; + } + + if (!priv->clicked) { + /* Decelerate gradually when pointer is raised */ + if ((!priv->overshot_dist_y) && + (!priv->overshot_dist_x)) { + + /* in case we move to a specific point do not decelerate when arriving */ + if ((priv->scroll_to_x != -1)||(priv->scroll_to_y != -1)) { + + if (ABS (priv->vel_x) >= 1.5) { + priv->vel_x *= priv->decel; + } + + if (ABS (priv->vel_y) >= 1.5) { + priv->vel_y *= priv->decel; + } + + } else { + if ((!priv->low_friction_mode) || + ((priv->mov_mode&HILDON_MOVEMENT_MODE_HORIZ) && + (ABS (priv->vel_x) < 0.8*priv->vmax))) + priv->vel_x *= priv->decel; + + if ((!priv->low_friction_mode) || + ((priv->mov_mode&HILDON_MOVEMENT_MODE_VERT) && + (ABS (priv->vel_y) < 0.8*priv->vmax))) + priv->vel_y *= priv->decel; + + if ((ABS (priv->vel_x) < 1.0) && (ABS (priv->vel_y) < 1.0)) { + priv->vel_x = 0; + priv->vel_y = 0; + priv->idle_id = 0; + + return FALSE; + } + } + } + } else if (priv->mode == HILDON_PANNABLE_AREA_MODE_AUTO) { + priv->idle_id = 0; + + return FALSE; + } + + hildon_pannable_area_scroll (area, priv->vel_x, priv->vel_y); + + return TRUE; +} + +static void +hildon_pannable_area_calculate_velocity (gdouble *vel, + gdouble delta, + gdouble dist, + gdouble vmax, + gdouble drag_inertia, + gdouble force, + guint sps) +{ + gdouble rawvel; + + if (ABS (dist) >= RATIO_TOLERANCE) { + rawvel = (dist / ABS (delta)) * force; + *vel = *vel * (1 - drag_inertia) + + rawvel * drag_inertia; + *vel = *vel > 0 ? MIN (*vel, vmax) + : MAX (*vel, -1 * vmax); + } +} + +static gboolean +hildon_pannable_area_motion_event_scroll_timeout (HildonPannableArea *area) +{ + HildonPannableAreaPrivate *priv = area->priv; + + if ((priv->motion_x != 0)||(priv->motion_y != 0)) + hildon_pannable_area_scroll (area, priv->motion_x, priv->motion_y); + + priv->motion_event_scroll_timeout = 0; + + return FALSE; +} + +static void +hildon_pannable_area_motion_event_scroll (HildonPannableArea *area, + gdouble x, gdouble y) +{ + HildonPannableAreaPrivate *priv = area->priv; + + if (priv->motion_event_scroll_timeout) { + + priv->motion_x += x; + priv->motion_y += y; + + } else { + + /* we do not delay the first event but the next ones */ + hildon_pannable_area_scroll (area, x, y); + + priv->motion_x = 0; + priv->motion_y = 0; + + priv->motion_event_scroll_timeout = gdk_threads_add_timeout + ((gint) (1000.0 / (gdouble) MOTION_EVENTS_PER_SECOND), + (GSourceFunc) hildon_pannable_area_motion_event_scroll_timeout, area); + } +} + +static gboolean +hildon_pannable_area_motion_notify_cb (GtkWidget * widget, + GdkEventMotion * event) +{ + HildonPannableArea *area = HILDON_PANNABLE_AREA (widget); + HildonPannableAreaPrivate *priv = area->priv; + gdouble x, y; + gdouble delta; + + if (gtk_bin_get_child (GTK_BIN (widget)) == NULL) + return TRUE; + + if ((!priv->enabled) || (!priv->clicked) || + ((event->time == priv->last_time) && (priv->last_type == 2))) { + gdk_window_get_pointer (widget->window, NULL, NULL, 0); + return TRUE; + } + + if (priv->last_type == 1) { + priv->first_drag = TRUE; + } + + x = event->x - priv->x; + y = event->y - priv->y; + + if (priv->first_drag && (!priv->moved) && + ((ABS (x) > (priv->panning_threshold)) + || (ABS (y) > (priv->panning_threshold)))) { + priv->moved = TRUE; + x = 0; + y = 0; + + if (priv->first_drag) { + gboolean vscroll_visible; + gboolean hscroll_visible; + + if (ABS (priv->iy - event->y) >= + ABS (priv->ix - event->x)) { + + g_signal_emit (area, + pannable_area_signals[VERTICAL_MOVEMENT], + 0, (priv->iy > event->y) ? + HILDON_MOVEMENT_UP : + HILDON_MOVEMENT_DOWN, + (gdouble)priv->ix, (gdouble)priv->iy); + + vscroll_visible = (priv->vadjust->upper - priv->vadjust->lower > + priv->vadjust->page_size); + + if (!((vscroll_visible)&& + (priv->mov_mode&HILDON_MOVEMENT_MODE_VERT))) { + + hscroll_visible = (priv->hadjust->upper - priv->hadjust->lower > + priv->hadjust->page_size); + + /* even in case we do not have to move we check if this + could be a fake horizontal movement */ + if (!((hscroll_visible)&& + (priv->mov_mode&HILDON_MOVEMENT_MODE_HORIZ)) || + (ABS (priv->iy - event->y) - + ABS (priv->ix - event->x) >= priv->direction_error_margin)) + priv->moved = FALSE; + } + } else { + + g_signal_emit (area, + pannable_area_signals[HORIZONTAL_MOVEMENT], + 0, (priv->ix > event->x) ? + HILDON_MOVEMENT_LEFT : + HILDON_MOVEMENT_RIGHT, + (gdouble)priv->ix, (gdouble)priv->iy); + + hscroll_visible = (priv->hadjust->upper - priv->hadjust->lower > + priv->hadjust->page_size); + + if (!((hscroll_visible)&& + (priv->mov_mode&HILDON_MOVEMENT_MODE_HORIZ))) { + + vscroll_visible = (priv->vadjust->upper - priv->vadjust->lower > + priv->vadjust->page_size); + + /* even in case we do not have to move we check if this + could be a fake vertical movement */ + if (!((vscroll_visible) && + (priv->mov_mode&HILDON_MOVEMENT_MODE_VERT)) || + (ABS (priv->ix - event->x) - + ABS (priv->iy - event->y) >= priv->direction_error_margin)) + priv->moved = FALSE; + } + } + + if ((priv->moved)&&(priv->child)) { + gint pos_x, pos_y; + + pos_x = priv->cx + (event->x - priv->ix); + pos_y = priv->cy + (event->y - priv->iy); + + synth_crossing (priv->child, pos_x, pos_y, event->x_root, + event->y_root, event->time, FALSE); + } + } + + priv->first_drag = FALSE; + + if ((priv->mode != HILDON_PANNABLE_AREA_MODE_PUSH) && + (priv->mode != HILDON_PANNABLE_AREA_MODE_AUTO)) { + + if (!priv->idle_id) + priv->idle_id = gdk_threads_add_timeout ((gint) + (1000.0 / (gdouble) priv->sps), + (GSourceFunc) + hildon_pannable_area_timeout, area); + } + } + + if (priv->moved) { + switch (priv->mode) { + case HILDON_PANNABLE_AREA_MODE_PUSH: + /* Scroll by the amount of pixels the cursor has moved + * since the last motion event. + */ + hildon_pannable_area_motion_event_scroll (area, x, y); + priv->x = event->x; + priv->y = event->y; + break; + case HILDON_PANNABLE_AREA_MODE_ACCEL: + /* Set acceleration relative to the initial click */ + priv->ex = event->x; + priv->ey = event->y; + priv->vel_x = ((x > 0) ? 1 : -1) * + (((ABS (x) / + (gdouble) widget->allocation.width) * + (priv->vmax - priv->vmin)) + priv->vmin); + priv->vel_y = ((y > 0) ? 1 : -1) * + (((ABS (y) / + (gdouble) widget->allocation.height) * + (priv->vmax - priv->vmin)) + priv->vmin); + break; + case HILDON_PANNABLE_AREA_MODE_AUTO: + + delta = event->time - priv->last_time; + + if (priv->mov_mode&HILDON_MOVEMENT_MODE_VERT) { + gdouble dist = event->y - priv->y; + + hildon_pannable_area_calculate_velocity (&priv->vel_y, + delta, + dist, + priv->vmax, + priv->drag_inertia, + priv->force, + priv->sps); + } else { + y = 0; + priv->vel_y = 0; + } + + if (priv->mov_mode&HILDON_MOVEMENT_MODE_HORIZ) { + gdouble dist = event->x - priv->x; + + hildon_pannable_area_calculate_velocity (&priv->vel_x, + delta, + dist, + priv->vmax, + priv->drag_inertia, + priv->force, + priv->sps); + } else { + x = 0; + priv->vel_x = 0; + } + + hildon_pannable_area_motion_event_scroll (area, x, y); + + if (priv->mov_mode&HILDON_MOVEMENT_MODE_HORIZ) + priv->x = event->x; + if (priv->mov_mode&HILDON_MOVEMENT_MODE_VERT) + priv->y = event->y; + + break; + + default: + break; + } + } else if (priv->child) { + gboolean in; + gint pos_x, pos_y; + + pos_x = priv->cx + (event->x - priv->ix); + pos_y = priv->cy + (event->y - priv->iy); + + in = (((0 <= pos_x)&&(priv->child_width >= pos_x)) && + ((0 <= pos_y)&&(priv->child_height >= pos_y))); + + if (((!priv->last_in)&&in)||((priv->last_in)&&(!in))) { + + synth_crossing (priv->child, pos_x, pos_y, event->x_root, + event->y_root, event->time, in); + + priv->last_in = in; + } + } + + priv->last_time = event->time; + priv->last_type = 2; + + if (priv->child) { + /* Send motion notify to child */ + event = (GdkEventMotion *) gdk_event_copy ((GdkEvent *) event); + event->x = priv->cx + (event->x - priv->ix); + event->y = priv->cy + (event->y - priv->iy); + event->window = g_object_ref (priv->child); + gdk_event_put ((GdkEvent *) event); + gdk_event_free ((GdkEvent *) event); + } + + gdk_window_get_pointer (widget->window, NULL, NULL, 0); + + return TRUE; +} + +static gboolean +hildon_pannable_leave_notify_event (GtkWidget *widget, + GdkEventCrossing *event) +{ + HildonPannableArea *area = HILDON_PANNABLE_AREA (widget); + HildonPannableAreaPrivate *priv = area->priv; + + if ((priv->child)&&(priv->last_in)) { + priv->last_in = FALSE; + + synth_crossing (priv->child, 0, 0, event->x_root, + event->y_root, event->time, FALSE); + } + + return FALSE; +} + +static gboolean +hildon_pannable_area_button_release_cb (GtkWidget * widget, + GdkEventButton * event) +{ + HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (widget)->priv; + gint x, y; + GdkWindow *child; + + if (((event->time == priv->last_time) && (priv->last_type == 3)) + || (gtk_bin_get_child (GTK_BIN (widget)) == NULL) + || (!priv->clicked) || (!priv->enabled) || (event->button != 1)) + return TRUE; + + priv->scroll_indicator_event_interrupt = 0; + priv->scroll_delay_counter = priv->scrollbar_fade_delay; + + /* move all the way to the last position */ + if (priv->motion_event_scroll_timeout) { + g_source_remove (priv->motion_event_scroll_timeout); + hildon_pannable_area_motion_event_scroll_timeout (HILDON_PANNABLE_AREA (widget)); + priv->motion_x = 0; + priv->motion_y = 0; + } + + if (priv->last_type == 2) { + gdouble delta = event->time - priv->last_time; + + if (priv->mov_mode&HILDON_MOVEMENT_MODE_VERT) { + gdouble dist = event->y - priv->y; + + if (ABS (dist) >= 1.0) { + hildon_pannable_area_calculate_velocity (&priv->vel_y, + delta, + dist, + priv->vmax, + priv->drag_inertia, + priv->force, + priv->sps); + + priv->motion_y = dist; + hildon_pannable_area_motion_event_scroll_timeout (HILDON_PANNABLE_AREA (widget)); + } else + if (delta >= CURSOR_STOPPED_TIMEOUT) { + y = 0; + priv->vel_y = 0; + } + } + + if (priv->mov_mode&HILDON_MOVEMENT_MODE_HORIZ) { + gdouble dist = event->x - priv->x; + + if (ABS (dist) >= 1.0) { + hildon_pannable_area_calculate_velocity (&priv->vel_x, + delta, + dist, + priv->vmax, + priv->drag_inertia, + priv->force, + priv->sps); + priv->motion_x = dist; + hildon_pannable_area_motion_event_scroll_timeout (HILDON_PANNABLE_AREA (widget)); + } else + if (delta >= CURSOR_STOPPED_TIMEOUT) { + x = 0; + priv->vel_x = 0; + } + } + } + + if ((ABS (priv->vel_y) > 1.0)|| + (ABS (priv->vel_x) > 1.0)) { + priv->scroll_indicator_alpha = 1.0; + } + + hildon_pannable_area_launch_fade_timeout (HILDON_PANNABLE_AREA (widget), + priv->scroll_indicator_alpha); + + priv->clicked = FALSE; + + if (priv->mode == HILDON_PANNABLE_AREA_MODE_AUTO || + priv->mode == HILDON_PANNABLE_AREA_MODE_ACCEL) { + + /* If overshoot has been initiated with a finger down, on release set max speed */ + if (priv->overshot_dist_y != 0) { + priv->overshooting_y = priv->bounce_steps; /* Hack to stop a bounce in the finger down case */ + priv->vel_y = priv->vmax_overshooting; + } + + if (priv->overshot_dist_x != 0) { + priv->overshooting_x = priv->bounce_steps; /* Hack to stop a bounce in the finger down case */ + priv->vel_x = priv->vmax_overshooting; + } + + if ((ABS (priv->vel_y) >= priv->vmin) || + (ABS (priv->vel_x) >= priv->vmin)) { + + if (!priv->idle_id) + priv->idle_id = gdk_threads_add_timeout ((gint) (1000.0 / (gdouble) priv->sps), + (GSourceFunc) + hildon_pannable_area_timeout, widget); + } + } + + priv->last_time = event->time; + priv->last_type = 3; + + if (!priv->child) { + priv->moved = FALSE; + return TRUE; + } + + child = + hildon_pannable_area_get_topmost (gtk_bin_get_child (GTK_BIN (widget))->window, + event->x, event->y, &x, &y, GDK_BUTTON_RELEASE_MASK); + + event = (GdkEventButton *) gdk_event_copy ((GdkEvent *) event); + event->x = x; + event->y = y; + + /* Leave the widget if we've moved - This doesn't break selection, + * but stops buttons from being clicked. + */ + if ((child != priv->child) || (priv->moved)) { + /* Send synthetic leave event */ + synth_crossing (priv->child, x, y, event->x_root, + event->y_root, event->time, FALSE); + /* Send synthetic button release event */ + ((GdkEventAny *) event)->window = g_object_ref (priv->child); + gdk_event_put ((GdkEvent *) event); + } else { + /* Send synthetic button release event */ + ((GdkEventAny *) event)->window = g_object_ref (child); + gdk_event_put ((GdkEvent *) event); + /* Send synthetic leave event */ + synth_crossing (priv->child, x, y, event->x_root, + event->y_root, event->time, FALSE); + } + g_object_remove_weak_pointer ((GObject *) priv->child, + (gpointer) & priv->child); + + priv->moved = FALSE; + gdk_event_free ((GdkEvent *) event); + + return TRUE; +} + +/* utility event handler */ +static gboolean +hildon_pannable_area_scroll_cb (GtkWidget *widget, + GdkEventScroll *event) +{ + GtkAdjustment *adj = NULL; + HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (widget)->priv; + + if ((!priv->enabled) || + (gtk_bin_get_child (GTK_BIN (widget)) == NULL)) + return TRUE; + + priv->scroll_indicator_event_interrupt = 0; + priv->scroll_delay_counter = priv->scrollbar_fade_delay + 20; + + hildon_pannable_area_launch_fade_timeout (HILDON_PANNABLE_AREA (widget), 1.0); + + /* Stop inertial scrolling */ + if (priv->idle_id) { + priv->vel_x = 0.0; + priv->vel_y = 0.0; + priv->overshooting_x = 0; + priv->overshooting_y = 0; + + if ((priv->overshot_dist_x>0)||(priv->overshot_dist_y>0)) { + priv->overshot_dist_x = 0; + priv->overshot_dist_y = 0; + + gtk_widget_queue_resize (GTK_WIDGET (widget)); + } + + g_source_remove (priv->idle_id); + priv->idle_id = 0; + } + + if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_DOWN) + adj = priv->vadjust; + else + adj = priv->hadjust; + + if (adj) + { + gdouble delta, new_value; + + /* from gtkrange.c calculate delta*/ + delta = pow (adj->page_size, 2.0 / 3.0); + + if (event->direction == GDK_SCROLL_UP || + event->direction == GDK_SCROLL_LEFT) + delta = - delta; + + new_value = CLAMP (adj->value + delta, adj->lower, adj->upper - adj->page_size); + + gtk_adjustment_set_value (adj, new_value); + } + + return TRUE; +} + +static void +hildon_pannable_area_child_mapped (GtkWidget *widget, + GdkEvent *event, + gpointer user_data) +{ + HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (user_data)->priv; + + if (priv->event_window != NULL && priv->enabled) + gdk_window_raise (priv->event_window); +} + +static void +hildon_pannable_area_add (GtkContainer *container, GtkWidget *child) +{ + HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (container)->priv; + + g_return_if_fail (gtk_bin_get_child (GTK_BIN (container)) == NULL); + + gtk_widget_set_parent (child, GTK_WIDGET (container)); + GTK_BIN (container)->child = child; + + g_signal_connect_after (child, "map-event", + G_CALLBACK (hildon_pannable_area_child_mapped), + container); + + if (!gtk_widget_set_scroll_adjustments (child, priv->hadjust, priv->vadjust)) { + g_warning ("%s: cannot add non scrollable widget, " + "wrap it in a viewport", __FUNCTION__); + } +} + +static void +hildon_pannable_area_remove (GtkContainer *container, GtkWidget *child) +{ + g_return_if_fail (HILDON_IS_PANNABLE_AREA (container)); + g_return_if_fail (child != NULL); + g_return_if_fail (gtk_bin_get_child (GTK_BIN (container)) == child); + + gtk_widget_set_scroll_adjustments (child, NULL, NULL); + + g_signal_handlers_disconnect_by_func (child, + hildon_pannable_area_child_mapped, + container); + + /* chain parent class handler to remove child */ + GTK_CONTAINER_CLASS (hildon_pannable_area_parent_class)->remove (container, child); +} + +static void +hildon_pannable_calculate_vel_factor (HildonPannableArea * self) +{ + HildonPannableAreaPrivate *priv = self->priv; + gfloat fct = 0; + gfloat fct_i = 1; + gint i, n; + + n = ceil (priv->sps * priv->scroll_time); + + for (i = 0; i < n && fct_i >= RATIO_TOLERANCE; i++) { + fct_i *= priv->decel; + fct += fct_i; + } + + priv->vel_factor = fct; +} + +/** + * hildon_pannable_area_new: + * + * Create a new pannable area widget + * + * Returns: the newly created #HildonPannableArea + * + * Since: 2.2 + */ + +GtkWidget * +hildon_pannable_area_new (void) +{ + return g_object_new (HILDON_TYPE_PANNABLE_AREA, NULL); +} + +/** + * hildon_pannable_area_new_full: + * @mode: #HildonPannableAreaMode + * @enabled: Value for the enabled property + * @vel_min: Value for the velocity-min property + * @vel_max: Value for the velocity-max property + * @decel: Value for the deceleration property + * @sps: Value for the sps property + * + * Create a new #HildonPannableArea widget and set various properties + * + * returns: the newly create #HildonPannableArea + * + * Since: 2.2 + */ + +GtkWidget * +hildon_pannable_area_new_full (gint mode, gboolean enabled, + gdouble vel_min, gdouble vel_max, + gdouble decel, guint sps) +{ + return g_object_new (HILDON_TYPE_PANNABLE_AREA, + "mode", mode, + "enabled", enabled, + "velocity_min", vel_min, + "velocity_max", vel_max, + "deceleration", decel, "sps", sps, NULL); +} + +/** + * hildon_pannable_area_add_with_viewport: + * @area: A #HildonPannableArea + * @child: Child widget to add to the viewport + * + * Convenience function used to add a child to a #GtkViewport, and add the + * viewport to the scrolled window. + * + * Since: 2.2 + */ + +void +hildon_pannable_area_add_with_viewport (HildonPannableArea * area, + GtkWidget * child) +{ + GtkBin *bin; + GtkWidget *viewport; + + g_return_if_fail (HILDON_IS_PANNABLE_AREA (area)); + g_return_if_fail (GTK_IS_WIDGET (child)); + g_return_if_fail (child->parent == NULL); + + bin = GTK_BIN (area); + + if (bin->child != NULL) + { + g_return_if_fail (GTK_IS_VIEWPORT (bin->child)); + g_return_if_fail (GTK_BIN (bin->child)->child == NULL); + + viewport = bin->child; + } + else + { + HildonPannableAreaPrivate *priv = area->priv; + + viewport = gtk_viewport_new (priv->hadjust, + priv->vadjust); + gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport), GTK_SHADOW_NONE); + gtk_container_add (GTK_CONTAINER (area), viewport); + } + + gtk_widget_show (viewport); + gtk_container_add (GTK_CONTAINER (viewport), child); +} + +/** + * hildon_pannable_area_scroll_to: + * @area: A #HildonPannableArea. + * @x: The x coordinate of the destination point or -1 to ignore this axis. + * @y: The y coordinate of the destination point or -1 to ignore this axis. + * + * Smoothly scrolls @area to ensure that (@x, @y) is a visible point + * on the widget. To move in only one coordinate, you must set the other one + * to -1. Notice that, in %HILDON_PANNABLE_AREA_MODE_PUSH mode, this function + * works just like hildon_pannable_area_jump_to(). + * + * This function is useful if you need to present the user with a particular + * element inside a scrollable widget, like #GtkTreeView. For instance, + * the following example shows how to scroll inside a #GtkTreeView to + * make visible an item, indicated by the #GtkTreeIter @iter. + * + * + * + * GtkTreePath *path; + * GdkRectangle *rect; + * + * path = gtk_tree_model_get_path (model, &iter); + * gtk_tree_view_get_background_area (GTK_TREE_VIEW (treeview), + * path, NULL, &rect); + * gtk_tree_view_convert_bin_window_to_tree_coords (GTK_TREE_VIEW (treeview), + * 0, rect.y, NULL, &y); + * hildon_pannable_area_scroll_to (panarea, -1, y); + * gtk_tree_path_free (path); + * + * + * + * If you want to present a child widget in simpler scenarios, + * use hildon_pannable_area_scroll_to_child() instead. + * + * There is a precondition to this function: the widget must be + * already realized. Check the hildon_pannable_area_jump_to_child() for + * more tips regarding how to call this function during + * initialization. + * + * Since: 2.2 + **/ +void +hildon_pannable_area_scroll_to (HildonPannableArea *area, + const gint x, const gint y) +{ + HildonPannableAreaPrivate *priv; + gint width, height; + gint dist_x, dist_y; + gboolean hscroll_visible, vscroll_visible; + + g_return_if_fail (GTK_WIDGET_REALIZED (area)); + g_return_if_fail (HILDON_IS_PANNABLE_AREA (area)); + + priv = area->priv; + + vscroll_visible = (priv->vadjust->upper - priv->vadjust->lower > + priv->vadjust->page_size); + hscroll_visible = (priv->hadjust->upper - priv->hadjust->lower > + priv->hadjust->page_size); + + if (((!vscroll_visible)&&(!hscroll_visible)) || + (x == -1 && y == -1)) { + return; + } + + if (priv->mode == HILDON_PANNABLE_AREA_MODE_PUSH) + hildon_pannable_area_jump_to (area, x, y); + + width = priv->hadjust->upper - priv->hadjust->lower; + height = priv->vadjust->upper - priv->vadjust->lower; + + g_return_if_fail (x < width || y < height); + + if ((x > -1)&&(hscroll_visible)) { + priv->scroll_to_x = x - priv->hadjust->page_size/2; + dist_x = priv->scroll_to_x - priv->hadjust->value; + if (dist_x == 0) { + priv->scroll_to_x = -1; + } else { + priv->vel_x = - dist_x/priv->vel_factor; + } + } else { + priv->scroll_to_x = -1; + } + + if ((y > -1)&&(vscroll_visible)) { + priv->scroll_to_y = y - priv->vadjust->page_size/2; + dist_y = priv->scroll_to_y - priv->vadjust->value; + if (dist_y == 0) { + priv->scroll_to_y = -1; + } else { + priv->vel_y = - dist_y/priv->vel_factor; + } + } else { + priv->scroll_to_y = y; + } + + if ((priv->scroll_to_y == -1) && (priv->scroll_to_y == -1)) { + return; + } + + hildon_pannable_area_launch_fade_timeout (area, 1.0); + + if (!priv->idle_id) + priv->idle_id = gdk_threads_add_timeout ((gint) (1000.0 / (gdouble) priv->sps), + (GSourceFunc) + hildon_pannable_area_timeout, area); +} + +/** + * hildon_pannable_area_jump_to: + * @area: A #HildonPannableArea. + * @x: The x coordinate of the destination point or -1 to ignore this axis. + * @y: The y coordinate of the destination point or -1 to ignore this axis. + * + * Jumps the position of @area to ensure that (@x, @y) is a visible + * point in the widget. In order to move in only one coordinate, you + * must set the other one to -1. See hildon_pannable_area_scroll_to() + * function for an example of how to calculate the position of + * children in scrollable widgets like #GtkTreeview. + * + * There is a precondition to this function: the widget must be + * already realized. Check the hildon_pannable_area_jump_to_child() for + * more tips regarding how to call this function during + * initialization. + * + * Since: 2.2 + **/ +void +hildon_pannable_area_jump_to (HildonPannableArea *area, + const gint x, const gint y) +{ + HildonPannableAreaPrivate *priv; + gint width, height; + + g_return_if_fail (HILDON_IS_PANNABLE_AREA (area)); + g_return_if_fail (GTK_WIDGET_REALIZED (area)); + g_return_if_fail (x >= -1 && y >= -1); + + if (x == -1 && y == -1) { + return; + } + + priv = area->priv; + + width = priv->hadjust->upper - priv->hadjust->lower; + height = priv->vadjust->upper - priv->vadjust->lower; + + g_return_if_fail (x < width || y < height); + + if (x != -1) { + gdouble jump_to = x - priv->hadjust->page_size/2; + + if (jump_to > priv->hadjust->upper - priv->hadjust->page_size) { + jump_to = priv->hadjust->upper - priv->hadjust->page_size; + } + + gtk_adjustment_set_value (priv->hadjust, jump_to); + } + + if (y != -1) { + gdouble jump_to = y - priv->vadjust->page_size/2; + + if (jump_to > priv->vadjust->upper - priv->vadjust->page_size) { + jump_to = priv->vadjust->upper - priv->vadjust->page_size; + } + + gtk_adjustment_set_value (priv->vadjust, jump_to); + } + + priv->scroll_indicator_alpha = 1.0; + + if (priv->scroll_indicator_timeout) { + g_source_remove (priv->scroll_indicator_timeout); + priv->scroll_indicator_timeout = 0; + } + + if (priv->idle_id) { + priv->vel_x = 0.0; + priv->vel_y = 0.0; + priv->overshooting_x = 0; + priv->overshooting_y = 0; + + if ((priv->overshot_dist_x>0)||(priv->overshot_dist_y>0)) { + priv->overshot_dist_x = 0; + priv->overshot_dist_y = 0; + + gtk_widget_queue_resize (GTK_WIDGET (area)); + } + + g_source_remove (priv->idle_id); + priv->idle_id = 0; + } +} + +/** + * hildon_pannable_area_scroll_to_child: + * @area: A #HildonPannableArea. + * @child: A #GtkWidget, descendant of @area. + * + * Smoothly scrolls until @child is visible inside @area. @child must + * be a descendant of @area. If you need to scroll inside a scrollable + * widget, e.g., #GtkTreeview, see hildon_pannable_area_scroll_to(). + * + * There is a precondition to this function: the widget must be + * already realized. Check the hildon_pannable_area_jump_to_child() for + * more tips regarding how to call this function during + * initialization. + * + * Since: 2.2 + **/ +void +hildon_pannable_area_scroll_to_child (HildonPannableArea *area, GtkWidget *child) +{ + GtkWidget *bin_child; + gint x, y; + + g_return_if_fail (GTK_WIDGET_REALIZED (area)); + g_return_if_fail (HILDON_IS_PANNABLE_AREA (area)); + g_return_if_fail (GTK_IS_WIDGET (child)); + g_return_if_fail (gtk_widget_is_ancestor (child, GTK_WIDGET (area))); + + if (GTK_BIN (area)->child == NULL) + return; + + /* We need to get to check the child of the inside the area */ + bin_child = GTK_BIN (area)->child; + + /* we check if we added a viewport */ + if (GTK_IS_VIEWPORT (bin_child)) { + bin_child = GTK_BIN (bin_child)->child; + } + + if (gtk_widget_translate_coordinates (child, bin_child, 0, 0, &x, &y)) + hildon_pannable_area_scroll_to (area, x, y); +} + +/** + * hildon_pannable_area_jump_to_child: + * @area: A #HildonPannableArea. + * @child: A #GtkWidget, descendant of @area. + * + * Jumps to make sure @child is visible inside @area. @child must + * be a descendant of @area. If you want to move inside a scrollable + * widget, like, #GtkTreeview, see hildon_pannable_area_scroll_to(). + * + * There is a precondition to this function: the widget must be + * already realized. You can control if the widget is ready with the + * GTK_WIDGET_REALIZED macro. If you want to call this function during + * the initialization process of the widget do it inside a callback to + * the ::realize signal, using g_signal_connect_after() function. + * + * Since: 2.2 + **/ +void +hildon_pannable_area_jump_to_child (HildonPannableArea *area, GtkWidget *child) +{ + GtkWidget *bin_child; + gint x, y; + + g_return_if_fail (GTK_WIDGET_REALIZED (area)); + g_return_if_fail (HILDON_IS_PANNABLE_AREA (area)); + g_return_if_fail (GTK_IS_WIDGET (child)); + g_return_if_fail (gtk_widget_is_ancestor (child, GTK_WIDGET (area))); + + if (gtk_bin_get_child (GTK_BIN (area)) == NULL) + return; + + /* We need to get to check the child of the inside the area */ + bin_child = gtk_bin_get_child (GTK_BIN (area)); + + /* we check if we added a viewport */ + if (GTK_IS_VIEWPORT (bin_child)) { + bin_child = gtk_bin_get_child (GTK_BIN (bin_child)); + } + + if (gtk_widget_translate_coordinates (child, bin_child, 0, 0, &x, &y)) + hildon_pannable_area_jump_to (area, x, y); +} + +/** + * hildon_pannable_get_child_widget_at: + * @area: A #HildonPannableArea. + * @x: horizontal coordinate of the point + * @y: vertical coordinate of the point + * + * Get the widget at the point (x, y) inside the pannable area. In + * case no widget found it returns NULL. + * + * returns: the #GtkWidget if we find a widget, NULL in any other case + * + * Since: 2.2 + **/ +GtkWidget* +hildon_pannable_get_child_widget_at (HildonPannableArea *area, + gdouble x, gdouble y) +{ + GdkWindow *window = NULL; + GtkWidget *child_widget = NULL; + + window = hildon_pannable_area_get_topmost + (gtk_bin_get_child (GTK_BIN (area))->window, + x, y, NULL, NULL, GDK_ALL_EVENTS_MASK); + + gdk_window_get_user_data (window, (gpointer) &child_widget); + + return child_widget; +} + + +/** + * hildon_pannable_area_get_hadjustment: + * @area: A #HildonPannableArea. + * + * Returns the horizontal adjustment. This adjustment is the internal + * widget adjustment used to control the animations. Do not modify it + * directly to change the position of the pannable, to do that use the + * pannable API. If you modify the object directly it could cause + * artifacts in the animations. + * + * returns: The horizontal #GtkAdjustment + * + * Since: 2.2 + **/ +GtkAdjustment* +hildon_pannable_area_get_hadjustment (HildonPannableArea *area) +{ + + g_return_val_if_fail (HILDON_IS_PANNABLE_AREA (area), NULL); + + return area->priv->hadjust; +} + +/** + * hildon_pannable_area_get_vadjustment: + * @area: A #HildonPannableArea. + * + * Returns the vertical adjustment. This adjustment is the internal + * widget adjustment used to control the animations. Do not modify it + * directly to change the position of the pannable, to do that use the + * pannable API. If you modify the object directly it could cause + * artifacts in the animations. + * + * returns: The vertical #GtkAdjustment + * + * Since: 2.2 + **/ +GtkAdjustment* +hildon_pannable_area_get_vadjustment (HildonPannableArea *area) +{ + g_return_val_if_fail (HILDON_IS_PANNABLE_AREA (area), NULL); + + return area->priv->vadjust; +} + + +/** + * hildon_pannable_area_get_size_request_policy: + * @area: A #HildonPannableArea. + * + * This function returns the current size request policy of the + * widget. That policy controls the way the size_request is done in + * the pannable area. Check + * hildon_pannable_area_set_size_request_policy() for a more detailed + * explanation. + * + * returns: the policy is currently being used in the widget + * #HildonSizeRequestPolicy. + * + * Since: 2.2 + **/ +HildonSizeRequestPolicy +hildon_pannable_area_get_size_request_policy (HildonPannableArea *area) +{ + HildonPannableAreaPrivate *priv; + + g_return_val_if_fail (HILDON_IS_PANNABLE_AREA (area), FALSE); + + priv = area->priv; + + return priv->size_request_policy; +} + +/** + * hildon_pannable_area_set_size_request_policy: + * @area: A #HildonPannableArea. + * @size_request_policy: One of the allowed #HildonSizeRequestPolicy + * + * This function sets the pannable area size request policy. That + * policy controls the way the size_request is done in the pannable + * area. Pannable can use the size request of its children + * (#HILDON_SIZE_REQUEST_CHILDREN) or the minimum size required for + * the area itself (#HILDON_SIZE_REQUEST_MINIMUM), the latter is the + * default. Recall this size depends on the scrolling policy you are + * requesting to the pannable area, if you set #GTK_POLICY_NEVER this + * parameter will not have any effect with + * #HILDON_SIZE_REQUEST_MINIMUM set. + * + * Since: 2.2 + * + * Deprecated: This method and the policy request is deprecated, DO + * NOT use it in future code, the only policy properly supported in + * gtk+ nowadays is the minimum size. Use #gtk_window_set_default_size + * or #gtk_window_set_geometry_hints with the proper size in your case + * to define the height of your dialogs. + **/ +void +hildon_pannable_area_set_size_request_policy (HildonPannableArea *area, + HildonSizeRequestPolicy size_request_policy) +{ + HildonPannableAreaPrivate *priv; + + g_return_if_fail (HILDON_IS_PANNABLE_AREA (area)); + + priv = area->priv; + + if (priv->size_request_policy == size_request_policy) + return; + + priv->size_request_policy = size_request_policy; + + gtk_widget_queue_resize (GTK_WIDGET (area)); + + g_object_notify (G_OBJECT (area), "size-request-policy"); +} + diff --git a/hildon/hildon-pannable-area.h b/hildon/hildon-pannable-area.h new file mode 100644 index 0000000..e1c59a7 --- /dev/null +++ b/hildon/hildon-pannable-area.h @@ -0,0 +1,177 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * This widget is based on MokoFingerScroll from libmokoui + * OpenMoko Application Framework UI Library + * Authored by Chris Lord + * Copyright (C) 2006-2007 OpenMoko Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +#ifndef _HILDON_PANNABLE_AREA +#define _HILDON_PANNABLE_AREA + +#include + +G_BEGIN_DECLS + +#define HILDON_TYPE_PANNABLE_AREA \ + hildon_pannable_area_get_type() + +#define HILDON_PANNABLE_AREA(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + HILDON_TYPE_PANNABLE_AREA, HildonPannableArea)) + +#define HILDON_PANNABLE_AREA_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + HILDON_TYPE_PANNABLE_AREA, HildonPannableAreaClass)) + +#define HILDON_IS_PANNABLE_AREA(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_PANNABLE_AREA)) + +#define HILDON_IS_PANNABLE_AREA_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_PANNABLE_AREA)) + +#define HILDON_PANNABLE_AREA_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + HILDON_TYPE_PANNABLE_AREA, HildonPannableAreaClass)) + +/** + * HildonPannableAreaMode: + * @HILDON_PANNABLE_AREA_MODE_PUSH: Areaing follows pointer + * @HILDON_PANNABLE_AREA_MODE_ACCEL: Areaing uses physics to "spin" the widget + * @HILDON_PANNABLE_AREA_MODE_AUTO: Automatically chooses between push and accel + * modes, depending on input. + * + * Used to change the behaviour of the pannable areaing + */ +typedef enum { + HILDON_PANNABLE_AREA_MODE_PUSH, + HILDON_PANNABLE_AREA_MODE_ACCEL, + HILDON_PANNABLE_AREA_MODE_AUTO +} HildonPannableAreaMode; + +/** + * HildonMovementMode: + * @HILDON_MOVEMENT_MODE_HORIZ: + * @HILDON_MOVEMENT_MODE_VERT: + * @HILDON_MOVEMENT_MODE_BOTH: + * + * Used to control the movement of the pannable, we can allow or + * disallow horizontal or vertical movement. This way the applications + * can control the movement using scroll_to and jump_to functions + */ +typedef enum { + HILDON_MOVEMENT_MODE_HORIZ = 1 << 1, + HILDON_MOVEMENT_MODE_VERT = 1 << 2, + HILDON_MOVEMENT_MODE_BOTH = 0x000006 +} HildonMovementMode; + +/** + * HildonMovementDirection: + * @HILDON_MOVEMENT_UP: + * @HILDON_MOVEMENT_DOWN: + * @HILDON_MOVEMENT_LEFT: + * @HILDON_MOVEMENT_RIGHT: + * + * Used to point out the direction of the movement + */ +typedef enum { + HILDON_MOVEMENT_UP, + HILDON_MOVEMENT_DOWN, + HILDON_MOVEMENT_LEFT, + HILDON_MOVEMENT_RIGHT +} HildonMovementDirection; + +/** + * HildonSizeRequestPolicy: + * @HILDON_SIZE_REQUEST_MINIMUM: The minimum size the widget could use + * to paint itself + * @HILDON_SIZE_REQUEST_CHILDREN: The minimum size of the children of + * the widget + * + * Used to control the size request policy of the widget + * + * Deprecated: This define and the policy request is deprecated, DO + * NOT use it in future code. Check + * #hildon_pannable_area_set_size_request_policy documentation for + * more information. + */ +#ifndef HILDON_DISABLE_DEPRECATED +typedef enum { + HILDON_SIZE_REQUEST_MINIMUM, + HILDON_SIZE_REQUEST_CHILDREN +} HildonSizeRequestPolicy; +#endif + +/** + * HildonPannableArea: + * + * HildonPannableArea has no publicly accessible fields + */ +typedef struct _HildonPannableArea HildonPannableArea; +typedef struct _HildonPannableAreaClass HildonPannableAreaClass; +typedef struct _HildonPannableAreaPrivate HildonPannableAreaPrivate; + +struct _HildonPannableArea +{ + GtkBin parent; + + /* private */ + HildonPannableAreaPrivate *priv; +}; + +struct _HildonPannableAreaClass +{ + GtkBinClass parent_class; + + void (* horizontal_movement) (HildonPannableArea *area, + HildonMovementDirection direction, + gdouble x, gdouble y); + void (* vertical_movement) (HildonPannableArea *area, + HildonMovementDirection direction, + gdouble x, gdouble y); +}; + +GType hildon_pannable_area_get_type (void); + +GtkWidget* hildon_pannable_area_new (void); +GtkWidget* hildon_pannable_area_new_full (gint mode, gboolean enabled, + gdouble vel_min, gdouble vel_max, + gdouble decel, guint sps); +void hildon_pannable_area_add_with_viewport (HildonPannableArea *area, + GtkWidget *child); +void hildon_pannable_area_scroll_to (HildonPannableArea *area, + const gint x, const gint y); +void hildon_pannable_area_jump_to (HildonPannableArea *area, + const gint x, const gint y); +void hildon_pannable_area_scroll_to_child (HildonPannableArea *area, + GtkWidget *child); +void hildon_pannable_area_jump_to_child (HildonPannableArea *area, + GtkWidget *child); +GtkWidget* hildon_pannable_get_child_widget_at (HildonPannableArea *area, + gdouble x, gdouble y); +#ifndef HILDON_DISABLE_DEPRECATED +HildonSizeRequestPolicy hildon_pannable_area_get_size_request_policy (HildonPannableArea *area); +void hildon_pannable_area_set_size_request_policy (HildonPannableArea *area, + HildonSizeRequestPolicy size_request_policy); +#endif +GtkAdjustment* hildon_pannable_area_get_hadjustment (HildonPannableArea *area); +GtkAdjustment* hildon_pannable_area_get_vadjustment (HildonPannableArea *area); + +G_END_DECLS + +#endif /* _HILDON_PANNABLE_AREA */ diff --git a/hildon/hildon-picker-button-private.h b/hildon/hildon-picker-button-private.h new file mode 100644 index 0000000..6760288 --- /dev/null +++ b/hildon/hildon-picker-button-private.h @@ -0,0 +1,30 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +#ifndef __HILDON_PICKER_BUTTON_PRIVATE__ +#define __HILDON_PICKER_BUTTON_PRIVATE__ + +#include "hildon-picker-button.h" + +G_BEGIN_DECLS + +G_GNUC_INTERNAL void +hildon_picker_button_disable_value_changed (HildonPickerButton *button, + gboolean disable); + +G_END_DECLS + +#endif /* __HILDON_PICKER_BUTTON_PRIVATE__ */ diff --git a/hildon/hildon-picker-button.c b/hildon/hildon-picker-button.c new file mode 100644 index 0000000..dd5d300 --- /dev/null +++ b/hildon/hildon-picker-button.c @@ -0,0 +1,614 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +/** + * SECTION:hildon-picker-button + * @short_description: A button that launches a #HildonPickerDialog and displays the + * selected item + * @see_also: #HildonTouchSelector, #HildonPickerDialog + * + * #HildonPickerButton is a widget that lets the user select a particular item from + * a list. Visually, it's a button with title and value labels that brings up a + * #HildonPickerDialog. The user can then use this dialog to choose an item, which + * will be displayed in the value label of the button. + * + * You should create your own #HildonTouchSelector at convenience and set it + * to the #HildonPickerButton with hildon_picker_button_set_selector(). For + * the common use cases of buttons to select date and time, you can use #HildonDateButton + * and #HildonTimeButton. + * + * + * + * GtkWidget * + * create_selector (void) + * { + * GtkWidget *selector; + * + * selector = hildon_touch_selector_new_text (); + * + * hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), "America"); + * hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), "Europe"); + * hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), "Asia"); + * hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), "Africa"); + * hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), "Australia"); + * + * hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, 2); + * + * return selector; + * } + * + * GtkWidget * + * create_button (HildonTouchSelector *selector) + * { + * GtkWidget *button; + * + * button = hildon_picker_button_new (HILDON_SIZE_AUTO, HILDON_BUTTON_ARRANGEMENT_VERTICAL); + * hildon_button_set_title (HILDON_BUTTON (button), "Continent"); + * + * hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (button), + * HILDON_TOUCH_SELECTOR (selector)); + * + * return button; + * } + * + * + */ + +#include "hildon-picker-button.h" +#include "hildon-picker-button-private.h" +#include "hildon-picker-dialog.h" + +G_DEFINE_TYPE (HildonPickerButton, hildon_picker_button, HILDON_TYPE_BUTTON) + +#define GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), HILDON_TYPE_PICKER_BUTTON, HildonPickerButtonPrivate)) + +typedef struct _HildonPickerButtonPrivate HildonPickerButtonPrivate; + +struct _HildonPickerButtonPrivate +{ + GtkWidget *selector; + GtkWidget *dialog; + gchar *done_button_text; + guint disable_value_changed : 1; +}; + +/* Signals */ +enum +{ + VALUE_CHANGED, + LAST_SIGNAL +}; + +enum +{ + PROP_SELECTOR = 1, + PROP_DONE_BUTTON_TEXT +}; + +static guint picker_button_signals[LAST_SIGNAL] = { 0 }; + +static gboolean +_current_selector_empty (HildonPickerButton *button); + +static void +hildon_picker_button_selector_selection_changed (HildonTouchSelector * selector, + gint column, + gpointer user_data); + +static void +hildon_picker_button_selector_columns_changed (HildonTouchSelector * selector, + gpointer user_data); + + +static void +hildon_picker_button_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + switch (property_id) { + case PROP_SELECTOR: + g_value_set_object (value, + hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (object))); + break; + case PROP_DONE_BUTTON_TEXT: + g_value_set_string (value, + hildon_picker_button_get_done_button_text (HILDON_PICKER_BUTTON (object))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +hildon_picker_button_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + switch (property_id) { + case PROP_SELECTOR: + hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (object), + g_value_get_object (value)); + break; + case PROP_DONE_BUTTON_TEXT: + hildon_picker_button_set_done_button_text (HILDON_PICKER_BUTTON (object), + g_value_get_string (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +hildon_picker_button_finalize (GObject * object) +{ + HildonPickerButtonPrivate *priv; + + priv = GET_PRIVATE (object); + + if (priv->selector) { + g_signal_handlers_disconnect_by_func (priv->selector, + hildon_picker_button_selector_selection_changed, + object); + g_signal_handlers_disconnect_by_func (priv->selector, + hildon_picker_button_selector_columns_changed, + object); + g_object_unref (priv->selector); + priv->selector = NULL; + } + if (priv->dialog) { + gtk_widget_destroy (priv->dialog); + priv->dialog = NULL; + } + + if (priv->done_button_text) { + g_free (priv->done_button_text); + priv->done_button_text = NULL; + } + + G_OBJECT_CLASS (hildon_picker_button_parent_class)->finalize (object); +} + +/** + * hildon_picker_button_value_changed: + * @button: a #HildonPickerButton + * + * Emits a "#HildonPickerButton::value-changed" signal to the given + * #HildonPickerButton + * + * Since: 2.2 + **/ +void +hildon_picker_button_value_changed (HildonPickerButton *button) +{ + HildonPickerButtonPrivate *priv; + g_return_if_fail (HILDON_IS_PICKER_BUTTON (button)); + priv = GET_PRIVATE (button); + + if (!priv->disable_value_changed) + g_signal_emit (button, picker_button_signals[VALUE_CHANGED], 0); +} + +G_GNUC_INTERNAL void +hildon_picker_button_disable_value_changed (HildonPickerButton *button, + gboolean disable) +{ + HildonPickerButtonPrivate *priv; + g_return_if_fail (HILDON_IS_PICKER_BUTTON (button)); + priv = GET_PRIVATE (button); + + priv->disable_value_changed = disable; +} + +static void +_selection_changed (HildonPickerButton *button) +{ + HildonPickerButtonPrivate *priv = GET_PRIVATE (button); + + if (!GTK_IS_WINDOW (priv->dialog) || + !GTK_WIDGET_VISIBLE (GTK_WINDOW (priv->dialog))) { + gchar *value = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (priv->selector)); + if (value) { + hildon_button_set_value (HILDON_BUTTON (button), value); + g_free (value); + hildon_picker_button_value_changed (button); + } + } +} + +static void +hildon_picker_button_on_dialog_response (GtkDialog *dialog, + gint response, + gpointer user_data) +{ + HildonPickerButton *button; + HildonPickerButtonPrivate *priv; + gchar *value; + + button = HILDON_PICKER_BUTTON (user_data); + priv = GET_PRIVATE (button); + + if (response == GTK_RESPONSE_OK) { + value = hildon_touch_selector_get_current_text + (HILDON_TOUCH_SELECTOR (priv->selector)); + hildon_button_set_value (HILDON_BUTTON (button), value); + g_free (value); + hildon_picker_button_value_changed (button); + } + + gtk_widget_hide (GTK_WIDGET (dialog)); +} + +static void +hildon_picker_button_clicked (GtkButton * button) +{ + GtkWidget *parent; + HildonPickerButtonPrivate *priv; + + priv = GET_PRIVATE (HILDON_PICKER_BUTTON (button)); + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (priv->selector)); + + /* Create the dialog if it doesn't exist already. */ + if (!priv->dialog) { + parent = gtk_widget_get_toplevel (GTK_WIDGET (button)); + if (GTK_WIDGET_TOPLEVEL (parent)) { + priv->dialog = hildon_picker_dialog_new (GTK_WINDOW (parent)); + } else { + priv->dialog = hildon_picker_dialog_new (NULL); + } + + hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (priv->dialog), + HILDON_TOUCH_SELECTOR (priv->selector)); + if (priv->done_button_text) { + hildon_picker_dialog_set_done_label (HILDON_PICKER_DIALOG (priv->dialog), + priv->done_button_text); + } + + gtk_window_set_modal (GTK_WINDOW (priv->dialog), + gtk_window_get_modal (GTK_WINDOW (parent))); + gtk_window_set_title (GTK_WINDOW (priv->dialog), + hildon_button_get_title (HILDON_BUTTON (button))); + g_signal_connect (priv->dialog, "response", + G_CALLBACK (hildon_picker_button_on_dialog_response), + button); + g_signal_connect (priv->dialog, "delete-event", + G_CALLBACK (gtk_widget_hide_on_delete), + NULL); + } + + if (_current_selector_empty (HILDON_PICKER_BUTTON (button))) { + g_warning ("There are no elements in the selector. Nothing to show."); + } { + gtk_window_present (GTK_WINDOW (priv->dialog)); + } +} + +static void +hildon_picker_button_selector_selection_changed (HildonTouchSelector * selector, + gint column, + gpointer user_data) + +{ + _selection_changed (HILDON_PICKER_BUTTON (user_data)); +} + +static void +hildon_picker_button_selector_columns_changed (HildonTouchSelector * selector, + gpointer user_data) + +{ + _selection_changed (HILDON_PICKER_BUTTON (user_data)); +} + +static void +hildon_picker_button_class_init (HildonPickerButtonClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass); + + g_type_class_add_private (klass, sizeof (HildonPickerButtonPrivate)); + + object_class->get_property = hildon_picker_button_get_property; + object_class->set_property = hildon_picker_button_set_property; + object_class->finalize = hildon_picker_button_finalize; + + button_class->clicked = hildon_picker_button_clicked; + + g_object_class_install_property (object_class, + PROP_SELECTOR, + g_param_spec_object ("touch-selector", + "HildonTouchSelector widget", + "HildonTouchSelector widget to be launched on button clicked", + HILDON_TYPE_TOUCH_SELECTOR, + G_PARAM_READWRITE)); + g_object_class_install_property (object_class, + PROP_DONE_BUTTON_TEXT, + g_param_spec_string ("done-button-text", + "HildonPickerDialog \"done\" button text", + "The text for the \"done\" button in the dialog launched", + NULL, + G_PARAM_READWRITE)); + + /** + * HildonPickerButton::value-changed: + * @widget: the widget that received the signal + * + * The ::value-changed signal is emitted each time the user chooses a different + * item from the #HildonTouchSelector related, and the value label gets updated. + * + * Since: 2.2 + */ + picker_button_signals[VALUE_CHANGED] = + g_signal_new ("value-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL); +} + +static void +hildon_picker_button_init (HildonPickerButton * self) +{ + HildonPickerButtonPrivate *priv; + + priv = GET_PRIVATE (self); + + priv->dialog = NULL; + priv->selector = NULL; + priv->done_button_text = NULL; + priv->disable_value_changed = FALSE; + + hildon_button_set_style (HILDON_BUTTON (self), + HILDON_BUTTON_STYLE_PICKER); +} + +static gboolean +_current_selector_empty (HildonPickerButton *button) +{ + HildonPickerButtonPrivate *priv; + HildonTouchSelector *selector = NULL; + GtkTreeModel *model = NULL; + GtkTreeIter iter; + gint i = 0; + + priv = GET_PRIVATE (button); + selector = HILDON_TOUCH_SELECTOR (priv->selector); + + g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), TRUE); + + if (hildon_touch_selector_has_multiple_selection (selector)) { + return FALSE; + } else { + for (i=0; i < hildon_touch_selector_get_num_columns (selector); i++) { + model = hildon_touch_selector_get_model (selector, i); + + if (gtk_tree_model_get_iter_first (model, &iter)) { + return FALSE; + } + } + return TRUE; + } +} + +/** + * hildon_picker_button_new: + * @size: One of #HildonSizeType, specifying the size of the new button. + * @arrangement: one of #HildonButtonArrangement, specifying the placement of the + * labels. + * + * Creates a new #HildonPickerButton. See hildon_button_new() for details on the + * parameters. + * + * Returns: a newly created #HildonPickerButton + * + * Since: 2.2 + **/ +GtkWidget * +hildon_picker_button_new (HildonSizeType size, + HildonButtonArrangement arrangement) +{ + GtkWidget *button; + + button = g_object_new (HILDON_TYPE_PICKER_BUTTON, + "arrangement", arrangement, "size", size, + NULL); + + return button; +} + +/** + * hildon_picker_button_set_selector: + * @button: a #HildonPickerButton + * @selector: a #HildonTouchSelector + * + * Sets @selector as the #HildonTouchSelector to be shown in the + * #HildonPickerDialog that @button brings up. + * + * Since: 2.2 + **/ +void +hildon_picker_button_set_selector (HildonPickerButton * button, + HildonTouchSelector * selector) +{ + HildonPickerButtonPrivate *priv; + gchar *value = NULL; + + g_return_if_fail (HILDON_IS_PICKER_BUTTON (button)); + g_return_if_fail (!selector || HILDON_IS_TOUCH_SELECTOR (selector)); + + priv = GET_PRIVATE (button); + + if (priv->selector) { + g_signal_handlers_disconnect_by_func (priv->selector, + hildon_picker_button_selector_selection_changed, + button); + g_signal_handlers_disconnect_by_func (priv->selector, + hildon_picker_button_selector_columns_changed, + button); + g_object_unref (priv->selector); + } + + priv->selector = GTK_WIDGET (selector); + + if (selector) { + g_object_ref (selector); + + g_signal_connect (G_OBJECT (selector), "changed", + G_CALLBACK (hildon_picker_button_selector_selection_changed), + button); + + g_signal_connect (G_OBJECT (selector), "columns-changed", + G_CALLBACK (hildon_picker_button_selector_columns_changed), + button); + + value = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (priv->selector)); + } + + if (!value) + value = g_strdup (""); + + hildon_button_set_value (HILDON_BUTTON (button), value); + hildon_picker_button_value_changed (button); + + g_free (value); +} + +/** + * hildon_picker_button_get_selector: + * @button: a #HildonPickerButton + * + * Retrieves the #HildonTouchSelector associated to @button. + * + * Returns: a #HildonTouchSelector + * + * Since: 2.2 + **/ +HildonTouchSelector * +hildon_picker_button_get_selector (HildonPickerButton * button) +{ + HildonPickerButtonPrivate *priv; + + g_return_val_if_fail (HILDON_IS_PICKER_BUTTON (button), NULL); + + priv = GET_PRIVATE (button); + + return HILDON_TOUCH_SELECTOR (priv->selector); +} + +/** + * hildon_picker_button_get_active: + * @button: a #HildonPickerButton + * + * Returns the index of the currently active item, or -1 if there's no + * active item. If the selector has several columns, only the first + * one is used. + * + * Returns: an integer which is the index of the currently active item, or -1 if there's no active item. + * + * Since: 2.2 + **/ +gint +hildon_picker_button_get_active (HildonPickerButton * button) +{ + HildonTouchSelector *sel; + g_return_val_if_fail (HILDON_IS_PICKER_BUTTON (button), -1); + + sel = hildon_picker_button_get_selector (button); + + return hildon_touch_selector_get_active (sel, 0); +} + +/** + * hildon_picker_button_set_active: + * @button: a #HildonPickerButton + * @index: the index of the item to select, or -1 to have no active item + * + * Sets the active item of the #HildonTouchSelector associated to + * @button to @index. If the selector has several columns, only the + * first one is used. + * + * Since: 2.2 + **/ +void +hildon_picker_button_set_active (HildonPickerButton * button, + gint index) +{ + HildonTouchSelector *sel; + gchar *text; + g_return_if_fail (HILDON_IS_PICKER_BUTTON (button)); + + sel = hildon_picker_button_get_selector (button); + hildon_touch_selector_set_active (sel, 0, index); + + text = hildon_touch_selector_get_current_text (sel); + hildon_button_set_value (HILDON_BUTTON (button), text); + g_free (text); +} + +/** + * hildon_picker_button_get_done_button_text: + * @button: a #HildonPickerButton + * + * Gets the text used in the #HildonPickerDialog that is launched by + * @button. If no custom text is set, then %NULL is returned. + * + * Returns: the custom string to be used, or %NULL if the default + * #HildonPickerDialog::done-button-text is to be used. + * + * Since: 2.2 + **/ +const gchar * +hildon_picker_button_get_done_button_text (HildonPickerButton *button) +{ + HildonPickerButtonPrivate *priv; + + g_return_val_if_fail (HILDON_IS_PICKER_BUTTON (button), NULL); + + priv = GET_PRIVATE (button); + + return priv->done_button_text; +} + +/** + * hildon_picker_button_set_done_button_text: + * @button: a #HildonPickerButton + * @done_button_text: a string + * + * Sets a custom string to be used in the "done" button in #HildonPickerDialog. + * If unset, the default HildonPickerButton::done-button-text property + * value will be used. + * + * Since: 2.2 + **/ +void +hildon_picker_button_set_done_button_text (HildonPickerButton *button, + const gchar *done_button_text) +{ + HildonPickerButtonPrivate *priv; + + g_return_if_fail (HILDON_IS_PICKER_BUTTON (button)); + g_return_if_fail (done_button_text != NULL); + + priv = GET_PRIVATE (button); + + g_free (priv->done_button_text); + priv->done_button_text = g_strdup (done_button_text); + + if (priv->dialog) { + hildon_picker_dialog_set_done_label (HILDON_PICKER_DIALOG (priv->dialog), + priv->done_button_text); + } +} diff --git a/hildon/hildon-picker-button.h b/hildon/hildon-picker-button.h new file mode 100644 index 0000000..cecc7a5 --- /dev/null +++ b/hildon/hildon-picker-button.h @@ -0,0 +1,94 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +#ifndef __HILDON_PICKER_BUTTON__ +#define __HILDON_PICKER_BUTTON__ + +#include + +#include "hildon-button.h" +#include "hildon-touch-selector.h" + +G_BEGIN_DECLS + +#define HILDON_TYPE_PICKER_BUTTON \ + hildon_picker_button_get_type() + +#define HILDON_PICKER_BUTTON(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + HILDON_TYPE_PICKER_BUTTON, HildonPickerButton)) + +#define HILDON_PICKER_BUTTON_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + HILDON_TYPE_PICKER_BUTTON, HildonPickerButtonClass)) + +#define HILDON_IS_PICKER_BUTTON(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_PICKER_BUTTON)) + +#define HILDON_IS_PICKER_BUTTON_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_PICKER_BUTTON)) + +#define HILDON_PICKER_BUTTON_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + HILDON_TYPE_PICKER_BUTTON, HildonPickerButtonClass)) + +typedef struct _HildonPickerButton HildonPickerButton; +typedef struct _HildonPickerButtonClass HildonPickerButtonClass; + +struct _HildonPickerButton +{ + HildonButton parent; +}; + +struct _HildonPickerButtonClass +{ + HildonButtonClass parent_class; +}; + +GType +hildon_picker_button_get_type (void); + +GtkWidget* +hildon_picker_button_new (HildonSizeType size, + HildonButtonArrangement arrangement); + +void +hildon_picker_button_set_selector (HildonPickerButton * button, + HildonTouchSelector *selector); + +HildonTouchSelector* +hildon_picker_button_get_selector (HildonPickerButton *button); + +void +hildon_picker_button_set_active (HildonPickerButton * button, + gint index); + +gint +hildon_picker_button_get_active (HildonPickerButton * button); + +const gchar * +hildon_picker_button_get_done_button_text (HildonPickerButton * button); + +void +hildon_picker_button_set_done_button_text (HildonPickerButton *button, + const gchar *done_button_text); + +void +hildon_picker_button_value_changed (HildonPickerButton *button); + +G_END_DECLS + +#endif /* __HILDON_PICKER_BUTTON__ */ diff --git a/hildon/hildon-picker-dialog.c b/hildon/hildon-picker-dialog.c new file mode 100644 index 0000000..5539c99 --- /dev/null +++ b/hildon/hildon-picker-dialog.c @@ -0,0 +1,643 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2008 Nokia Corporation. + * + * 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; either + * version 2 of the License, or (at your option) any later version. or (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/** + * SECTION:hildon-picker-dialog + * @short_description: A utility widget that shows a #HildonTouchSelector widget + * + * #HildonPickerDialog is a dialog that is used to show a + * #HildonTouchSelector widget and a 'Done' button to allow users to + * finish their selections. + * + * The #HildonPickerDialog will show a 'Done' button in case the + * #HildonTouchSelector allows multiple selection. The label of the + * button can be set using hildon_picker_dialog_set_done_label() and + * retrieved using hildon_picker_dialog_get_done_label() + * + * Note that in most cases developers don't need to deal directly with + * this widget. #HildonPickerButton is designed to pop up a + * #HildonPickerDialog and manage the interaction with it. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "hildon-touch-selector.h" +#include "hildon-touch-selector-entry.h" +#include "hildon-picker-dialog.h" + +#define _(String) dgettext("hildon-libs", String) + +#define HILDON_PICKER_DIALOG_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_PICKER_DIALOG, HildonPickerDialogPrivate)) + +G_DEFINE_TYPE (HildonPickerDialog, hildon_picker_dialog, HILDON_TYPE_DIALOG) + +#define HILDON_TOUCH_SELECTOR_HEIGHT 320 + +struct _HildonPickerDialogPrivate +{ + GtkWidget *selector; + GtkWidget *button; + + gulong signal_changed_id; + gulong signal_columns_changed_id; + + gboolean center_on_show; + GSList *current_selection; + gchar *current_text; +}; + +/* properties */ +enum +{ + PROP_0, + PROP_DONE_BUTTON_TEXT, + PROP_CENTER_ON_SHOW, + PROP_LAST +}; + +enum +{ + RESPONSE, + LAST_SIGNAL +}; + +#define DEFAULT_DONE_BUTTON_TEXT _("wdgt_bd_done") + +static void +hildon_picker_dialog_set_property (GObject * object, + guint prop_id, + const GValue * value, + GParamSpec * pspec); + +static void +hildon_picker_dialog_get_property (GObject * object, + guint prop_id, + GValue * value, GParamSpec * pspec); + +static void +hildon_picker_dialog_finalize (GObject *object); + +/* gtkwidget */ +static void +hildon_picker_dialog_show (GtkWidget *widget); + +static void +hildon_picker_dialog_realize (GtkWidget *widget); + +/* private functions */ +static gboolean +requires_done_button (HildonPickerDialog * dialog); + +static void +prepare_action_area (HildonPickerDialog *dialog); + +static void +setup_interaction_mode (HildonPickerDialog * dialog); + +static void +_select_on_selector_changed_cb (HildonTouchSelector * dialog, + gint column, + gpointer data); + +static gboolean +_hildon_picker_dialog_set_selector (HildonPickerDialog * dialog, + HildonTouchSelector * selector); + +static void +_on_dialog_response (GtkDialog *dialog, + gint response_id, + gpointer data); + +static void +_save_current_selection (HildonPickerDialog *dialog); + +static void +_restore_current_selection (HildonPickerDialog *dialog); + +static void +_clean_current_selection (HildonPickerDialog *dialog); + +/**********************************************************************************/ + +static void +hildon_picker_dialog_class_init (HildonPickerDialogClass * class) +{ + GObjectClass *gobject_class; + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + GtkContainerClass *container_class; + + gobject_class = (GObjectClass *) class; + object_class = (GtkObjectClass *) class; + widget_class = (GtkWidgetClass *) class; + container_class = (GtkContainerClass *) class; + + /* GObject */ + gobject_class->set_property = hildon_picker_dialog_set_property; + gobject_class->get_property = hildon_picker_dialog_get_property; + gobject_class->finalize = hildon_picker_dialog_finalize; + + /* GtkWidget */ + widget_class->show = hildon_picker_dialog_show; + widget_class->realize = hildon_picker_dialog_realize; + + /* HildonPickerDialog */ + class->set_selector = _hildon_picker_dialog_set_selector; + + /* signals */ + + /* properties */ + /** + * HildonPickerDialog + * + * Button label + * + * Since: 2.2 + */ + g_object_class_install_property (gobject_class, + PROP_DONE_BUTTON_TEXT, + g_param_spec_string ("done-button-text", + "Done Button Label", + "Done Button Label", + DEFAULT_DONE_BUTTON_TEXT, + G_PARAM_READABLE | + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property (gobject_class, + PROP_CENTER_ON_SHOW, + g_param_spec_boolean ("center-on-show", + "Center on show", + "If the dialog should center" + " on the current selection" + " when it is showed", + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_type_class_add_private (object_class, sizeof (HildonPickerDialogPrivate)); +} + + +static void +hildon_picker_dialog_init (HildonPickerDialog * dialog) +{ + dialog->priv = HILDON_PICKER_DIALOG_GET_PRIVATE (dialog); + + dialog->priv->selector = NULL; + dialog->priv->button = + gtk_dialog_add_button (GTK_DIALOG (dialog), "", GTK_RESPONSE_OK); + gtk_widget_grab_default (dialog->priv->button); + + dialog->priv->signal_changed_id = 0; + dialog->priv->signal_columns_changed_id = 0; + dialog->priv->center_on_show = TRUE; + dialog->priv->current_selection = NULL; + dialog->priv->current_text = NULL; + + g_signal_connect (G_OBJECT (dialog), + "response", G_CALLBACK (_on_dialog_response), + NULL); +} + + +static void +hildon_picker_dialog_set_property (GObject * object, + guint param_id, + const GValue * value, GParamSpec * pspec) +{ + HildonPickerDialog *dialog; + + dialog = HILDON_PICKER_DIALOG (object); + + switch (param_id) { + case PROP_DONE_BUTTON_TEXT: + hildon_picker_dialog_set_done_label (HILDON_PICKER_DIALOG (object), + g_value_get_string (value)); + break; + case PROP_CENTER_ON_SHOW: + dialog->priv->center_on_show = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +hildon_picker_dialog_get_property (GObject * object, + guint param_id, + GValue * value, GParamSpec * pspec) +{ + HildonPickerDialog *dialog; + + dialog = HILDON_PICKER_DIALOG (object); + + switch (param_id) { + case PROP_DONE_BUTTON_TEXT: + g_value_set_string (value, hildon_picker_dialog_get_done_label (dialog)); + break; + case PROP_CENTER_ON_SHOW: + g_value_set_boolean (value, dialog->priv->center_on_show); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +hildon_picker_dialog_finalize (GObject *object) +{ + _clean_current_selection (HILDON_PICKER_DIALOG (object)); + + G_OBJECT_CLASS (hildon_picker_dialog_parent_class)->finalize (object); +} + +static void +hildon_picker_dialog_show (GtkWidget *widget) +{ + HildonPickerDialog *dialog = HILDON_PICKER_DIALOG (widget); + HildonTouchSelector *selector; + + GTK_WIDGET_CLASS (hildon_picker_dialog_parent_class)->show (widget); + + if (dialog->priv->center_on_show) { + selector = hildon_picker_dialog_get_selector (dialog); + hildon_touch_selector_center_on_selected (selector); + } + + _save_current_selection (dialog); + prepare_action_area (dialog); + +} + +static void +hildon_picker_dialog_realize (GtkWidget *widget) +{ + setup_interaction_mode (HILDON_PICKER_DIALOG (widget)); + + GTK_WIDGET_CLASS (hildon_picker_dialog_parent_class)->realize (widget); +} + +/* ------------------------------ PRIVATE METHODS ---------------------------- */ + +static void +_select_on_selector_changed_cb (HildonTouchSelector * selector, + gint column, gpointer data) +{ + g_return_if_fail (HILDON_IS_PICKER_DIALOG (data)); + + gtk_dialog_response (GTK_DIALOG (data), GTK_RESPONSE_OK); +} + +static gboolean +selection_completed (HildonPickerDialog *dialog) +{ + HildonPickerDialogPrivate *priv; + GList *list; + gint i, n_cols; + gboolean all_selected = TRUE; + + priv = HILDON_PICKER_DIALOG_GET_PRIVATE (dialog); + + n_cols = hildon_touch_selector_get_num_columns (HILDON_TOUCH_SELECTOR (priv->selector)); + for (i = 0; i < n_cols; i++) { + list = hildon_touch_selector_get_selected_rows (HILDON_TOUCH_SELECTOR (priv->selector), i); + if (list == NULL) { + all_selected = FALSE; + break; + } + g_list_foreach (list, (GFunc)gtk_tree_path_free, NULL); + g_list_free (list); + } + + return all_selected; +} + +static void +_on_dialog_response (GtkDialog *dialog, + gint response_id, + gpointer data) +{ + if (response_id == GTK_RESPONSE_OK) { + if (selection_completed (HILDON_PICKER_DIALOG (dialog)) == FALSE) { + g_signal_stop_emission_by_name (dialog, "response"); + } + } else if (response_id == GTK_RESPONSE_DELETE_EVENT) { + _restore_current_selection (HILDON_PICKER_DIALOG (dialog)); + } +} + +static void +on_selector_columns_changed (HildonTouchSelector * selector, gpointer userdata) +{ + HildonPickerDialog * dialog; + + dialog = HILDON_PICKER_DIALOG (userdata); + + prepare_action_area (dialog); + if (GTK_WIDGET_REALIZED (dialog)) { + setup_interaction_mode (dialog); + } +} + +/** + * hildon_picker_dialog_set_done_label: + * @dialog: a #HildonPickerDialog + * @label: a string + * + * Sets a custom string to be used as the 'Done' button label in @dialog. + * + * Since: 2.2 + **/ +void +hildon_picker_dialog_set_done_label (HildonPickerDialog * dialog, + const gchar * label) +{ + HildonPickerDialogPrivate *priv; + + g_return_if_fail (HILDON_IS_PICKER_DIALOG (dialog)); + g_return_if_fail (label != NULL); + + priv = HILDON_PICKER_DIALOG_GET_PRIVATE (dialog); + + gtk_button_set_label (GTK_BUTTON (priv->button), label); +} + +/** + * hildon_picker_dialog_get_done_label: + * @dialog: a #HildonPickerDialog + * + * Retrieves current 'Done' button label. + * + * Returns: the custom string to be used. + * + * Since: 2.2 + **/ +const gchar * +hildon_picker_dialog_get_done_label (HildonPickerDialog * dialog) +{ + HildonPickerDialogPrivate *priv; + + g_return_val_if_fail (HILDON_IS_PICKER_DIALOG (dialog), NULL); + + priv = HILDON_PICKER_DIALOG_GET_PRIVATE (dialog); + + return gtk_button_get_label (GTK_BUTTON (priv->button)); +} + +static void +free_path_list (GList *list) +{ + g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL); + g_list_free (list); +} + +static void +_clean_current_selection (HildonPickerDialog *dialog) +{ + if (dialog->priv->current_selection) { + g_slist_foreach (dialog->priv->current_selection, (GFunc) free_path_list, NULL); + g_slist_free (dialog->priv->current_selection); + dialog->priv->current_selection = NULL; + } + if (dialog->priv->current_text) { + g_free (dialog->priv->current_text); + dialog->priv->current_text = NULL; + } +} + +static void +_save_current_selection (HildonPickerDialog *dialog) +{ + HildonTouchSelector *selector; + gint i, columns; + + selector = HILDON_TOUCH_SELECTOR (dialog->priv->selector); + + _clean_current_selection (dialog); + + columns = hildon_touch_selector_get_num_columns (selector); + for (i = 0; i < columns; i++) { + dialog->priv->current_selection + = g_slist_append (dialog->priv->current_selection, + hildon_touch_selector_get_selected_rows (selector, i)); + } + if (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector)) { + HildonEntry *entry = hildon_touch_selector_entry_get_entry (HILDON_TOUCH_SELECTOR_ENTRY (selector)); + dialog->priv->current_text = g_strdup (hildon_entry_get_text (entry)); + } +} + +static void +_restore_current_selection (HildonPickerDialog *dialog) +{ + GSList *current_selection, *iter; + GList *selected, *selected_iter; + GtkTreePath *current_path; + HildonTouchSelector *selector; + GtkTreeModel *model; + GtkTreeIter tree_iter; + gint i; + + if (dialog->priv->current_selection == NULL) + return; + + current_selection = dialog->priv->current_selection; + selector = HILDON_TOUCH_SELECTOR (dialog->priv->selector); + + if (hildon_touch_selector_get_num_columns (selector) != + g_slist_length (current_selection)) { + /* We conclude that if the current selection has the same + numbers of columns that the selector, all this ok + Anyway this shouldn't happen. */ + g_critical ("Trying to restore the selection on a selector after change" + " the number of columns. Are you removing columns while the" + " dialog is open?"); + return; + } + + if (dialog->priv->signal_changed_id) + g_signal_handler_block (selector, dialog->priv->signal_changed_id); + for (iter = current_selection, i = 0; iter; iter = g_slist_next (iter), i++) { + selected = (GList *) (iter->data); + model = hildon_touch_selector_get_model (selector, i); + hildon_touch_selector_unselect_all (selector, i); + for (selected_iter = selected; selected_iter; selected_iter = g_list_next (selected_iter)) { + current_path = (GtkTreePath *) selected_iter->data; + gtk_tree_model_get_iter (model, &tree_iter, current_path); + hildon_touch_selector_select_iter (selector, i, &tree_iter, FALSE); + } + } + if (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector) && dialog->priv->current_text != NULL) { + HildonEntry *entry = hildon_touch_selector_entry_get_entry (HILDON_TOUCH_SELECTOR_ENTRY (selector)); + hildon_entry_set_text (entry, dialog->priv->current_text); + } + if (dialog->priv->signal_changed_id) + g_signal_handler_unblock (selector, dialog->priv->signal_changed_id); +} + +static gboolean +requires_done_button (HildonPickerDialog * dialog) +{ + return hildon_touch_selector_has_multiple_selection + (HILDON_TOUCH_SELECTOR (dialog->priv->selector)); +} + +static void +prepare_action_area (HildonPickerDialog *dialog) +{ + if (requires_done_button (dialog)) { + gtk_dialog_set_has_separator (GTK_DIALOG (dialog), TRUE); + gtk_widget_show (GTK_DIALOG (dialog)->action_area); + } else { + gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE); + gtk_widget_hide (GTK_DIALOG (dialog)->action_area); + } +} + +static void +setup_interaction_mode (HildonPickerDialog * dialog) +{ + if (dialog->priv->signal_changed_id) { + g_signal_handler_disconnect (dialog->priv->selector, + dialog->priv->signal_changed_id); + } + + if (requires_done_button (dialog) == FALSE) { + dialog->priv->signal_changed_id = + g_signal_connect (G_OBJECT (dialog->priv->selector), "changed", + G_CALLBACK (_select_on_selector_changed_cb), dialog); + } +} + +/*------------------------- PUBLIC METHODS ---------------------------- */ + +/** + * hildon_picker_dialog_new: + * @parent: the parent window + * + * Creates a new #HildonPickerDialog + * + * Returns: a new #HildonPickerDialog + * + * Since: 2.2 + **/ +GtkWidget * +hildon_picker_dialog_new (GtkWindow * parent) +{ + GtkDialog *dialog = NULL; + + dialog = g_object_new (HILDON_TYPE_PICKER_DIALOG, NULL); + + if (parent) { + gtk_window_set_transient_for (GTK_WINDOW (dialog), parent); + } + + return GTK_WIDGET (dialog); +} + + +static gboolean +_hildon_picker_dialog_set_selector (HildonPickerDialog * dialog, + HildonTouchSelector * selector) +{ + g_object_ref (selector); + + /* Remove the old selector, if any */ + if (dialog->priv->selector != NULL) { + gtk_container_remove (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), + dialog->priv->selector); + if (dialog->priv->signal_columns_changed_id) { + g_signal_handler_disconnect (dialog->priv->selector, + dialog->priv->signal_columns_changed_id); + } + } + + dialog->priv->selector = GTK_WIDGET (selector); + + /* Pack the new selector */ + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), + dialog->priv->selector, TRUE, TRUE, 0); + + g_object_unref (selector); + + /* Ensure that the dialog's height is correct */ + gtk_widget_set_size_request (GTK_WIDGET (dialog->priv->selector), -1, + HILDON_TOUCH_SELECTOR_HEIGHT); + + gtk_widget_show (dialog->priv->selector); + + prepare_action_area (dialog); + if (GTK_WIDGET_REALIZED (dialog)) { + setup_interaction_mode (dialog); + } + + dialog->priv->signal_columns_changed_id = g_signal_connect (G_OBJECT (dialog->priv->selector), + "columns-changed", + G_CALLBACK (on_selector_columns_changed), dialog); + return TRUE; +} + +/** + * hildon_picker_dialog_set_selector: + * @dialog: a #HildonPickerDialog + * @selector: a #HildonTouchSelector + * + * Sets @selector as the #HildonTouchSelector to be shown in @dialog + * + * Returns: %TRUE if @selector was set, %FALSE otherwise + * + * Since: 2.2 + **/ +gboolean +hildon_picker_dialog_set_selector (HildonPickerDialog * dialog, + HildonTouchSelector * selector) +{ + g_return_val_if_fail (HILDON_IS_PICKER_DIALOG (dialog), FALSE); + g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE); + + return HILDON_PICKER_DIALOG_GET_CLASS (dialog)->set_selector (dialog, selector); +} + +/** + * hildon_picker_dialog_get_selector: + * @dialog: a #HildonPickerDialog + * + * Retrieves the #HildonTouchSelector associated to @dialog. + * + * Returns: a #HildonTouchSelector + * + * Since: 2.2 + **/ +HildonTouchSelector * +hildon_picker_dialog_get_selector (HildonPickerDialog * dialog) +{ + g_return_val_if_fail (HILDON_IS_PICKER_DIALOG (dialog), NULL); + + return HILDON_TOUCH_SELECTOR (dialog->priv->selector); +} diff --git a/hildon/hildon-picker-dialog.h b/hildon/hildon-picker-dialog.h new file mode 100644 index 0000000..3d867f5 --- /dev/null +++ b/hildon/hildon-picker-dialog.h @@ -0,0 +1,103 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2008 Nokia Corporation. + * + * 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; either + * version 2 of the License, or (at your option) any later version. or (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __HILDON_PICKER_DIALOG_H__ +#define __HILDON_PICKER_DIALOG_H__ + +#ifdef HILDON_DISABLE_DEPRECATED + #define __SHOULD_REENABLE_DISABLE_DEPRECATED +#endif + +#undef HILDON_DISABLE_DEPRECATED +#include "hildon-dialog.h" + +#ifdef __SHOULD_REENABLE_DISABLE_DEPRECATED + #define HILDON_DISABLE_DEPRECATED +#endif + +#include "hildon-touch-selector.h" + +G_BEGIN_DECLS + +#define HILDON_TYPE_PICKER_DIALOG \ + (hildon_picker_dialog_get_type ()) + +#define HILDON_PICKER_DIALOG(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + HILDON_TYPE_PICKER_DIALOG, HildonPickerDialog)) + +#define HILDON_PICKER_DIALOG_CLASS(vtable) \ + (G_TYPE_CHECK_CLASS_CAST ((vtable), \ + HILDON_TYPE_PICKER_DIALOG, HildonPickerDialogClass)) + +#define HILDON_IS_PICKER_DIALOG(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_PICKER_DIALOG)) + +#define HILDON_IS_PICKER_DIALOG_CLASS(vtable) \ + (G_TYPE_CHECK_CLASS_TYPE ((vtable), HILDON_TYPE_PICKER_DIALOG)) + +#define HILDON_PICKER_DIALOG_GET_CLASS(inst) \ + (G_TYPE_INSTANCE_GET_CLASS ((inst), \ + HILDON_TYPE_PICKER_DIALOG, HildonPickerDialogClass)) + +typedef struct _HildonPickerDialog HildonPickerDialog; +typedef struct _HildonPickerDialogClass HildonPickerDialogClass; +typedef struct _HildonPickerDialogPrivate HildonPickerDialogPrivate; + +struct _HildonPickerDialog +{ + HildonDialog parent_instance; + + /*< private > */ + HildonPickerDialogPrivate *priv; +}; + +struct _HildonPickerDialogClass +{ + HildonDialogClass parent_class; + + gboolean (* set_selector) (HildonPickerDialog *dialog, + HildonTouchSelector *selector); +}; + +/* construction */ +GType +hildon_picker_dialog_get_type (void) G_GNUC_CONST; + +GtkWidget* +hildon_picker_dialog_new (GtkWindow * parent); + +gboolean +hildon_picker_dialog_set_selector (HildonPickerDialog *dialog, + HildonTouchSelector *selector); + +void +hildon_picker_dialog_set_done_label (HildonPickerDialog *dialog, + const gchar *label); + +const gchar* +hildon_picker_dialog_get_done_label (HildonPickerDialog *dialog); + +HildonTouchSelector* +hildon_picker_dialog_get_selector (HildonPickerDialog *dialog); + +G_END_DECLS + +#endif /* __HILDON_PICKER_SELECTOR_H__ */ diff --git a/hildon/hildon-private.c b/hildon/hildon-private.c new file mode 100644 index 0000000..b7190c8 --- /dev/null +++ b/hildon/hildon-private.c @@ -0,0 +1,81 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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 + * + */ + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "hildon-private.h" +#include "hildon-date-editor.h" +#include "hildon-time-editor.h" + +/* This function is a private function of hildon. 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 G_GNUC_INTERNAL +hildon_private_composite_focus (GtkWidget *widget, + GtkDirectionType direction, + GtkDirectionType *effective_direction) +{ + GtkWidget *toplevel = NULL; + GtkWidget *focus_widget = NULL; + gboolean coming_from_outside = FALSE; + + toplevel = gtk_widget_get_toplevel (widget); + + focus_widget = GTK_WINDOW (toplevel)->focus_widget; + + if (focus_widget == NULL || gtk_widget_is_ancestor (focus_widget, widget) == FALSE) + { + /* When coming from outside we want to give focus to the first + item in the widgets */ + *effective_direction = GTK_DIR_TAB_FORWARD; + coming_from_outside = TRUE; + } + else + *effective_direction = direction; + + switch (direction) { + case GTK_DIR_UP: + case GTK_DIR_DOWN: + case GTK_DIR_TAB_FORWARD: + case GTK_DIR_TAB_BACKWARD: + if ((HILDON_IS_DATE_EDITOR (widget) || HILDON_IS_TIME_EDITOR(widget)) && + !coming_from_outside) + return FALSE; + /* fall through */ + default: + return TRUE; + } + + g_assert_not_reached (); + return TRUE; +} + + diff --git a/hildon/hildon-private.h b/hildon/hildon-private.h new file mode 100644 index 0000000..67b79f4 --- /dev/null +++ b/hildon/hildon-private.h @@ -0,0 +1,43 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#ifndef __HILDON_PRIVATE_H__ +#define __HILDON_PRIVATE_H__ + +#include + +G_BEGIN_DECLS + +gboolean G_GNUC_INTERNAL +hildon_private_composite_focus (GtkWidget *widget, + GtkDirectionType direction, + GtkDirectionType *effective_direction); + +G_END_DECLS + +#endif /* __HILDON_PRIVATE_H__ */ + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-program-private.h b/hildon/hildon-program-private.h new file mode 100644 index 0000000..bf2a3f7 --- /dev/null +++ b/hildon/hildon-program-private.h @@ -0,0 +1,55 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_PRIVATE_H__ +#define __HILDON_PROGRAM_PRIVATE_H__ + +#include + +#include "hildon-window.h" +#include "hildon-stackable-window.h" + +G_BEGIN_DECLS + +#define HILDON_PROGRAM_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_PROGRAM, HildonProgramPrivate)); + +typedef struct _HildonProgramPrivate HildonProgramPrivate; + +struct _HildonProgramPrivate +{ + gboolean killable; + gboolean is_topmost; + guint window_count; + GtkMenu *common_menu; + HildonAppMenu *common_app_menu; + GtkWidget *common_toolbar; + GSList *windows; + Window window_group; +}; + +G_END_DECLS + +#endif /* __HILDON_PROGRAM_PRIVATE_H__ */ diff --git a/hildon/hildon-program.c b/hildon/hildon-program.c new file mode 100644 index 0000000..47ead29 --- /dev/null +++ b/hildon/hildon-program.c @@ -0,0 +1,843 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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-program + * @short_description: An object that represents an application running in the Hildon framework. + * @see_also: #HildonWindow, #HildonStackableWindow + * + * #HildonProgram is an object used to represent an application running + * in the Hildon framework. + * + * Applications can have one or more #HildonWindows. These + * can be registered in the #HildonProgram with hildon_program_add_window(), + * and can be unregistered similarly with hildon_program_remove_window(). + * + * #HildonProgram provides the programmer with commodities such + * as applying a common toolbar and menu to all registered + * #HildonWindows. This is done with hildon_program_set_common_menu(), + * hildon_program_set_common_app_menu() and hildon_program_set_common_toolbar(). + * + * #HildonProgram is also used to apply program-wide properties that + * are specific to the Hildon framework. For instance + * hildon_program_set_can_hibernate() sets whether or not an application + * can be set to hibernate by the Hildon task navigator, in situations of + * low memory. + * + * + * + * HildonProgram *program; + * HildonWindow *window1; + * HildonWindow *window2; + * GtkToolbar *common_toolbar, *window_specific_toolbar; + * HildonAppMenu *menu; + * + * program = HILDON_PROGRAM (hildon_program_get_instance ()); + * + * window1 = HILDON_WINDOW (hildon_window_new ()); + * window2 = HILDON_WINDOW (hildon_window_new ()); + * + * common_toolbar = create_common_toolbar (); + * window_specific_toolbar = create_window_specific_toolbar (); + * + * menu = create_menu (); + * + * hildon_program_add_window (program, window1); + * hildon_program_add_window (program, window2); + * + * hildon_program_set_common_app_menu (program, menu); + * + * hildon_program_set_common_toolbar (program, common_toolbar); + * hildon_window_add_toolbar (window1, window_specific_toolbar); + * + * hildon_program_set_can_hibernate (program, TRUE); + * + * + */ + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "hildon-program.h" +#include "hildon-program-private.h" +#include "hildon-window-private.h" +#include "hildon-window-stack.h" +#include "hildon-app-menu-private.h" + +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 G_GNUC_CONST +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) +{ + HildonProgramPrivate *priv = HILDON_PROGRAM_GET_PRIVATE (self); + g_assert (priv); + + 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_menu = NULL; + priv->common_app_menu = NULL; + priv->common_toolbar = NULL; + priv->windows = NULL; +} + +static void +hildon_program_finalize (GObject *self) +{ + HildonProgramPrivate *priv = HILDON_PROGRAM_GET_PRIVATE (HILDON_PROGRAM (self)); + g_assert (priv); + + 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; + } +} + +static void +hildon_program_class_init (HildonProgramClass *self) +{ + GObjectClass *object_class = G_OBJECT_CLASS (self); + + g_type_class_add_private (self, sizeof (HildonProgramPrivate)); + + /* 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 */ + + /** + * HildonProgram:is-topmost: + * + * Whether one of the program's window or dialog currently + * is activated by window manager. + */ + 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)); + + /** + * HildonProgram:can-hibernate: + * + * Whether the program should be set to hibernate by the Task + * Navigator in low memory situation. + */ + 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) +{ + HildonProgramPrivate *priv = HILDON_PROGRAM_GET_PRIVATE (object); + g_assert (priv); + + 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; + } +} + +/** + * hildon_program_pop_window_stack: + * @self: A #HildonProgram + * + * Pops a window from the stack. + * + * Deprecated: Use hildon_window_stack_pop() instead + * + * Returns: A #HildonStackableWindow, or %NULL + * + * Since: 2.2 + */ +HildonStackableWindow * +hildon_program_pop_window_stack (HildonProgram *self) +{ + HildonWindowStack *stack = hildon_window_stack_get_default (); + GtkWidget *win = hildon_window_stack_pop_1 (stack); + g_warning ("%s: this function is deprecated. Use hildon_window_stack_pop() instead", __FUNCTION__); + return win ? HILDON_STACKABLE_WINDOW (win) : NULL; +} + +/** + * hildon_program_peek_window_stack: + * @self: A #HildonProgram + * + * Deprecated: Use hildon_window_stack_peek() instead + * + * Returns: A #HildonStackableWindow, or %NULL + * + * Since: 2.2 + */ +HildonStackableWindow * +hildon_program_peek_window_stack (HildonProgram *self) +{ + HildonWindowStack *stack = hildon_window_stack_get_default (); + GtkWidget *win = hildon_window_stack_peek (stack); + g_warning ("%s: this function is deprecated. Use hildon_window_stack_peek() instead", __FUNCTION__); + return win ? HILDON_STACKABLE_WINDOW (win) : NULL; +} + +/* Utilities */ +static gint +hildon_program_window_list_compare (gconstpointer window_a, + gconstpointer window_b) +{ + g_return_val_if_fail (HILDON_IS_WINDOW(window_a) && + HILDON_IS_WINDOW(window_b), 1); + + 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) +{ + gboolean is_topmost; + Window active_window; + HildonProgramPrivate *priv; + + priv = HILDON_PROGRAM_GET_PRIVATE (program); + g_assert (priv); + + active_window = hildon_window_get_active_window(); + is_topmost = FALSE; + + if (active_window) + { + gint xerror; + XWMHints *wm_hints; + + gdk_error_trap_push (); + wm_hints = XGetWMHints (GDK_DISPLAY (), active_window); + xerror = gdk_error_trap_pop (); + if (xerror) + { + if (wm_hints) + XFree (wm_hints); + return; + } + + if (wm_hints) + { + is_topmost = (wm_hints->window_group == priv->window_group); + XFree (wm_hints); + } + } + + /* Send notification if is_topmost has changed */ + if (!priv->is_topmost != !is_topmost) + { + priv->is_topmost = is_topmost; + g_object_notify (G_OBJECT (program), "is-topmost"); + } + + /* Check each window if it was is_topmost */ + g_slist_foreach (priv->windows, + (GFunc)hildon_program_window_list_is_is_topmost, &active_window); +} + +/* + * 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; +} + +/* + * 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)); +} + +/** + * hildon_program_get_instance: + * + * Returns the #HildonProgram for the current process. The object is + * created on the first call. Note that you're not supposed to unref + * the returned object since it's not reffed in the first place. + * + * Return value: the #HildonProgram. + **/ +HildonProgram* +hildon_program_get_instance (void) +{ + static HildonProgram *program = NULL; + + if (! program) + { + program = g_object_new (HILDON_TYPE_PROGRAM, NULL); + } + + return program; +} + +/** + * hildon_program_add_window: + * @self: 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(), hildon_program_set_common_app_menu() + * and hildon_program_set_common_toolbar(). + **/ +void +hildon_program_add_window (HildonProgram *self, + HildonWindow *window) +{ + HildonProgramPrivate *priv; + + g_return_if_fail (HILDON_IS_PROGRAM (self)); + g_return_if_fail (HILDON_IS_WINDOW (window)); + + priv = HILDON_PROGRAM_GET_PRIVATE (self); + g_assert (priv); + + 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(), hildon_program_set_common_app_menu() + * and hildon_program_set_common_toolbar() will not affect the window. + **/ +void +hildon_program_remove_window (HildonProgram *self, + HildonWindow *window) +{ + HildonProgramPrivate *priv; + + g_return_if_fail (HILDON_IS_PROGRAM (self)); + g_return_if_fail (HILDON_IS_WINDOW (window)); + + priv = HILDON_PROGRAM_GET_PRIVATE (self); + g_assert (priv); + + g_return_if_fail (g_slist_find (priv->windows, window)); + + 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 can_hibernate) +{ + HildonProgramPrivate *priv; + + g_return_if_fail (HILDON_IS_PROGRAM (self)); + + priv = HILDON_PROGRAM_GET_PRIVATE (self); + g_assert (priv); + + if (priv->killable != can_hibernate) + { + g_slist_foreach (priv->windows, + (GFunc) hildon_window_set_can_hibernate_property, &can_hibernate); + } + + priv->killable = can_hibernate; +} + +/** + * hildon_program_get_can_hibernate: + * @self: The #HildonProgram which can hibernate or not + * + * Returns whether the #HildonProgram is set to be support hibernation + * from the Hildon task navigator + * + * Return value: %TRUE if the program can hibernate, %FALSE otherwise. + **/ +gboolean +hildon_program_get_can_hibernate (HildonProgram *self) +{ + HildonProgramPrivate *priv; + + g_return_val_if_fail (HILDON_IS_PROGRAM (self), FALSE); + + priv = HILDON_PROGRAM_GET_PRIVATE (self); + g_assert (priv); + + 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 #HildonWindows + * registered with the #HildonProgram. Only one common #GtkMenu can be + * set, further calls will detach the previous common #GtkMenu. A + * #HildonWindow can use its own #GtkMenu with + * hildon_window_set_menu() + * + * This method does not support #HildonAppMenus. See + * hildon_program_set_common_app_menu() for that. + * + * Since: 2.2 + **/ +void +hildon_program_set_common_menu (HildonProgram *self, + GtkMenu *menu) +{ + HildonProgramPrivate *priv; + + g_return_if_fail (HILDON_IS_PROGRAM (self)); + + priv = HILDON_PROGRAM_GET_PRIVATE (self); + g_assert (priv); + + if (priv->common_menu) + { + if (GTK_WIDGET_VISIBLE (priv->common_menu)) + { + gtk_menu_popdown (priv->common_menu); + gtk_menu_shell_deactivate (GTK_MENU_SHELL (priv->common_menu)); + } + + if (gtk_menu_get_attach_widget (priv->common_menu)) + { + gtk_menu_detach (priv->common_menu); + } + else + { + g_object_unref (priv->common_menu); + } + } + + priv->common_menu = 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 + * + * Returns the #GtkMenu that was set as common menu for this + * #HildonProgram. + * + * Return value: the #GtkMenu or %NULL of no common menu was set. + **/ +GtkMenu* +hildon_program_get_common_menu (HildonProgram *self) +{ + HildonProgramPrivate *priv; + + g_return_val_if_fail (HILDON_IS_PROGRAM (self), NULL); + + priv = HILDON_PROGRAM_GET_PRIVATE (self); + g_assert (priv); + + return priv->common_menu; +} + +/** + * hildon_program_set_common_app_menu: + * @self: The #HildonProgram in which the common menu should be used + * @menu: A #HildonAppMenu to use as common menu for the program + * + * Sets a #HildonAppMenu that will appear in all + * #HildonWindows registered with the #HildonProgram. Only + * one common #HildonAppMenu can be set, further calls will detach the + * previous common #HildonAppMenu. A #HildonWindow can use its own + * #HildonAppMenu with hildon_window_set_app_menu() + * + * This method does not support #GtkMenus. See + * hildon_program_set_common_menu() for that. + * + * Since: 2.2 + **/ +void +hildon_program_set_common_app_menu (HildonProgram *self, + HildonAppMenu *menu) +{ + HildonProgramPrivate *priv; + HildonAppMenu *old_menu; + + g_return_if_fail (HILDON_IS_PROGRAM (self)); + g_return_if_fail (menu == NULL || HILDON_IS_APP_MENU (menu)); + + priv = HILDON_PROGRAM_GET_PRIVATE (self); + g_assert (priv); + + old_menu = priv->common_app_menu; + + /* Set new menu */ + priv->common_app_menu = menu; + if (menu) + g_object_ref_sink (menu); + + /* Hide and unref old menu */ + if (old_menu) { + hildon_app_menu_set_parent_window (old_menu, NULL); + g_object_unref (old_menu); + } +} + +/** + * hildon_program_get_common_app_menu: + * @self: The #HildonProgram from which to retrieve the common app menu + * + * Returns the #HildonAppMenu that was set as common menu for this + * #HildonProgram. + * + * Return value: the #HildonAppMenu or %NULL of no common app menu was + * set. + * + * Since: 2.2 + **/ +HildonAppMenu* +hildon_program_get_common_app_menu (HildonProgram *self) +{ + HildonProgramPrivate *priv; + + g_return_val_if_fail (HILDON_IS_PROGRAM (self), NULL); + + priv = HILDON_PROGRAM_GET_PRIVATE (self); + g_assert (priv); + + return priv->common_app_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_add_toolbar(). Both + * #HildonProgram and #HildonWindow specific toolbars will be shown + **/ +void +hildon_program_set_common_toolbar (HildonProgram *self, + GtkToolbar *toolbar) +{ + HildonProgramPrivate *priv; + + g_return_if_fail (HILDON_IS_PROGRAM (self)); + + priv = HILDON_PROGRAM_GET_PRIVATE (self); + g_assert (priv); + + 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 + * + * Returns the #GtkToolbar that was set as common toolbar for this + * #HildonProgram. + * + * Return value: the #GtkToolbar or %NULL of no common toolbar was + * set. + **/ +GtkToolbar* +hildon_program_get_common_toolbar (HildonProgram *self) +{ + HildonProgramPrivate *priv; + + g_return_val_if_fail (HILDON_IS_PROGRAM (self), NULL); + + priv = HILDON_PROGRAM_GET_PRIVATE (self); + g_assert (priv); + + return priv->common_toolbar ? GTK_TOOLBAR (priv->common_toolbar) : NULL; +} + +/** + * hildon_program_get_is_topmost: + * @self: A #HildonWindow + * + * Returns whether one of the program's windows or dialogs is + * currently activated by the window manager. + * + * Return value: %TRUE if a window or dialog is topmost, %FALSE + * otherwise. + **/ +gboolean +hildon_program_get_is_topmost (HildonProgram *self) +{ + HildonProgramPrivate *priv; + + g_return_val_if_fail (HILDON_IS_PROGRAM (self), FALSE); + + priv = HILDON_PROGRAM_GET_PRIVATE (self); + g_assert (priv); + + return priv->is_topmost; +} + +/** + * hildon_program_go_to_root_window: + * @self: A #HildonProgram + * + * Goes to the root window of the stack. + * + * Deprecated: See #HildonWindowStack + * + * Since: 2.2 + */ +void +hildon_program_go_to_root_window (HildonProgram *self) +{ + HildonWindowStack *stack = hildon_window_stack_get_default (); + gint n = hildon_window_stack_size (stack); + g_warning ("%s: this function is deprecated. Use hildon_window_stack_pop() instead.", __FUNCTION__); + if (n > 1) { + hildon_window_stack_pop (stack, n-1, NULL); + } +} diff --git a/hildon/hildon-program.h b/hildon/hildon-program.h new file mode 100644 index 0000000..a4d3210 --- /dev/null +++ b/hildon/hildon-program.h @@ -0,0 +1,133 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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" +#include "hildon-stackable-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_PROGRAM_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_CAST ((obj), \ + HILDON_TYPE_PROGRAM, HildonProgramClass)) + +#define HILDON_IS_PROGRAM(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_PROGRAM)) + +#define HILDON_IS_PROGRAM_CLASS(klass) \ + (G_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_PROGRAM)) + +#define HILDON_PROGRAM_GET_CLASS(obj) \ + ((HildonProgramClass *) G_OBJECT_GET_CLASS(obj)) + +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 G_GNUC_CONST +hildon_program_get_type (void); + +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 can_hibernate); + +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_app_menu (HildonProgram *self, + HildonAppMenu *menu); + +HildonAppMenu* +hildon_program_get_common_app_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); + +#ifndef HILDON_DISABLE_DEPRECATED +HildonStackableWindow * +hildon_program_pop_window_stack (HildonProgram *self); + +HildonStackableWindow * +hildon_program_peek_window_stack (HildonProgram *self); + +void +hildon_program_go_to_root_window (HildonProgram *self); +#endif /* HILDON_DISABLE_DEPRECATED */ + +G_END_DECLS + +#endif /* __HILDON_PROGRAM_H__ */ diff --git a/hildon/hildon-range-editor-private.h b/hildon/hildon-range-editor-private.h new file mode 100644 index 0000000..d23d60e --- /dev/null +++ b/hildon/hildon-range-editor-private.h @@ -0,0 +1,51 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_PRIVATE_H__ +#define __HILDON_RANGE_EDITOR_PRIVATE_H__ + +G_BEGIN_DECLS + +#define HILDON_RANGE_EDITOR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_RANGE_EDITOR, HildonRangeEditorPrivate)); + +typedef struct _HildonRangeEditorPrivate HildonRangeEditorPrivate; + +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 */ +}; + +G_END_DECLS + +#endif /* __HILDON_RANGE_EDITOR_PRIVATE_H__ */ diff --git a/hildon/hildon-range-editor.c b/hildon/hildon-range-editor.c new file mode 100644 index 0000000..beb5322 --- /dev/null +++ b/hildon/hildon-range-editor.c @@ -0,0 +1,1079 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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. + * + * + * + * #HildonRangeEditor has been deprecated since Hildon 2.2 and should not + * be used in newly written code. See + * Migrating Number Widgets + * section to know how to migrate this deprecated widget. + * + * + * + * + * + * range_editor = hildon_range_editor_new (); + * hildon_range_editor_set_limits (editor, start, end ); + * hildon_range_editor_get_range (editor, &start, &end); + * + * + */ + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include "hildon-range-editor.h" +#include "hildon-banner.h" +#include "hildon-range-editor-private.h" + +#define _(string) \ + dgettext("hildon-libs", 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 + +static GtkContainerClass *parent_class = NULL; + +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); + +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); + +enum +{ + PROP_0, + PROP_LOWER = 1, + PROP_HIGHER, + PROP_MIN, + PROP_MAX, + PROP_SEPARATOR +}; + +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); + g_assert (priv); + + 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); + +#ifdef MAEMO_GTK + g_object_set (G_OBJECT (priv->start_entry), + "hildon-input-mode", HILDON_GTK_INPUT_MODE_NUMERIC, NULL); + + g_object_set( G_OBJECT (priv->end_entry), + "hildon-input-mode", HILDON_GTK_INPUT_MODE_NUMERIC, NULL); +#endif + + 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); + g_assert (priv); + + /* 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 (GTK_ENTRY (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); + g_assert (priv); + + 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 useful 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); + g_assert (priv); + + 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); + g_assert (priv); + + 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); + g_assert (priv); + + 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 = {0}; + GtkAllocation child2_allocation = {0}; + GtkAllocation child3_allocation = {0}; + + priv = HILDON_RANGE_EDITOR_GET_PRIVATE (widget); + g_assert (priv); + + 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); + g_assert (priv); + + 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); +} + +/** + * hildon_range_editor_get_type: + * + * Initializes, and returns the type of a hildon range editor. + * + * Returns: GType of #HildonRangeEditor + * + */ +GType G_GNUC_CONST +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) +{ + g_return_if_fail (HILDON_IS_RANGE_EDITOR (editor) && start && end); + + *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/hildon-range-editor.h b/hildon/hildon-range-editor.h new file mode 100644 index 0000000..5f10e60 --- /dev/null +++ b/hildon/hildon-range-editor.h @@ -0,0 +1,131 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#ifndef __HILDON_RANGE_EDITOR_H__ +#define __HILDON_RANGE_EDITOR_H__ + +#include + +G_BEGIN_DECLS + +#define HILDON_TYPE_RANGE_EDITOR \ + (hildon_range_editor_get_type()) + +#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)) + +#define HILDON_RANGE_EDITOR_GET_CLASS(obj) \ + ((HildonRangeEditorClass *) G_OBJECT_GET_CLASS(obj)) + +typedef struct _HildonRangeEditor HildonRangeEditor; + +typedef struct _HildonRangeEditorClass HildonRangeEditorClass; + +struct _HildonRangeEditor +{ + GtkContainer parent; +}; + +struct _HildonRangeEditorClass +{ + GtkContainerClass parent_class; +}; + +GType G_GNUC_CONST +hildon_range_editor_get_type (void); + +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__ */ + +#endif /* HILDON_DISABLE_DEPRECATED */ + diff --git a/hildon/hildon-remote-texture-private.h b/hildon/hildon-remote-texture-private.h new file mode 100644 index 0000000..806cc22 --- /dev/null +++ b/hildon/hildon-remote-texture-private.h @@ -0,0 +1,84 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_REMOTE_TEXTURE_PRIVATE_H__ +#define __HILDON_REMOTE_TEXTURE_PRIVATE_H__ + + +#include +#include + +G_BEGIN_DECLS + +typedef struct _HildonRemoteTexturePrivate HildonRemoteTexturePrivate; + +#define HILDON_REMOTE_TEXTURE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_REMOTE_TEXTURE, HildonRemoteTexturePrivate)); + +struct _HildonRemoteTexturePrivate +{ + guint ready : 1; + + guint set_shm : 1; + guint set_damage : 1; + guint set_show : 1; + guint set_position : 1; + guint set_offset : 1; + guint set_scale : 1; + guint set_parent : 1; + + key_t shm_key; + guint shm_width; + guint shm_height; + guint shm_bpp; + + gint damage_x1; + gint damage_y1; + gint damage_x2; + gint damage_y2; + + guint show; + guint opacity; + + gint x; + gint y; + gint width; + gint height; + + double offset_x; + double offset_y; + + double scale_x; + double scale_y; + + GtkWindow* parent; + gulong parent_map_event_cb_id; + + gulong map_event_cb_id; +}; + +G_END_DECLS + +#endif /* __HILDON_REMOTE_TEXTURE_PRIVATE_H__ */ diff --git a/hildon/hildon-remote-texture.c b/hildon/hildon-remote-texture.c new file mode 100644 index 0000000..f8bbbd7 --- /dev/null +++ b/hildon/hildon-remote-texture.c @@ -0,0 +1,943 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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-remote-texture + * @short_description: Widget representing a Clutter/GLES texture created + * from a shared memory area. + * + * The #HildonRemoteTexture is a GTK+ widget which allows the rendering of + * a shared memory area within hildon-desktop. It allows the memory area to + * be positioned and scaled, without altering its' contents. + */ + +#include +#include + +#include "hildon-remote-texture.h" +#include "hildon-remote-texture-private.h" + +G_DEFINE_TYPE (HildonRemoteTexture, hildon_remote_texture, GTK_TYPE_WINDOW); + +static GdkFilterReturn +hildon_remote_texture_event_filter (GdkXEvent *xevent, + GdkEvent *event, + gpointer data); +static void +hildon_remote_texture_update_ready (HildonRemoteTexture *self); +static void +hildon_remote_texture_send_pending_messages (HildonRemoteTexture *self); +static void +hildon_remote_texture_send_all_messages (HildonRemoteTexture *self); +static gboolean +hildon_remote_texture_parent_map_event (GtkWidget *parent, + GdkEvent *event, + gpointer user_data); +static gboolean +hildon_remote_texture_map_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data); + +static guint32 shm_atom; +static guint32 damage_atom; +static guint32 show_atom; +static guint32 position_atom; +static guint32 offset_atom; +static guint32 scale_atom; +static guint32 parent_atom; +static guint32 ready_atom; + +static gboolean atoms_initialized = FALSE; + +static void +hildon_remote_texture_realize (GtkWidget *widget) +{ + GdkDisplay *display; + Atom wm_type, applet_type; + + GTK_WIDGET_CLASS (hildon_remote_texture_parent_class)->realize (widget); + + /* Set remote texture window type. */ + + display = gdk_drawable_get_display (widget->window); + + wm_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"); + applet_type = gdk_x11_get_xatom_by_name_for_display (display, "_HILDON_WM_WINDOW_TYPE_REMOTE_TEXTURE"); + + XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (widget->window), wm_type, + XA_ATOM, 32, PropModeReplace, + (unsigned char *) &applet_type, 1); + + /* This is a bit of a hack, but for the sake of speed (it is assumed that + * once HildonRemoteTexture is created, a lot of ClientMessages will + * follow), we cache all ClientMessages atoms in static variables. */ + + if (!atoms_initialized) + { + shm_atom = + gdk_x11_get_xatom_by_name_for_display + (display, "_HILDON_TEXTURE_CLIENT_MESSAGE_SHM"); + damage_atom = + gdk_x11_get_xatom_by_name_for_display + (display, "_HILDON_TEXTURE_CLIENT_MESSAGE_DAMAGE"); + show_atom = + gdk_x11_get_xatom_by_name_for_display + (display, "_HILDON_TEXTURE_CLIENT_MESSAGE_SHOW"); + position_atom = + gdk_x11_get_xatom_by_name_for_display + (display, "_HILDON_TEXTURE_CLIENT_MESSAGE_POSITION"); + offset_atom = + gdk_x11_get_xatom_by_name_for_display + (display, "_HILDON_TEXTURE_CLIENT_MESSAGE_OFFSET"); + scale_atom = + gdk_x11_get_xatom_by_name_for_display + (display, "_HILDON_TEXTURE_CLIENT_MESSAGE_SCALE"); + parent_atom = + gdk_x11_get_xatom_by_name_for_display + (display, "_HILDON_TEXTURE_CLIENT_MESSAGE_PARENT"); + ready_atom = + gdk_x11_get_xatom_by_name_for_display + (display, "_HILDON_TEXTURE_CLIENT_READY"); +#if 0 + g_debug ("shm atom = %lu\n", shm_atom); + g_debug ("damage atom = %lu\n", damage_atom); + g_debug ("show atom = %lu\n", show_atom); + g_debug ("position atom = %lu\n", position_atom); + g_debug ("offset atom = %lu\n", offset_atom); + g_debug ("scale atom = %lu\n", scale_atom); + g_debug ("parent atom = %lu\n", parent_atom); + g_debug ("ready atom = %lu\n", ready_atom); +#endif + + atoms_initialized = TRUE; + } + + /* Wait for a ready message */ + + gdk_window_add_filter (widget->window, + hildon_remote_texture_event_filter, + widget); +} + +static void +hildon_remote_texture_unrealize (GtkWidget *widget) +{ + gdk_window_remove_filter (widget->window, + hildon_remote_texture_event_filter, + widget); + + GTK_WIDGET_CLASS (hildon_remote_texture_parent_class)->unrealize (widget); +} + +static void +hildon_remote_texture_show (GtkWidget *widget) +{ + HildonRemoteTexture *self = HILDON_REMOTE_TEXTURE (widget); + + GTK_WIDGET_CLASS (hildon_remote_texture_parent_class)->show (widget); + hildon_remote_texture_set_show (self, 1); +} + +static void +hildon_remote_texture_hide (GtkWidget *widget) +{ + HildonRemoteTexture *self = HILDON_REMOTE_TEXTURE (widget); + + hildon_remote_texture_set_show (self, 0); + GTK_WIDGET_CLASS (hildon_remote_texture_parent_class)->hide (widget); +} + +static void +hildon_remote_texture_class_init (HildonRemoteTextureClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + widget_class->realize = hildon_remote_texture_realize; + widget_class->unrealize = hildon_remote_texture_unrealize; + widget_class->show = hildon_remote_texture_show; + widget_class->hide = hildon_remote_texture_hide; + + g_type_class_add_private (klass, sizeof (HildonRemoteTexturePrivate)); +} + +static void +hildon_remote_texture_init (HildonRemoteTexture *self) +{ + HildonRemoteTexturePrivate + *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); + + /* Default non-zero values for the private variables */ + + priv->scale_x = 1; + priv->scale_y = 1; + priv->opacity = 0xff; +} + +/** + * hildon_remote_texture_new: + * + * Creates a new #HildonRemoteTexture. + * + * Return value: A #HildonRemoteTexture + * + * Since: 2.2 + **/ +GtkWidget* +hildon_remote_texture_new (void) +{ + HildonRemoteTexture *newwindow = g_object_new (HILDON_TYPE_REMOTE_TEXTURE, NULL); + + gtk_window_set_decorated (GTK_WINDOW (newwindow), FALSE); + + return GTK_WIDGET (newwindow); +} + +/* + * An filter for GDK X11 events, waiting for PropertyNotify (window property + * changes) events, keeping track of remote texture ready atom. + * Having the ready atom set on the window by the window manager will trigger + * updates of actor parameters (position/rotation/etc...) to be sent off + * to the window manager for processing. + */ +static GdkFilterReturn +hildon_remote_texture_event_filter (GdkXEvent *xevent, + GdkEvent *event, + gpointer data) +{ + HildonRemoteTexture *self = HILDON_REMOTE_TEXTURE (data); + XAnyEvent *any = xevent; + + if (any->type == PropertyNotify) + { + XPropertyEvent *property = xevent; + + if (property->atom == ready_atom) + { + hildon_remote_texture_update_ready (self); + } + } + + return GDK_FILTER_CONTINUE; +} + +/* + * Check for the ready atom on the remote texture X11 window. + * If present, send all pending remote texture messages to the + * window manager. + */ +static void +hildon_remote_texture_update_ready (HildonRemoteTexture *self) +{ + HildonRemoteTexturePrivate + *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); + GtkWidget *widget = GTK_WIDGET (self); + Display *display = GDK_WINDOW_XDISPLAY (widget->window); + Window window = GDK_WINDOW_XID (widget->window); + + int status; + gint xerror; + + Atom actual_type; + int actual_format; + unsigned long nitems, bytes_after; + unsigned char *prop = NULL; + + /* Check for the "ready" property */ + + gdk_error_trap_push (); + status = XGetWindowProperty (display, window, + ready_atom, 0, 32, + False, XA_ATOM, + &actual_type, &actual_format, + &nitems, &bytes_after, &prop); + xerror = gdk_error_trap_pop(); + + if (prop) + { + /* We do not actually use the property value for anything, + * it is enough that the property is set. */ + + XFree (prop); + } + + if (xerror || + (status != Success) || (actual_type != XA_ATOM) || + (actual_format != 32) || (nitems != 1)) + { + priv->ready = 0; + return; + } + + if (priv->ready) + { + /* The ready flag has been set once already. This means that + * the WM has restarted. Trigger re-mapping of the widget to + * update the texture actor first. Then push all remote + * texture settings anew. */ + + priv->map_event_cb_id = + g_signal_connect (G_OBJECT (self), + "map-event", + G_CALLBACK(hildon_remote_texture_map_event), + self); + + if (GTK_WIDGET_MAPPED (GTK_WIDGET (self))) + { + gtk_widget_unmap (GTK_WIDGET (self)); + gtk_widget_map (GTK_WIDGET (self)); + } + + return; + } + + priv->ready = 1; + + /* Send all pending messages */ + + hildon_remote_texture_send_pending_messages (self); +} + +static void +hildon_remote_texture_send_pending_messages (HildonRemoteTexture *self) +{ + HildonRemoteTexturePrivate + *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); + + if (priv->set_shm) + hildon_remote_texture_set_image(self, + priv->shm_key, + priv->shm_width, priv->shm_height, + priv->shm_bpp); + + if (priv->set_damage) + hildon_remote_texture_update_area (self, + priv->damage_x1, + priv->damage_y1, + priv->damage_x2 - priv->damage_x1, + priv->damage_y2 - priv->damage_y1); + + if (priv->set_position) + hildon_remote_texture_set_position (self, + priv->x, + priv->y, + priv->width, + priv->height); + + if (priv->set_offset) + hildon_remote_texture_set_offset (self, + priv->offset_x, + priv->offset_y); + + if (priv->set_scale) + hildon_remote_texture_set_scale (self, + priv->scale_x, + priv->scale_y); + + if (priv->set_parent) + hildon_remote_texture_set_parent (self, + priv->parent); + + if (priv->set_show) + hildon_remote_texture_set_show_full (self, + priv->show, priv->opacity); +} + +static void +hildon_remote_texture_send_all_messages (HildonRemoteTexture *self) +{ + HildonRemoteTexturePrivate + *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); + + priv->set_shm = 1; + priv->set_damage = 1; + priv->set_position = 1; + priv->set_scale = 1; + priv->set_parent = 1; + priv->set_show = 1; + + hildon_remote_texture_send_pending_messages (self); +} + +/* ------------------------------------------------------------- */ + +/** + * hildon_remote_texture_send_message: + * @self: A #HildonRemoteTexture + * @message_type: Message id for the remote texture message. + * @l0: 1st remote texture message parameter. + * @l1: 2nd remote texture message parameter. + * @l2: 3rd remote texture message parameter. + * @l3: 4th remote texture message parameter. + * @l4: 5th remote texture message parameter. + * + * Sends an X11 ClientMessage event to the window manager with + * the specified parameters -- id (@message_type) and data (@l0, + * @l1, @l2, @l3, @l4). + * + * This is an internal utility function that application will + * not need to call directly. + * + * Since: 2.2 + **/ +void +hildon_remote_texture_send_message (HildonRemoteTexture *self, + guint32 message_type, + guint32 l0, + guint32 l1, + guint32 l2, + guint32 l3, + guint32 l4) +{ + GtkWidget *widget = GTK_WIDGET (self); + Display *display = GDK_WINDOW_XDISPLAY (widget->window); + Window window = GDK_WINDOW_XID (widget->window); + + XEvent event = { 0 }; + + event.xclient.type = ClientMessage; + event.xclient.window = window; + event.xclient.message_type = (Atom)message_type; + event.xclient.format = 32; + event.xclient.data.l[0] = l0; + event.xclient.data.l[1] = l1; + event.xclient.data.l[2] = l2; + event.xclient.data.l[3] = l3; + event.xclient.data.l[4] = l4; + +#if 0 + g_debug ("%lu (%lu %lu %lu %lu %lu) -> %lu\n", + message_type, + l0, l1, l2, l3, l4, + window); +#endif + + XSendEvent (display, window, True, + StructureNotifyMask, + (XEvent *)&event); +} + +/** + * hildon_remote_texture_set_image: + * @self: A #HildonRemoteTexture + * @key: The key that would be used with shmget in hildon-desktop. The key + * should probably be created with ftok, and the relevant shared memory + * area should be created before this call. + * @width: width of image in pixels + * @height: height of image in pixels + * @bpp: BYTES per pixel - usually 2,3 or 4 + * + * Since: 2.2 + */ +void +hildon_remote_texture_set_image (HildonRemoteTexture *self, + key_t key, + guint width, + guint height, + guint bpp) +{ + HildonRemoteTexturePrivate + *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); + GtkWidget *widget = GTK_WIDGET (self); + + priv->set_shm = 1; + priv->shm_key = key; + priv->shm_width = width; + priv->shm_height = height; + priv->shm_bpp = bpp; + + if (GTK_WIDGET_MAPPED (widget) && priv->ready) + { + /* Defer messages until the remote texture is parented + * and the parent window is mapped */ + if (!priv->parent || !GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent))) + return; + hildon_remote_texture_send_message (self, + shm_atom, + priv->shm_key, + priv->shm_width, + priv->shm_height, + priv->shm_bpp, + 0); + priv->set_shm = 0; + } +} + +/** + * hildon_remote_texture_update_area: + * @self: A #HildonRemoteTexture + * @x: offset of damaged area in pixels + * @y: offset of damaged area in pixels + * @width: width of damaged area in pixels + * @height: height of damaged area in pixels + * + * This signals to hildon-desktop that a specific region of the memory area + * has changed. This will trigger a redraw and will update the relevant tiles + * of the texture. + * + * Since: 2.2 + */ +void +hildon_remote_texture_update_area (HildonRemoteTexture *self, + gint x, + gint y, + gint width, + gint height) +{ + HildonRemoteTexturePrivate + *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); + GtkWidget *widget = GTK_WIDGET (self); + + if (priv->damage_x1==priv->damage_x2 || priv->damage_y1==priv->damage_y2) + { + priv->damage_x1 = x; + priv->damage_y1 = y; + priv->damage_x2 = x+width; + priv->damage_y2 = y+height; + } + else + { + if (xdamage_x1) priv->damage_x1 = x; + if (ydamage_y1) priv->damage_y1 = y; + if (x+width>priv->damage_x2) priv->damage_x2 = x+width; + if (y+height>priv->damage_y2) priv->damage_y2 = y+height; + } + priv->set_damage = 1; + + if (GTK_WIDGET_MAPPED (widget) && priv->ready) + { + /* Defer messages until the remote texture is parented + * and the parent window is mapped */ + if (!priv->parent || !GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent))) + return; + hildon_remote_texture_send_message (self, + damage_atom, + priv->damage_x1, + priv->damage_y1, + priv->damage_x2 - priv->damage_x1, + priv->damage_y2 - priv->damage_y1, + 0); + priv->set_damage = 0; + priv->damage_x1 = 0; + priv->damage_y1 = 0; + priv->damage_x2 = 0; + priv->damage_y2 = 0; + } +} + +/** + * hildon_remote_texture_set_show_full: + * @self: A #HildonRemoteTexture + * @show: A boolean flag setting the visibility of the remote texture. + * @opacity: Desired opacity setting + * + * Send a message to the window manager setting the visibility of + * the remote texture. This will only affect the visibility of + * the remote texture set by the compositing window manager in its own + * rendering pipeline, after X has drawn the window to the off-screen + * buffer. This setting, naturally, has no effect if the #HildonRemoteTexture + * widget is not visible in X11 terms (i.e. realized and mapped). + * + * Furthermore, if a widget is parented, its final visibility will be + * affected by that of the parent window. + * + * The opacity setting ranges from zero (0), being completely transparent + * to 255 (0xff) being fully opaque. + * + * If the remote texture WM-counterpart is not ready, the show message + * will be queued until the WM is ready for it. + * + * Since: 2.2 + **/ +void +hildon_remote_texture_set_show_full (HildonRemoteTexture *self, + gint show, + gint opacity) +{ + HildonRemoteTexturePrivate + *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); + GtkWidget *widget = GTK_WIDGET (self); + + if (opacity > 255) + opacity = 255; + + if (opacity < 0) + opacity = 0; + + priv->show = show; + priv->opacity = opacity; + priv->set_show = 1; + + if (GTK_WIDGET_MAPPED (widget) && priv->ready) + { + /* Defer show messages until the remote texture is parented + * and the parent window is mapped */ + if (!priv->parent || !GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent))) + return; + hildon_remote_texture_send_message (self, + show_atom, + show, opacity, + 0, 0, 0); + priv->set_show = 0; + } +} + +/** + * hildon_remote_texture_set_show: + * @self: A #HildonRemoteTexture + * @show: A boolean flag setting the visibility of the remote texture. + * + * This function is a shortcut for hildon_remote_texture_set_show_full(), + * setting the overall actor visibility without changing it's opacity + * setting. + * + * Since: 2.2 + **/ +void +hildon_remote_texture_set_show (HildonRemoteTexture *self, + gint show) +{ + HildonRemoteTexturePrivate + *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); + + hildon_remote_texture_set_show_full (self, + show, priv->opacity); +} + +/** + * hildon_remote_texture_set_opacity: + * @self: A #HildonRemoteTexture + * @opacity: Desired opacity setting + * + * This function is a shortcut for hildon_remote_texture_set_show_full(), + * setting actor opacity without changing it's overall visibility. + * + * See hildon_remote_texture_set_show_full() for description of the range + * of values @opacity argument takes. + * + * Since: 2.2 + **/ +void +hildon_remote_texture_set_opacity (HildonRemoteTexture *self, + gint opacity) +{ + HildonRemoteTexturePrivate + *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); + + hildon_remote_texture_set_show_full (self, + priv->show, opacity); +} + +/** + * hildon_remote_texture_set_position: + * @self: A #HildonRemoteTexture + * @x: Desired X coordinate + * @y: Desired Y coordinate + * @width: Desired width + * @height: Desired height + * + * Send a message to the window manager setting the offset of the remote + * texture in the window (in Remote texture's pixels). The texture + * is also subject to the animation effects rendered by the compositing + * window manager on that window (like those by task switcher). + * + * If the remote texture WM-counterpart is not ready, the show message + * will be queued until the WM is ready for it. + * + * Since: 2.2 + **/ +void +hildon_remote_texture_set_position (HildonRemoteTexture *self, + gint x, + gint y, + gint width, + gint height) +{ + HildonRemoteTexturePrivate + *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); + GtkWidget *widget = GTK_WIDGET (self); + + priv->x = x; + priv->y = y; + priv->width = width; + priv->height = height; + priv->set_position = 1; + + if (GTK_WIDGET_MAPPED (widget) && priv->ready) + { + /* Defer messages until the remote texture is parented + * and the parent window is mapped */ + + if (!priv->parent || !GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent))) + return; + hildon_remote_texture_send_message (self, + position_atom, + x, y, + width, height, 0); + priv->set_position = 0; + } +} + +/** + * hildon_remote_texture_set_offset: + * @self: A #HildonRemoteTexture + * @x: Desired X offset + * @y: Desired Y offset + * + * Send a message to the window manager setting the offset of the remote + * texture in the window (in Remote texture's pixels). The texture + * is also subject to the animation effects rendered by the compositing + * window manager on that window (like those by task switcher). + * + * If the remote texture WM-counterpart is not ready, the show message + * will be queued until the WM is ready for it. + * + * Since: 2.2 + **/ +void +hildon_remote_texture_set_offset (HildonRemoteTexture *self, + double x, + double y) +{ + HildonRemoteTexturePrivate + *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); + GtkWidget *widget = GTK_WIDGET (self); + + priv->offset_x = x; + priv->offset_y = y; + priv->set_offset = 1; + + if (GTK_WIDGET_MAPPED (widget) && priv->ready) + { + /* Defer messages until the remote texture is parented + * and the parent window is mapped */ + + if (!priv->parent || !GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent))) + return; + hildon_remote_texture_send_message (self, + offset_atom, + (gint)(x*65536), (gint)(y*65536), + 0, 0, 0); + priv->set_offset = 0; + } +} + +/** + * hildon_remote_texture_set_scalex: + * @self: A #HildonRemoteTexture + * @x_scale: The scale factor for the memory area to be rendered in the X-axis + * @y_scale: The scale factor for the memory area to be rendered in the X-axis + * + * Since: 2.2 + **/ +void +hildon_remote_texture_set_scale (HildonRemoteTexture *self, + double x_scale, + double y_scale) +{ + HildonRemoteTexturePrivate + *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); + GtkWidget *widget = GTK_WIDGET (self); + + priv->scale_x = x_scale; + priv->scale_y = y_scale; + priv->set_scale = 1; + + if (GTK_WIDGET_MAPPED (widget) && priv->ready) + { + /* Defer messages until the remote texture is parented + * and the parent window is mapped */ + if (!priv->parent || !GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent))) + return; + hildon_remote_texture_send_message (self, + scale_atom, + priv->scale_x * (1 << 16), + priv->scale_y * (1 << 16), + 0, 0, 0); + priv->set_scale = 0; + } +} + +/* + * This callback will be triggered by the parent widget of + * an remote texture when it is mapped. The compositing + * window manager is now ready to parent the remote texture + * into the target parent window. + */ +static gboolean +hildon_remote_texture_parent_map_event (GtkWidget *parent, + GdkEvent *event, + gpointer user_data) +{ + hildon_remote_texture_set_parent (HILDON_REMOTE_TEXTURE (user_data), + GTK_WINDOW (parent)); + return FALSE; +} + +/* + * This callback will be triggered by the widget re-mapping + * itself in case of WM restarting. The point is to push all + * remote texture parameters anew to the WM. + */ +static gboolean +hildon_remote_texture_map_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data) +{ + HildonRemoteTexture + *self = HILDON_REMOTE_TEXTURE (user_data); + HildonRemoteTexturePrivate + *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); + + hildon_remote_texture_send_all_messages (self); + + /* Disconnect the "map-event" handler after the "emergency resend all + * actor parameters" drill is over. */ + + if (priv->map_event_cb_id) + { + g_signal_handler_disconnect (self, + priv->map_event_cb_id); + priv->map_event_cb_id = 0; + } + + return FALSE; +} + +/** + * hildon_remote_texture_set_parent: + * @self: A #HildonRemoteTexture + * @parent: A #GtkWindow that the actor will be parented to. + * + * Send a message to the window manager setting the parent window + * for the remote texture. Parenting an actor will not affect the + * X window that the HildonRemoteTexture represents, but it's off-screen + * bitmap as it is handled by the compositing window manager. + * + * Parenting an remote texture will affect its visibility as set + * by the gtk_widget_show(), gtk_widget_hide() and + * hildon_remote_texture_set_show(). The remote texture will only be + * visible when the top-level window it is parented is visible. + * + * Passing %NULL as a @parent argument will unparent the remote texture. + * This will restore the actor's visibility if it was suppressed by + * being unparented or parented to an unmapped window. + * + * If the remote texture WM-counterpart is not ready, the show message + * will be queued until the WM is ready for it. + * + * Since: 2.2 + **/ +void +hildon_remote_texture_set_parent (HildonRemoteTexture *self, + GtkWindow *parent) +{ + HildonRemoteTexturePrivate + *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); + GtkWidget *widget = GTK_WIDGET (self); + + gtk_window_set_transient_for (GTK_WINDOW (self), parent); + + if (priv->parent != parent) + { + /* Setting a new parent */ + + if (priv->parent) + { + if (priv->parent_map_event_cb_id) + g_signal_handler_disconnect (priv->parent, + priv->parent_map_event_cb_id); + + /* Might need a synchronized "parent(0)" or "parent(new parent)" + * message here before we can safely decrease the reference count. */ + + g_object_unref (priv->parent); + } + + priv->parent = parent; + priv->set_parent = 1; + + if (parent != 0) + { + /* The widget is being (re)parented, not unparented. */ + + g_object_ref (parent); + + priv->parent_map_event_cb_id = + g_signal_connect (G_OBJECT (priv->parent), + "map-event", + G_CALLBACK(hildon_remote_texture_parent_map_event), + self); + } + else + { + priv->parent_map_event_cb_id = 0; + } + } + + if (GTK_WIDGET_MAPPED (widget) && priv->ready) + { + Window win = 0; + + /* If the remote texture is being unparented or parented to an + * unmapped widget, force its visibility to "hidden". */ + + if (!priv->parent || !GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent))) + { + hildon_remote_texture_send_message (self, + show_atom, + 0, priv->opacity, + 0, 0, 0); + } + + /* If the widget is being parented (parent != 0), only proceed when + * the parent widget is realized, since we need the X window id of + * the parent. If the widget is being unparented (parent == 0), pass + * the "special" window id of 0 in the message. */ + + if (priv->parent) + { + if (!GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent))) + return; + + GdkWindow *gdk = GTK_WIDGET (parent)->window; + win = GDK_WINDOW_XID (gdk); + } + + hildon_remote_texture_send_message (self, + parent_atom, + win, + 0, 0, 0, 0); + priv->set_parent = 0; + + /* Set remote texture visibility to desired value (in case it was + * forced off when the actor was parented into an unmapped widget). */ + + hildon_remote_texture_send_message (self, + show_atom, + priv->show, priv->opacity, + 0, 0, 0); + priv->set_show = 0; + } +} + diff --git a/hildon/hildon-remote-texture.h b/hildon/hildon-remote-texture.h new file mode 100644 index 0000000..3bdfd1d --- /dev/null +++ b/hildon/hildon-remote-texture.h @@ -0,0 +1,136 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_REMOTE_TEXTURE_H__ +#define __HILDON_REMOTE_TEXTURE_H__ + +#include "hildon-window.h" +#include +#include + +G_BEGIN_DECLS + +#define HILDON_TYPE_REMOTE_TEXTURE \ + (hildon_remote_texture_get_type()) + +#define HILDON_REMOTE_TEXTURE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + HILDON_TYPE_REMOTE_TEXTURE, \ + HildonRemoteTexture)) + +#define HILDON_REMOTE_TEXTURE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + HILDON_TYPE_REMOTE_TEXTURE, \ + HildonRemoteTextureClass)) + +#define HILDON_IS_REMOTE_TEXTURE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + HILDON_TYPE_REMOTE_TEXTURE)) + +#define HILDON_IS_REMOTE_TEXTURE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + HILDON_TYPE_REMOTE_TEXTURE)) + +#define HILDON_REMOTE_TEXTURE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + HILDON_TYPE_REMOTE_TEXTURE, \ + HildonRemoteTextureClass)) + +typedef struct _HildonRemoteTexture HildonRemoteTexture; +typedef struct _HildonRemoteTextureClass HildonRemoteTextureClass; + +struct _HildonRemoteTextureClass +{ + GtkWindowClass parent_class; + + /* Padding for future extension */ + void (*_hildon_reserved1)(void); + void (*_hildon_reserved2)(void); + void (*_hildon_reserved3)(void); + void (*_hildon_reserved4)(void); +}; + +struct _HildonRemoteTexture +{ + GtkWindow parent; +}; + +GType +hildon_remote_texture_get_type (void) G_GNUC_CONST; + +GtkWidget* +hildon_remote_texture_new (void); + +void +hildon_remote_texture_send_message (HildonRemoteTexture *self, + guint32 message_type, + guint32 l0, + guint32 l1, + guint32 l2, + guint32 l3, + guint32 l4); + +void +hildon_remote_texture_set_image (HildonRemoteTexture *self, + key_t key, + guint width, + guint height, + guint bpp); +void +hildon_remote_texture_update_area (HildonRemoteTexture *self, + gint x, + gint y, + gint width, + gint height); +void +hildon_remote_texture_set_show_full (HildonRemoteTexture *self, + gint show, + gint opacity); +void +hildon_remote_texture_set_show (HildonRemoteTexture *self, + gint show); +void +hildon_remote_texture_set_opacity (HildonRemoteTexture *self, + gint opacity); +void +hildon_remote_texture_set_position (HildonRemoteTexture *self, + gint x, + gint y, + gint width, + gint height); +void +hildon_remote_texture_set_offset (HildonRemoteTexture *self, + double x, + double y); +void +hildon_remote_texture_set_scale (HildonRemoteTexture *self, + double x_scale, + double y_scale); +void +hildon_remote_texture_set_parent (HildonRemoteTexture *self, + GtkWindow *parent); + +G_END_DECLS + +#endif /* __HILDON_REMOTE_TEXTURE_H__ */ diff --git a/hildon/hildon-seekbar-private.h b/hildon/hildon-seekbar-private.h new file mode 100644 index 0000000..b58f881 --- /dev/null +++ b/hildon/hildon-seekbar-private.h @@ -0,0 +1,47 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_PRIVATE_H__ +#define __HILDON_SEEKBAR_PRIVATE_H__ + +G_BEGIN_DECLS + +typedef struct _HildonSeekbarPrivate HildonSeekbarPrivate; + +#define HILDON_SEEKBAR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_SEEKBAR, HildonSeekbarPrivate)); + +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.. */ +}; + +G_END_DECLS + +#endif /* __HILDON_SEEKBAR_PRIVATE_H__ */ diff --git a/hildon/hildon-seekbar.c b/hildon/hildon-seekbar.c new file mode 100644 index 0000000..19c8351 --- /dev/null +++ b/hildon/hildon-seekbar.c @@ -0,0 +1,618 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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. + */ + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "hildon-seekbar.h" +#include "hildon-seekbar-private.h" + +static GtkScaleClass* parent_class = NULL; + +static void +hildon_seekbar_class_init (HildonSeekbarClass *seekbar_class); + +static void +hildon_seekbar_init (HildonSeekbar *seekbar); + +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); + +static void +hildon_seekbar_size_request (GtkWidget *widget, + GtkRequisition *event); + +static void +hildon_seekbar_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); + +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 + +#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 + +#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 + +enum +{ + PROP_0, + PROP_TOTAL_TIME, + PROP_POSITION, + PROP_FRACTION +}; + +/** + * hildon_seekbar_get_type: + * + * Initializes, and returns the type of a hildon seekbar. + * + * Returns: GType of #HildonSeekbar + * + */ +GType G_GNUC_CONST +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->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; + + /** + * HildonSeekbar:total-time: + * + * Total playing time of this media file. + */ + 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)); + + /** + * HildonSeekbar:position: + * + * Current position in this media file. + */ + 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)); + + /** + * HildonSeekbar:fraction: + * + * Current fraction related to the progress indicator. + */ + 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) +{ + GtkRange *range = GTK_RANGE(seekbar); + + /* Initialize range widget */ + range->orientation = GTK_ORIENTATION_HORIZONTAL; + range->flippable = 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); + +#if defined(MAEMO_GTK) || GTK_CHECK_VERSION(2,11,0) + return gtk_range_get_fill_level (GTK_RANGE (seekbar)); +#else + return 0; +#endif +} + +/** + * 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), "show-fill-level", TRUE, NULL); + + fraction = CLAMP (fraction, range->adjustment->lower, + range->adjustment->upper); + +#if defined(MAEMO_GTK) || GTK_CHECK_VERSION(2,11,0) + /* Update stream position of range widget */ + gtk_range_set_fill_level (range, fraction); +#endif + + 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 defined(MAEMO_GTK) || GTK_CHECK_VERSION(2,11,0) + if (value <= gtk_range_get_fill_level (range)) { +#else + if (value) { +#endif + 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 (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); +} + +/* + * 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/hildon-seekbar.h b/hildon/hildon-seekbar.h new file mode 100644 index 0000000..1937076 --- /dev/null +++ b/hildon/hildon-seekbar.h @@ -0,0 +1,101 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#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)) + +#define HILDON_SEEKBAR_GET_CLASS(obj) \ + ((HildonSeekBarClass *) G_OBJECT_GET_CLASS(obj)) + + +typedef struct _HildonSeekbar HildonSeekbar; + +typedef struct _HildonSeekbarClass HildonSeekbarClass; + +struct _HildonSeekbar +{ + GtkScale parent; +}; + +struct _HildonSeekbarClass +{ + GtkScaleClass parent_class; +}; + +GType G_GNUC_CONST +hildon_seekbar_get_type (void); + +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__ */ + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-set-password-dialog-private.h b/hildon/hildon-set-password-dialog-private.h new file mode 100644 index 0000000..1eef7f3 --- /dev/null +++ b/hildon/hildon-set-password-dialog-private.h @@ -0,0 +1,56 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_PRIVATE_H__ +#define __HILDON_SET_PASSWORD_DIALOG_PRIVATE_H__ + +G_BEGIN_DECLS + +#define HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(obj)\ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_SET_PASSWORD_DIALOG, \ + HildonSetPasswordDialogPrivate)); + +typedef struct _HildonSetPasswordDialogPrivate HildonSetPasswordDialogPrivate; + +struct _HildonSetPasswordDialogPrivate +{ + GtkWidget *checkbox; + + GtkLabel *message_label; + + GtkWidget *pwd1st_entry; + GtkWidget *pwd1st_caption; + gchar *pwd1st_caption_string; + + GtkWidget *pwd2nd_entry; + GtkWidget *pwd2nd_caption; + gchar *pwd2nd_caption_string; + + gboolean protection; +}; + +G_END_DECLS + +#endif /* __HILDON_SET_PASSWORD_DIALOG_PRIVATE_H__ */ diff --git a/hildon/hildon-set-password-dialog.c b/hildon/hildon-set-password-dialog.c new file mode 100644 index 0000000..baf4bcf --- /dev/null +++ b/hildon/hildon-set-password-dialog.c @@ -0,0 +1,743 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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. + */ + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hildon-set-password-dialog.h" +#include "hildon-caption.h" +#include "hildon-note.h" +#include "hildon-defines.h" +#include "hildon-banner.h" +#include "hildon-set-password-dialog-private.h" +#include "hildon-entry.h" +#include "hildon-check-button.h" + +#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 "wdgt_bd_done" + +#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 "wdgt_bd_done" + +#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" + +#define _(String) dgettext("hildon-libs", String) + +#define c_(String) dgettext("hildon-common-strings", String) + +static GtkDialogClass* parent_class; + +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); + +enum +{ + PROP_0, + PROP_MESSAGE, + PROP_PASSWORD, + PROP_HILDON_PASSWORD_DIALOG +}; + +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); + g_assert (priv); + + switch (prop_id) { + + case PROP_MESSAGE: + /* Update domain label to display new value */ + gtk_label_set_text (priv->message_label, g_value_get_string (value)); + break; + + case PROP_PASSWORD: + /* Update password entry to display new value */ + hildon_entry_set_text (HILDON_ENTRY (priv->pwd1st_entry), 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 */ + /* FIXME It looks kinda extremally bad that this is here... + * what about situations where this prop is NOT set during + * constructing? */ + 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); + g_assert (priv); + + switch (prop_id) { + + case PROP_MESSAGE: + g_value_set_string (value, gtk_label_get_text (priv->message_label)); + break; + + case PROP_PASSWORD: + g_value_set_string (value, + hildon_entry_get_text (HILDON_ENTRY (priv->pwd1st_entry))); + 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; + AtkObject *atk_aux = NULL; + + GtkSizeGroup *group; + + priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE (dialog); + g_assert (priv); + 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->message_label = GTK_LABEL (gtk_label_new (NULL)); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), + GTK_WIDGET(priv->message_label), FALSE, FALSE, 0); + gtk_widget_show (GTK_WIDGET (priv->message_label)); + + if (priv->protection == TRUE) { + /* Use Change Password Dialog strings */ + priv->pwd1st_caption_string = _(HILDON_SET_MODIFY_PASSWORD_DIALOG_PASSWORD); + priv->pwd2nd_caption_string = _(HILDON_SET_MODIFY_PASSWORD_DIALOG_VERIFY_PASSWORD); + + /* Setup checkbox to enable/disable password protection */ + priv->checkbox = hildon_check_button_new (HILDON_SIZE_AUTO_WIDTH | HILDON_SIZE_FINGER_HEIGHT); + gtk_button_set_label (GTK_BUTTON (priv->checkbox), _(HILDON_SET_MODIFY_PASSWORD_DIALOG_LABEL)); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), + priv->checkbox, TRUE, TRUE, 0); + gtk_widget_show (priv->checkbox); + hildon_check_button_set_active (HILDON_CHECK_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->pwd1st_caption_string = _(HILDON_SET_PASSWORD_DIALOG_PASSWORD); + priv->pwd2nd_caption_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->pwd1st_entry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH); + if ((atk_aux = gtk_widget_get_accessible(priv->pwd1st_entry))) + { + atk_object_set_name(atk_aux, "Old Passwd"); + } + + +#ifdef MAEMO_GTK + g_object_set (priv->pwd1st_entry, "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL); +#endif + + gtk_entry_set_visibility (GTK_ENTRY(priv->pwd1st_entry), FALSE); + gtk_widget_show (priv->pwd1st_entry); + priv->pwd1st_caption = hildon_caption_new (group, + priv->pwd1st_caption_string, + priv->pwd1st_entry, + NULL, HILDON_CAPTION_OPTIONAL); + + hildon_caption_set_separator (HILDON_CAPTION(priv->pwd1st_caption), ""); + gtk_entry_set_visibility (GTK_ENTRY (priv->pwd1st_entry), FALSE); + gtk_box_pack_start (GTK_BOX(GTK_DIALOG (dialog)->vbox), + priv->pwd1st_caption, TRUE, TRUE, 0); + gtk_widget_show (priv->pwd1st_caption); + + /* Create the password verify field */ + priv->pwd2nd_entry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH); + if ((atk_aux = gtk_widget_get_accessible(priv->pwd2nd_entry))) + { + atk_object_set_name(atk_aux, "New Passwd"); + } + + +#ifdef MAEMO_GTK + g_object_set (priv->pwd2nd_entry, "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL); +#endif + + gtk_widget_show (priv->pwd2nd_entry); + priv->pwd2nd_caption = hildon_caption_new (group, + priv->pwd2nd_caption_string, + priv->pwd2nd_entry, + NULL, HILDON_CAPTION_OPTIONAL); + hildon_caption_set_separator (HILDON_CAPTION (priv->pwd2nd_caption), ""); + gtk_entry_set_visibility (GTK_ENTRY (priv->pwd2nd_entry), FALSE); + gtk_box_pack_start (GTK_BOX(GTK_DIALOG (dialog)->vbox), + priv->pwd2nd_caption, TRUE, TRUE, 0); + gtk_widget_show (priv->pwd2nd_caption); + + /* 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 */ + gtk_dialog_add_button (GTK_DIALOG (dialog), _(priv->protection + ? HILDON_SET_MODIFY_PASSWORD_DIALOG_OK + : HILDON_SET_PASSWORD_DIALOG_OK), GTK_RESPONSE_OK); + + gtk_widget_show_all (GTK_DIALOG (dialog)->vbox); + gtk_widget_show_all (GTK_DIALOG (dialog)->action_area); + + /* 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_MESSAGE, + g_param_spec_string ("message", + "Message", + "A message to display to the user", + NULL, + G_PARAM_READWRITE)); + + /** + * HildonSetPasswordDialog:modify-protection: + * + * Password type. + */ + 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)); + + /** + * HildonSetPasswordDialog:password: + * + * Content of the password field. + */ + 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 *pwd1st_entry; + GtkEntry *pwd2nd_entry; + gchar *text1; + gchar *text2; + HildonNote *note; + gint i; + HildonSetPasswordDialogPrivate *priv; + + priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE (dialog); + g_assert (priv); + + /* Password and verification */ + pwd1st_entry = GTK_ENTRY (gtk_bin_get_child + (GTK_BIN (priv->pwd1st_caption))); + pwd2nd_entry = GTK_ENTRY (gtk_bin_get_child + (GTK_BIN (priv->pwd2nd_caption))); + text1 = GTK_ENTRY (pwd1st_entry)->text; + text2 = GTK_ENTRY (pwd2nd_entry)->text; + + /* User accepted the dialog */ + if (arg1 == GTK_RESPONSE_OK) { + /* Is the checkbox marked, so password protection is still in use? */ + if (hildon_check_button_get_active (HILDON_CHECK_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"); + + hildon_banner_show_information (GTK_WIDGET (dialog), NULL, + c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH)); + + gtk_widget_grab_focus (GTK_WIDGET (pwd2nd_entry)); + + } else { + /* Error: Passwords don't match, so start over */ + g_signal_stop_emission_by_name (G_OBJECT(dialog), + "response"); + + hildon_entry_set_text (HILDON_ENTRY (pwd1st_entry), ""); + hildon_entry_set_text (HILDON_ENTRY (pwd2nd_entry), ""); + + hildon_banner_show_information (GTK_WIDGET (dialog), NULL, + c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH)); + + gtk_widget_grab_focus (GTK_WIDGET (pwd1st_entry)); + } + } 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 */ + hildon_banner_show_information (GTK_WIDGET (dialog), NULL, c_(HILDON_SET_PASSWORD_DIALOG_EMPTY)); + } else { + /* Error: Second field doesn't match + the empty first field, so start over */ + hildon_banner_show_information (GTK_WIDGET (dialog), NULL, c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH)); + hildon_entry_set_text (HILDON_ENTRY (pwd2nd_entry), ""); + } + + gtk_widget_grab_focus (GTK_WIDGET (pwd1st_entry)); + } + } 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 *pwd1st_entry; + GtkEntry *pwd2nd_entry; + gchar *text1; + gchar *text2; + + HildonSetPasswordDialogPrivate *priv; + + priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE (dialog); + g_assert (priv); + + /* Password and confirmation */ + pwd1st_entry = GTK_ENTRY (gtk_bin_get_child + (GTK_BIN (priv->pwd1st_caption))); + + pwd2nd_entry = GTK_ENTRY (gtk_bin_get_child + (GTK_BIN (priv->pwd2nd_caption))); + + text1 = GTK_ENTRY (pwd1st_entry)->text; + text2 = GTK_ENTRY (pwd2nd_entry)->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"); + hildon_banner_show_information (GTK_WIDGET (dialog), NULL, c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH)); + + gtk_widget_grab_focus (GTK_WIDGET (priv->pwd2nd_entry)); + + } else { + /* Error: Passwords don't match, so start over */ + g_signal_stop_emission_by_name (G_OBJECT(dialog), "response"); + hildon_entry_set_text (HILDON_ENTRY (pwd1st_entry), ""); + hildon_entry_set_text (HILDON_ENTRY (pwd2nd_entry), ""); + hildon_banner_show_information (GTK_WIDGET (dialog), NULL, c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH)); + + gtk_widget_grab_focus (GTK_WIDGET (priv->pwd1st_entry)); + } + } else { + /* First field is empty */ + g_signal_stop_emission_by_name (G_OBJECT (dialog), "response"); + if (text2[0] == '\0') { + /* Error: Both fields are empty */ + hildon_banner_show_information (GTK_WIDGET (dialog), NULL, c_(HILDON_SET_PASSWORD_DIALOG_EMPTY)); + } else { + /* Error: Second field doesn't match + the empty first field, so start over */ + hildon_banner_show_information (GTK_WIDGET (dialog), NULL, c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH)); + hildon_entry_set_text (HILDON_ENTRY (pwd2nd_entry), ""); + } + + gtk_widget_grab_focus (GTK_WIDGET (pwd1st_entry)); + } + } 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; + + g_assert (priv); + + /* If the user enabled/disabled the password protection feature + we enable/disable password entries accordingly */ + active = hildon_check_button_get_active (HILDON_CHECK_BUTTON (widget)); + gtk_widget_set_sensitive (GTK_WIDGET (priv->pwd1st_entry), active); + gtk_widget_set_sensitive (GTK_WIDGET (priv->pwd2nd_entry), active); +} + +/** + * hildon_set_password_dialog_get_type: + * + * Returns GType for HildonPasswordDialog as produced by + * g_type_register_static(). + * + * Returns: HildonSetPasswordDialog type + */ +GType G_GNUC_CONST +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); + g_assert (priv); + + return GTK_ENTRY (priv->pwd1st_entry)->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); + g_assert (priv); + + return priv->protection; +} + +/** + * hildon_set_password_dialog_set_message: + * @dialog: the dialog + * @message: the message or some other descriptive text to be set + * + * Sets the optional descriptive text. + */ +void +hildon_set_password_dialog_set_message (HildonSetPasswordDialog *dialog, + const gchar *message) +{ + HildonSetPasswordDialogPrivate *priv = NULL; + + g_return_if_fail (HILDON_IS_SET_PASSWORD_DIALOG (dialog)); + + priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE (dialog); + g_assert (priv); + + gtk_label_set_text (priv->message_label, message); +} diff --git a/hildon/hildon-set-password-dialog.h b/hildon/hildon-set-password-dialog.h new file mode 100644 index 0000000..4c360eb --- /dev/null +++ b/hildon/hildon-set-password-dialog.h @@ -0,0 +1,91 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#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)) + +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 G_GNUC_CONST +hildon_set_password_dialog_get_type (void); + +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_message (HildonSetPasswordDialog *dialog, + const gchar *message); + +G_END_DECLS + +#endif /* __HILDON_SET_PASSWORD_DIALOG_H__ */ + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-sort-dialog-private.h b/hildon/hildon-sort-dialog-private.h new file mode 100644 index 0000000..788660e --- /dev/null +++ b/hildon/hildon-sort-dialog-private.h @@ -0,0 +1,57 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_PRIVATE_H__ +#define __HILDON_SORT_DIALOG_PRIVATEH__ + +G_BEGIN_DECLS + +#define HILDON_SORT_DIALOG_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), HILDON_TYPE_SORT_DIALOG, HildonSortDialogPrivate)); + +typedef struct _HildonSortDialogPrivate HildonSortDialogPrivate; + +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; +}; + +G_END_DECLS + +#endif /* __HILDON_SORT_DIALOG_PRIVATE_H__ */ diff --git a/hildon/hildon-sort-dialog.c b/hildon/hildon-sort-dialog.c new file mode 100644 index 0000000..3f5b49f --- /dev/null +++ b/hildon/hildon-sort-dialog.c @@ -0,0 +1,589 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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. + * + * + * + * #HildonSortDialog has been deprecated since Hildon 2.2 + * See Migrating Sort Dialogs + * section to know how to migrate this deprecated widget. + * + * + * + * + * An example for using HildonSortDialog + * + * HildonSortDialog *sort_dialog = HILDON_SORT_DIALOG (hildon_sort_dialog_new (parent)); + * + * gint response_id, add_sort_index; + * + * sort_by[0] = STR_SORT_BY_DATE; + * sort_by[1] = STR_SORT_BY_NAME; + * sort_by[2] = STR_SORT_BY_SIZE; + * sort_by[3] = NULL; + * + * sorting_order[0] = STR_SORTING_ORDER_ASCENDING; + * sorting_order[1] = STR_SORTING_ORDER_DESCENDING; + * sorting_order[2] = NULL; + * + * add_sort_index = hildon_sort_dialog_add_sort_key (sort_dialog, STR_SORT_BY_DATE); + * + * hildon_sort_dialog_add_sort_key (sort_dialog, STR_SORT_BY_NAME); + * + * hildon_sort_dialog_add_sort_key (sort_dialog, STR_SORT_BY_SIZE); + * + * if (dialog.first_time_clicked == TRUE) + * { + * hildon_sort_dialog_set_sort_key (sort_dialog, add_sort_index); + * } + * + * if (dialog.first_time_clicked == FALSE) + * { + * hildon_sort_dialog_set_sort_key (sort_dialog, dialog.sort_key); + * hildon_sort_dialog_set_sort_order (sort_dialog, dialog.sort_order); + * } + * + * gtk_widget_show (GTK_WIDGET (sort_dialog)); + * + * response_id = gtk_dialog_run (GTK_DIALOG (sort_dialog)); + * + * if (response_id == GTK_RESPONSE_OK) + * { + * dialog.sort_key = hildon_sort_dialog_get_sort_key (sort_dialog); + * + * gtk_label_set_text (GTK_LABEL (dialog.label1), sort_by [dialog.sort_key]); + * + * dialog.sort_order = hildon_sort_dialog_get_sort_order (sort_dialog); + * + * gtk_label_set_text (GTK_LABEL (dialog.label2), sorting_order [dialog.sort_order]); + * + * dialog.first_time_clicked = FALSE; + * } + * + * + */ + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "hildon-sort-dialog.h" +#include "hildon-caption.h" +#include "hildon-sort-dialog-private.h" + +#define _(String) \ + dgettext("hildon-libs", String) + +static GtkDialogClass* parent_class; + +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 void +sort_key_changed (GtkWidget *widget, + HildonSortDialog *dialog); + +static void +hildon_sort_dialog_finalize (GObject *object); + +static gint +hildon_sort_dialog_add_sort_key_with_sorting (HildonSortDialog *dialog, + const gchar *sort_key, + gboolean sorting); + +enum +{ + PROP_0, + PROP_SORT_KEY, + PROP_SORT_ORDER +}; + +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); + g_assert (priv); + + gint index = gtk_combo_box_get_active (GTK_COMBO_BOX (widget)); + g_return_if_fail (index < priv->index_counter && index > 0); + + 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; + + /** + * HildonSortDialog:sort-key: + * + * The currently active sort key. + */ + 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)); + + /** + * HildonSortDialog:sort-order: + * + * The sort order for the currently active sort key. + */ + 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); + g_return_val_if_fail (sort_key != NULL, -1); + + priv = HILDON_SORT_DIALOG_GET_PRIVATE (dialog); + g_assert (priv); + + 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); + g_assert (priv); + + 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); + g_assert (priv); + + 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), + _("wdgt_bd_sort"), + GTK_RESPONSE_OK); + /* 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 */ +} + +/** + * hildon_sort_dialog_get_type: + * + * Returns GType for HildonSortDialog as produced by + * g_type_register_static(). + * + * Returns: HildonSortDialog type + */ +GType G_GNUC_CONST +hildon_sort_dialog_get_type (void) +{ + 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); + g_assert (priv); + + 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); + g_assert (priv); + + 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); + g_assert (priv); + + 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); + g_assert (priv); + + 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 + * + */ +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; + + dialog = HILDON_SORT_DIALOG (object); + priv = HILDON_SORT_DIALOG_GET_PRIVATE (dialog); + g_assert (priv); + + 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/hildon-sort-dialog.h b/hildon/hildon-sort-dialog.h new file mode 100644 index 0000000..0653e89 --- /dev/null +++ b/hildon/hildon-sort-dialog.h @@ -0,0 +1,100 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#ifndef __HILDON_SORT_DIALOG_H__ +#define __HILDON_SORT_DIALOG_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _HildonSortDialog HildonSortDialog; + +typedef struct _HildonSortDialogClass HildonSortDialogClass; + + +#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)) + +#define HILDON_SORT_DIALOG_GET_CLASS(obj) \ + ((HildonSortDialogClass *) G_OBJECT_GET_CLASS(obj)) + +struct _HildonSortDialog +{ + GtkDialog parent; +}; + +struct _HildonSortDialogClass +{ + GtkDialogClass parent_class; +}; + +GType G_GNUC_CONST +hildon_sort_dialog_get_type (void); + +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, + int 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); + +gint +hildon_sort_dialog_add_sort_key_reversed (HildonSortDialog *dialog, + const gchar *sort_key); + +G_END_DECLS + +#endif /* __HILDON_SORT_DIALOG_H__ */ + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-sound.c b/hildon/hildon-sound.c new file mode 100644 index 0000000..1bbc264 --- /dev/null +++ b/hildon/hildon-sound.c @@ -0,0 +1,129 @@ +/* + * This file is a part of libhildon + * + * Copyright (C) 2005-2008 Nokia Corporation. All rights reserved. + * + * Contact: Kimmo Hämäläinen + * + * 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, or (at your option) any later version. + * + * 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-sound + * @short_description: libcanberra-based utility function for playing a sound. + * + */ + +#include +#include +#include + +#include "hildon-sound.h" + +#define ALARM_GCONF_PATH "/apps/osso/sound/system_alert_volume" + +static ca_context *hildon_ca_context_get (void); + +/* + * hildon_ca_context_get: + * + * hildon maintains a single application-global ca_context object. + * + * This functions is based on ca_gtk_context_get + * + * Returns: a ca_context object + */ +static ca_context * +hildon_ca_context_get (void) +{ + static GStaticPrivate context_private = G_STATIC_PRIVATE_INIT; + ca_context *c = NULL; + const gchar *name = NULL; + gint ret; + + if ((c = g_static_private_get(&context_private))) + return c; + + if ((ret = ca_context_create(&c)) != CA_SUCCESS) { + g_warning("ca_context_create: %s\n", ca_strerror(ret)); + return NULL; + } + if ((ret = ca_context_open(c)) != CA_SUCCESS) { + g_warning("ca_context_open: %s\n", ca_strerror(ret)); + ca_context_destroy(c); + return NULL; + } + + if ((name = g_get_application_name())) + ca_context_change_props(c, CA_PROP_APPLICATION_NAME, name, NULL); + + g_static_private_set(&context_private, c, (GDestroyNotify) ca_context_destroy); + + return c; +} + +/** + * hildon_play_system_sound: + * @sample: sound file to play + * + * Plays the given sample using libcanberra. + * Volume level is received from gconf. + */ +void +hildon_play_system_sound(const gchar *sample) +{ + float volume = 0; + int ret; + ca_context *ca_con = NULL; + ca_proplist *pl = NULL; + +#if 0 /* FIXME: Check volume handling. Would be great not to use Gconf... */ + GConfClient *client; + GConfValue *value; + gint gconf_vol; + + /* + * The volume is from -0dB to -6dB, + The full volume is marked as 2 in gconf */ + 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) + gconf_vol = 2; + else + gconf_vol = gconf_value_get_int(value); + + if (value) + gconf_value_free(value); + g_object_unref (client); + + volume = ((1.0 - (float)gconf_vol / 2.0)) * (-6.0); +#endif + + ca_con = hildon_ca_context_get (); + + ca_proplist_create(&pl); + ca_proplist_sets(pl, CA_PROP_MEDIA_FILENAME, sample); + ca_proplist_setf(pl, CA_PROP_CANBERRA_VOLUME, "%f", volume); + + ret = ca_context_play_full(ca_con, 0, pl, NULL, NULL); + g_debug("ca_context_play_full (vol %f): %s\n", volume, ca_strerror(ret)); + + ca_proplist_destroy(pl); +} diff --git a/hildon/hildon-sound.h b/hildon/hildon-sound.h new file mode 100644 index 0000000..75b843f --- /dev/null +++ b/hildon/hildon-sound.h @@ -0,0 +1,37 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_SOUND_H__ +#define __HILDON_SOUND_H__ + +#include + +G_BEGIN_DECLS + +void +hildon_play_system_sound (const gchar *sample); + +G_END_DECLS + +#endif /* __HILDON_SOUND_H__ */ diff --git a/hildon/hildon-stackable-window-private.h b/hildon/hildon-stackable-window-private.h new file mode 100644 index 0000000..e32f8d2 --- /dev/null +++ b/hildon/hildon-stackable-window-private.h @@ -0,0 +1,49 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_STACKABLE_WINDOW_PRIVATE_H__ +#define __HILDON_STACKABLE_WINDOW_PRIVATE_H__ + +G_BEGIN_DECLS + +typedef struct _HildonStackableWindowPrivate HildonStackableWindowPrivate; + +struct _HildonStackableWindowPrivate +{ + HildonWindowStack *stack; + gint stack_position; +}; + +#define HILDON_STACKABLE_WINDOW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ + HILDON_TYPE_STACKABLE_WINDOW, HildonStackableWindowPrivate)) + +void G_GNUC_INTERNAL +hildon_stackable_window_set_stack (HildonStackableWindow *self, + HildonWindowStack *stack, + gint position); + +G_END_DECLS + +#endif /* __HILDON_STACKABLE_WINDOW_PRIVATE_H__ */ diff --git a/hildon/hildon-stackable-window.c b/hildon/hildon-stackable-window.c new file mode 100644 index 0000000..d047a96 --- /dev/null +++ b/hildon/hildon-stackable-window.c @@ -0,0 +1,258 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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-stackable-window + * @short_description: Widget representing a stackable, top-level window in the Hildon framework. + * @see_also: #HildonWindowStack, #HildonProgram, #HildonWindow + * + * The #HildonStackableWindow is a GTK+ widget which represents a + * top-level window in the Hildon framework. It is derived from + * #HildonWindow. Applications that use stackable windows are organized + * in a hierarchical way so users can go from any window back to the + * application's root window. + * + * The user can only see and interact with the window on top of the + * stack. Although all other windows are mapped and visible, they are + * obscured by the topmost one so in practice they appear as if they + * were hidden. + * + * To add a window to the stack, just use gtk_widget_show(). The + * previous one will be obscured by the new one. When the new window + * is destroyed, the previous one will appear again. + * + * Alternatively, you can remove a window from the top of the stack + * without destroying it by using hildon_window_stack_pop(). The + * window will be automatically hidden and the previous one will + * appear. + * + * For advanced details on stack handling, see #HildonWindowStack + * + * + * Basic HildonStackableWindow example + * + * static void + * show_new_window (void) + * { + * GtkWidget *win; + * + * win = hildon_stackable_window_new (); + * + * // ... configure new window + * + * gtk_widget_show (win); + * } + * + * int + * main (int argc, char **argv) + * { + * GtkWidget *win; + * GtkWidget *button; + * + * gtk_init (&argc, &args); + * + * win = hildon_stackable_window_new (); + * gtk_window_set_title (GTK_WINDOW (win), "Main window); + * + * // ... add some widgets to the window + * + * g_signal_connect (button, "clicked", G_CALLBACK (show_new_window), NULL); + * g_signal_connect (win, "destroy", G_CALLBACK (gtk_main_quit), NULL); + * + * gtk_widget_show_all (win); + * gtk_main (); + * + * return 0; + * } + * + * + */ + +#include +#include +#include + +#include "hildon-stackable-window.h" +#include "hildon-stackable-window-private.h" +#include "hildon-window-stack.h" +#include "hildon-window-stack-private.h" + +G_DEFINE_TYPE (HildonStackableWindow, hildon_stackable_window, HILDON_TYPE_WINDOW); + +void G_GNUC_INTERNAL +hildon_stackable_window_set_stack (HildonStackableWindow *self, + HildonWindowStack *stack, + gint position) +{ + HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (self); + + if (stack) + g_object_ref (stack); + + if (priv->stack) + g_object_unref (priv->stack); + + priv->stack = stack; + priv->stack_position = position; +} + +/** + * hildon_stackable_window_get_stack: + * @self: a #HildonStackableWindow + * + * Returns the stack where window @self is on, or %NULL if the window + * is not stacked. + * + * Return value: a #HildonWindowStack, or %NULL + * + * Since: 2.2 + **/ +HildonWindowStack * +hildon_stackable_window_get_stack (HildonStackableWindow *self) +{ + HildonStackableWindowPrivate *priv; + + g_return_val_if_fail (HILDON_IS_STACKABLE_WINDOW (self), NULL); + + priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (self); + + return priv->stack; +} + +/** + * hildon_stackable_window_set_main_menu: + * @self: a #HildonStackableWindow + * @menu: a #HildonAppMenu to be used for this window + * + * Deprecated: Hildon 2.2: use hildon_window_set_app_menu() + **/ +void +hildon_stackable_window_set_main_menu (HildonStackableWindow *self, + HildonAppMenu *menu) +{ + hildon_window_set_app_menu (HILDON_WINDOW (self), menu); +} + +static void +hildon_stackable_window_map (GtkWidget *widget) +{ + GdkDisplay *display; + Atom atom; + unsigned long val; + HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (widget); + + val = priv->stack_position; + + /* Set additional property "_HILDON_STACKABLE_WINDOW", to allow the WM to manage + it as a stackable window. */ + display = gdk_drawable_get_display (widget->window); + atom = gdk_x11_get_xatom_by_name_for_display (display, "_HILDON_STACKABLE_WINDOW"); + XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (widget->window), atom, + XA_INTEGER, 32, PropModeReplace, + (unsigned char *) &val, 1); + + GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->map (widget); +} + +static void +hildon_stackable_window_show (GtkWidget *widget) +{ + HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (widget); + + /* Stack the window if not already stacked */ + if (priv->stack == NULL) { + HildonWindowStack *stack = hildon_window_stack_get_default (); + _hildon_window_stack_do_push (stack, HILDON_STACKABLE_WINDOW (widget)); + } + + GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->show (widget); +} + +static void +hildon_stackable_window_hide (GtkWidget *widget) +{ + HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (widget); + + if (priv->stack) { + hildon_window_stack_remove (HILDON_STACKABLE_WINDOW (widget)); + } + + GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->hide (widget); +} + +static gboolean +hildon_stackable_window_delete_event (GtkWidget *widget, + GdkEventAny *event) +{ + HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (widget); + gboolean retvalue = FALSE; + + if (priv->stack && hildon_window_stack_peek (priv->stack) != widget) { + /* Ignore the delete event if this window is not the topmost one */ + retvalue = TRUE; + } else if (GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->delete_event) { + retvalue = GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->delete_event (widget, event); + } + + return retvalue; +} + +static void +hildon_stackable_window_class_init (HildonStackableWindowClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + widget_class->map = hildon_stackable_window_map; + widget_class->show = hildon_stackable_window_show; + widget_class->hide = hildon_stackable_window_hide; + widget_class->delete_event = hildon_stackable_window_delete_event; + + g_type_class_add_private (klass, sizeof (HildonStackableWindowPrivate)); +} + +static void +hildon_stackable_window_init (HildonStackableWindow *self) +{ + HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (self); + + priv->stack = NULL; + priv->stack_position = -1; +} + +/** + * hildon_stackable_window_new: + * + * Creates a new #HildonStackableWindow. + * + * Return value: A #HildonStackableWindow + * + * Since: 2.2 + **/ +GtkWidget* +hildon_stackable_window_new (void) +{ + HildonStackableWindow *newwindow = g_object_new (HILDON_TYPE_STACKABLE_WINDOW, NULL); + + return GTK_WIDGET (newwindow); +} diff --git a/hildon/hildon-stackable-window.h b/hildon/hildon-stackable-window.h new file mode 100644 index 0000000..2e2a712 --- /dev/null +++ b/hildon/hildon-stackable-window.h @@ -0,0 +1,100 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_STACKABLE_WINDOW_H__ +#define __HILDON_STACKABLE_WINDOW_H__ + +#include "hildon-window.h" +#include "hildon-app-menu.h" + +G_BEGIN_DECLS + +#define HILDON_TYPE_STACKABLE_WINDOW \ + (hildon_stackable_window_get_type()) + +#define HILDON_STACKABLE_WINDOW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + HILDON_TYPE_STACKABLE_WINDOW, \ + HildonStackableWindow)) + +#define HILDON_STACKABLE_WINDOW_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + HILDON_TYPE_STACKABLE_WINDOW, \ + HildonStackableWindowClass)) + +#define HILDON_IS_STACKABLE_WINDOW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + HILDON_TYPE_STACKABLE_WINDOW)) + +#define HILDON_IS_STACKABLE_WINDOW_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + HILDON_TYPE_STACKABLE_WINDOW)) + +#define HILDON_STACKABLE_WINDOW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + HILDON_TYPE_STACKABLE_WINDOW, \ + HildonStackableWindowClass)) + +#ifndef _TYPEDEF_HILDON_WINDOW_STACK_ +#define _TYPEDEF_HILDON_WINDOW_STACK_ +typedef struct _HildonWindowStack HildonWindowStack; +#endif + +typedef struct _HildonStackableWindow HildonStackableWindow; +typedef struct _HildonStackableWindowClass HildonStackableWindowClass; + +struct _HildonStackableWindowClass +{ + HildonWindowClass parent_class; + + /* Padding for future extension */ + void (*_hildon_reserved1)(void); + void (*_hildon_reserved2)(void); + void (*_hildon_reserved3)(void); + void (*_hildon_reserved4)(void); +}; + +struct _HildonStackableWindow +{ + HildonWindow parent; +}; + +GType +hildon_stackable_window_get_type (void) G_GNUC_CONST; + +GtkWidget* +hildon_stackable_window_new (void); + +#ifndef HILDON_DISABLE_DEPRECATED +void +hildon_stackable_window_set_main_menu (HildonStackableWindow *self, + HildonAppMenu *menu); +#endif + +HildonWindowStack * +hildon_stackable_window_get_stack (HildonStackableWindow *self); + +G_END_DECLS + +#endif /* __HILDON_STACKABLE_WINDOW_H__ */ diff --git a/hildon/hildon-text-view.c b/hildon/hildon-text-view.c new file mode 100644 index 0000000..4630999 --- /dev/null +++ b/hildon/hildon-text-view.c @@ -0,0 +1,342 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +/** + * SECTION:hildon-text-view + * @short_description: Widget representing a text view in the Hildon framework. + * + * The #HildonTextView is a GTK widget which represents a text + * view. It is derived from the #GtkTextView widget and provides + * additional commodities specific to the Hildon framework. + * + * Besides all the features inherited from #GtkTextView, a + * #HildonTextView can also have a placeholder text. This text will be + * shown if the text view is empty and doesn't have the input focus, + * but it's otherwise ignored. Thus, calls to + * hildon_text_view_get_buffer() will never return the placeholder + * text, not even when it's being displayed. + * + * Although #HildonTextView is derived from #GtkTextView, + * gtk_text_view_get_buffer() and gtk_text_view_set_buffer() must + * never be used to get/set the buffer in this + * widget. hildon_text_view_get_buffer() and + * hildon_text_view_set_buffer() must be used instead. + * + * + * Creating a HildonTextView with a placeholder + * + * GtkWidget * + * create_text_view (void) + * { + * GtkWidget *text_view; + * + * text_view = hildon_text_view_new (); + * hildon_text_view_set_placeholder (HILDON_TEXT_VIEW (text_view), + * "Type some text here"); + * + * return text_view; + * } + * + * + */ + +#include "hildon-text-view.h" +#include "hildon-helper.h" +#include + +#define HILDON_TEXT_VIEW_DRAG_THRESHOLD 16.0 + +G_DEFINE_TYPE (HildonTextView, hildon_text_view, GTK_TYPE_TEXT_VIEW); + +#define HILDON_TEXT_VIEW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_TEXT_VIEW, HildonTextViewPrivate)); + +typedef struct _HildonTextViewPrivate HildonTextViewPrivate; + +struct _HildonTextViewPrivate +{ + GtkTextBuffer *main_buffer; /* Used to show the "real" contents */ + GtkTextBuffer *placeholder_buffer; /* Internal, used to display the placeholder */ + gulong changed_id; /* ID of the main_buffer::changed signal handler */ + gdouble x; /* tap x position */ + gdouble y; /* tap y position */ +}; + +/* Function used to decide whether to show the placeholder or not */ +static void +hildon_text_view_refresh_contents (GtkWidget *text_view) +{ + HildonTextViewPrivate *priv = HILDON_TEXT_VIEW_GET_PRIVATE (text_view); + gint bufsize = gtk_text_buffer_get_char_count (priv->main_buffer); + + if ((bufsize > 0) || GTK_WIDGET_HAS_FOCUS (text_view)) { + /* Display the main buffer if it contains text or the widget is focused */ + hildon_helper_set_logical_color (text_view, GTK_RC_TEXT, GTK_STATE_NORMAL, "ReversedTextColor"); + gtk_text_view_set_buffer (GTK_TEXT_VIEW (text_view), priv->main_buffer); + } else { + /* Otherwise, display the placeholder */ + hildon_helper_set_logical_color (text_view, GTK_RC_TEXT, GTK_STATE_NORMAL, "ReversedSecondaryTextColor"); + gtk_text_view_set_buffer (GTK_TEXT_VIEW (text_view), priv->placeholder_buffer); + } +} + +/** + * hildon_text_view_set_buffer: + * @text_view: a #HildonTextView + * @buffer: a #GtkTextBuffer + * + * Sets @buffer as the buffer being displayed by @text_view. The + * previous buffer displayed by the text view is unreferenced, and a + * reference is added to @buffer. If you owned a reference to @buffer + * before passing it to this function, you must remove that reference + * yourself + * + * Note that you must never use gtk_text_view_set_buffer() to set the + * buffer of a #HildonTextView. + * + * Since: 2.2 + */ +void +hildon_text_view_set_buffer (HildonTextView *text_view, + GtkTextBuffer *buffer) +{ + HildonTextViewPrivate *priv; + + g_return_if_fail (HILDON_IS_TEXT_VIEW (text_view)); + g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer)); + + priv = HILDON_TEXT_VIEW_GET_PRIVATE (text_view); + + /* If this is the same buffer, don't do anything */ + if (buffer == priv->main_buffer) + return; + + /* Disconnect the signal handler from the old buffer */ + g_signal_handler_disconnect (priv->main_buffer, priv->changed_id); + + /* Replace the old buffer with the new one */ + g_object_unref (priv->main_buffer); + priv->main_buffer = g_object_ref (buffer); + + /* Attach a callback to the new text buffer */ + priv->changed_id = + g_signal_connect_swapped (priv->main_buffer, "changed", + G_CALLBACK (hildon_text_view_refresh_contents), text_view); + + /* Refresh textview contents */ + hildon_text_view_refresh_contents (GTK_WIDGET (text_view)); +} + +/** + * hildon_text_view_get_buffer: + * @text_view: a #HildonTextView + * + * Returns the text buffer in @text_view. The reference count is not + * incremented; the caller of this function won't own a new reference. + * + * Note that you must never use gtk_text_view_get_buffer() to get the + * buffer from a #HildonTextView. + * + * Also note that placeholder text (set using + * hildon_text_view_set_placeholder()) is never contained in this + * buffer. + * + * Returns: a #GtkTextBuffer + * + * Since: 2.2 + */ +GtkTextBuffer * +hildon_text_view_get_buffer (HildonTextView *text_view) +{ + HildonTextViewPrivate *priv; + + g_return_val_if_fail (HILDON_IS_TEXT_VIEW (text_view), NULL); + + priv = HILDON_TEXT_VIEW_GET_PRIVATE (text_view); + + /* Always return priv->main_buffer even if the placeholder is + * being displayed */ + return priv->main_buffer; +} + +/** + * hildon_text_view_set_placeholder: + * @text_view: a #HildonTextView + * @text: the new text + * + * Sets the placeholder text in @text_view to @text. + * + * Since: 2.2 + */ +void +hildon_text_view_set_placeholder (HildonTextView *text_view, + const gchar *text) +{ + HildonTextViewPrivate *priv; + + g_return_if_fail (HILDON_IS_TEXT_VIEW (text_view) && text != NULL); + + priv = HILDON_TEXT_VIEW_GET_PRIVATE (text_view); + + gtk_text_buffer_set_text (priv->placeholder_buffer, text, -1); +} + +/** + * hildon_text_view_new: + * + * Creates a new text view. + * + * Returns: a new #HildonTextView + * + * Since: 2.2 + */ +GtkWidget * +hildon_text_view_new (void) +{ + GtkWidget *entry = g_object_new (HILDON_TYPE_TEXT_VIEW, NULL); + + return entry; +} + +static gboolean +hildon_text_view_focus_in_event (GtkWidget *widget, + GdkEventFocus *event) +{ + hildon_text_view_refresh_contents (widget); + + if (GTK_WIDGET_CLASS (hildon_text_view_parent_class)->focus_in_event) { + return GTK_WIDGET_CLASS (hildon_text_view_parent_class)->focus_in_event (widget, event); + } else { + return FALSE; + } +} + +static gboolean +hildon_text_view_focus_out_event (GtkWidget *widget, + GdkEventFocus *event) +{ + hildon_text_view_refresh_contents (widget); + + if (GTK_WIDGET_CLASS (hildon_text_view_parent_class)->focus_out_event) { + return GTK_WIDGET_CLASS (hildon_text_view_parent_class)->focus_out_event (widget, event); + } else { + return FALSE; + } +} + +static gint +hildon_text_view_button_press_event (GtkWidget *widget, + GdkEventButton *event) +{ + HildonTextViewPrivate *priv = HILDON_TEXT_VIEW_GET_PRIVATE (widget); + + if (GTK_TEXT_VIEW (widget)->editable && + hildon_gtk_im_context_filter_event (GTK_TEXT_VIEW (widget)->im_context, (GdkEvent*)event)) { + GTK_TEXT_VIEW (widget)->need_im_reset = TRUE; + return TRUE; + } + + if (event->button == 1 && event->type == GDK_BUTTON_PRESS) { + priv->x = event->x; + priv->y = event->y; + + return TRUE; + } + + return FALSE; +} + +static gint +hildon_text_view_button_release_event (GtkWidget *widget, + GdkEventButton *event) +{ + GtkTextView *text_view = GTK_TEXT_VIEW (widget); + HildonTextViewPrivate *priv = HILDON_TEXT_VIEW_GET_PRIVATE (widget); + GtkTextIter iter; + gint x, y; + + if (text_view->editable && + hildon_gtk_im_context_filter_event (text_view->im_context, (GdkEvent*)event)) { + text_view->need_im_reset = TRUE; + return TRUE; + } + + if (event->button == 1 && event->type == GDK_BUTTON_RELEASE) { + if (fabs (priv->x - event->x) < HILDON_TEXT_VIEW_DRAG_THRESHOLD && + fabs (priv->y - event->y) < HILDON_TEXT_VIEW_DRAG_THRESHOLD) { + GtkTextWindowType window_type; + + window_type = gtk_text_view_get_window_type (text_view, event->window); + gtk_text_view_window_to_buffer_coords (text_view, + window_type, + event->x, event->y, + &x, &y); + gtk_text_view_get_iter_at_location (text_view, &iter, x, y); + if (gtk_text_buffer_get_char_count (priv->main_buffer)) + gtk_text_buffer_place_cursor (priv->main_buffer, &iter); + + gtk_widget_grab_focus (GTK_WIDGET (text_view)); + + return TRUE; + } + } + return FALSE; +} + +static void +hildon_text_view_finalize (GObject *object) +{ + HildonTextViewPrivate *priv = HILDON_TEXT_VIEW_GET_PRIVATE (object); + + g_signal_handler_disconnect (priv->main_buffer, priv->changed_id); + g_object_unref (priv->main_buffer); + g_object_unref (priv->placeholder_buffer); + + if (G_OBJECT_CLASS (hildon_text_view_parent_class)->finalize) + G_OBJECT_CLASS (hildon_text_view_parent_class)->finalize (object); +} + +static void +hildon_text_view_class_init (HildonTextViewClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass *)klass; + GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; + + gobject_class->finalize = hildon_text_view_finalize; + widget_class->focus_in_event = hildon_text_view_focus_in_event; + widget_class->focus_out_event = hildon_text_view_focus_out_event; + widget_class->motion_notify_event = NULL; + widget_class->button_press_event = hildon_text_view_button_press_event; + widget_class->button_release_event = hildon_text_view_button_release_event; + + g_type_class_add_private (klass, sizeof (HildonTextViewPrivate)); +} + +static void +hildon_text_view_init (HildonTextView *self) +{ + HildonTextViewPrivate *priv = HILDON_TEXT_VIEW_GET_PRIVATE (self); + + priv->main_buffer = gtk_text_buffer_new (NULL); + priv->placeholder_buffer = gtk_text_buffer_new (NULL); + + hildon_text_view_refresh_contents (GTK_WIDGET (self)); + + priv->changed_id = + g_signal_connect_swapped (priv->main_buffer, "changed", + G_CALLBACK (hildon_text_view_refresh_contents), self); +} diff --git a/hildon/hildon-text-view.h b/hildon/hildon-text-view.h new file mode 100644 index 0000000..87b78a6 --- /dev/null +++ b/hildon/hildon-text-view.h @@ -0,0 +1,79 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +#ifndef __HILDON_TEXT_VIEW_H__ +#define __HILDON_TEXT_VIEW_H__ + +#include + +G_BEGIN_DECLS + +#define HILDON_TYPE_TEXT_VIEW \ + (hildon_text_view_get_type()) + +#define HILDON_TEXT_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + HILDON_TYPE_TEXT_VIEW, HildonTextView)) + +#define HILDON_TEXT_VIEW_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + HILDON_TYPE_TEXT_VIEW, HildonTextViewClass)) + +#define HILDON_IS_TEXT_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_TEXT_VIEW)) + +#define HILDON_IS_TEXT_VIEW_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_TEXT_VIEW)) + +#define HILDON_TEXT_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + HILDON_TYPE_TEXT_VIEW, HildonTextViewClass)) + +typedef struct _HildonTextView HildonTextView; + +typedef struct _HildonTextViewClass HildonTextViewClass; + +struct _HildonTextViewClass +{ + GtkTextViewClass parent_class; +}; + +struct _HildonTextView +{ + GtkTextView parent; +}; + + +GType +hildon_text_view_get_type (void) G_GNUC_CONST; + +GtkWidget * +hildon_text_view_new (void); + +void +hildon_text_view_set_buffer (HildonTextView *text_view, + GtkTextBuffer *buffer); + +GtkTextBuffer * +hildon_text_view_get_buffer (HildonTextView *text_view); + +void +hildon_text_view_set_placeholder (HildonTextView *text_view, + const gchar *text); + +G_END_DECLS + +#endif /* __HILDON_TEXT_VIEW_H__ */ diff --git a/hildon/hildon-time-button.c b/hildon/hildon-time-button.c new file mode 100644 index 0000000..86f13f2 --- /dev/null +++ b/hildon/hildon-time-button.c @@ -0,0 +1,188 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +/** + * SECTION:hildon-time-button + * @Short_Description: Button displaying and allowing selection of a time. + * @See_Also: #HildonPickerButton, #HildonDateButton + * + * #HildonTimeButton is a widget that shows a text label and a time, and allows + * the user to select a different time. Visually, it's a button that, once clicked, + * presents a #HildonPickerDialog containing a #HildonTimeSelector. Once the user selects + * a different time from the selector, this will be shown in the button. + */ + +#include + +#include "hildon-time-selector.h" +#include "hildon-touch-selector.h" +#include "hildon-picker-button.h" +#include "hildon-time-button.h" + +#define _(String) \ + dgettext("hildon-libs", String) + +#define c_(String) \ + dgettext("hildon-common-strings", String) + +G_DEFINE_TYPE (HildonTimeButton, hildon_time_button, HILDON_TYPE_PICKER_BUTTON) + +#if 0 +#define GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), HILDON_TYPE_TIME_BUTTON, HildonTimeButtonPrivate)) +typedef struct _HildonTimeButtonPrivate HildonTimeButtonPrivate; + +struct _HildonTimeButtonPrivate +{ +}; +#endif + +#if 0 +static void +hildon_time_button_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +hildon_time_button_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} +#endif + +static void +hildon_time_button_class_init (HildonTimeButtonClass * klass) +{ +#if 0 + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (HildonTimeButtonPrivate)); + + object_class->get_property = hildon_time_button_get_property; + object_class->set_property = hildon_time_button_set_property; +#endif +} + +static void +hildon_time_button_init (HildonTimeButton * self) +{ +} + +/** + * hildon_time_button_new: + * @size: One of #HildonSizeType + * @arrangement: one of #HildonButtonArrangement + * + * Creates a new #HildonTimeButton. See hildon_button_new() for details on the + * parameters. + * + * Returns: a new #HildonTimeButton + * + * Since: 2.2 + **/ +GtkWidget * +hildon_time_button_new (HildonSizeType size, + HildonButtonArrangement arrangement) +{ + return hildon_time_button_new_step (size, arrangement, 1); +} + +/** + * hildon_time_button_new_step: + * @size: One of #HildonSizeType + * @arrangement: one of #HildonButtonArrangement + * @minutes_step: step between the minutes in the selector options + * + * Creates a new #HildonTimeButton. See hildon_button_new() for details on the + * parameters. + * + * Returns: a new #HildonTimeButton + * + * Since: 2.2 + **/ +GtkWidget * +hildon_time_button_new_step (HildonSizeType size, + HildonButtonArrangement arrangement, + guint minutes_step) +{ + return g_object_new (HILDON_TYPE_TIME_BUTTON, + "title", _("wdgt_ti_time"), + "arrangement", arrangement, + "size", size, + "touch-selector", hildon_time_selector_new_step (minutes_step), + NULL); +} + +/** + * hildon_time_button_get_time: + * @button: a #HildonTimeButton + * @hours: return location for the hours of the time selected + * @minutes: return location for the minutes of the time selected + * + * Retrieves the time from @button. + * + * Since: 2.2 + **/ +void +hildon_time_button_get_time (HildonTimeButton * button, + guint * hours, guint * minutes) +{ + HildonTouchSelector *selector; + + g_return_if_fail (HILDON_IS_TIME_BUTTON (button)); + + selector = hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (button)); + + hildon_time_selector_get_time (HILDON_TIME_SELECTOR (selector), hours, minutes); +} + +/** + * hildon_time_button_set_time: + * @button: a #HildonTimeButton + * @hours: the hours to be set + * @minutes: the time to be set + * + * Sets the time to be displayed in @button. This time will + * be selected by default on the #HildonTimeSelector. + * + * Since: 2.2 + **/ +void +hildon_time_button_set_time (HildonTimeButton * button, + guint hours, guint minutes) +{ + HildonTouchSelector *selector; + gchar *time; + + g_return_if_fail (HILDON_IS_TIME_BUTTON (button)); + + selector = hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (button)); + + hildon_time_selector_set_time (HILDON_TIME_SELECTOR (selector), hours, minutes); + + time = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector)); + hildon_button_set_value (HILDON_BUTTON (button), time); + g_free (time); +} diff --git a/hildon/hildon-time-button.h b/hildon/hildon-time-button.h new file mode 100644 index 0000000..4beb669 --- /dev/null +++ b/hildon/hildon-time-button.h @@ -0,0 +1,82 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; version 2 of the license. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + */ + +#ifndef __HILDON_TIME_BUTTON__ +#define __HILDON_TIME_BUTTON__ + +#include + +G_BEGIN_DECLS + +#define HILDON_TYPE_TIME_BUTTON \ + hildon_time_button_get_type() + +#define HILDON_TIME_BUTTON(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj),\ + HILDON_TYPE_TIME_BUTTON, HildonTimeButton)) + +#define HILDON_TIME_BUTTON_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + HILDON_TYPE_TIME_BUTTON, HildonTimeButtonClass)) + +#define HILDON_IS_TIME_BUTTON(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_TIME_BUTTON)) + +#define HILDON_IS_TIME_BUTTON_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_TIME_BUTTON)) + +#define HILDON_TIME_BUTTON_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + HILDON_TYPE_TIME_BUTTON, HildonTimeButtonClass)) + +typedef struct _HildonTimeButton HildonTimeButton; +typedef struct _HildonTimeButtonClass HildonTimeButtonClass; + +struct _HildonTimeButton +{ + HildonPickerButton parent; +}; + +struct _HildonTimeButtonClass +{ + HildonPickerButtonClass parent_class; +}; + +GType +hildon_time_button_get_type (void); + +GtkWidget* +hildon_time_button_new (HildonSizeType size, + HildonButtonArrangement arrangement); + +GtkWidget * +hildon_time_button_new_step (HildonSizeType size, + HildonButtonArrangement arrangement, + guint minutes_step); + +void +hildon_time_button_get_time (HildonTimeButton *button, + guint *hours, + guint *minutes); + +void +hildon_time_button_set_time (HildonTimeButton *button, + guint hours, + guint minutes); + +G_END_DECLS + +#endif /* _HILDON_TIME_BUTTON */ diff --git a/hildon/hildon-time-editor-private.h b/hildon/hildon-time-editor-private.h new file mode 100644 index 0000000..db51b30 --- /dev/null +++ b/hildon/hildon-time-editor-private.h @@ -0,0 +1,85 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_PRIVATE_H__ +#define __HILDON_TIME_EDITOR_PRIVATE_H__ + +#include + +G_BEGIN_DECLS + +#define HILDON_TIME_EDITOR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ + HILDON_TYPE_TIME_EDITOR, HildonTimeEditorPrivate)); + +/* Indices for h/m/s entries in priv->entries */ +enum { + ENTRY_HOURS, + ENTRY_MINS, + ENTRY_SECS, + + ENTRY_COUNT +}; + +typedef struct _HildonTimeEditorPrivate HildonTimeEditorPrivate; + +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. */ +}; + +G_END_DECLS + +#endif /* __HILDON_TIME_EDITOR_H__ */ diff --git a/hildon/hildon-time-editor.c b/hildon/hildon-time-editor.c new file mode 100644 index 0000000..8e2112b --- /dev/null +++ b/hildon/hildon-time-editor.c @@ -0,0 +1,1936 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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. + * + * + * + * #HildonTimeEditor has been deprecated since Hildon 2.2 and should not + * be used in newly written code. See + * Migrating Time Widgets + * section to know how to migrate this deprecated widget. + * + * + * + * + * HildonTimePicker example + * + * + * editor = hildon_time_editor_new (); + * hildon_time_editor_set_time (editor, h, m, s); + * + * gtk_box_pack_start (..., editor) + * + * hildon_time_editor_get_time (editor, &h, &m, &s); + * + * + * + * + */ + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include "hildon-time-editor.h" +#include "hildon-defines.h" +#include "hildon-time-picker.h" +#include "hildon-banner.h" +#include "hildon-private.h" +#include "hildon-marshalers.h" +#include "hildon-enum-types.h" +#include "hildon-time-editor-private.h" + +#define _(String) dgettext("hildon-libs", String) + +#define c_(String) dgettext("hildon-common-strings", String) + +#define TICKS(h,m,s) \ + ((h) * 3600 + (m) * 60 + (s)) + +#define TIME_EDITOR_HEIGHT 30 + +#define ICON_PRESSED 4 + +#define ICON_NAME "widgets_time_editor" + +#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; + +enum +{ + PROP_0, + PROP_TICKS, + PROP_DURATION_MODE, + PROP_DURATION_MIN, + PROP_DURATION_MAX, + PROP_SHOW_SECONDS, + PROP_SHOW_HOURS +}; + +/* 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] = { + HILDON_DATE_TIME_ERROR_MAX_HOURS, + HILDON_DATE_TIME_ERROR_MIN_HOURS, + HILDON_DATE_TIME_ERROR_EMPTY_HOURS }; + +static guint min_errors[NUM_ERROR_CODES] = { + HILDON_DATE_TIME_ERROR_MAX_MINS, + HILDON_DATE_TIME_ERROR_MIN_MINS, + HILDON_DATE_TIME_ERROR_EMPTY_MINS }; + +static guint sec_errors[NUM_ERROR_CODES] = { + HILDON_DATE_TIME_ERROR_MAX_SECS, + HILDON_DATE_TIME_ERROR_MIN_SECS, + HILDON_DATE_TIME_ERROR_EMPTY_SECS }; + +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); + +static gboolean +hildon_time_editor_entry_focus_out (GtkWidget *widget, + GdkEventFocus *event, + gpointer data); + +static gboolean +hildon_time_editor_entry_focus_in (GtkWidget *widget, + GdkEventFocus *event, + gpointer data); + +static gboolean +hildon_time_editor_time_error (HildonTimeEditor *editor, + HildonDateTimeError 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_focus (GtkWidget *widget, + GtkDirectionType direction); + +static gboolean +hildon_time_editor_entry_keypress (GtkEntry *entry, + GdkEventKey* event, + gpointer user_data); + +static gboolean +hildon_time_editor_check_locale (HildonTimeEditor *editor); + +#ifdef MAEMO_GTK +static void +hildon_time_editor_tap_and_hold_setup (GtkWidget *widget, + GtkWidget *menu, + GtkCallback func, + GtkWidgetTapAndHoldFlags flags); +#endif + +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); + +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); + +/** + * hildon_time_editor_get_type: + * + * Initializes and returns the type of a hildon time editor. + * + * Returns: GType of #HildonTimeEditor + */ +GType G_GNUC_CONST +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) +{ + HildonTimeEditorPrivate *priv; + + g_assert (HILDON_IS_TIME_EDITOR (container)); + g_assert (callback != NULL); + + priv = HILDON_TIME_EDITOR_GET_PRIVATE (container); + + g_assert (priv); + + 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); + g_assert (priv); + + 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->focus = hildon_time_editor_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_DATE_TIME_ERROR); + + /** + * 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) ); +} + +#ifdef MAEMO_GTK +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); +} +#endif + +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); + g_assert (priv); + + 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_SMALL); + 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); + +#ifdef MAEMO_GTK + /* Set the entries to accept only numeric characters */ + g_object_set (priv->entries[i], "hildon-input-mode", HILDON_GTK_INPUT_MODE_NUMERIC, NULL); +#endif + + /* 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_focus_in), editor); + g_signal_connect (priv->entries[i], "focus-out-event", + G_CALLBACK (hildon_time_editor_entry_focus_out), 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 (); + +#ifdef MAEMO_GTK + g_signal_connect (editor, "tap-and-hold-setup", + G_CALLBACK (hildon_time_editor_tap_and_hold_setup), + NULL); +#endif + +} + +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_assert (priv); + + if (priv->am_symbol) + g_free (priv->am_symbol); + + if (priv->pm_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: + * @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); + + /* 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++; + + if (hm_sep_label != NULL) + { + 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_return_if_fail (HILDON_IS_TIME_EDITOR (editor)); + + priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor); + g_assert (priv); + + /* 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_focus_out, 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_focus_out, 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 (HILDON_IS_TIME_EDITOR (editor), 0); + + priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); + g_assert (priv); + + 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); + g_assert (priv); + + 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); + g_assert (priv); + + 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); + g_assert (priv); + + 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); + g_assert (priv); + + 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); + g_assert (priv); + + 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); + g_assert (priv); + + 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); + g_assert (priv); + + 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); + g_assert (priv); + + 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) +{ + g_return_if_fail (HILDON_IS_TIME_EDITOR (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); + g_assert (priv); + + /* 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); + g_assert (priv); + + *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); + g_assert (priv); + + /* 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_focus_in (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, + HildonDateTimeError 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); + g_assert (priv); + + /* 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, HILDON_DATE_TIME_ERROR_MIN_DURATION, &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, HILDON_DATE_TIME_ERROR_MAX_DURATION, &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); + g_assert (priv); + + 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_focus_out, 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_focus_out, 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); + g_assert (priv); + + /* 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); + g_assert (priv); + + /* 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_focus_out (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); + g_assert (priv); + + /* 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); + g_assert (priv); + + /* 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; + gboolean rtl; + + g_assert (priv); + + rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL); + 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 */ + if (rtl) + gtk_widget_get_child_requisition (priv->iconbutton, &req); + else + gtk_widget_get_child_requisition (priv->frame, &req); + + alloc.width = req.width; + alloc.height = max_req.height; + if (rtl) + gtk_widget_size_allocate (priv->iconbutton, &alloc); + else + gtk_widget_size_allocate (priv->frame, &alloc); + + /* allocate icon */ + if (GTK_WIDGET_VISIBLE (priv->iconbutton)) { + if (rtl) + gtk_widget_get_child_requisition (priv->frame, &req); + else + gtk_widget_get_child_requisition (priv->iconbutton, &req); + + alloc.x += alloc.width + HILDON_MARGIN_DEFAULT; + alloc.width = req.width; + + if (rtl) + gtk_widget_size_allocate (priv->frame, &alloc); + else + 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_focus (GtkWidget *widget, + GtkDirectionType direction) +{ + gboolean retval; + GtkDirectionType effective_direction; + + g_assert (HILDON_IS_TIME_EDITOR (widget)); + + retval = hildon_private_composite_focus (widget, direction, &effective_direction); + + if (retval == TRUE) + return GTK_WIDGET_CLASS (parent_class)->focus (widget, effective_direction); + else + return FALSE; +} + +static gboolean +hildon_time_editor_entry_keypress (GtkEntry *entry, + GdkEventKey *event, + gpointer data) +{ + switch (event->keyval) + { + case GDK_Return: + case GDK_ISO_Enter: + hildon_time_editor_icon_clicked (GTK_WIDGET (entry), data); + return TRUE; + default: + return FALSE; + } + + g_assert_not_reached (); +} + +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. + * @show_hours: Enable or disable showing of hours. + * + * This function shows or hides the hours field. + * + **/ +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); + g_assert (priv); + + 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: + * @editor: the @HildonTimeEditor widget. + * + * This function returns a boolean indicating the visibility of + * hours in the @HildonTimeEditor + * + * Return value: TRUE if hours are visible. + * + **/ +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); + g_assert (priv); + + return priv->show_hours; +} + +/* 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/hildon-time-editor.h b/hildon/hildon-time-editor.h new file mode 100644 index 0000000..f1f09b9 --- /dev/null +++ b/hildon/hildon-time-editor.h @@ -0,0 +1,173 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#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 +{ + HILDON_DATE_TIME_ERROR_NO_ERROR = -1, + HILDON_DATE_TIME_ERROR_MAX_HOURS, + HILDON_DATE_TIME_ERROR_MAX_MINS, + HILDON_DATE_TIME_ERROR_MAX_SECS, + HILDON_DATE_TIME_ERROR_MAX_DAY, + HILDON_DATE_TIME_ERROR_MAX_MONTH, + HILDON_DATE_TIME_ERROR_MAX_YEAR, + HILDON_DATE_TIME_ERROR_MIN_HOURS, + HILDON_DATE_TIME_ERROR_MIN_MINS, + HILDON_DATE_TIME_ERROR_MIN_SECS, + HILDON_DATE_TIME_ERROR_MIN_DAY, + HILDON_DATE_TIME_ERROR_MIN_MONTH, + HILDON_DATE_TIME_ERROR_MIN_YEAR, + HILDON_DATE_TIME_ERROR_EMPTY_HOURS, + HILDON_DATE_TIME_ERROR_EMPTY_MINS, + HILDON_DATE_TIME_ERROR_EMPTY_SECS, + HILDON_DATE_TIME_ERROR_EMPTY_DAY, + HILDON_DATE_TIME_ERROR_EMPTY_MONTH, + HILDON_DATE_TIME_ERROR_EMPTY_YEAR, + HILDON_DATE_TIME_ERROR_MIN_DURATION, + HILDON_DATE_TIME_ERROR_MAX_DURATION, + HILDON_DATE_TIME_ERROR_INVALID_CHAR, + HILDON_DATE_TIME_ERROR_INVALID_DATE, + HILDON_DATE_TIME_ERROR_INVALID_TIME +} HildonDateTimeError; + +typedef struct _HildonTimeEditor HildonTimeEditor; + +typedef struct _HildonTimeEditorClass HildonTimeEditorClass; + +struct _HildonTimeEditor +{ + GtkContainer parent; +}; + +struct _HildonTimeEditorClass +{ + GtkContainerClass parent_class; + + gboolean (*time_error) (HildonTimeEditor *editor, + HildonDateTimeError type); +}; + +GType G_GNUC_CONST +hildon_time_editor_get_type (void); + +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); + +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); + +void +hildon_time_editor_get_time_separators (GtkLabel *hm_sep_label, + GtkLabel *ms_sep_label); + +G_END_DECLS + +#endif /* __HILDON_TIME_EDITOR_H__ */ + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-time-picker-private.h b/hildon/hildon-time-picker-private.h new file mode 100644 index 0000000..af57d8c --- /dev/null +++ b/hildon/hildon-time-picker-private.h @@ -0,0 +1,84 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_PRIVATE_H__ +#define __HILDON_TIME_PICKER_PRIVATE_H__ + +G_BEGIN_DECLS + +typedef struct _HildonTimePickerPrivate HildonTimePickerPrivate; + +#define HILDON_TIME_PICKER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_TIME_PICKER, HildonTimePickerPrivate)) + +enum +{ + WIDGET_GROUP_HOURS, + WIDGET_GROUP_10_MINUTES, + WIDGET_GROUP_1_MINUTES, + WIDGET_GROUP_AMPM, + + WIDGET_GROUP_COUNT +}; + +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; + +struct _HildonTimePickerPrivate +{ + HildonTimePickerWidgetGroup widgets[WIDGET_GROUP_COUNT]; + + gchar *am_symbol; + gchar *pm_symbol; + + 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; +}; + +G_END_DECLS + +#endif /* __HILDON_TIME_PICKER_PRIVATE_H__ */ diff --git a/hildon/hildon-time-picker.c b/hildon/hildon-time-picker.c new file mode 100644 index 0000000..04855da --- /dev/null +++ b/hildon/hildon-time-picker.c @@ -0,0 +1,1019 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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. + * + * + * + * #HildonTimePicker has been deprecated since Hildon 2.2 and should not + * be used in newly written code. See + * Migrating Time Widgets + * section to know how to migrate this deprecated widget. + * + * + * + * + * HildonTimePicker example + * + * + * 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: + * hildon_time_picker_get_time(HILDON_TIME_PICKER (picker), &h, &m ); + * foo_set_time(h,m); + * break; + * default: + * break; + * } + * + * gtk_widget_destroy( picker ); + * + * + * + */ + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hildon-time-picker.h" +#include "hildon-defines.h" +#include "hildon-time-picker-private.h" +#include "hildon-time-editor.h" + +#define _(String) \ + dgettext("hildon-libs", String) + +#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 + +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_realize (GtkWidget *widget); + +static void +hildon_time_picker_style_set (GtkWidget *widget, + GtkStyle *previous_style); + +static void +frame_size_request (GtkWidget *widget, + GtkRequisition *requistion); + +static GtkDialogClass* parent_class; + +enum +{ + PROP_0, + PROP_MINUTES +}; + +static const gint button_multipliers[WIDGET_GROUP_COUNT][2] = +{ + { MINS_IN_1H, -MINS_IN_1H }, + { 10, -10 }, + { 1, -1 }, + { 0, 0 } +}; + +/** + * hildon_time_picker_get_type: + * + * Returns the type of HildonTimePicker. + * + * Returns: HildonTimePicker type + */ +GType G_GNUC_CONST +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->realize = hildon_time_picker_realize; + widget_class->style_set = hildon_time_picker_style_set; + + /** + * 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]; + GtkDialog *dialog = GTK_DIALOG (picker); + GtkTable *table = NULL; + GtkWidget *maintocenter, *colon_label; + const struct tm *local = NULL; + time_t stamp; + gint i = 0; + + g_assert (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->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 (); + + /* 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, _("wdgt_bd_done"), + 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) +{ + HildonTimePickerPrivate *priv = HILDON_TIME_PICKER_GET_PRIVATE (object); + + g_assert (priv); + + /* Make sure the timer is stopped */ + if (priv->timer_id) + g_source_remove(priv->timer_id); + + g_free(priv->am_symbol); + g_free(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_GET_PRIVATE (object); + g_assert (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_realize (GtkWidget *widget) +{ + GTK_WIDGET_CLASS (parent_class)->realize(widget); + + /* We only want the border for the dialog. */ + gdk_window_set_decorations (widget->window, GDK_DECOR_BORDER); +} + +static void +hildon_time_picker_style_set (GtkWidget *widget, + GtkStyle *previous_style) +{ + guint width, height; + gint i, button; + HildonTimePickerPrivate *priv = HILDON_TIME_PICKER_GET_PRIVATE (widget); + g_assert (priv); + + GTK_WIDGET_CLASS (parent_class)->style_set(widget, previous_style); + + /* 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); + } + } + } +} + +/* + * Clicked hour/minute field. Move focus to it. + */ +static gboolean +hildon_time_picker_event_box_button_press (GtkWidget *widget, + GdkEventKey *event, + gpointer unused) +{ + gtk_widget_grab_focus (widget); + return FALSE; +} + +/* + * Clicked AM/PM label. Move focus to it and move the time by 12 hours. + */ +static gboolean +hildon_time_picker_ampm_release (GtkWidget *widget, + GdkEvent *event, + HildonTimePicker *picker) +{ + HildonTimePickerPrivate *priv = HILDON_TIME_PICKER_GET_PRIVATE (picker); + g_assert (priv); + + gtk_widget_grab_focus (widget); + hildon_time_picker_change_time (picker, priv->minutes > MINS_IN_12H ? + priv->minutes - MINS_IN_12H : + priv->minutes + MINS_IN_12H); + + return FALSE; +} + +static gboolean +hildon_time_picker_arrow_press (GtkWidget *widget, + GdkEvent *event, + HildonTimePicker *picker) +{ + HildonTimePickerPrivate *priv = HILDON_TIME_PICKER_GET_PRIVATE (picker); + gint i, button; + gint newval = 0; + gint key_repeat = 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); + + /* Get button press repeater timeout from settings (in milliseconds) */ + g_object_get (gtk_widget_get_settings (widget), + "gtk-timeout-repeat", &key_repeat, NULL); + + key_repeat *= 8; + + /* 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 (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 = HILDON_TIME_PICKER_GET_PRIVATE (picker); + g_assert (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; + HildonTimePickerPrivate *priv = HILDON_TIME_PICKER_GET_PRIVATE (picker); + + g_assert (priv); + + for (i = 0; i < WIDGET_GROUP_COUNT; i++) + { + if (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 = HILDON_TIME_PICKER_GET_PRIVATE (picker); + HildonTimePickerWidgetGroup *group; + gint group_idx; + + g_assert (priv); + + /* 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 : &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; + HildonTimePickerPrivate *priv = HILDON_TIME_PICKER_GET_PRIVATE (picker); + + g_assert (priv); + + /* 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 = &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; + gint key_repeat = 0; + + picker = HILDON_TIME_PICKER(tpicker); + g_assert(picker != NULL); + + priv = HILDON_TIME_PICKER_GET_PRIVATE (tpicker); + g_assert (priv); + + GDK_THREADS_ENTER (); + + /* 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) + { + /* Get button press repeater timeout from settings (in milliseconds) */ + g_object_get (gtk_widget_get_settings ((GtkWidget *) tpicker), + "gtk-timeout-repeat", &key_repeat, NULL); + + key_repeat *= 8; + + /* 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 (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 = HILDON_TIME_PICKER_GET_PRIVATE (picker); + + gchar str[3] = "00"; + guint hours = 0; + gboolean ampm = TRUE; + + g_assert (priv); + + /* 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)); + + HildonTimePickerPrivate *priv = HILDON_TIME_PICKER_GET_PRIVATE (picker); + g_assert (priv); + + current = priv->minutes; + *hours = current / MINS_IN_1H; + *minutes = current % MINS_IN_1H; +} + + diff --git a/hildon/hildon-time-picker.h b/hildon/hildon-time-picker.h new file mode 100644 index 0000000..e36d777 --- /dev/null +++ b/hildon/hildon-time-picker.h @@ -0,0 +1,92 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#ifndef __HILDON_TIME_PICKER_H__ +#define __HILDON_TIME_PICKER_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _HildonTimePicker HildonTimePicker; + +typedef struct _HildonTimePickerClass HildonTimePickerClass; + +#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)) + +#define HILDON_TIME_PICKER_GET_CLASS(obj) \ + ((HildonTimePickerClass *) G_OBJECT_GET_CLASS(obj)) + +struct _HildonTimePicker +{ + GtkDialog parent; +}; + +struct _HildonTimePickerClass +{ + GtkDialogClass parent_class; +}; + +GType G_GNUC_CONST +hildon_time_picker_get_type (void); + +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__ */ + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-time-selector.c b/hildon/hildon-time-selector.c new file mode 100644 index 0000000..e605d40 --- /dev/null +++ b/hildon/hildon-time-selector.c @@ -0,0 +1,731 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2008 Nokia Corporation. + * + * 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; either + * version 2 of the License, or (at your option) any later version. or (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/** + * SECTION:hildon-time-selector + * @short_description: A widget to select the current time. + * + * #HildonTimeSelector allows users to choose a time by selecting hour + * and minute. It also allows choosing between AM or PM format. + * + * The currently selected time can be altered with + * hildon_time_selector_set_time(), and retrieved using + * hildon_time_selector_get_time(). + * + * Use this widget instead of deprecated HildonTimeEditor widget. + */ + +#define _GNU_SOURCE /* needed for GNU nl_langinfo_l */ +#define __USE_GNU /* needed for locale */ + +#ifdef HAVE_SYS_TIME_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "hildon-enum-types.h" +#include "hildon-time-selector.h" +#include "hildon-touch-selector-private.h" + +#define HILDON_TIME_SELECTOR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_TIME_SELECTOR, HildonTimeSelectorPrivate)) + +G_DEFINE_TYPE (HildonTimeSelector, hildon_time_selector, HILDON_TYPE_TOUCH_SELECTOR) + +#define INIT_YEAR 100 +#define LAST_YEAR 50 /* since current year */ + +#define _(String) dgettext("hildon-libs", String) +#define N_(String) String + + +/* FIXME: we should get this two props from the clock ui headers */ +#define CLOCK_GCONF_PATH "/apps/clock" +#define CLOCK_GCONF_IS_24H_FORMAT CLOCK_GCONF_PATH "/time-format" + +enum { + COLUMN_STRING, + COLUMN_INT, + TOTAL_MODEL_COLUMNS +}; + +enum { + COLUMN_HOURS = 0, + COLUMN_MINUTES, + COLUMN_AMPM, + TOTAL_TIME_COLUMNS +}; + +enum +{ + PROP_0, + PROP_MINUTES_STEP, + PROP_TIME_FORMAT_POLICY +}; + +struct _HildonTimeSelectorPrivate +{ + GtkTreeModel *hours_model; + GtkTreeModel *minutes_model; + GtkTreeModel *ampm_model; + + guint minutes_step; + HildonTimeSelectorFormatPolicy format_policy; + gboolean ampm_format; /* if using am/pm format or 24 h one */ + + gboolean pm; /* if we are on pm (only useful if ampm_format == TRUE) */ + + gint creation_hours; + gint creation_minutes; +}; + +static void hildon_time_selector_finalize (GObject * object); +static GObject* hildon_time_selector_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_params); +static void hildon_time_selector_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec); +static void hildon_time_selector_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec); + +/* private functions */ +static GtkTreeModel *_create_hours_model (HildonTimeSelector * selector); +static GtkTreeModel *_create_minutes_model (guint minutes_step); +static GtkTreeModel *_create_ampm_model (HildonTimeSelector * selector); + +static void _get_real_time (gint * hours, gint * minutes); +static void _manage_ampm_selection_cb (HildonTouchSelector * selector, + gint num_column, gpointer data); +static void _set_pm (HildonTimeSelector * selector, gboolean pm); + +static gchar *_custom_print_func (HildonTouchSelector * selector, + gpointer user_data); + +static void +check_automatic_ampm_format (HildonTimeSelector * selector); + +static void +update_format_policy (HildonTimeSelector *selector, + HildonTimeSelectorFormatPolicy new_policy); +static void +update_format_dependant_columns (HildonTimeSelector *selector, + guint hours, + guint minutes); + +static void +hildon_time_selector_class_init (HildonTimeSelectorClass * class) +{ + GObjectClass *gobject_class; + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + GtkContainerClass *container_class; + + gobject_class = (GObjectClass *) class; + object_class = (GtkObjectClass *) class; + widget_class = (GtkWidgetClass *) class; + container_class = (GtkContainerClass *) class; + + /* GObject */ + gobject_class->get_property = hildon_time_selector_get_property; + gobject_class->set_property = hildon_time_selector_set_property; + gobject_class->constructor = hildon_time_selector_constructor; + gobject_class->finalize = hildon_time_selector_finalize; + + g_object_class_install_property (gobject_class, + PROP_MINUTES_STEP, + g_param_spec_uint ("minutes-step", + "Step between minutes in the model", + "Step between the minutes in the list of" + " options of the widget ", + 1, 30, 1, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); + + /** + * HildonTimeSelector:time-format-policy: + * + * The visual policy of the time format + * + * Since: 2.2 + */ + g_object_class_install_property (gobject_class, + PROP_TIME_FORMAT_POLICY, + g_param_spec_enum ("time_format_policy", + "time format policy", + "Visual policy of the time format", + HILDON_TYPE_TIME_SELECTOR_FORMAT_POLICY, + HILDON_TIME_SELECTOR_FORMAT_POLICY_AUTOMATIC, + G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); + + /* GtkWidget */ + + /* GtkContainer */ + + /* signals */ + + g_type_class_add_private (object_class, sizeof (HildonTimeSelectorPrivate)); +} + +/* FIXME: the constructor was required because as we need the initial values + of the properties passed on g_object_new. But, probably use the method + constructed could be easier */ +static GObject* +hildon_time_selector_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_params) +{ + GObject *object; + HildonTimeSelector *selector; + HildonTouchSelectorColumn *column; + + object = (* G_OBJECT_CLASS (hildon_time_selector_parent_class)->constructor) + (type, n_construct_properties, construct_params); + + selector = HILDON_TIME_SELECTOR (object); + + selector->priv->hours_model = _create_hours_model (selector); + + column = hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), + selector->priv->hours_model, TRUE); + g_object_set (column, "text-column", 0, NULL); + + + /* we need initialization parameters in order to create minute models*/ + selector->priv->minutes_step = selector->priv->minutes_step ? selector->priv->minutes_step : 1; + + selector->priv->minutes_model = _create_minutes_model (selector->priv->minutes_step); + + column = hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), + selector->priv->minutes_model, TRUE); + g_object_set (column, "text-column", 0, NULL); + + if (selector->priv->ampm_format) { + selector->priv->ampm_model = _create_ampm_model (selector); + + hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), + selector->priv->ampm_model, TRUE); + + g_signal_connect (G_OBJECT (selector), + "changed", G_CALLBACK (_manage_ampm_selection_cb), + NULL); + } + + + /* By default we should select the current day */ + hildon_time_selector_set_time (selector, + selector->priv->creation_hours, + selector->priv->creation_minutes); + + return object; + +} + +static void +hildon_time_selector_init (HildonTimeSelector * selector) +{ + selector->priv = HILDON_TIME_SELECTOR_GET_PRIVATE (selector); + + GTK_WIDGET_SET_FLAGS (GTK_WIDGET (selector), GTK_NO_WINDOW); + gtk_widget_set_redraw_on_allocate (GTK_WIDGET (selector), FALSE); + + hildon_touch_selector_set_print_func (HILDON_TOUCH_SELECTOR (selector), + _custom_print_func); + + /* By default we use the automatic ampm format */ + selector->priv->pm = TRUE; + check_automatic_ampm_format (selector); + + _get_real_time (&selector->priv->creation_hours, + &selector->priv->creation_minutes); +} + +static void +hildon_time_selector_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + HildonTimeSelectorPrivate *priv = HILDON_TIME_SELECTOR_GET_PRIVATE (object); + + switch (param_id) + { + case PROP_MINUTES_STEP: + g_value_set_uint (value, priv->minutes_step); + break; + case PROP_TIME_FORMAT_POLICY: + g_value_set_enum (value, priv->format_policy); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +hildon_time_selector_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + HildonTimeSelectorPrivate *priv = HILDON_TIME_SELECTOR_GET_PRIVATE (object); + + switch (param_id) + { + case PROP_MINUTES_STEP: + priv->minutes_step = g_value_get_uint (value); + break; + case PROP_TIME_FORMAT_POLICY: + update_format_policy (HILDON_TIME_SELECTOR (object), + g_value_get_enum (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +hildon_time_selector_finalize (GObject * object) +{ + /* Note: we don't require to free the models. We don't manage it using own + references, so will be freed on the hildon-touch-selector finalize code. + See the implementation notes related to that on the touch selector + code. */ + + (*G_OBJECT_CLASS (hildon_time_selector_parent_class)->finalize) (object); +} + +/* ------------------------------ PRIVATE METHODS ---------------------------- */ + +static gchar * +_custom_print_func (HildonTouchSelector * touch_selector, + gpointer user_data) +{ + gchar *result = NULL; + struct tm tm = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + HildonTimeSelector *selector = NULL; + static gchar string[255]; + guint hours = 0; + guint minutes = 0; + + selector = HILDON_TIME_SELECTOR (touch_selector); + + hildon_time_selector_get_time (selector, &hours, &minutes); + + tm.tm_min = minutes; + tm.tm_hour = hours; + + if (selector->priv->ampm_format) { + if (selector->priv->pm) { + strftime (string, 255, _("wdgt_va_12h_time_pm"), &tm); + } else { + strftime (string, 255, _("wdgt_va_12h_time_am"), &tm); + } + } else { + strftime (string, 255, _("wdgt_va_24h_time"), &tm); + } + + + result = g_strdup (string); + + return result; +} + +static GtkTreeModel * +_create_minutes_model (guint minutes_step) +{ + GtkListStore *store_minutes = NULL; + gint i = 0; + static gchar label[255]; + struct tm tm = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + GtkTreeIter iter; + + store_minutes = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT); + for (i = 0; i <= 59; i=i+minutes_step) { + tm.tm_min = i; + strftime (label, 255, _("wdgt_va_minutes"), &tm); + + gtk_list_store_append (store_minutes, &iter); + gtk_list_store_set (store_minutes, &iter, + COLUMN_STRING, label, COLUMN_INT, i, -1); + } + + return GTK_TREE_MODEL (store_minutes); +} + +static GtkTreeModel * +_create_hours_model (HildonTimeSelector * selector) +{ + GtkListStore *store_hours = NULL; + gint i = 0; + GtkTreeIter iter; + struct tm tm = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + static gchar label[255]; + static gint range_12h[12] = {12, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11}; + static gint range_24h[24] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11, + 12,13,14,15,16,17,18,19,20,21,22,23}; + gint *range = NULL; + gint num_elements = 0; + gchar *format_string = NULL; + + if (selector->priv->ampm_format) { + range = range_12h; + num_elements = 12; + format_string = N_("wdgt_va_12h_hours"); + } else { + range = range_24h; + num_elements = 24; + format_string = N_("wdgt_va_24h_hours"); + } + + store_hours = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT); + for (i = 0; i < num_elements; i++) { + tm.tm_hour = range[i]; + strftime (label, 255, _(format_string), &tm); + + gtk_list_store_append (store_hours, &iter); + gtk_list_store_set (store_hours, &iter, + COLUMN_STRING, label, COLUMN_INT, range[i], -1); + } + + return GTK_TREE_MODEL (store_hours); +} + +static GtkTreeModel * +_create_ampm_model (HildonTimeSelector * selector) +{ + GtkListStore *store_ampm = NULL; + GtkTreeIter iter; + static gchar label[255]; + + store_ampm = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT); + + snprintf (label, 255, _("wdgt_va_am")); + gtk_list_store_append (store_ampm, &iter); + gtk_list_store_set (store_ampm, &iter, + COLUMN_STRING, label, + COLUMN_INT, 0, -1); + + snprintf (label, 255, _("wdgt_va_pm")); + gtk_list_store_append (store_ampm, &iter); + gtk_list_store_set (store_ampm, &iter, + COLUMN_STRING, label, + COLUMN_INT, 1, -1); + + return GTK_TREE_MODEL (store_ampm); +} + +static void +_get_real_time (gint * hours, gint * minutes) +{ + time_t secs; + struct tm *tm = NULL; + + secs = time (NULL); + tm = localtime (&secs); + + if (hours != NULL) { + *hours = tm->tm_hour; + } + + if (minutes != NULL) { + *minutes = tm->tm_min; + } +} + +static void +_manage_ampm_selection_cb (HildonTouchSelector * touch_selector, + gint num_column, gpointer data) +{ + HildonTimeSelector *selector = NULL; + gint pm; + GtkTreeIter iter; + + g_return_if_fail (HILDON_IS_TIME_SELECTOR (touch_selector)); + selector = HILDON_TIME_SELECTOR (touch_selector); + + if (num_column == COLUMN_AMPM && + hildon_touch_selector_get_selected (HILDON_TOUCH_SELECTOR (selector), + COLUMN_AMPM, &iter)) { + gtk_tree_model_get (selector->priv->ampm_model, &iter, COLUMN_INT, &pm, -1); + + selector->priv->pm = pm; + } +} + +static void +check_automatic_ampm_format (HildonTimeSelector * selector) +{ + GConfClient *client = NULL; + gboolean value = TRUE; + GError *error = NULL; + + client = gconf_client_get_default (); + value = gconf_client_get_bool (client, CLOCK_GCONF_IS_24H_FORMAT, &error); + if (error != NULL) { + g_warning + ("Error trying to get gconf variable %s, using 24h format by default", + CLOCK_GCONF_IS_24H_FORMAT); + g_error_free (error); + } + + selector->priv->ampm_format = !value; +} + +static void +_set_pm (HildonTimeSelector * selector, gboolean pm) +{ + GtkTreeIter iter; + + selector->priv->pm = pm; + + if (selector->priv->ampm_model != NULL) { + gtk_tree_model_iter_nth_child (selector->priv->ampm_model, &iter, NULL, pm); + + hildon_touch_selector_select_iter (HILDON_TOUCH_SELECTOR (selector), + COLUMN_AMPM, &iter, FALSE); + } +} + +static void +update_format_policy (HildonTimeSelector *selector, + HildonTimeSelectorFormatPolicy new_policy) +{ + gboolean prev_ampm_format = FALSE; + guint hours; + guint minutes; + gint num_columns = -1; + + num_columns = hildon_touch_selector_get_num_columns (HILDON_TOUCH_SELECTOR (selector)); + prev_ampm_format = selector->priv->ampm_format; + + if (new_policy != selector->priv->format_policy) { + selector->priv->format_policy = new_policy; + + /* We get the hour previous all the changes, to avoid problems with the + changing widget structure */ + if (num_columns >= 2) {/* we are on the object construction */ + hildon_time_selector_get_time (selector, &hours, &minutes); + } + + switch (new_policy) + { + case HILDON_TIME_SELECTOR_FORMAT_POLICY_AMPM: + selector->priv->ampm_format = TRUE; + break; + case HILDON_TIME_SELECTOR_FORMAT_POLICY_24H: + selector->priv->ampm_format = FALSE; + break; + case HILDON_TIME_SELECTOR_FORMAT_POLICY_AUTOMATIC: + check_automatic_ampm_format (selector); + break; + } + } + + if (prev_ampm_format != selector->priv->ampm_format) { + update_format_dependant_columns (selector, hours, minutes); + } +} + +static void +update_format_dependant_columns (HildonTimeSelector *selector, + guint hours, + guint minutes) +{ + gint num_columns = -1; + + num_columns = hildon_touch_selector_get_num_columns (HILDON_TOUCH_SELECTOR (selector)); + if (num_columns < 2) {/* we are on the object construction */ + return; + } + + /* To avoid an extra and wrong VALUE_CHANGED signal on the model update */ + hildon_touch_selector_block_changed (HILDON_TOUCH_SELECTOR(selector)); + + selector->priv->hours_model = _create_hours_model (selector); + hildon_touch_selector_set_model (HILDON_TOUCH_SELECTOR (selector), + 0, + selector->priv->hours_model); + + /* We need to set NOW the correct hour on the hours column, because the number of + columns will be updated too, so a signal COLUMNS_CHANGED will be emitted. Some + other widget could have connected to this signal and ask for the hour, so this + emission could have a wrong hour. We could use a custom func to only modify the + hours selection, but hildon_time_selector_time manage yet all the ampm issues + to select the correct one */ + hildon_time_selector_set_time (selector, hours, minutes); + + /* if we are at this function, we are sure that a change on the number of columns + will happen, so check the column number is not required */ + if (selector->priv->ampm_format) { + selector->priv->ampm_model = _create_ampm_model (selector); + + hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), + selector->priv->ampm_model, TRUE); + + g_signal_connect (G_OBJECT (selector), + "changed", G_CALLBACK (_manage_ampm_selection_cb), + NULL); + } else { + selector->priv->ampm_model = NULL; + hildon_touch_selector_remove_column (HILDON_TOUCH_SELECTOR (selector), 2); + } + + _set_pm (selector, hours >= 12); + + hildon_touch_selector_unblock_changed (HILDON_TOUCH_SELECTOR (selector)); +} +/* ------------------------------ PUBLIC METHODS ---------------------------- */ + +/** + * hildon_time_selector_new: + * + * Creates a new #HildonTimeSelector + * + * Returns: a new #HildonTimeSelector + * + * Since: 2.2 + **/ +GtkWidget * +hildon_time_selector_new () +{ + return g_object_new (HILDON_TYPE_TIME_SELECTOR, NULL); +} + + +/** + * hildon_time_selector_new_step: + * + * Creates a new #HildonTimeSelector + * @minutes_step: step between the minutes we are going to show in the + * selector + * + * Returns: a new #HildonTimeSelector + * + * Since: 2.2 + **/ +GtkWidget * +hildon_time_selector_new_step (guint minutes_step) +{ + return g_object_new (HILDON_TYPE_TIME_SELECTOR, "minutes-step", + minutes_step, NULL); +} + +/** + * hildon_time_selector_set_time + * @selector: the #HildonTimeSelector + * @hours: the current hour (0-23) + * @minutes: the current minute (0-59) + * + * Sets the current active hour on the #HildonTimeSelector widget + * + * The format of the hours accepted is always 24h format, with a range + * (0-23):(0-59). + * + * Since: 2.2 + * + * Returns: %TRUE on success, %FALSE otherwise + **/ +gboolean +hildon_time_selector_set_time (HildonTimeSelector * selector, + guint hours, guint minutes) +{ + GtkTreeIter iter; + gint hours_item = 0; + + g_return_val_if_fail (HILDON_IS_TIME_SELECTOR (selector), FALSE); + g_return_val_if_fail (hours <= 23, FALSE); + g_return_val_if_fail (minutes <= 59, FALSE); + + _set_pm (selector, hours >= 12); + + if (selector->priv->ampm_format) { + hours_item = hours - selector->priv->pm * 12; + } else { + hours_item = hours; + } + + gtk_tree_model_iter_nth_child (selector->priv->hours_model, &iter, NULL, + hours_item); + hildon_touch_selector_select_iter (HILDON_TOUCH_SELECTOR (selector), + COLUMN_HOURS, &iter, FALSE); + + g_assert (selector->priv->minutes_step>0); + minutes = minutes/selector->priv->minutes_step; + gtk_tree_model_iter_nth_child (selector->priv->minutes_model, &iter, NULL, + minutes); + hildon_touch_selector_select_iter (HILDON_TOUCH_SELECTOR (selector), + COLUMN_MINUTES, &iter, FALSE); + + return TRUE; +} + +/** + * hildon_time_selector_get_time + * @selector: the #HildonTimeSelector + * @hours: to set the current hour (0-23) + * @minutes: to set the current minute (0-59) + * + * Gets the current active hour on the #HildonTimeSelector widget. Both @year + * and @minutes can be NULL. + * + * This method returns the date always in 24h format, with a range (0-23):(0-59) + * + * Since: 2.2 + **/ +void +hildon_time_selector_get_time (HildonTimeSelector * selector, + guint * hours, guint * minutes) +{ + GtkTreeIter iter; + + g_return_if_fail (HILDON_IS_TIME_SELECTOR (selector)); + + if (hours != NULL) { + if (hildon_touch_selector_get_selected (HILDON_TOUCH_SELECTOR (selector), + COLUMN_HOURS, &iter)) { + + gtk_tree_model_get (selector->priv->hours_model, + &iter, COLUMN_INT, hours, -1); + } + if (selector->priv->ampm_format) { + *hours %= 12; + *hours += selector->priv->pm * 12; + } + } + + if (minutes != NULL) { + if (hildon_touch_selector_get_selected (HILDON_TOUCH_SELECTOR (selector), + COLUMN_MINUTES, &iter)) { + gtk_tree_model_get (selector->priv->minutes_model, + &iter, COLUMN_INT, minutes, -1); + } + } +} diff --git a/hildon/hildon-time-selector.h b/hildon/hildon-time-selector.h new file mode 100644 index 0000000..f01b704 --- /dev/null +++ b/hildon/hildon-time-selector.h @@ -0,0 +1,107 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2008 Nokia Corporation. + * + * 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; either + * version 2 of the License, or (at your option) any later version. or (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __HILDON_TIME_SELECTOR_H__ +#define __HILDON_TIME_SELECTOR_H__ + +#include "hildon-touch-selector.h" + +G_BEGIN_DECLS + +#define HILDON_TYPE_TIME_SELECTOR \ + (hildon_time_selector_get_type ()) + +#define HILDON_TIME_SELECTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + HILDON_TYPE_TIME_SELECTOR, HildonTimeSelector)) + +#define HILDON_TIME_SELECTOR_CLASS(vtable) \ + (G_TYPE_CHECK_CLASS_CAST ((vtable), \ + HILDON_TYPE_TIME_SELECTOR, HildonTimeSelectorClass)) + +#define HILDON_IS_TIME_SELECTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_TIME_SELECTOR)) + +#define HILDON_IS_TIME_SELECTOR_CLASS(vtable) \ + (G_TYPE_CHECK_CLASS_TYPE ((vtable), HILDON_TYPE_TIME_SELECTOR)) + +#define HILDON_TIME_SELECTOR_GET_CLASS(inst) \ + (G_TYPE_INSTANCE_GET_CLASS ((inst), \ + HILDON_TYPE_TIME_SELECTOR, HildonTimeSelectorClass)) + +typedef struct _HildonTimeSelector HildonTimeSelector; +typedef struct _HildonTimeSelectorClass HildonTimeSelectorClass; +typedef struct _HildonTimeSelectorPrivate HildonTimeSelectorPrivate; + +struct _HildonTimeSelector +{ + HildonTouchSelector parent_instance; + + /*< private > */ + HildonTimeSelectorPrivate *priv; +}; + +struct _HildonTimeSelectorClass +{ + HildonTouchSelectorClass parent_class; + + /* signals */ +}; + + +/** + * HildonTimeSelectorFormatPolicy: + * @HILDON_TIME_SELECTOR_FORMAT_POLICY_AMPM: The time selector will use a AMPM time format + * @HILDON_TIME_SELECTOR_FORMAT_POLICY_24H: The time selector will use a 24H time format + * @HILDON_TIME_SELECTOR_FORMAT_POLICY_AUTOMATIC: The time selector will use AMPM or 24H depending + * on the current environment + * + * Describes the time format used at #HildonTimeSelector + **/ +typedef enum { + HILDON_TIME_SELECTOR_FORMAT_POLICY_AMPM, + HILDON_TIME_SELECTOR_FORMAT_POLICY_24H, + HILDON_TIME_SELECTOR_FORMAT_POLICY_AUTOMATIC +} HildonTimeSelectorFormatPolicy; + +/* construction */ +GType +hildon_time_selector_get_type (void) G_GNUC_CONST; + +GtkWidget* +hildon_time_selector_new (void); + +GtkWidget* +hildon_time_selector_new_step (guint minutes_step); + +/* time management */ +gboolean +hildon_time_selector_set_time (HildonTimeSelector *selector, + guint hours, + guint minutes); + +void +hildon_time_selector_get_time (HildonTimeSelector *selector, + guint *hours, + guint *minutes); + +G_END_DECLS + +#endif /* __HILDON_TIME_SELECTOR_H__ */ diff --git a/hildon/hildon-touch-selector-column.h b/hildon/hildon-touch-selector-column.h new file mode 100644 index 0000000..0ee68d5 --- /dev/null +++ b/hildon/hildon-touch-selector-column.h @@ -0,0 +1,74 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2008 Nokia Corporation. + * + * 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; either + * version 2 of the License, or (at your option) any later version. or (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __HILDON_TOUCH_SELECTOR_COLUMN_H__ +#define __HILDON_TOUCH_SELECTOR_COLUMN_H__ + +#include + +G_BEGIN_DECLS + +#define HILDON_TYPE_TOUCH_SELECTOR_COLUMN \ + (hildon_touch_selector_column_get_type ()) + +#define HILDON_TOUCH_SELECTOR_COLUMN(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + HILDON_TYPE_TOUCH_SELECTOR_COLUMN, HildonTouchSelectorColumn)) + +#define HILDON_TOUCH_SELECTOR_COLUMN_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + HILDON_TYPE_TOUCH_SELECTOR_COLUMN, HildonTouchSelectorColumnClass)) + +#define HILDON_IS_TOUCH_SELECTOR_COLUMN(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + HILDON_TYPE_TOUCH_SELECTOR_COLUMN)) + +#define HILDON_IS_TOUCH_SELECTOR_COLUMN_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + HILDON_TYPE_TOUCH_SELECTOR_COLUMN)) + +#define HILDON_TOUCH_SELECTOR_COLUMN_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + HILDON_TYPE_TOUCH_SELECTOR_COLUMN, HildonTouchSelectorColumnClass)) + +typedef struct _HildonTouchSelectorColumn HildonTouchSelectorColumn; +typedef struct _HildonTouchSelectorColumnClass HildonTouchSelectorColumnClass; +typedef struct _HildonTouchSelectorColumnPrivate HildonTouchSelectorColumnPrivate; + +struct _HildonTouchSelectorColumn +{ + GObject parent; + + /* < private > */ + HildonTouchSelectorColumnPrivate *priv; +}; + +struct _HildonTouchSelectorColumnClass +{ + GObjectClass parent_class; +}; + +GType +hildon_touch_selector_column_get_type (void) G_GNUC_CONST; + +G_END_DECLS + + +#endif /*__HILDON_TOUCH_SELECTOR_COLUMN_H__ */ diff --git a/hildon/hildon-touch-selector-entry.c b/hildon/hildon-touch-selector-entry.c new file mode 100644 index 0000000..9e4913d --- /dev/null +++ b/hildon/hildon-touch-selector-entry.c @@ -0,0 +1,533 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation. + * + * 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; either + * version 2 of the License, or (at your option) any later version. or (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/** + * SECTION:hildon-touch-selector-entry + * @short_description: A selector widget with one column and a text entry + * @see_also: #HildonTouchSelector, #HildonPickerButton + * + * #HildonTouchSelectorEntry is a selector widget with a text entry, similar in + * behaviour to #GtkComboBoxEntry, that allows user to select an item from a + * predefined list or to enter a different one in a #HildonEntry. Items can also + * be searched and selected by typing in the entry. For more specific use cases, + * the #HildonEntry can be accessed directly with hildon_touch_selector_get_entry(). + * + * The main difference between the #GtkTreeModel used by #HildonTouchSelector + * and #HildonTouchSelectorEntry, is that the latter must always include a text + * column. You should set it with hildon_touch_selector_entry_set_text_column(). + * + * Normally, you would use #HildonTouchSelectorEntry together with a + * #HildonPickerDialog activated from a button. For the most common + * cases, you should use #HildonPickerButton. + * + * If you only need a text only, one column selector, you can create it with + * hildon_touch_selector_entry_new_text() and populate it with + * hildon_touch_selector_append_text(), hildon_touch_selector_prepend_text(), + * and hildon_touch_selector_insert_text(). + * + */ + +#include "hildon-touch-selector.h" +#include "hildon-touch-selector-entry.h" +#include "hildon-entry.h" + +G_DEFINE_TYPE (HildonTouchSelectorEntry, hildon_touch_selector_entry, HILDON_TYPE_TOUCH_SELECTOR) + +#define HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), HILDON_TYPE_TOUCH_SELECTOR_ENTRY, HildonTouchSelectorEntryPrivate)) + +typedef struct _HildonTouchSelectorEntryPrivate HildonTouchSelectorEntryPrivate; + +static void entry_on_text_changed (GtkEditable * editable, gpointer userdata); +static void hildon_touch_selector_entry_changed (HildonTouchSelector * selector, + gint column, + gpointer user_data); +static void hildon_touch_selector_entry_set_model (HildonTouchSelector * selector, + gint column, GtkTreeModel *model); +static gboolean hildon_touch_selector_entry_has_multiple_selection (HildonTouchSelector * selector); + +static void +_text_column_modified (GObject *pspec, GParamSpec *gobject, gpointer data); + + +struct _HildonTouchSelectorEntryPrivate { + gulong signal_id; + GtkWidget *entry; +}; + +enum { + PROP_TEXT_COLUMN = 1 +}; + +static void +hildon_touch_selector_entry_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + switch (property_id) { + case PROP_TEXT_COLUMN: + g_value_set_int (value, + hildon_touch_selector_entry_get_text_column (HILDON_TOUCH_SELECTOR_ENTRY (object))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +hildon_touch_selector_entry_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + switch (property_id) { + case PROP_TEXT_COLUMN: + hildon_touch_selector_entry_set_text_column (HILDON_TOUCH_SELECTOR_ENTRY (object), + g_value_get_int (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +hildon_touch_selector_entry_class_init (HildonTouchSelectorEntryClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + HildonTouchSelectorClass *selector_class = HILDON_TOUCH_SELECTOR_CLASS (klass); + + g_type_class_add_private (klass, sizeof (HildonTouchSelectorEntryPrivate)); + + selector_class->set_model = hildon_touch_selector_entry_set_model; + selector_class->has_multiple_selection = hildon_touch_selector_entry_has_multiple_selection; + + object_class->get_property = hildon_touch_selector_entry_get_property; + object_class->set_property = hildon_touch_selector_entry_set_property; + + /** + * HildonTouchSelectorEntry:text-column: + * + * Deprecated: now this property is in HildonTouchSelectorColumn use + * hildon_touch_selector_entry_set_text_column() and + * hildon_touch_selector_entry_get_text_column() to manage this. + * + * Since: 2.2 + **/ + g_object_class_install_property (G_OBJECT_CLASS (klass), + PROP_TEXT_COLUMN, + g_param_spec_int ("text-column", + "Text Column", + "A column in the data source model to get the strings from.", + -1, + G_MAXINT, + -1, + G_PARAM_READWRITE)); +} + +static gchar * +hildon_touch_selector_entry_print_func (HildonTouchSelector * selector, gpointer user_data) +{ + HildonTouchSelectorEntryPrivate *priv; + GtkTreeModel *model; + GtkTreeIter iter; + gint column; + gchar *text = NULL; + + priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector); + + if (*(gtk_entry_get_text (GTK_ENTRY (priv->entry))) != '\0') { + text = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->entry))); + } else { + model = hildon_touch_selector_get_model (selector, 0); + if (hildon_touch_selector_get_selected (selector, 0, &iter)) { + column = hildon_touch_selector_entry_get_text_column (HILDON_TOUCH_SELECTOR_ENTRY (selector)); + gtk_tree_model_get (model, &iter, column, &text, -1); + } + } + + return text; +} + +static void +hildon_touch_selector_entry_init (HildonTouchSelectorEntry *self) +{ + HildonTouchSelectorEntryPrivate *priv; + GtkEntryCompletion *completion; + HildonGtkInputMode input_mode; + + priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (self); + + priv->entry = hildon_entry_new (HILDON_SIZE_AUTO); + gtk_entry_set_activates_default (GTK_ENTRY (priv->entry), TRUE); + input_mode = hildon_gtk_entry_get_input_mode (GTK_ENTRY (priv->entry)); + + /* Disable unsupported input modes. */ + input_mode &= ~HILDON_GTK_INPUT_MODE_MULTILINE; + input_mode &= ~HILDON_GTK_INPUT_MODE_INVISIBLE; + input_mode &= ~HILDON_GTK_INPUT_MODE_DICTIONARY; + + hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry), input_mode); + + completion = gtk_entry_completion_new (); + gtk_entry_completion_set_inline_completion (completion, TRUE); + gtk_entry_completion_set_popup_completion (completion, FALSE); + gtk_entry_set_completion (GTK_ENTRY (priv->entry), completion); + + gtk_widget_show (priv->entry); + g_signal_connect (G_OBJECT (priv->entry), "changed", + G_CALLBACK (entry_on_text_changed), self); + priv->signal_id = g_signal_connect (G_OBJECT (self), "changed", + G_CALLBACK (hildon_touch_selector_entry_changed), NULL); + + hildon_touch_selector_set_print_func (HILDON_TOUCH_SELECTOR (self), hildon_touch_selector_entry_print_func); + gtk_box_pack_start (GTK_BOX (self), priv->entry, FALSE, FALSE, 0); +} + +/** + * hildon_touch_selector_entry_new: + * + * Creates a #HildonTouchSelectorEntry + * + * Returns: A new #HildonTouchSelectorEntry + * + * Since: 2.2 + **/ +GtkWidget * +hildon_touch_selector_entry_new (void) +{ + return g_object_new (HILDON_TYPE_TOUCH_SELECTOR_ENTRY, NULL); +} + +/** + * hildon_touch_selector_entry_new_text: + * + * Creates a #HildonTouchSelectorEntry with a single text column that + * can be populated conveniently through hildon_touch_selector_append_text(), + * hildon_touch_selector_prepend_text(), hildon_touch_selector_insert_text(). + * + * Returns: A new #HildonTouchSelectorEntry + * + * Since: 2.2 + **/ +GtkWidget * +hildon_touch_selector_entry_new_text (void) +{ + GtkListStore *model; + GtkWidget *selector; + GtkEntryCompletion *completion; + HildonTouchSelectorEntryPrivate *priv; + HildonTouchSelectorColumn *column = NULL; + + selector = hildon_touch_selector_entry_new (); + + priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector); + + model = gtk_list_store_new (1, G_TYPE_STRING); + completion = gtk_entry_get_completion (GTK_ENTRY (priv->entry)); + gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (model)); + column = hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), + GTK_TREE_MODEL (model), FALSE); + + g_signal_connect (column, "notify::text-column", G_CALLBACK (_text_column_modified), + selector); + hildon_touch_selector_entry_set_text_column (HILDON_TOUCH_SELECTOR_ENTRY (selector), 0); + + return selector; +} + +static void +_text_column_modified (GObject *pspec, GParamSpec *gobject, gpointer data) +{ + HildonTouchSelectorEntry *selector; + HildonTouchSelectorEntryPrivate *priv; + GtkEntryCompletion *completion; + gint text_column = -1; + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (data)); + selector = HILDON_TOUCH_SELECTOR_ENTRY (data); + + priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (HILDON_TOUCH_SELECTOR_ENTRY(selector)); + completion = gtk_entry_get_completion (GTK_ENTRY (priv->entry)); + + text_column = hildon_touch_selector_entry_get_text_column (selector); + + gtk_entry_completion_set_text_column (completion, text_column); +} + +/** + * hildon_touch_selector_entry_set_text_column: + * @selector: A #HildonTouchSelectorEntry + * @text_column: A column in model to get the strings from + * + * Sets the model column which touch selector box should use to get strings + * from to be @text_column. + * + * Since: 2.2 + **/ +void +hildon_touch_selector_entry_set_text_column (HildonTouchSelectorEntry *selector, + gint text_column) +{ + HildonTouchSelectorColumn *column = NULL; + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector)); + g_return_if_fail (text_column >= -1); + + column = hildon_touch_selector_get_column (HILDON_TOUCH_SELECTOR (selector), 0); + + g_object_set (G_OBJECT (column), "text-column", text_column, NULL); +} + +/** + * hildon_touch_selector_entry_get_text_column: + * @selector: A #HildonTouchSelectorEntry + * + * Gets the text column that @selector is using as a text column. + * + * Returns: the number of the column used as a text column. + * + * Since: 2.2 + **/ +gint +hildon_touch_selector_entry_get_text_column (HildonTouchSelectorEntry *selector) +{ + HildonTouchSelectorColumn *column = NULL; + gint text_column = -1; + + g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector), -1); + + column = hildon_touch_selector_get_column (HILDON_TOUCH_SELECTOR (selector), + 0); + + g_object_get (G_OBJECT (column), "text-column", &text_column, NULL); + + return text_column; +} + +/** + * hildon_touch_selector_entry_set_input_mode: + * @selector: a #HildonTouchSelectorEntry + * @input_mode: #HildonGtkInputMode mask + * + * Sets the input mode to be used in the #GtkEntry in @selector. See hildon_gtk_entry_set_input_mode() + * for details. + * + * It must be noted that not all input modes are available for the + * entry in @selector. In particular, + * %HILDON_GTK_INPUT_MODE_MULTILINE, %HILDON_GTK_INPUT_MODE_INVISIBLE, + * %HILDON_GTK_INPUT_MODE_DICTIONARY are disabled, since these are irrelevant + * for #HildonTouchSelectorEntry. + * + * Since: 2.2 + **/ +void +hildon_touch_selector_entry_set_input_mode (HildonTouchSelectorEntry * selector, + HildonGtkInputMode input_mode) +{ + HildonTouchSelectorEntryPrivate *priv; + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector)); + g_return_if_fail (!(input_mode & (HILDON_GTK_INPUT_MODE_MULTILINE | + HILDON_GTK_INPUT_MODE_INVISIBLE | + HILDON_GTK_INPUT_MODE_DICTIONARY))); + + priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector); + + hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry), input_mode); +} + +/** + * hildon_touch_selector_entry_get_input_mode: + * @selector: a #HildonTouchSelectorEntry + * + * Gets the input mode used in the #GtkEntry in @selector. See hildon_gtk_entry_get_input_mode() + * for details. + * + * Returns: a mask of #HildonGtkInputMode + * + * Since: 2.2 + **/ +HildonGtkInputMode +hildon_touch_selector_entry_get_input_mode (HildonTouchSelectorEntry * selector) +{ + HildonTouchSelectorEntryPrivate *priv; + + g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector), HILDON_GTK_INPUT_MODE_ALPHA); + + priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector); + + return hildon_gtk_entry_get_input_mode (GTK_ENTRY (priv->entry)); +} + +static void +entry_on_text_changed (GtkEditable * editable, + gpointer userdata) +{ + HildonTouchSelector *selector; + HildonTouchSelectorEntryPrivate *priv; + GtkTreeModel *model; + GtkTreeIter iter; + GtkEntry *entry; + const gchar *prefix; + gchar *text; + gboolean found = FALSE; + gint text_column = -1; + + entry = GTK_ENTRY (editable); + selector = HILDON_TOUCH_SELECTOR (userdata); + priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector); + + text_column = + hildon_touch_selector_entry_get_text_column (HILDON_TOUCH_SELECTOR_ENTRY (selector)); + + prefix = gtk_entry_get_text (entry); + + if (prefix[0] == '\0') { + return; + } + + model = hildon_touch_selector_get_model (selector, 0); + + if (!gtk_tree_model_get_iter_first (model, &iter)) { + return; + } + + do { + gtk_tree_model_get (model, &iter, text_column, &text, -1); + found = g_str_has_prefix (text, prefix); + g_free (text); + } while (found != TRUE && gtk_tree_model_iter_next (model, &iter)); + + g_signal_handler_block (selector, priv->signal_id); + { + /* We emit the HildonTouchSelector::changed signal because a change in the + GtkEntry represents a change in current selection, and therefore, users + should be notified. */ + if (found) { + hildon_touch_selector_select_iter (selector, 0, &iter, TRUE); + } + g_signal_emit_by_name (selector, "changed", 0); + } + g_signal_handler_unblock (selector, priv->signal_id); + +} + +/* FIXME: This is actually a very ugly way to retrieve the text. Ideally, + we would have API to retrieve it from the base clase (HildonTouchSelector). + In the meantime, leaving it here. + */ +static gchar * +hildon_touch_selector_get_text_from_model (HildonTouchSelectorEntry * selector) +{ + GtkTreeModel *model; + GtkTreeIter iter; + GtkTreePath *path; + GList *selected_rows; + gchar *text; + gint text_column = -1; + + model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0); + text_column = hildon_touch_selector_entry_get_text_column (selector); + selected_rows = hildon_touch_selector_get_selected_rows (HILDON_TOUCH_SELECTOR (selector), 0); + + if (selected_rows == NULL) { + return NULL; + } + + /* We are in single selection mode */ + g_assert (selected_rows->next == NULL); + + path = (GtkTreePath *)selected_rows->data; + gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_model_get (model, &iter, text_column, &text, -1); + + gtk_tree_path_free (path); + g_list_free (selected_rows); + + return text; +} + +static void +hildon_touch_selector_entry_changed (HildonTouchSelector * selector, + gint column, gpointer user_data) +{ + HildonTouchSelectorEntryPrivate *priv; + gchar *text; + + priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector); + + text = hildon_touch_selector_get_text_from_model (HILDON_TOUCH_SELECTOR_ENTRY (selector)); + if (text != NULL) { + gtk_entry_set_text (GTK_ENTRY (priv->entry), text); + gtk_editable_select_region (GTK_EDITABLE (priv->entry), 0, -1); + g_free (text); + } +} + +static void +hildon_touch_selector_entry_set_model (HildonTouchSelector * selector, + gint column, GtkTreeModel *model) +{ + GtkEntryCompletion *completion; + HildonTouchSelectorEntryPrivate *priv; + gint text_column = -1; + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector)); + g_return_if_fail (column == 0); + g_return_if_fail (GTK_IS_TREE_MODEL (model)); + + HILDON_TOUCH_SELECTOR_CLASS (hildon_touch_selector_entry_parent_class)->set_model (selector, column, model); + + priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector); + + completion = gtk_entry_get_completion (GTK_ENTRY (priv->entry)); + gtk_entry_completion_set_model (completion, model); + + text_column = hildon_touch_selector_entry_get_text_column (HILDON_TOUCH_SELECTOR_ENTRY (selector)); + + gtk_entry_completion_set_text_column (completion, text_column); +} + +static gboolean +hildon_touch_selector_entry_has_multiple_selection (HildonTouchSelector * selector) +{ + /* Always TRUE, given the GtkEntry. */ + return TRUE; +} + +/** + * hildon_touch_selector_entry_get_entry: + * @selector: a #HildonTouchSelectorEntry. + * + * Provides access to the #HildonEntry in @selector. Use to programmatically + * change the contents in entry or modify its behavior. + * + * Returns: a #HildonEntry. + * + * Since: 2.2 + **/ +HildonEntry * +hildon_touch_selector_entry_get_entry (HildonTouchSelectorEntry * selector) +{ + HildonTouchSelectorEntryPrivate *priv; + + g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector), NULL); + + priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector); + + return HILDON_ENTRY (priv->entry); +} diff --git a/hildon/hildon-touch-selector-entry.h b/hildon/hildon-touch-selector-entry.h new file mode 100644 index 0000000..a244330 --- /dev/null +++ b/hildon/hildon-touch-selector-entry.h @@ -0,0 +1,95 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation. + * + * 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; either + * version 2 of the License, or (at your option) any later version. or (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __HILDON_TOUCH_SELECTOR_ENTRY__ +#define __HILDON_TOUCH_SELECTOR_ENTRY__ + +#include "hildon-touch-selector.h" +#include "hildon-entry.h" + +G_BEGIN_DECLS + +#define HILDON_TYPE_TOUCH_SELECTOR_ENTRY \ + (hildon_touch_selector_entry_get_type()) + +#define HILDON_TOUCH_SELECTOR_ENTRY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + HILDON_TYPE_TOUCH_SELECTOR_ENTRY, HildonTouchSelectorEntry)) + +#define HILDON_TOUCH_SELECTOR_ENTRY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + HILDON_TYPE_TOUCH_SELECTOR_ENTRY, HildonTouchSelectorEntryClass)) + +#define HILDON_IS_TOUCH_SELECTOR_ENTRY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + HILDON_TYPE_TOUCH_SELECTOR_ENTRY)) + +#define HILDON_IS_TOUCH_SELECTOR_ENTRY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + HILDON_TYPE_TOUCH_SELECTOR_ENTRY)) + +#define HILDON_TOUCH_SELECTOR_ENTRY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + HILDON_TYPE_TOUCH_SELECTOR_ENTRY, HildonTouchSelectorEntryClass)) + +typedef struct _HildonTouchSelectorEntry HildonTouchSelectorEntry; +typedef struct _HildonTouchSelectorEntryClass HildonTouchSelectorEntryClass; + +struct _HildonTouchSelectorEntry +{ + HildonTouchSelector parent; + + /*< private > */ +}; + +struct _HildonTouchSelectorEntryClass +{ + HildonTouchSelectorClass parent_class; +}; + +GType +hildon_touch_selector_entry_get_type (void); + +GtkWidget* +hildon_touch_selector_entry_new (void); + +GtkWidget* +hildon_touch_selector_entry_new_text (void); + +void +hildon_touch_selector_entry_set_text_column (HildonTouchSelectorEntry *selector, + gint text_column); +gint +hildon_touch_selector_entry_get_text_column (HildonTouchSelectorEntry *selector); + +HildonGtkInputMode +hildon_touch_selector_entry_get_input_mode (HildonTouchSelectorEntry * selector); + +void +hildon_touch_selector_entry_set_input_mode (HildonTouchSelectorEntry * selector, + HildonGtkInputMode input_mode); + +HildonEntry * +hildon_touch_selector_entry_get_entry (HildonTouchSelectorEntry * selector); + +G_END_DECLS + +#endif /* __HILDON_TOUCH_SELECTOR_ENTRY__ */ + diff --git a/hildon/hildon-touch-selector-private.h b/hildon/hildon-touch-selector-private.h new file mode 100644 index 0000000..eeee475 --- /dev/null +++ b/hildon/hildon-touch-selector-private.h @@ -0,0 +1,36 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2009 Nokia Corporation. + * + * Contact: Rodrigo Novo + * + * 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; either + * version 2 of the License, or (at your option) any later version. or (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef __HILDON_TOUCH_SELECTOR_PRIVATE_H__ +#define __HILDON_TOUCH_SELECTOR_PRIVATE_H__ + + +G_BEGIN_DECLS + +void G_GNUC_INTERNAL +hildon_touch_selector_block_changed (HildonTouchSelector *selector); + +void G_GNUC_INTERNAL +hildon_touch_selector_unblock_changed (HildonTouchSelector *selector); + +G_END_DECLS + +#endif diff --git a/hildon/hildon-touch-selector.c b/hildon/hildon-touch-selector.c new file mode 100644 index 0000000..4ab005d --- /dev/null +++ b/hildon/hildon-touch-selector.c @@ -0,0 +1,2120 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2008 Nokia Corporation. + * + * 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; either + * version 2 of the License, or (at your option) any later version. or (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/** + * SECTION:hildon-touch-selector + * @short_description: A selector widget with several columns. + * + * #HildonTouchSelector is a selector widget, that allows users to + * select items from one to many predefined lists. It is very similar + * to #GtkComboBox, but with several individual pannable columns. + * + * Normally, you would use #HildonTouchSelector together with a + * #HildonPickerDialog activated from a button. For the most common + * cases, you should use #HildonPickerButton. + * + * The composition of each column in the selector is represented by a + * #GtkTreeModel. To add a new column to a #HildonTouchSelector, use + * hildon_touch_selector_append_column(). If you want to add a + * text-only column, without special attributes, use + * hildon_touch_selector_append_text_column(). + * + * It is highly recommended that you use only one column + * #HildonTouchSelectors. + * If you only need a text only, one column selector, you can create it with + * hildon_touch_selector_new_text() and populate with + * hildon_touch_selector_append_text(), hildon_touch_selector_prepend_text(), + * and hildon_touch_selector_insert_text(). + * + * If you need a selector widget that also accepts user inputs, you + * can use #HildonTouchSelectorEntry. + * + * The current selection has a string representation. In the most common cases, + * each column model will contain a text column. You can configure + * which column in particular using the #HildonTouchSelectorColumn property + * #HildonTouchSelectorColumn:text-column + * + * You can get this string representation using + * hildon_touch_selector_get_current_text(). + * You can configure how the selection is printed with + * hildon_touch_selector_set_print_func(), that sets the current hildon touch + * selector print function. The widget has a default print function, that + * uses the #HildonTouchSelectorColumn:text-column property on each + * #HildonTouchSelectorColumn to compose the final representation. + * + * If you create the selector using hildon_touch_selector_new_text() you + * don't need to take care of this property, as the model is created internally. + * If you create the selector using hildon_touch_selector_new(), you + * need to specify properly the property for your custom model in order to get a + * non-empty string representation, or define your custom print function. + * + * + * Creating a HildonTouchSelector + * + * void + * selection_changed (HildonTouchSelector * selector, + * gpointer *user_data) + * { + * gchar *current_selection = NULL; + * + * current_selection = hildon_touch_selector_get_current_text (selector); + * g_debug ("Current selection : %s", current_selection); + * } + * + * static GtkWidget * + * create_customized_selector () + * { + * GtkWidget *selector = NULL; + * GSList *icon_list = NULL; + * GtkListStore *store_icons = NULL; + * GSList *item = NULL; + * GtkCellRenderer *renderer = NULL; + * HildonTouchSelectorColumn *column = NULL; + * + * selector = hildon_touch_selector_new (); + * + * icon_list = gtk_stock_list_ids (); + * + * store_icons = gtk_list_store_new (1, G_TYPE_STRING); + * for (item = icon_list; item; item = g_slist_next (item)) { + * GtkTreeIter iter; + * gchar *label = item->data; + * + * gtk_list_store_append (store_icons, &iter); + * gtk_list_store_set (store_icons, &iter, 0, label, -1); + * g_free (label); + * } + * g_slist_free (icon_list); + * + * renderer = gtk_cell_renderer_pixbuf_new (); + * gtk_cell_renderer_set_fixed_size (renderer, -1, 100); + * + * column = hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), + * GTK_TREE_MODEL (store_icons), + * renderer, "stock-id", 0, NULL); + * + * g_object_set (G_OBJECT (column), "text-column", 0, NULL); + * + * hildon_touch_selector_set_column_selection_mode (HILDON_TOUCH_SELECTOR (selector), + * HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE); + * + * g_signal_connect (G_OBJECT (selector), "changed", + * G_CALLBACK (selection_changed), NULL); + * + * return selector; + * } + * + * static GtkWidget * + * create_simple_selector () + * { + * GtkWidget *selector = NULL; + * gint i; + * + * selector = hildon_touch_selector_new_text (); + * hildon_touch_selector_set_column_selection_mode (HILDON_TOUCH_SELECTOR (selector), + * HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE); + * + * g_signal_connect (G_OBJECT (selector), "changed", + * G_CALLBACK (selection_changed), NULL); + * + * for (i = 1; i <= 10 ; i++) { + * gchar *label = g_strdup_printf ("Item &percnt;d", i); + * + * hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), + * label); + * + * g_free (label); + * } + * + * return selector; + * } + * + * + */ + +/** + * SECTION:hildon-touch-selector-column + * @short_description: A visible column in a #HildonTouchSelector + * + * #HildonTouchSelectorColumn object represents a visible column in + * #HildonTouchSelector. It allows to manage the cell renderers related to each + * column. + */ + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "hildon-gtk.h" + +#include "hildon-pannable-area.h" +#include "hildon-touch-selector.h" +#include "hildon-touch-selector-private.h" + +#define HILDON_TOUCH_SELECTOR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_TOUCH_SELECTOR, HildonTouchSelectorPrivate)) + +G_DEFINE_TYPE (HildonTouchSelector, hildon_touch_selector, GTK_TYPE_VBOX) + +/* + * IMPLEMENTATION NOTES: + * Struct to maintain the data of each column. The columns are the elements + * of the widget that belongs properly to the selection behaviour. Although + * internally the columns are arranged in a private #GtkHBox, as the selector + * itself is a #GtkVBox, you can add more widgets, like buttons etc., so + * you finally could have a widget with more elements that the columns, but + * this doesn't belongs to the selection logic + */ +struct _HildonTouchSelectorColumnPrivate +{ + HildonTouchSelector *parent; /* the selector that contains this column */ + GtkTreeModel *model; + gint text_column; + GtkTreeView *tree_view; + gulong realize_handler; + GtkTreePath *initial_path; + + GtkWidget *panarea; /* the pannable widget */ +}; + +struct _HildonTouchSelectorPrivate +{ + GSList *columns; /* the selection columns */ + GtkWidget *hbox; /* the container for the selector's columns */ + gboolean initial_scroll; /* whether initial fancy scrolling to selection */ + + gboolean changed_blocked; + + HildonTouchSelectorPrintFunc print_func; + gpointer print_user_data; + GDestroyNotify print_destroy_func; +}; + +enum +{ + PROP_HAS_MULTIPLE_SELECTION = 1, + PROP_INITIAL_SCROLL +}; + +enum +{ + CHANGED, + COLUMNS_CHANGED, + LAST_SIGNAL +}; + +static gint hildon_touch_selector_signals[LAST_SIGNAL] = { 0 }; + +static void +hildon_touch_selector_dispose (GObject * object); + +static void +hildon_touch_selector_get_property (GObject * object, + guint prop_id, + GValue * value, + GParamSpec * pspec); +static void +hildon_touch_selector_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +/* gtkwidget */ + +/* gtkcontainer */ +static void hildon_touch_selector_remove (GtkContainer * container, + GtkWidget * widget); +/* private functions */ +static void _row_tapped_cb (GtkTreeView * tree_view, + GtkTreePath * path, + gpointer user_data); +static gchar *_default_print_func (HildonTouchSelector * selector, + gpointer user_data); + +static HildonTouchSelectorColumn *_create_new_column (HildonTouchSelector * selector, + GtkTreeModel * model, + gboolean *emit_changed, + GtkCellRenderer * renderer, + va_list args); +static gboolean +on_realize_cb (GtkWidget *widget, + gpointer data); +static void +hildon_touch_selector_scroll_to (HildonTouchSelectorColumn *column, + GtkTreeView *tv, + GtkTreePath *path); +static gboolean +_hildon_touch_selector_center_on_selected_items (HildonTouchSelector *selector, + HildonTouchSelectorColumn *column); +static void +_hildon_touch_selector_set_model (HildonTouchSelector * selector, + gint num_column, + GtkTreeModel * model); +static gboolean +_hildon_touch_selector_has_multiple_selection (HildonTouchSelector * selector); + +static void +hildon_touch_selector_emit_value_changed (HildonTouchSelector *selector, + gint column); + +/* GtkCellLayout implementation (HildonTouchSelectorColumn)*/ +static void hildon_touch_selector_column_cell_layout_init (GtkCellLayoutIface *iface); + +static void hildon_touch_selector_column_cell_layout_pack_start (GtkCellLayout *cell_layout, + GtkCellRenderer *cell, + gboolean expand); +static void hildon_touch_selector_column_cell_layout_pack_end (GtkCellLayout *cell_layout, + GtkCellRenderer *cell, + gboolean expand); +static void hildon_touch_selector_column_cell_layout_clear (GtkCellLayout *cell_layout); +static void hildon_touch_selector_column_cell_layout_add_attribute(GtkCellLayout *cell_layout, + GtkCellRenderer *cell, + const gchar *attribute, + gint column); +static void hildon_touch_selector_column_cell_layout_set_cell_data_func (GtkCellLayout *cell_layout, + GtkCellRenderer *cell, + GtkCellLayoutDataFunc func, + gpointer func_data, + GDestroyNotify destroy); +static void hildon_touch_selector_column_cell_layout_clear_attributes (GtkCellLayout *cell_layout, + GtkCellRenderer *cell); +static void hildon_touch_selector_column_cell_layout_reorder (GtkCellLayout *cell_layout, + GtkCellRenderer *cell, + gint position); +static GList *hildon_touch_selector_column_cell_layout_get_cells (GtkCellLayout *cell_layout); + + +static void +hildon_touch_selector_class_init (HildonTouchSelectorClass * class) +{ + GObjectClass *gobject_class; + GtkObjectClass *object_class; + GtkContainerClass *container_class; + + gobject_class = G_OBJECT_CLASS (class); + object_class = GTK_OBJECT_CLASS (class); + container_class = GTK_CONTAINER_CLASS (class); + + /* GObject */ + gobject_class->dispose = hildon_touch_selector_dispose; + gobject_class->get_property = hildon_touch_selector_get_property; + gobject_class->set_property = hildon_touch_selector_set_property; + + /* GtkWidget */ + + /* GtkContainer */ + container_class->remove = hildon_touch_selector_remove; + + /* HildonTouchSelector */ + class->changed = NULL; + class->set_model = _hildon_touch_selector_set_model; + + class->has_multiple_selection = _hildon_touch_selector_has_multiple_selection; + + /* signals */ + /** + * HildonTouchSelector::changed: + * @widget: the object which received the signal + * @column: the number of the column that has changed + * + * The "changed" signal is emitted when the active item on any column is changed. + * This can be due to the user selecting a different item from the list, or + * due to a call to hildon_touch_selector_select_iter() on one of the columns. + * + * Since: 2.2 + */ + hildon_touch_selector_signals[CHANGED] = + g_signal_new ("changed", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (HildonTouchSelectorClass, changed), + NULL, NULL, + g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); + + /** + * HildonTouchSelector::columns-changed: + * @selector: the object which received the signal + * + * The "columns-changed" signal is emitted when the number + * of columns in the #HildonTouchSelector change. + * + * Since: 2.2 + */ + hildon_touch_selector_signals[COLUMNS_CHANGED] = + g_signal_new ("columns-changed", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_LAST, 0, + NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + /* properties */ + + g_object_class_install_property (gobject_class, PROP_HAS_MULTIPLE_SELECTION, + g_param_spec_boolean ("has-multiple-selection", + "has multiple selection", + "Whether the widget has multiple " + "selection (like multiple columns, " + "multiselection mode, or multiple " + "internal widgets) and therefore " + "it may need a confirmation button, " + "for instance.", + FALSE, + G_PARAM_READABLE)); + + g_object_class_install_property (G_OBJECT_CLASS (gobject_class), + PROP_INITIAL_SCROLL, + g_param_spec_boolean ("initial-scroll", + "Initial scroll", + "Whether to scroll to the" + "current selection when" + "the selector is first" + "shown", + TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + /* style properties */ + /* We need to ensure fremantle mode for the treeview in order to work + properly. This is not about the appearance, this is about behaviour */ + gtk_rc_parse_string ("style \"fremantle-htst\" {\n" + " GtkWidget::hildon-mode = 1\n" + "} widget \"*.fremantle-htst\" style \"fremantle-htst\"" + "widget_class \"*.GtkTreeView\" style :highest \"fremantle-htst\""); + + g_type_class_add_private (object_class, sizeof (HildonTouchSelectorPrivate)); +} + +static void +hildon_touch_selector_get_property (GObject * object, + guint prop_id, + GValue * value, GParamSpec * pspec) +{ + HildonTouchSelectorPrivate *priv = HILDON_TOUCH_SELECTOR (object)->priv; + + switch (prop_id) { + case PROP_HAS_MULTIPLE_SELECTION: + g_value_set_boolean (value, + hildon_touch_selector_has_multiple_selection (HILDON_TOUCH_SELECTOR (object))); + break; + case PROP_INITIAL_SCROLL: + g_value_set_boolean (value, priv->initial_scroll); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +hildon_touch_selector_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + HildonTouchSelectorPrivate *priv = HILDON_TOUCH_SELECTOR (object)->priv; + + switch (prop_id) { + case PROP_INITIAL_SCROLL: + priv->initial_scroll = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +static void +hildon_touch_selector_init (HildonTouchSelector * selector) +{ + selector->priv = HILDON_TOUCH_SELECTOR_GET_PRIVATE (selector); + + GTK_WIDGET_SET_FLAGS (GTK_WIDGET (selector), GTK_NO_WINDOW); + gtk_widget_set_redraw_on_allocate (GTK_WIDGET (selector), FALSE); + + selector->priv->columns = NULL; + + selector->priv->print_func = NULL; + selector->priv->print_user_data = NULL; + selector->priv->print_destroy_func = NULL; + selector->priv->initial_scroll = TRUE; + selector->priv->hbox = gtk_hbox_new (FALSE, 0); + + selector->priv->changed_blocked = FALSE; + + gtk_box_pack_end (GTK_BOX (selector), selector->priv->hbox, + TRUE, TRUE, 0); + gtk_widget_show (selector->priv->hbox); +} + +static void +hildon_touch_selector_dispose (GObject * object) +{ + GObjectClass *gobject_class; + + hildon_touch_selector_set_print_func_full (HILDON_TOUCH_SELECTOR (object), + NULL, NULL, NULL); + + gobject_class = G_OBJECT_CLASS (hildon_touch_selector_parent_class); + + if (gobject_class->dispose) + (* gobject_class->dispose) (object); +} + +/* + * IMPLEMENTATION NOTES: + * Some people sent questions regarding a missing dispose/finalize function on + * this widget that could lead to leak memory, so we will clarify this topic. + * + * This is not required as #HildonTouchSelector extends #GtkContainer. When the + * widget is freed, the #GtkContainer freeing memory functions are called. This + * process includes remove each widget individually, so all the widgets are + * properly freed. + * + * In the same way, this widget redefines gtk_container->remove function, in + * order to free the column related information if it is required. + * + * Please take a look to hildon_touch_selector_remove for more information. + */ + +/*------------------------------ GtkContainer ------------------------------ */ + +/* + * Required in order to free the column at the columns list + */ +static void +hildon_touch_selector_remove (GtkContainer * container, GtkWidget * widget) +{ + HildonTouchSelector *selector = NULL; + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (container)); + selector = HILDON_TOUCH_SELECTOR (container); + + /* Remove the extra data related to the columns, if required. */ + if (widget == selector->priv->hbox) { + g_slist_foreach (selector->priv->columns, (GFunc) g_object_unref, NULL); + + g_slist_free (selector->priv->columns); + + selector->priv->columns = NULL; + } else { + g_debug ("Freeing a widget outside the columns logic"); + } + + /* Now remove the widget itself from the container */ + GTK_CONTAINER_CLASS (hildon_touch_selector_parent_class)->remove (container, widget); +} + +/* ------------------------------ PRIVATE METHODS ---------------------------- */ +void +hildon_touch_selector_block_changed (HildonTouchSelector *selector) +{ + selector->priv->changed_blocked = TRUE; +} + +void +hildon_touch_selector_unblock_changed (HildonTouchSelector *selector) +{ + selector->priv->changed_blocked = FALSE; +} + +static void +hildon_touch_selector_emit_value_changed (HildonTouchSelector *selector, + gint column) +{ + if (!selector->priv->changed_blocked) { + g_signal_emit (selector, hildon_touch_selector_signals[CHANGED], 0, column); + } +} + +/** + * default_print_func: + * @selector: a #HildonTouchSelector + * + * Default print function + * + * Returns: a new string that represents the selected items + * + * Since: 2.2 + **/ +static gchar * +_default_print_func (HildonTouchSelector * selector, gpointer user_data) +{ + gchar *result = NULL; + gchar *aux = NULL; + gint num_columns = 0; + GtkTreeIter iter; + GtkTreeModel *model = NULL; + gchar *current_string = NULL; + gint i; + HildonTouchSelectorSelectionMode mode; + GList *item = NULL; + GtkTreePath *current_path = NULL; + GList *selected_rows = NULL; + gint initial_value = 0; + gint text_column = -1; + HildonTouchSelectorColumn *column = NULL; + + num_columns = hildon_touch_selector_get_num_columns (selector); + + mode = hildon_touch_selector_get_column_selection_mode (selector); + + if ((mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE) + && (num_columns > 0)) { + /* In this case we get the first column first */ + selected_rows = hildon_touch_selector_get_selected_rows (selector, 0); + model = hildon_touch_selector_get_model (selector, 0); + column = hildon_touch_selector_get_column (selector, 0); + g_object_get (G_OBJECT(column), "text-column", &text_column, NULL); + + result = g_strdup_printf ("("); + i = 0; + for (item = selected_rows; item; item = g_list_next (item)) { + current_path = item->data; + gtk_tree_model_get_iter (model, &iter, current_path); + + if (text_column != -1) { + gtk_tree_model_get (model, &iter, text_column, ¤t_string, -1); + } + + if (i < g_list_length (selected_rows) - 1) { + aux = g_strconcat (result, current_string, ",", NULL); + g_free (result); + result = aux; + } else { + aux = g_strconcat (result, current_string, NULL); + g_free (result); + result = aux; + } + + if (current_string) { + g_free (current_string); + current_string = NULL; + } + + i++; + } + + aux = g_strconcat (result, ")", NULL); + g_free (result); + result = aux; + + g_list_foreach (selected_rows, (GFunc) (gtk_tree_path_free), NULL); + g_list_free (selected_rows); + initial_value = 1; + } else { + initial_value = 0; + } + + for (i = initial_value; i < num_columns; i++) { + model = hildon_touch_selector_get_model (selector, i); + column = hildon_touch_selector_get_column (selector, i); + g_object_get (G_OBJECT(column), "text-column", &text_column, NULL); + + if (hildon_touch_selector_get_selected (selector, i, &iter)) { + if (text_column == -1 ) { + g_warning ("Trying to use the default print function in HildonTouchSelector, but " + "\"text-column\" property is not set for HildonTouchSelectorColumn %p.", column); + current_string = NULL; + } else { + gtk_tree_model_get (model, &iter, text_column, ¤t_string, -1); + } + + if (i == 0) { + result = current_string; + } else { + aux = g_strconcat (result, ":", current_string, NULL); + g_free (result); + g_free (current_string); + current_string = NULL; + result = aux; + } + } + } + + return result; +} + +static void +_row_tapped_cb (GtkTreeView * tree_view, GtkTreePath * path, gpointer user_data) +{ + HildonTouchSelector *selector = NULL; + HildonTouchSelectorColumn *column = NULL; + gint num_column = -1; + + column = HILDON_TOUCH_SELECTOR_COLUMN (user_data); + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (column->priv->parent)); + + selector = column->priv->parent; + + num_column = g_slist_index (selector->priv->columns, column); + + hildon_touch_selector_emit_value_changed (selector, num_column); +} + + +static HildonTouchSelectorColumn * +_create_new_column (HildonTouchSelector * selector, + GtkTreeModel * model, + gboolean *emit_changed, + GtkCellRenderer * renderer, va_list args) +{ + HildonTouchSelectorColumn *new_column = NULL; + GtkTreeViewColumn *tree_column = NULL; + GtkTreeView *tv = NULL; + GtkWidget *panarea = NULL; + GtkTreeSelection *selection = NULL; + GtkTreeIter iter; + gchar *attribute; + gint value; + + tree_column = gtk_tree_view_column_new (); + + if (renderer != NULL) { + gtk_tree_view_column_pack_start (tree_column, renderer, TRUE); + + attribute = va_arg (args, gchar *); + while (attribute != NULL) { + value = va_arg (args, gint); + gtk_tree_view_column_add_attribute (tree_column, renderer, attribute, + value); + attribute = va_arg (args, gchar *); + } + } + +#ifdef MAEMO_GTK + tv = GTK_TREE_VIEW (hildon_gtk_tree_view_new (HILDON_UI_MODE_EDIT)); +#else + tv = GTK_TREE_VIEW (gtk_tree_view_new ()); +#endif /* MAEMO_GTK */ + + gtk_tree_view_set_enable_search (tv, FALSE); + GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (tv), GTK_CAN_FOCUS); + + gtk_tree_view_set_model (tv, model); + gtk_tree_view_set_rules_hint (tv, TRUE); + + gtk_tree_view_append_column (GTK_TREE_VIEW (tv), tree_column); + + new_column = g_object_new (HILDON_TYPE_TOUCH_SELECTOR_COLUMN, NULL); + new_column->priv->parent = selector; + + panarea = hildon_pannable_area_new (); + + g_object_set (G_OBJECT (panarea), + "initial-hint", FALSE, NULL); + + gtk_container_add (GTK_CONTAINER (panarea), GTK_WIDGET (tv)); + + new_column->priv->model = model; + new_column->priv->tree_view = tv; + new_column->priv->panarea = panarea; + new_column->priv->realize_handler = 0; + new_column->priv->initial_path = NULL; + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv)); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE); + + /* select the first item */ + *emit_changed = FALSE; + if (gtk_tree_model_get_iter_first (model, &iter)) { + gtk_tree_selection_select_iter (selection, &iter); + *emit_changed = TRUE; + } + + gtk_widget_grab_focus (GTK_WIDGET (tv)); + + /* connect to the hildon-row-tapped signal connection */ + g_signal_connect (G_OBJECT (tv), "hildon-row-tapped", + G_CALLBACK (_row_tapped_cb), new_column); + + return new_column; +} + + +/* ------------------------ HildonTouchSelectorColumn implementation ---------------------- */ +G_DEFINE_TYPE_WITH_CODE (HildonTouchSelectorColumn, hildon_touch_selector_column, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT, + hildon_touch_selector_column_cell_layout_init)) + +enum +{ + PROP_TEXT_COLUMN = 1 +}; + +static void +hildon_touch_selector_column_class_init (HildonTouchSelectorColumnClass *klass); + +static void +hildon_touch_selector_column_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec); + +static void +hildon_touch_selector_column_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec); + +static void +hildon_touch_selector_column_set_text_column (HildonTouchSelectorColumn *column, + gint text_column); +static gint +hildon_touch_selector_column_get_text_column (HildonTouchSelectorColumn *column); + + +static void +hildon_touch_selector_column_class_init (HildonTouchSelectorColumnClass *klass) +{ + GObjectClass *gobject_class = NULL; + + gobject_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (gobject_class, sizeof (HildonTouchSelectorColumnPrivate)); + + /* GObject */ + gobject_class->get_property = hildon_touch_selector_column_get_property; + gobject_class->set_property = hildon_touch_selector_column_set_property; + + g_object_class_install_property (G_OBJECT_CLASS(klass), + PROP_TEXT_COLUMN, + g_param_spec_int ("text-column", + "Text Column", + "A column in the data source model to get the strings from.", + -1, + G_MAXINT, + -1, + G_PARAM_READWRITE)); +} + +static void +hildon_touch_selector_column_init (HildonTouchSelectorColumn *column) +{ + column->priv = G_TYPE_INSTANCE_GET_PRIVATE (column, HILDON_TYPE_TOUCH_SELECTOR_COLUMN, + HildonTouchSelectorColumnPrivate); + column->priv->text_column = -1; +} + +static void +hildon_touch_selector_column_set_text_column (HildonTouchSelectorColumn *column, + gint text_column) +{ + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (column)); + g_return_if_fail (text_column >= -1); + + column->priv->text_column = text_column; + + g_object_notify (G_OBJECT (column), "text-column"); +} + +static gint +hildon_touch_selector_column_get_text_column (HildonTouchSelectorColumn *column) +{ + g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (column), -1); + + return column->priv->text_column; +} + +static void +hildon_touch_selector_column_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + switch (property_id) { + case PROP_TEXT_COLUMN: + g_value_set_int (value, + hildon_touch_selector_column_get_text_column (HILDON_TOUCH_SELECTOR_COLUMN (object))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +hildon_touch_selector_column_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + switch (property_id) { + case PROP_TEXT_COLUMN: + hildon_touch_selector_column_set_text_column (HILDON_TOUCH_SELECTOR_COLUMN (object), + g_value_get_int (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +/* ------------------------ GtkCellLayout implementation -------------------- */ +static void +hildon_touch_selector_column_cell_layout_init (GtkCellLayoutIface *iface) +{ + iface->pack_start = hildon_touch_selector_column_cell_layout_pack_start; + iface->pack_end = hildon_touch_selector_column_cell_layout_pack_end; + iface->clear = hildon_touch_selector_column_cell_layout_clear; + iface->add_attribute = hildon_touch_selector_column_cell_layout_add_attribute; + iface->set_cell_data_func = hildon_touch_selector_column_cell_layout_set_cell_data_func; + iface->clear_attributes = hildon_touch_selector_column_cell_layout_clear_attributes; + iface->reorder = hildon_touch_selector_column_cell_layout_reorder; + iface->get_cells = hildon_touch_selector_column_cell_layout_get_cells; +} + +static void +hildon_touch_selector_column_cell_layout_pack_start (GtkCellLayout *cell_layout, + GtkCellRenderer *cell, + gboolean expand) +{ + HildonTouchSelectorColumn *sel_column = NULL; + GtkTreeViewColumn *view_column = NULL; + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout)); + sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout); + + view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0); + + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT(view_column), cell, expand); + +} + +static void +hildon_touch_selector_column_cell_layout_pack_end (GtkCellLayout *cell_layout, + GtkCellRenderer *cell, + gboolean expand) +{ + HildonTouchSelectorColumn *sel_column = NULL; + GtkTreeViewColumn *view_column = NULL; + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout)); + sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout); + + view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0); + + gtk_cell_layout_pack_end (GTK_CELL_LAYOUT(view_column), cell, expand); +} + +static void +hildon_touch_selector_column_cell_layout_clear (GtkCellLayout *cell_layout) +{ + HildonTouchSelectorColumn *sel_column = NULL; + GtkTreeViewColumn *view_column = NULL; + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout)); + sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout); + + view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0); + + gtk_cell_layout_clear (GTK_CELL_LAYOUT(view_column)); +} + +static void +hildon_touch_selector_column_cell_layout_add_attribute (GtkCellLayout *cell_layout, + GtkCellRenderer *cell, + const gchar *attribute, + gint column) +{ + HildonTouchSelectorColumn *sel_column = NULL; + GtkTreeViewColumn *view_column = NULL; + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout)); + sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout); + + view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0); + + gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT(view_column), cell, attribute, column); +} + + +static void +hildon_touch_selector_column_cell_layout_set_cell_data_func (GtkCellLayout *cell_layout, + GtkCellRenderer *cell, + GtkCellLayoutDataFunc func, + gpointer func_data, + GDestroyNotify destroy) +{ + HildonTouchSelectorColumn *sel_column = NULL; + GtkTreeViewColumn *view_column = NULL; + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout)); + sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout); + + view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0); + + gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT(view_column), cell, func, + func_data, destroy); +} + +static void +hildon_touch_selector_column_cell_layout_clear_attributes (GtkCellLayout *cell_layout, + GtkCellRenderer *cell) +{ + HildonTouchSelectorColumn *sel_column = NULL; + GtkTreeViewColumn *view_column = NULL; + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout)); + sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout); + + view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0); + + gtk_cell_layout_clear_attributes (GTK_CELL_LAYOUT (view_column), cell); +} + +static void +hildon_touch_selector_column_cell_layout_reorder (GtkCellLayout *cell_layout, + GtkCellRenderer *cell, + gint position) +{ + HildonTouchSelectorColumn *sel_column = NULL; + GtkTreeViewColumn *view_column = NULL; + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout)); + sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout); + + view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0); + + gtk_cell_layout_reorder (GTK_CELL_LAYOUT(view_column), cell, position); +} + +static GList* +hildon_touch_selector_column_cell_layout_get_cells (GtkCellLayout *cell_layout) +{ + HildonTouchSelectorColumn *sel_column = NULL; + GtkTreeViewColumn *view_column = NULL; + + g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout), NULL); + sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout); + + view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0); + + return gtk_cell_layout_get_cells (GTK_CELL_LAYOUT(view_column)); +} + +/* ------------------------------ PUBLIC METHODS ---------------------------- */ + +/** + * hildon_touch_selector_new: + * + * Creates a new empty #HildonTouchSelector. + * + * Returns: a new #HildonTouchSelector. + * + * Since: 2.2 + **/ +GtkWidget * +hildon_touch_selector_new (void) +{ + return g_object_new (HILDON_TYPE_TOUCH_SELECTOR, NULL); +} + +/** + * hildon_touch_selector_new_text: + * + * Creates a #HildonTouchSelector with a single text column that + * can be populated conveniently through hildon_touch_selector_append_text(), + * hildon_touch_selector_prepend_text(), hildon_touch_selector_insert_text(). + * + * Returns: A new #HildonTouchSelector + * + * Since: 2.2 + **/ +GtkWidget * +hildon_touch_selector_new_text (void) +{ + GtkWidget *selector; + GtkListStore *store; + HildonTouchSelectorColumn *column = NULL; + + selector = hildon_touch_selector_new (); + store = gtk_list_store_new (1, G_TYPE_STRING); + + column = hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), + GTK_TREE_MODEL (store), TRUE); + + g_object_set (G_OBJECT (column), "text-column", 0, NULL); + + return selector; +} + +/** + * hildon_touch_selector_append_text: + * @selector: A #HildonTouchSelector. + * @text: a non %NULL text string. + * + * Appends a new entry in a #HildonTouchSelector created with + * hildon_touch_selector_new_text(). + * + * Since: 2.2 + **/ +void +hildon_touch_selector_append_text (HildonTouchSelector * selector, + const gchar * text) +{ + GtkTreeIter iter; + GtkTreeModel *model; + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); + g_return_if_fail (text != NULL); + + model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0); + + g_return_if_fail (GTK_IS_LIST_STORE (model)); + + gtk_list_store_append (GTK_LIST_STORE (model), &iter); + gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, text, -1); +} + +/** + * hildon_touch_selector_prepend_text: + * @selector: A #HildonTouchSelector. + * @text: a non %NULL text string. + * + * Prepends a new entry in a #HildonTouchSelector created with + * hildon_touch_selector_new_text(). + * + * Since: 2.2 + **/ +void +hildon_touch_selector_prepend_text (HildonTouchSelector * selector, + const gchar * text) +{ + GtkTreeIter iter; + GtkTreeModel *model; + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); + g_return_if_fail (text != NULL); + + model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0); + + g_return_if_fail (GTK_IS_LIST_STORE (model)); + + gtk_list_store_prepend (GTK_LIST_STORE (model), &iter); + gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, text, -1); +} + +/** + * hildon_touch_selector_insert_text: + * @selector: a #HildonTouchSelector. + * @position: the position to insert @text. + * @text: A non %NULL text string. + * + * Inserts a new entry in a particular position of a + * #HildonTouchSelector created with hildon_touch_selector_new_text(). + * + * Since: 2.2 + **/ +void +hildon_touch_selector_insert_text (HildonTouchSelector * selector, + gint position, const gchar * text) +{ + GtkTreeIter iter; + GtkTreeModel *model; + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); + g_return_if_fail (text != NULL); + g_return_if_fail (position >= 0); + + model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0); + + g_return_if_fail (GTK_IS_LIST_STORE (model)); + + gtk_list_store_insert (GTK_LIST_STORE (model), &iter, position); + gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, text, -1); +} + +/** + * hildon_touch_selector_append_column + * @selector: a #HildonTouchSelector + * @model: the #GtkTreeModel with the data of the column + * @cell_renderer: The #GtkCellRenderer where to draw each row contents. + * @Varargs: a %NULL-terminated pair of attributes and column numbers. + * + * This functions adds a new column to the widget, whose data will + * be obtained from the model. Only widgets added this way should used on + * the selection logic, i.e., the print function, the #HildonTouchPicker::changed + * signal, etc. + * + * You can optionally pass a #GtkCellRenderer in @cell_renderer, + * together with a %NULL-terminated list of pairs property/value, in + * the same way you would use gtk_tree_view_column_set_attributes(). + * This will pack @cell_renderer at the start of the column, expanded by default. + * If you prefer not to add it this way, you can simply pass %NULL to @cell_renderer + * and use the #GtkCellLayout interface on the returned #HildonTouchSelectorColumn + * to set your renderers. + * + * There is a prerequisite to be considered on models used: text data must + * be in the first column. + * + * This method basically adds a #GtkTreeView to the widget, using the model and + * the data received. + * + * Returns: the new column added added, %NULL otherwise. + * + * Since: 2.2 + **/ + +HildonTouchSelectorColumn* +hildon_touch_selector_append_column (HildonTouchSelector * selector, + GtkTreeModel * model, + GtkCellRenderer * cell_renderer, ...) +{ + va_list args; + HildonTouchSelectorColumn *new_column = NULL; + gboolean emit_changed = FALSE; + gint colnum; + + g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL); + g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL); + + if (model != NULL) { + + va_start (args, cell_renderer); + new_column = _create_new_column (selector, model, &emit_changed, cell_renderer, args); + va_end (args); + + selector->priv->columns = g_slist_append (selector->priv->columns, + new_column); + gtk_box_pack_start (GTK_BOX (selector->priv->hbox), + new_column->priv->panarea, + TRUE, TRUE, 6); + + gtk_widget_show_all (new_column->priv->panarea); + + if (selector->priv->initial_scroll) { + _hildon_touch_selector_center_on_selected_items (selector, new_column); + } + + } else { + return NULL; + } + + g_signal_emit (selector, hildon_touch_selector_signals[COLUMNS_CHANGED], 0); + if (emit_changed) { + colnum = g_slist_length (selector->priv->columns); + hildon_touch_selector_emit_value_changed (selector, colnum); + } + + return new_column; +} + +/** + * hildon_touch_selector_append_text_column + * @selector: a #HildonTouchSelector + * @model: a #GtkTreeModel with data for the column + * @center: whether to center the text on the column + * + * Equivalent to hildon_touch_selector_append_column(), but using a + * default text cell renderer. This is the most common use case of the + * widget. + * + * Returns: the new column added, NULL otherwise. + * + * Since: 2.2 + **/ +HildonTouchSelectorColumn* +hildon_touch_selector_append_text_column (HildonTouchSelector * selector, + GtkTreeModel * model, gboolean center) +{ + gfloat xalign = center ? 0.5 : 0.0; + GtkCellRenderer *renderer; + + g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL); + g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL); + + renderer = gtk_cell_renderer_text_new (); + + g_object_set (renderer, + "width", 1, + "xalign", xalign, + NULL); + + return hildon_touch_selector_append_column (selector, model, renderer, + "text", 0, NULL); +} + +/** + * hildon_touch_selector_remove_column: + * @selector: a #HildonTouchSelector + * @column: the position of the column to be removed + * + * Removes a column from @selector. + * + * Returns: %TRUE if the column was removed, %FALSE otherwise + * + * Since: 2.2 + **/ +gboolean +hildon_touch_selector_remove_column (HildonTouchSelector * selector, gint column) +{ + HildonTouchSelectorColumn *current_column = NULL; + HildonTouchSelectorPrivate *priv; + + g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE); + g_return_val_if_fail (column < + hildon_touch_selector_get_num_columns (selector), FALSE); + + priv = HILDON_TOUCH_SELECTOR_GET_PRIVATE (selector); + current_column = g_slist_nth_data (priv->columns, column); + + gtk_container_remove (GTK_CONTAINER (priv->hbox), current_column->priv->panarea); + priv->columns = g_slist_remove (priv->columns, current_column); + g_object_unref (current_column); + + g_signal_emit (selector, hildon_touch_selector_signals[COLUMNS_CHANGED], 0); + + return TRUE; +} + +/** + * hildon_touch_selector_set_column_attributes: + * @selector: a #HildonTouchSelector + * @num_column: the number of the column whose attributes we're setting + * @cell_renderer: the #GtkCellRendere we're setting the attributes of + * @Varargs: A %NULL-terminated list of attributes. + * + * Sets the attributes for the given column. The attributes must be given + * in attribute/column pairs, just like in gtk_tree_view_column_set_attributes(). + * All existing attributes are removed and replaced with the new ones. + * + * Deprecated: #HildonTouchSelectorColumn implements #GtkCellLayout, use this + * interface instead. See + * hildon_touch_selector_get_column(). + * + * Since: 2.2 + **/ +void +hildon_touch_selector_set_column_attributes (HildonTouchSelector * selector, + gint num_column, + GtkCellRenderer * cell_renderer, + ...) +{ + va_list args; + GtkTreeViewColumn *tree_column = NULL; + HildonTouchSelectorColumn *current_column = NULL; + gchar *attribute = NULL; + gint value = 0; + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); + g_return_if_fail (num_column < + hildon_touch_selector_get_num_columns (selector)); + + current_column = g_slist_nth_data (selector->priv->columns, num_column); + + tree_column = gtk_tree_view_get_column (current_column->priv->tree_view, 0); + gtk_tree_view_remove_column (current_column->priv->tree_view, tree_column); + + tree_column = gtk_tree_view_column_new (); + gtk_tree_view_column_pack_start (tree_column, cell_renderer, TRUE); + + va_start (args, cell_renderer); + attribute = va_arg (args, gchar *); + + gtk_tree_view_column_clear_attributes (tree_column, cell_renderer); + + while (attribute != NULL) { + value = va_arg (args, gint); + gtk_tree_view_column_add_attribute (tree_column, cell_renderer, + attribute, value); + attribute = va_arg (args, gchar *); + } + + va_end (args); + + gtk_tree_view_append_column (current_column->priv->tree_view, tree_column); +} + +/** + * hildon_touch_selector_get_num_columns: + * @selector: a #HildonTouchSelector + * + * Gets the number of columns in the #HildonTouchSelector. + * + * Returns: the number of columns in @selector. + * + * Since: 2.2 + **/ +gint +hildon_touch_selector_get_num_columns (HildonTouchSelector * selector) +{ + g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), -1); + + return g_slist_length (selector->priv->columns); +} + +/** + * hildon_touch_selector_get_column_selection_mode: + * @selector: a #HildonTouchSelector + * + * Gets the selection mode of @selector. + * + * Returns: one of #HildonTouchSelectorSelectionMode + * + * Since: 2.2 + **/ +HildonTouchSelectorSelectionMode +hildon_touch_selector_get_column_selection_mode (HildonTouchSelector * selector) +{ + HildonTouchSelectorSelectionMode result = + HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE; + GtkSelectionMode treeview_mode = GTK_SELECTION_BROWSE; + HildonTouchSelectorColumn *column = NULL; + GtkTreeSelection *selection = NULL; + + g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), result); + g_return_val_if_fail (hildon_touch_selector_get_num_columns (selector) > 0, + result); + + column = HILDON_TOUCH_SELECTOR_COLUMN (selector->priv->columns->data); + + selection = gtk_tree_view_get_selection (column->priv->tree_view); + treeview_mode = gtk_tree_selection_get_mode (selection); + + + if (treeview_mode == GTK_SELECTION_MULTIPLE) { + result = HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE; + } else { + result = HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE; + } + + return result; +} + +/** + * hildon_touch_selector_set_column_selection_mode: + * @selector: a #HildonTouchSelector + * @mode: the #HildonTouchSelectorMode for @selector + * + * Sets the selection mode for @selector. See #HildonTouchSelectorSelectionMode. + * + * Since: 2.2 + **/ +void +hildon_touch_selector_set_column_selection_mode (HildonTouchSelector * selector, + HildonTouchSelectorSelectionMode mode) +{ + GtkTreeView *tv = NULL; + HildonTouchSelectorColumn *column = NULL; + GtkTreeSelection *selection = NULL; + GtkSelectionMode treeview_mode = GTK_SELECTION_MULTIPLE; + GtkTreeIter iter; + HildonTouchSelectorSelectionMode current_mode; + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); + g_return_if_fail (hildon_touch_selector_get_num_columns (selector) > 0); + + current_mode = hildon_touch_selector_get_column_selection_mode (selector); + + if (current_mode == mode) { + return; + } + + column = HILDON_TOUCH_SELECTOR_COLUMN ((g_slist_nth (selector->priv->columns, 0))->data); + tv = column->priv->tree_view; + + if (tv) { + switch (mode) { + case HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE: + treeview_mode = GTK_SELECTION_BROWSE; + break; + case HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE: + treeview_mode = GTK_SELECTION_MULTIPLE; + break; + } + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv)); + gtk_tree_selection_set_mode (selection, treeview_mode); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv)); + gtk_tree_model_get_iter_first (column->priv->model, &iter); + gtk_tree_selection_unselect_all (selection); + gtk_tree_selection_select_iter (selection, &iter); + + /* the column changed was the first one */ + hildon_touch_selector_emit_value_changed (selector, 0); + } + +} + +/** + * hildon_touch_selector_set_print_func: + * @selector: a #HildonTouchSelector + * @func: a #HildonTouchSelectorPrintFunc function + * + * Sets the function to be used by hildon_touch_selector_get_current_text() + * to produce a text representation of the currently selected items in @selector. + * The default function will return a concatenation of comma separated items + * selected in each column in @selector. Use this to override this method if you + * need a particular representation for your application. + * + * Since: 2.2 + **/ +void +hildon_touch_selector_set_print_func (HildonTouchSelector * selector, + HildonTouchSelectorPrintFunc func) +{ + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); + + hildon_touch_selector_set_print_func_full (selector, func, NULL, NULL); +} + +/** + * hildon_touch_selector_set_print_func_full: + * @selector: a #HildonTouchSelector + * @func: a #HildonTouchSelectorPrintFunc function + * @user_data: a pointer to user data or %NULL + * @destroy_func: a callback for freeing the user data or %NULL + * + * Sets the function to be used by hildon_touch_selector_get_current_text() + * to produce a text representation of the currently selected items in @selector. + * The default function will return a concatenation of comma separated items + * selected in each column in @selector. Use this to override this method if you + * need a particular representation for your application. + * + * Since: 2.2 + **/ +void +hildon_touch_selector_set_print_func_full (HildonTouchSelector *selector, + HildonTouchSelectorPrintFunc func, + gpointer user_data, + GDestroyNotify destroy_func) +{ + gpointer old_user_data; + GDestroyNotify old_destroy_func; + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); + + old_user_data = selector->priv->print_user_data; + old_destroy_func = selector->priv->print_destroy_func; + + selector->priv->print_func = func; + selector->priv->print_user_data = user_data; + selector->priv->print_destroy_func = destroy_func; + + if (old_destroy_func && old_user_data != user_data) + (*old_destroy_func) (old_user_data); +} + +/** + * hildon_touch_selector_get_print_func: + * @selector: a #HildonTouchSelector + * + * Gets the #HildonTouchSelectorPrintFunc currently used. See + * hildon_touch_selector_set_print_func(). + * + * Returns: a #HildonTouchSelectorPrintFunc or %NULL if the default + * one is currently used. + **/ +HildonTouchSelectorPrintFunc +hildon_touch_selector_get_print_func (HildonTouchSelector * selector) +{ + g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL); + + return selector->priv->print_func; +} + +/** + * hildon_touch_selector_set_active: + * @selector: a #HildonTouchSelector + * @column: column number + * @index: the index of the item to select, or -1 to have no active item + * + * Sets the active item of the #HildonTouchSelector to @index. The + * column number is taken from @column. + * + * @selector must be in %HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE + * + * Since: 2.2 + **/ +void +hildon_touch_selector_set_active (HildonTouchSelector *selector, + gint column, + gint index) +{ + GtkTreeSelection *selection = NULL; + HildonTouchSelectorColumn *current_column = NULL; + HildonTouchSelectorSelectionMode mode; + GtkTreePath *path; + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); + g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector)); + mode = hildon_touch_selector_get_column_selection_mode (selector); + g_return_if_fail (mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE); + + current_column = g_slist_nth_data (selector->priv->columns, column); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (current_column->priv->tree_view)); + path = gtk_tree_path_new_from_indices (index, -1); + gtk_tree_selection_unselect_all (selection); + if (index != -1) + gtk_tree_selection_select_path (selection, path); + + hildon_touch_selector_emit_value_changed (selector, column); + + gtk_tree_path_free (path); +} + +/** + * hildon_touch_selector_get_active: + * @selector: a #HildonTouchSelector + * @column: column number + * + * Returns the index of the currently active item in column number + * @column, or -1 if there's no active item. + * + * @selector must be in %HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE + * + * Returns: an integer which is the index of the currently active + * item, or -1 if there's no active item. + * + * Since: 2.2 + **/ +gint +hildon_touch_selector_get_active (HildonTouchSelector *selector, + gint column) +{ + GtkTreeSelection *selection = NULL; + HildonTouchSelectorColumn *current_column = NULL; + HildonTouchSelectorSelectionMode mode; + GtkTreeModel *model; + GtkTreeIter iter; + GtkTreePath *path; + gint index; + + g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), -1); + g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector), -1); + mode = hildon_touch_selector_get_column_selection_mode (selector); + g_return_val_if_fail (mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE, -1); + + current_column = g_slist_nth_data (selector->priv->columns, column); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (current_column->priv->tree_view)); + g_return_val_if_fail (gtk_tree_selection_get_selected (selection, NULL, &iter), -1); + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (current_column->priv->tree_view)); + path = gtk_tree_model_get_path (model, &iter); + index = (gtk_tree_path_get_indices (path))[0]; + + gtk_tree_path_free (path); + + return index; +} + +/** + * hildon_touch_selector_get_selected: + * @selector: a #HildonTouchSelector + * @column: the column number we want to get the element + * @iter: #GtkTreeIter currently selected + * + * Sets @iter to the currently selected node on the nth-column, if selection is + * set to %HILDON_TOUCH_SELECTOR_SINGLE or %HILDON_TOUCH_SELECTOR_MULTIPLE with + * a column different that the first one. @iter may be %NULL if you just want to + * test if selection has any selected items. + * + * This function will not work if selection is in + * %HILDON_TOUCH_SELECTOR_MULTIPLE mode and the column is the first one. + * + * See gtk_tree_selection_get_selected() for more information. + * + * Returns: %TRUE if @iter was correctly set, %FALSE otherwise + * + * Since: 2.2 + **/ +gboolean +hildon_touch_selector_get_selected (HildonTouchSelector * selector, + gint column, GtkTreeIter * iter) +{ + GtkTreeSelection *selection = NULL; + HildonTouchSelectorColumn *current_column = NULL; + HildonTouchSelectorSelectionMode mode; + + g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE); + g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector), + FALSE); + mode = hildon_touch_selector_get_column_selection_mode (selector); + g_return_val_if_fail + ((mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE) || + ((mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)&&(column>0)), + FALSE); + + current_column = g_slist_nth_data (selector->priv->columns, column); + + selection = + gtk_tree_view_get_selection (GTK_TREE_VIEW (current_column->priv->tree_view)); + + return gtk_tree_selection_get_selected (selection, NULL, iter); +} + +/** + * hildon_touch_selector_select_iter + * @selector: a #HildonTouchSelector + * @column: the column to selects + * @iter: the #GtkTreeIter to be selected + * @scroll_to: whether to smoothly scroll to the item + * + * Sets the currently selected item in the column @column to the one pointed by @iter, + * optionally smoothly scrolling to it. + * + * Since: 2.2 + **/ +void +hildon_touch_selector_select_iter (HildonTouchSelector * selector, + gint column, GtkTreeIter * iter, + gboolean scroll_to) +{ + GtkTreePath *path; + GtkTreeModel *model; + HildonTouchSelectorColumn *current_column = NULL; + GtkTreeView *tv = NULL; + GtkTreeSelection *selection = NULL; + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); + g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector)); + + current_column = g_slist_nth_data (selector->priv->columns, column); + + tv = current_column->priv->tree_view; + selection = gtk_tree_view_get_selection (tv); + model = gtk_tree_view_get_model (tv); + path = gtk_tree_model_get_path (model, iter); + + gtk_tree_selection_select_iter (selection, iter); + + if (scroll_to) { + hildon_touch_selector_scroll_to (current_column, tv, path); + } + + hildon_touch_selector_emit_value_changed (selector, column); + + gtk_tree_path_free (path); +} + +/** + * hildon_touch_selector_unselect_iter + * @selector: a #HildonTouchSelector + * @column: the column to unselects from + * @iter: the #GtkTreeIter to be unselected + * + * Unselect the item pointed by @iter in the column @column + * + * Since: 2.2 + **/ + +void hildon_touch_selector_unselect_iter (HildonTouchSelector * selector, + gint column, + GtkTreeIter * iter) +{ + HildonTouchSelectorColumn *current_column = NULL; + GtkTreeSelection *selection = NULL; + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); + g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector)); + + current_column = g_slist_nth_data (selector->priv->columns, column); + selection = gtk_tree_view_get_selection (current_column->priv->tree_view); + gtk_tree_selection_unselect_iter (selection, iter); + + hildon_touch_selector_emit_value_changed (selector, column); +} + +/** + * hildon_touch_selector_unselect_all: + * @selector: a #HildonTouchSelector + * @column: the position of the column to get the selected rows from + * + * Unselects all the selected items in the column @column. + * + * Since: 2.2 + **/ +void +hildon_touch_selector_unselect_all (HildonTouchSelector * selector, + gint column) +{ + HildonTouchSelectorColumn *current_column = NULL; + GtkTreeSelection *selection = NULL; + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); + g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector)); + + current_column = g_slist_nth_data (selector->priv->columns, column); + selection = gtk_tree_view_get_selection (current_column->priv->tree_view); + gtk_tree_selection_unselect_all (selection); + + hildon_touch_selector_emit_value_changed (selector, column); +} + +/** + * hildon_touch_selector_get_selected_rows: + * @selector: a #HildonTouchSelector + * @column: the position of the column to get the selected rows from + * + * Creates a list of #GtkTreePaths of all selected rows in a column. Additionally, + * if you to plan to modify the model after calling this function, you may + * want to convert the returned list into a list of GtkTreeRowReferences. To do this, + * you can use gtk_tree_row_reference_new(). + * + * See gtk_tree_selection_get_selected_rows() for more information. + * + * Returns: A new #GList containing a #GtkTreePath for each selected row in the column @column. + * + * Since: 2.2 + **/ +GList * +hildon_touch_selector_get_selected_rows (HildonTouchSelector * selector, + gint column) +{ + GList *result = NULL; + HildonTouchSelectorColumn *current_column = NULL; + GtkTreeSelection *selection = NULL; + + g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL); + g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector), + NULL); + + current_column = g_slist_nth_data (selector->priv->columns, column); + selection = gtk_tree_view_get_selection (current_column->priv->tree_view); + + result = gtk_tree_selection_get_selected_rows (selection, NULL); + + return result; +} + +/** + * hildon_touch_selector_get_model: + * @selector: a #HildonTouchSelector + * @column: the position of the column in @selector + * + * Gets the model of a column of @selector. + * + * Returns: the #GtkTreeModel for the column @column of @selector. + * + * Since: 2.2 + **/ +GtkTreeModel * +hildon_touch_selector_get_model (HildonTouchSelector * selector, gint column) +{ + HildonTouchSelectorColumn *current_column = NULL; + + g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL); + g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector), + NULL); + + current_column = g_slist_nth_data (selector->priv->columns, column); + + return current_column->priv->model; +} + +static void +_hildon_touch_selector_set_model (HildonTouchSelector * selector, + gint column, GtkTreeModel * model) +{ + HildonTouchSelectorColumn *current_column = NULL; + + current_column = + HILDON_TOUCH_SELECTOR_COLUMN (g_slist_nth_data (selector->priv->columns, column)); + + current_column->priv->model = model; + gtk_tree_view_set_model (current_column->priv->tree_view, + current_column->priv->model); +} + +/** + * hildon_touch_selector_set_model: + * @selector: a #HildonTouchSelector + * @column: the position of the column to set the model to + * @model: a #GtkTreeModel + * + * Sets the #GtkTreeModel for a particular column in @model. + * + * Since: 2.2 + **/ +void +hildon_touch_selector_set_model (HildonTouchSelector * selector, + gint column, GtkTreeModel * model) +{ + g_return_if_fail (HILDON_TOUCH_SELECTOR (selector)); + g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector)); + + HILDON_TOUCH_SELECTOR_GET_CLASS (selector)->set_model (selector, column, model); +} + +/** + * hildon_touch_selector_get_current_text: + * @selector: a #HildonTouchSelector + * + * Returns a string representing the currently selected items for + * each column of @selector. See hildon_touch_selector_set_print_func(). + * + * Returns: a newly allocated string. + * + * Since: 2.2 + **/ +gchar * +hildon_touch_selector_get_current_text (HildonTouchSelector * selector) +{ + gchar *result = NULL; + g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL); + + if (selector->priv->print_func) { + result = (*selector->priv->print_func) (selector, selector->priv->print_user_data); + } else { + result = _default_print_func (selector, NULL); + } + + return result; +} + +static void +search_nearest_element (HildonPannableArea *panarea, + GtkTreeView *tv, + GList *selected_rows, + GtkTreePath **nearest_path) +{ + GtkAdjustment *adj = NULL; + gdouble target_value = 0; + GdkRectangle rect; + GList *iter = NULL; + GtkTreePath *path = NULL; + gint y = -1; + gdouble nearest_distance = -1; + gdouble current_distance = -1; + GtkTreePath *result_path = NULL; + + g_assert (nearest_path != NULL); + + if (selected_rows == NULL) { + *nearest_path = NULL; + return; + } + + adj = hildon_pannable_area_get_vadjustment (panarea); + g_return_if_fail (adj != NULL); + + /* we add this in order to check the nearest to the center of + the visible area */ + target_value = gtk_adjustment_get_value (adj) + adj->page_size/2; + + path = result_path = selected_rows->data; + gtk_tree_view_get_background_area (tv, path, NULL, &rect); + gtk_tree_view_convert_bin_window_to_tree_coords (tv, 0, rect.y, NULL, &y); + nearest_distance = abs (target_value - y); + + for (iter = selected_rows->next; iter; iter = g_list_next (iter)) { + gtk_tree_view_get_background_area (tv, path, NULL, &rect); + gtk_tree_view_convert_bin_window_to_tree_coords (tv, 0, rect.y, NULL, &y); + current_distance = abs (target_value - y); + if (current_distance < nearest_distance) { + nearest_distance = current_distance; + result_path = path; + } + } + + *nearest_path = result_path; +} + +static gboolean +on_realize_cb (GtkWidget *widget, + gpointer data) +{ + HildonTouchSelectorColumn *column = NULL; + GdkRectangle rect; + gint y; + + column = HILDON_TOUCH_SELECTOR_COLUMN (data); + + if (column->priv->initial_path) { + gtk_tree_view_get_background_area (GTK_TREE_VIEW (column->priv->tree_view), + column->priv->initial_path, NULL, &rect); + gtk_tree_view_convert_bin_window_to_tree_coords + (GTK_TREE_VIEW (column->priv->tree_view), + 0, rect.y, NULL, &y); + + hildon_pannable_area_scroll_to (HILDON_PANNABLE_AREA (column->priv->panarea), + -1, y); + + gtk_tree_path_free (column->priv->initial_path); + + column->priv->initial_path = NULL; + + } + + g_signal_handler_disconnect (column->priv->panarea, + column->priv->realize_handler); + + return FALSE; +} + +static void +hildon_touch_selector_scroll_to (HildonTouchSelectorColumn *column, + GtkTreeView *tv, + GtkTreePath *path) +{ + if (GTK_WIDGET_REALIZED (column->priv->panarea)) { + GdkRectangle rect; + gint y; + + gtk_tree_view_get_background_area (tv, + path, NULL, &rect); + gtk_tree_view_convert_bin_window_to_tree_coords (tv, + 0, rect.y, NULL, &y); + + hildon_pannable_area_scroll_to (HILDON_PANNABLE_AREA + (column->priv->panarea), -1, y); + } else { + if (column->priv->realize_handler != 0) { + + if (column->priv->initial_path) { + gtk_tree_path_free (column->priv->initial_path); + column->priv->initial_path = NULL; + } + + g_signal_handler_disconnect (column->priv->panarea, + column->priv->realize_handler); + column->priv->realize_handler = 0; + } + + column->priv->initial_path = gtk_tree_path_copy (path); + column->priv->realize_handler = + g_signal_connect_after (G_OBJECT (column->priv->panarea), "realize", + G_CALLBACK (on_realize_cb), + column); + } +} + +/** + * + * Center on the selected item of a concrete column + * + * Returns: TRUE if was able to do that + * FALSE otherwise + */ +static gboolean +_hildon_touch_selector_center_on_selected_items (HildonTouchSelector *selector, + HildonTouchSelectorColumn *column) +{ + GtkTreePath *path = NULL; + GList *selected_rows = NULL; + gint num_column = -1; + + num_column = g_slist_index (selector->priv->columns, column); + + selected_rows = hildon_touch_selector_get_selected_rows (selector, num_column); + if (selected_rows) { + search_nearest_element (HILDON_PANNABLE_AREA (column->priv->panarea), + GTK_TREE_VIEW (column->priv->tree_view), + selected_rows, + &path); + + if (path != NULL) { + hildon_touch_selector_scroll_to (column, + GTK_TREE_VIEW (column->priv->tree_view), + path); + } else { + return FALSE; + } + + g_list_foreach (selected_rows, (GFunc) (gtk_tree_path_free), NULL); + g_list_free (selected_rows); + } + + return TRUE; +} + +static gboolean +_hildon_touch_selector_has_multiple_selection (HildonTouchSelector * selector) +{ + HildonTouchSelectorSelectionMode mode; + gint n_columns; + + n_columns = hildon_touch_selector_get_num_columns (selector); + mode = hildon_touch_selector_get_column_selection_mode (selector); + + return ((n_columns > 1) || (mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)); +} + +/** + * hildon_touch_selector_has_multiple_selection: + * @selector: A #HildonTouchSelector + * + * Determines whether @selector is complex enough to actually require an + * extra selection step than only picking an item. This is normally %TRUE + * if @selector has multiple columns, multiple selection, or when it is a + * more complex widget, like #HildonTouchSelectorEntry. + * + * This information is useful for widgets containing a #HildonTouchSelector, + * like #HildonPickerDialog, that could need a "Done" button, in case that + * its internal #HildonTouchSelector has multiple columns, for instance. + * + * Returns: %TRUE if @selector requires multiple selection steps. + * + * Since: 2.2 + **/ +gboolean +hildon_touch_selector_has_multiple_selection (HildonTouchSelector * selector) +{ + g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE); + + return HILDON_TOUCH_SELECTOR_GET_CLASS (selector)->has_multiple_selection (selector); +} + + +/** + * hildon_touch_selector_get_column: + * @selector: A #HildonTouchSelector + * @column: a column number + * + * Use this method to retrieve a #HildonTouchSelectorColumn. Then, you can use + * the #GtkCellLayout interface to set up the layout of the column. + * + * Returns: the @column-th #HildonTouchSelectorColumn in @selector + * + * Since: 2.2 + **/ +HildonTouchSelectorColumn * +hildon_touch_selector_get_column (HildonTouchSelector * selector, + gint column) +{ + gint num_columns = -1; + + g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL); + num_columns = hildon_touch_selector_get_num_columns (selector); + g_return_val_if_fail (column < num_columns && column >= 0, NULL); + + return g_slist_nth_data (selector->priv->columns, column); +} + + +/** + * hildon_touch_selector_center_on_selected: + * @selector: a #HildonTouchSelector + * + * Ensures all the columns in a #HildonTouchSelector show a selected + * item. If one of the columns is in + * %HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE mode, that column + * will be scrolled to ensure the selected item that is closest to the + * currently visible area is shown. + * + * Since: 2.2 + **/ +void +hildon_touch_selector_center_on_selected (HildonTouchSelector *selector) +{ + GSList *iter = NULL; + + g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); + + for (iter = selector->priv->columns; iter; iter = g_slist_next (iter)) { + _hildon_touch_selector_center_on_selected_items (selector, + HILDON_TOUCH_SELECTOR_COLUMN (iter->data)); + } +} diff --git a/hildon/hildon-touch-selector.h b/hildon/hildon-touch-selector.h new file mode 100644 index 0000000..14b4d9f --- /dev/null +++ b/hildon/hildon-touch-selector.h @@ -0,0 +1,220 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2008 Nokia Corporation. + * + * 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; either + * version 2 of the License, or (at your option) any later version. or (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __HILDON_TOUCH_SELECTOR_H__ +#define __HILDON_TOUCH_SELECTOR_H__ + +#include +#include "hildon-touch-selector-column.h" + +G_BEGIN_DECLS + +#define HILDON_TYPE_TOUCH_SELECTOR \ + (hildon_touch_selector_get_type ()) + +#define HILDON_TOUCH_SELECTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + HILDON_TYPE_TOUCH_SELECTOR, HildonTouchSelector)) + +#define HILDON_TOUCH_SELECTOR_CLASS(vtable) \ + (G_TYPE_CHECK_CLASS_CAST ((vtable), \ + HILDON_TYPE_TOUCH_SELECTOR, HildonTouchSelectorClass)) + +#define HILDON_IS_TOUCH_SELECTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + HILDON_TYPE_TOUCH_SELECTOR)) + +#define HILDON_IS_TOUCH_SELECTOR_CLASS(vtable) \ + (G_TYPE_CHECK_CLASS_TYPE ((vtable), HILDON_TYPE_TOUCH_SELECTOR)) + +#define HILDON_TOUCH_SELECTOR_GET_CLASS(inst) \ + (G_TYPE_INSTANCE_GET_CLASS ((inst), \ + HILDON_TYPE_TOUCH_SELECTOR, HildonTouchSelectorClass)) + +typedef struct _HildonTouchSelector HildonTouchSelector; +typedef struct _HildonTouchSelectorClass HildonTouchSelectorClass; +typedef struct _HildonTouchSelectorPrivate HildonTouchSelectorPrivate; + +typedef gchar *(*HildonTouchSelectorPrintFunc) (HildonTouchSelector * selector, + gpointer user_data); + +struct _HildonTouchSelector +{ + GtkVBox parent_instance; + + /*< private > */ + HildonTouchSelectorPrivate *priv; +}; + +struct _HildonTouchSelectorClass +{ + GtkVBoxClass parent_class; + + /* signals */ + void (*changed) (HildonTouchSelector *selector, + gint column); + + /* virtual methods */ + void (*set_model) (HildonTouchSelector *selector, + gint column, + GtkTreeModel *model); + + gboolean (*has_multiple_selection) (HildonTouchSelector *selector); +}; + +/** + * HildonTouchSelectorSelectionMode: + * @HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE: Users can select one item + * @HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE: Users can select one to many items + * + * Describes the selection mode of a #HildonTouchSelector. + **/ +typedef enum +{ + HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE, + HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE +} HildonTouchSelectorSelectionMode; + +/* construction */ +GType +hildon_touch_selector_get_type (void) G_GNUC_CONST; + +GtkWidget * +hildon_touch_selector_new (void); + +/* Simple (and recommended) API for one-text-column selectors. */ +GtkWidget * +hildon_touch_selector_new_text (void); + +void +hildon_touch_selector_append_text (HildonTouchSelector *selector, + const gchar *text); +void +hildon_touch_selector_prepend_text (HildonTouchSelector *selector, + const gchar *text); +void +hildon_touch_selector_insert_text (HildonTouchSelector *selector, + gint position, + const gchar *text); + +/* column related */ +HildonTouchSelectorColumn* +hildon_touch_selector_append_text_column (HildonTouchSelector *selector, + GtkTreeModel * model, + gboolean center); + +HildonTouchSelectorColumn* +hildon_touch_selector_append_column (HildonTouchSelector *selector, + GtkTreeModel *model, + GtkCellRenderer *cell_renderer, + ...); +#ifndef HILDON_DISABLE_DEPRECATED +void +hildon_touch_selector_set_column_attributes (HildonTouchSelector *selector, + gint num_column, + GtkCellRenderer *cell_renderer, + ...); +#endif + +gboolean +hildon_touch_selector_remove_column (HildonTouchSelector *selector, + gint column); + +gint +hildon_touch_selector_get_num_columns (HildonTouchSelector *selector); + +void +hildon_touch_selector_set_column_selection_mode (HildonTouchSelector *selector, + HildonTouchSelectorSelectionMode mode); + +HildonTouchSelectorSelectionMode +hildon_touch_selector_get_column_selection_mode (HildonTouchSelector *selector); + +HildonTouchSelectorColumn * +hildon_touch_selector_get_column (HildonTouchSelector *selector, + gint column); + +/* get/set active item */ +void +hildon_touch_selector_set_active (HildonTouchSelector *selector, + gint column, + gint index); +gint +hildon_touch_selector_get_active (HildonTouchSelector *selector, + gint column); + +gboolean +hildon_touch_selector_get_selected (HildonTouchSelector *selector, + gint column, + GtkTreeIter *iter); + +void +hildon_touch_selector_select_iter (HildonTouchSelector *selector, + gint column, + GtkTreeIter *iter, + gboolean scroll_to); + +void +hildon_touch_selector_unselect_iter (HildonTouchSelector *selector, + gint column, + GtkTreeIter *iter); + +void +hildon_touch_selector_unselect_all (HildonTouchSelector * selector, + gint column); + +GList * +hildon_touch_selector_get_selected_rows (HildonTouchSelector *selector, + gint column); +/* model */ +void +hildon_touch_selector_set_model (HildonTouchSelector *selector, + gint column, + GtkTreeModel *model); +GtkTreeModel * +hildon_touch_selector_get_model (HildonTouchSelector *selector, + gint column); + +/* show the current element selected */ +gchar * +hildon_touch_selector_get_current_text (HildonTouchSelector *selector); + +void +hildon_touch_selector_set_print_func (HildonTouchSelector *selector, + HildonTouchSelectorPrintFunc func); + +void +hildon_touch_selector_set_print_func_full (HildonTouchSelector *selector, + HildonTouchSelectorPrintFunc func, + gpointer user_data, + GDestroyNotify destroy_func); + +HildonTouchSelectorPrintFunc +hildon_touch_selector_get_print_func (HildonTouchSelector *selector); + +gboolean +hildon_touch_selector_has_multiple_selection (HildonTouchSelector *selector); + +void +hildon_touch_selector_center_on_selected (HildonTouchSelector *selector); + +G_END_DECLS + +#endif /* __HILDON_TOUCH_SELECTOR_H__ */ diff --git a/hildon/hildon-version.h.in b/hildon/hildon-version.h.in new file mode 100644 index 0000000..6fec0ff --- /dev/null +++ b/hildon/hildon-version.h.in @@ -0,0 +1,39 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006, 2007 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, or (at your option) any later version. + * + * 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_VERSION_H__ +#define __HILDON_VERSION_H__ + +#define HILDON_MAJOR_VERSION (@PACKAGE_VERSION_MAJOR@) +#define HILDON_MINOR_VERSION (@PACKAGE_VERSION_MINOR@) +#define HILDON_MICRO_VERSION (@PACKAGE_VERSION_MICRO@) + +#define HILDON_CHECK_VERSION(major,minor,micro) \ + (HILDON_MAJOR_VERSION > (major) || \ + (HILDON_MAJOR_VERSION == (major) && HILDON_MINOR_VERSION > (minor)) || \ + (HILDON_MAJOR_VERSION == (major) && HILDON_MINOR_VERSION == (minor) && \ + HILDON_MICRO_VERSION >= (micro))) + +#endif /* __HILDON_VERSION_H__ */ + diff --git a/hildon/hildon-volumebar-private.h b/hildon/hildon-volumebar-private.h new file mode 100644 index 0000000..62a5095 --- /dev/null +++ b/hildon/hildon-volumebar-private.h @@ -0,0 +1,56 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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 "hildon-volumebar-range.h" + +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 G_GNUC_INTERNAL +hildon_volumebar_mute_toggled (HildonVolumebar * self); + +void G_GNUC_INTERNAL +hildon_volumebar_level_change (HildonVolumebar *self); + +G_END_DECLS + +#endif /* __HILDON_VOLUMEBAR_PRIVATE__ */ diff --git a/hildon/hildon-volumebar-range.c b/hildon/hildon-volumebar-range.c new file mode 100644 index 0000000..11ff1f1 --- /dev/null +++ b/hildon/hildon-volumebar-range.c @@ -0,0 +1,326 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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-range + * @short_description: 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]. + * + * + * + * #HildonVolumebarRange has been deprecated since Hildon 2.2 and should not + * be used in newly written code. See + * Migrating Volume Bars + * section to know how to migrate this deprecated widget. + * + * + */ + +#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_0, + PROP_LEVEL +}; + +/** + * hildon_volumebar_range_get_type: + * + * Initializes and returns the type of a hildon volumebar range. + * + * Returns: GType of #HildonVolumebarRange + */ +GType G_GNUC_CONST +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; + + /** + * HildonVolumebarRange:level: + * + * Current volume level. + */ + 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) +{ + /* do nothing. */ +} + +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/hildon-volumebar-range.h b/hildon/hildon-volumebar-range.h new file mode 100644 index 0000000..9e5eb59 --- /dev/null +++ b/hildon/hildon-volumebar-range.h @@ -0,0 +1,85 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_TYPE_VOLUMEBAR_RANGE + * + * Macro for getting type of volumebar range. + */ +#define HILDON_TYPE_VOLUMEBAR_RANGE \ + (hildon_volumebar_range_get_type()) + +#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 G_GNUC_CONST +hildon_volumebar_range_get_type (void); + +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/hildon-volumebar.c b/hildon/hildon-volumebar.c new file mode 100644 index 0000000..42ae2a7 --- /dev/null +++ b/hildon/hildon-volumebar.c @@ -0,0 +1,806 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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. + * + * + * + * #HildonVolumebar has been deprecated since Hildon 2.2 and should not + * be used in newly written code. See + * Migrating Volume Bars + * section to know how to migrate this deprecated widget. + * + * + */ + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include +#endif + +#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_grab_focus (GtkWidget *widget); + +static gboolean +hildon_volumebar_focus (GtkWidget *widget, + GtkDirectionType direction); + +static void +hildon_volumebar_notify (GObject *self, GParamSpec *param); + +enum +{ + MUTE_TOGGLED_SIGNAL, + LEVEL_CHANGED_SIGNAL, + LAST_SIGNAL +}; + +enum { + PROP_0, + PROP_HILDON_HAS_MUTE, + PROP_HILDON_LEVEL, + PROP_HILDON_MUTE +}; + +static guint signals [LAST_SIGNAL] = { 0 }; + +/** + * hildon_volumebar_get_type: + * + * Initializes and returns the type of a hildon volumebar. + * + * Returns: GType of #HildonVolumebar + */ +GType G_GNUC_CONST +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->grab_focus = hildon_volumebar_grab_focus; + widget_class->focus = hildon_volumebar_focus; + 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, + g_cclosure_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, + g_cclosure_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; + + /** + * HildonVolumebar:has-mute: + * + * Whether the mute button is visibile. + */ + 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)); + + /** + * HildonVolumebar:level: + * + * Current volume level. + */ + 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)); + + /** + * HildonVolumebar:mute: + * + * Whether volume is muted. + */ + 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); + g_assert (priv); + + /* Should set GTK_NO_WINDOW flag, because widget is derived from + GtkContainer */ + GTK_WIDGET_SET_FLAGS (GTK_WIDGET (volumebar), GTK_NO_WINDOW); + GTK_WIDGET_SET_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); + g_assert (priv); + + 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); + g_assert (priv); + + 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); + g_assert (priv); + + 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); + g_assert (priv); + + 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); + g_assert (priv); + + gdk_window_hide (priv->event_window); + + GTK_WIDGET_CLASS (parent_class)->unmap(widget); +} + +static void +hildon_volumebar_grab_focus (GtkWidget *widget) +{ + HildonVolumebarPrivate *priv; + + priv = HILDON_VOLUMEBAR_GET_PRIVATE (widget); + g_assert (priv); + + if (GTK_WIDGET_CAN_FOCUS (widget)) { + if (gtk_toggle_button_get_active (priv->tbutton)) + gtk_widget_grab_focus (GTK_WIDGET (priv->tbutton)); + else + gtk_widget_grab_focus (GTK_WIDGET (priv->volumebar)); + } +} + +static gboolean +hildon_volumebar_focus (GtkWidget *widget, + GtkDirectionType direction) +{ + HildonVolumebarPrivate *priv; + GtkOrientation orientation; + gboolean has_focus; + + priv = HILDON_VOLUMEBAR_GET_PRIVATE (widget); + g_assert (priv); + + orientation = GTK_RANGE (priv->volumebar)->orientation; + + has_focus = (GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (priv->volumebar)) || + GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (priv->tbutton))); + + switch (direction) { + case GTK_DIR_UP: + case GTK_DIR_DOWN: + case GTK_DIR_TAB_FORWARD: + case GTK_DIR_TAB_BACKWARD: + if (has_focus && orientation == GTK_ORIENTATION_HORIZONTAL) + return FALSE; + break; + + case GTK_DIR_LEFT: + case GTK_DIR_RIGHT: + if (has_focus && orientation == GTK_ORIENTATION_VERTICAL) + return FALSE; + break; + + default: + break; + } + + return GTK_WIDGET_CLASS (parent_class)->focus (widget, direction); +} + +static void +hildon_child_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) +{ + HildonVolumebarPrivate *priv; + + priv = HILDON_VOLUMEBAR_GET_PRIVATE (container); + g_assert (callback != NULL); + g_assert (priv); + + /* 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); + g_assert (priv); + + if (g_str_equal (param->name, "can-focus")) { + /* call set_mute() because that updates the widget's UI state */ + hildon_volumebar_set_mute (HILDON_VOLUMEBAR (self), + hildon_volumebar_get_mute (HILDON_VOLUMEBAR (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); + g_assert (priv); + + 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); + g_assert (priv); + + 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_LEVEL: + hildon_volumebar_set_level (HILDON_VOLUMEBAR (object), + g_value_get_double (value)); + break; + + case PROP_HILDON_MUTE: + hildon_volumebar_set_mute (HILDON_VOLUMEBAR (object), + 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) +{ + HildonVolumebarPrivate *priv; + HildonVolumebar *vb; + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(object); + g_assert (priv); + + vb = HILDON_VOLUMEBAR (object); + + switch (prop_id) { + + case PROP_HILDON_HAS_MUTE: + g_value_set_boolean (value, GTK_WIDGET_VISIBLE (priv->tbutton)); + 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_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); + g_assert (priv); + + 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); + g_assert (priv); + + 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 has_focus; + + g_return_if_fail (HILDON_IS_VOLUMEBAR (self)); + + priv = HILDON_VOLUMEBAR_GET_PRIVATE (self); + g_assert (priv); + + has_focus = (GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (priv->volumebar)) || + GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (priv->tbutton))); + + /* Slider should be insensitive when mute is on */ + gtk_widget_set_sensitive (GTK_WIDGET (priv->volumebar), !mute); + + if (mute) { + /* Make mute button focusable since the slider isn't anymore */ + g_object_set (G_OBJECT (priv->tbutton), "can-focus", TRUE, NULL); + + if (has_focus) + gtk_widget_grab_focus (GTK_WIDGET (priv->tbutton)); + } + else + { + g_object_set (G_OBJECT (priv->tbutton), "can-focus", FALSE, NULL); + + if (has_focus) + gtk_widget_grab_focus (GTK_WIDGET (priv->volumebar)); + } + + /* Update mute button state and redraw */ + gtk_toggle_button_set_active (priv->tbutton, mute); +} + +/** + * 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); + g_assert (priv); + + 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 pass to hildon_appview_set_connected_adjustment which + * will allow changing the volume with 'increase' / 'decrease' + * hardware buttons. + * + * 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); + g_assert (priv); + + 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); + g_assert (priv != NULL); + + /* 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. + */ +void G_GNUC_INTERNAL +hildon_volumebar_mute_toggled (HildonVolumebar * self) +{ + g_return_if_fail (HILDON_IS_VOLUMEBAR (self)); + /* FIXME Emit by id */ + g_signal_emit_by_name (self, "mute_toggled"); +} + +void G_GNUC_INTERNAL +hildon_volumebar_level_change (HildonVolumebar *self) +{ + g_return_if_fail (HILDON_IS_VOLUMEBAR (self)); + + /* FIXME Use numerical val, id */ + g_signal_emit_by_name (GTK_WIDGET (self), "level_changed"); +} + +/** + * hildon_volumebar_set_range_insensitive_message: + * @widget: A @GtkWidget to assign the banner to + * @message: A message to display to the user + * + * Used to asign an insensitive message to the slider of the given volumebar. + * It simply calls hildon_helper_set_insensitive_message on the slider/range of + * the volumebar. + * + * Deprecated: As of hildon 2.2, it is strongly discouraged to use insensitive messages. + */ +void +hildon_volumebar_set_range_insensitive_message (HildonVolumebar *widget, + const gchar *message) +{ + g_return_if_fail (HILDON_IS_VOLUMEBAR (widget)); + + HildonVolumebarPrivate *priv; + priv = HILDON_VOLUMEBAR_GET_PRIVATE (widget); + + hildon_helper_set_insensitive_message ((GtkWidget *) priv->volumebar, message); +} + +/** + * hildon_volumebar_set_range_insensitive_messagef: + * @widget: A @GtkWidget to assign the banner to + * @format : a printf-like format string + * @varargs : arguments for the format string + * + * A helper printf-like variant of hildon_helper_set_insensitive_message. + * + * Deprecated: As of hildon 2.2, it is strongly discouraged to use insensitive messages. + */ +void +hildon_volumebar_set_range_insensitive_messagef (HildonVolumebar *widget, + const gchar *format, + ...) +{ + g_return_if_fail (HILDON_IS_VOLUMEBAR (widget)); + + HildonVolumebarPrivate *priv; + priv = HILDON_VOLUMEBAR_GET_PRIVATE (widget); + + gchar *message; + va_list args; + + va_start (args, format); + message = g_strdup_vprintf (format, args); + va_end (args); + + hildon_helper_set_insensitive_message ((GtkWidget *) priv->volumebar, message); + + g_free (message); +} + + diff --git a/hildon/hildon-volumebar.h b/hildon/hildon-volumebar.h new file mode 100644 index 0000000..510f7ab --- /dev/null +++ b/hildon/hildon-volumebar.h @@ -0,0 +1,108 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#ifndef __HILDON_VOLUMEBAR_H__ +#define __HILDON_VOLUMEBAR_H__ + +#include + +#include "hildon-helper.h" + +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)) + +#define HILDON_VOLUMEBAR_GET_CLASS(obj) \ + ((HildonVolumebarClass *) G_OBJECT_GET_CLASS(obj)) + +typedef struct _HildonVolumebar HildonVolumebar; + +typedef struct _HildonVolumebarClass HildonVolumebarClass; + +struct _HildonVolumebar +{ + GtkContainer parent; +}; + +struct _HildonVolumebarClass +{ + GtkContainerClass parent_class; + + /* signals */ + void (*mute_toggled) (HildonVolumebar * self); + void (*level_changed) (HildonVolumebar * self); +}; + +GType G_GNUC_CONST +hildon_volumebar_get_type (void); + +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); + +GtkAdjustment* +hildon_volumebar_get_adjustment (HildonVolumebar *self); + +#ifndef HILDON_DISABLE_DEPRECATED +void +hildon_volumebar_set_range_insensitive_message (HildonVolumebar *widget, + const gchar *message); + +void +hildon_volumebar_set_range_insensitive_messagef (HildonVolumebar *widget, + const gchar *format, + ...); +#endif + +G_END_DECLS + +#endif /* __HILDON_VOLUMEBAR_H__ */ + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-vvolumebar.c b/hildon/hildon-vvolumebar.c new file mode 100644 index 0000000..5e0cec4 --- /dev/null +++ b/hildon/hildon-vvolumebar.c @@ -0,0 +1,283 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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. + * + * + * + * #HildonVVolumebar has been deprecated since Hildon 2.2 and should not + * be used in newly written code. See + * Migrating Volume Bars + * section to know how to migrate this deprecated widget. + * + * + * + * Here is an example that creates a vertical volume bar and connects + * both its signals. + * + * + * HildonVVolumebar example + * + * GtkWidget *volbar = hildon_vvolumebar_new (); + * g_signal_connect (G_OBJECT (volbar), "mute_toggled", G_CALLBACK (mute_toggle), NULL); + * g_signal_connect (G_OBJECT (volbar), "level_changed", G_CALLBACK (level_change), NULL); + * + * + */ + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "hildon-vvolumebar.h" +#include "hildon-volumebar-range.h" +#include "hildon-volumebar-private.h" + +/* Volume bar */ +#define DEFAULT_BAR_WIDTH 60 + +#define MINIMUM_BAR_HEIGHT 165 + +/* Toggle button */ + +#define DEFAULT_VERTICAL_TBUTTON_WIDTH 60 + +#define DEFAULT_VERTICAL_TBUTTON_HEIGHT 60 + +#define DEFAULT_ENDING_SIZE 0 + +/* Gap to leave for mute button */ + +#define HORIZONTAL_MUTE_GAP 0 + +#define VERTICAL_MUTE_GAP 0 + +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); + +/** + * hildon_vvolumebar_get_type: + * + * Initializes and returns the type of a hildon vvolumebar. + * + * Returns: GType of #HildonVVolumebar + */ +GType G_GNUC_CONST +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); + g_assert (priv); + + priv->volumebar = HILDON_VOLUMEBAR_RANGE (hildon_volumebar_range_new + (GTK_ORIENTATION_VERTICAL)); + + 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); + + /* FIXME Not sure why this is here */ + 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; + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(HILDON_VOLUMEBAR(widget)); + g_assert (priv); + + 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) +{ + 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; + + priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget); + g_assert (priv); + + /* 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 - + DEFAULT_VERTICAL_TBUTTON_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/hildon-vvolumebar.h b/hildon/hildon-vvolumebar.h new file mode 100644 index 0000000..ba1c471 --- /dev/null +++ b/hildon/hildon-vvolumebar.h @@ -0,0 +1,77 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#ifndef __HILDON_VVOLUMEBAR_H__ +#define __HILDON_VVOLUMEBAR_H__ + +#include "hildon-volumebar.h" + +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)) + +#define HILDON_VVOLUMEBAR_GET_CLASS(obj) \ + ((HildonVVolumebarClass *) G_OBJECT_GET_CLASS(obj)) + +typedef struct _HildonVVolumebar HildonVVolumebar; + +typedef struct _HildonVVolumebarClass HildonVVolumebarClass; + +struct _HildonVVolumebar +{ + HildonVolumebar parent; +}; + +struct _HildonVVolumebarClass +{ + HildonVolumebarClass parent_class; +}; + +GType G_GNUC_CONST +hildon_vvolumebar_get_type (void); + +GtkWidget* +hildon_vvolumebar_new (void); + +G_END_DECLS + +#endif /* __HILDON_VVOLUMEBAR_H__ */ + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-weekday-picker-private.h b/hildon/hildon-weekday-picker-private.h new file mode 100644 index 0000000..a97ca29 --- /dev/null +++ b/hildon/hildon-weekday-picker-private.h @@ -0,0 +1,44 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_PRIVATE_H__ +#define __HILDON_WEEKDAY_PICKER_PRIVATE_H__ + +G_BEGIN_DECLS + +typedef struct _HildonWeekdayPickerPrivate HildonWeekdayPickerPrivate; + +#define HILDON_WEEKDAY_PICKER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_WEEKDAY_PICKER, HildonWeekdayPickerPrivate)); + +struct _HildonWeekdayPickerPrivate +{ + GtkWidget *buttons[8]; /* weekday buttons in show order */ + GtkWidget *day_order_buttons[8]; /* weekday buttons in glib day order */ +}; + +G_END_DECLS + +#endif /* __HILDON_WEEKDAY_PICKER_PRIVATE_H__ */ diff --git a/hildon/hildon-weekday-picker.c b/hildon/hildon-weekday-picker.c new file mode 100644 index 0000000..d357c91 --- /dev/null +++ b/hildon/hildon-weekday-picker.c @@ -0,0 +1,565 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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. + * + * + * + * #HildonWeekdayPicker has been deprecated since Hildon 2.2 and should not + * be used in newly written code. See + * Migrating Date Widgets + * section to know how to migrate this deprecated widget. + * + * + * + * + * HildonWeekdayPicker example + * + * gint i; + * HildonWeekdayPicker *picker = hildon_weekday_picker_new (); + * + * hildon_weekday_picker_set_day (picker, i); + * hildon_weekday_picker_unset_day (picker, i); + * hildon_weekday_picker_toggle_day (picker, i); + * hildon_weekday_picker_set_all (picker); + * + * hildon_weekday_picker_unset_all( picker ); + * + * + * + */ + + /* 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 */ + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hildon-weekday-picker.h" +#include "hildon-private.h" +#include "hildon-weekday-picker-private.h" + +static GtkContainerClass* parent_class; + +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 gboolean +hildon_weekday_picker_focus (GtkWidget *widget, + GtkDirectionType direction); +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); + +enum +{ + SELECTION_CHANGED_SIGNAL, + LAST_SIGNAL +}; + +static guint signals [LAST_SIGNAL] = { 0 } ; + +/** + * hildon_weekday_picker_get_type: + * + * Initializes and returns the type of a hildon weekday picker. + * + * Returns: GType of #HildonWeekdayPicker + */ +GType G_GNUC_CONST +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_weekday_picker_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, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); +} + +static void +hildon_weekday_picker_init (HildonWeekdayPicker *picker) +{ + HildonWeekdayPickerPrivate *priv; + gint i, day; + + priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (picker); + g_assert (priv); + + /* 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); + + + /* 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); + g_assert (priv); + + /* 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); + g_assert (priv); + + /* 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); + g_assert (priv); + + 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); + g_assert (priv); + + 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 gboolean +hildon_weekday_picker_focus (GtkWidget *widget, + GtkDirectionType direction) +{ + gboolean retval; + GtkDirectionType effective_direction; + + g_assert (HILDON_IS_WEEKDAY_PICKER (widget)); + + retval = hildon_private_composite_focus (widget, direction, &effective_direction); + + if (retval == TRUE) + return GTK_WIDGET_CLASS (parent_class)->focus (widget, effective_direction); + else + return FALSE; +} + +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); + g_assert (picker); + priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (picker); + g_assert (priv); + + 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 (HILDON_IS_WEEKDAY_PICKER (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 + * + * Unselect specified weekday. + */ +void +hildon_weekday_picker_unset_day (HildonWeekdayPicker *picker, + GDateWeekday day) +{ + HildonWeekdayPickerPrivate *priv; + + g_return_if_fail (HILDON_IS_WEEKDAY_PICKER (picker)); + g_return_if_fail (g_date_valid_weekday (day)); + + priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (picker); + g_assert (priv); + + 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 (HILDON_IS_WEEKDAY_PICKER (picker)); + g_return_if_fail (g_date_valid_weekday (day)); + + priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (picker); + g_assert (priv); + + 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 (HILDON_IS_WEEKDAY_PICKER (picker)); + + priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (picker); + g_assert (priv); + + 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 (HILDON_IS_WEEKDAY_PICKER (picker)); + + priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (picker); + g_assert (priv); + + 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 (HILDON_IS_WEEKDAY_PICKER (picker), FALSE); + g_return_val_if_fail (g_date_valid_weekday (day), FALSE); + + priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (picker); + g_assert (picker); + + return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->day_order_buttons[day])); +} + diff --git a/hildon/hildon-weekday-picker.h b/hildon/hildon-weekday-picker.h new file mode 100644 index 0000000..afba2a9 --- /dev/null +++ b/hildon/hildon-weekday-picker.h @@ -0,0 +1,102 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_DISABLE_DEPRECATED + +#ifndef __HILDON_WEEKDAY_PICKER_H__ +#define __HILDON_WEEKDAY_PICKER_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _HildonWeekdayPicker HildonWeekdayPicker; + +typedef struct _HildonWeekdayPickerClass HildonWeekdayPickerClass; + +#define HILDON_TYPE_WEEKDAY_PICKER \ + (hildon_weekday_picker_get_type()) + +#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)) + +#define HILDON_WEEKDAY_PICKER_GET_CLASS(obj) \ + ((HildonWeekdayPickerClass *) G_OBJECT_GET_CLASS(obj)) + +struct _HildonWeekdayPicker +{ + GtkContainer parent; +}; + +struct _HildonWeekdayPickerClass +{ + GtkContainerClass parent_class; + + void (*selection_changed) (HildonWeekdayPicker *self); +}; + +GType G_GNUC_CONST +hildon_weekday_picker_get_type (void); + +GtkWidget* +hildon_weekday_picker_new (void); + +void +hildon_weekday_picker_set_day (HildonWeekdayPicker *picker, + GDateWeekday day); + +void +hildon_weekday_picker_unset_day (HildonWeekdayPicker *picker, + GDateWeekday day); + +void +hildon_weekday_picker_toggle_day (HildonWeekdayPicker *picker, + GDateWeekday day); + +void +hildon_weekday_picker_set_all (HildonWeekdayPicker *picker); + +void +hildon_weekday_picker_unset_all (HildonWeekdayPicker *picker); + +gboolean +hildon_weekday_picker_isset_day (HildonWeekdayPicker * picker, + GDateWeekday day); + +G_END_DECLS + +#endif /* __HILDON_WEEKDAY_PICKER_H__ */ + +#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/hildon/hildon-window-private.h b/hildon/hildon-window-private.h new file mode 100644 index 0000000..97034a6 --- /dev/null +++ b/hildon/hildon-window-private.h @@ -0,0 +1,89 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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__ + +#include "hildon-program.h" + +#include + +G_BEGIN_DECLS + +typedef struct _HildonWindowPrivate HildonWindowPrivate; + +struct _HildonWindowPrivate +{ + GtkMenu *menu; + HildonAppMenu *app_menu; + GtkWidget *vbox; + GtkWidget *edit_toolbar; + + GtkBorder *borders; + GtkBorder *toolbar_borders; + + GtkAllocation allocation; + + gchar *markup; + + guint fullscreen; + guint is_topmost; + guint escape_timeout; + gint visible_toolbars; + gint previous_vbox_y; + + HildonProgram *program; +}; + +#define HILDON_WINDOW_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ + HILDON_TYPE_WINDOW, HildonWindowPrivate)) + +void G_GNUC_INTERNAL +hildon_window_set_program (HildonWindow *self, + GObject *program); + +void G_GNUC_INTERNAL +hildon_window_unset_program (HildonWindow *self); + +void G_GNUC_INTERNAL +hildon_window_set_can_hibernate_property (HildonWindow *self, + gpointer can_hibernate); + +void G_GNUC_INTERNAL +hildon_window_take_common_toolbar (HildonWindow *self); + +void G_GNUC_INTERNAL +hildon_window_update_topmost (HildonWindow *self, + Window window_id); + +Window G_GNUC_INTERNAL +hildon_window_get_active_window (void); + +void G_GNUC_INTERNAL +hildon_window_update_title (HildonWindow *window); + +G_END_DECLS + +#endif /* __HILDON_WINDOW_PRIVATE_H__ */ diff --git a/hildon/hildon-window-stack-private.h b/hildon/hildon-window-stack-private.h new file mode 100644 index 0000000..fb453b6 --- /dev/null +++ b/hildon/hildon-window-stack-private.h @@ -0,0 +1,37 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * 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, or (at your option) any later version. + * + * 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_STACK_PRIVATE_H__ +#define __HILDON_WINDOW_STACK_PRIVATE_H__ + +G_BEGIN_DECLS + +void G_GNUC_INTERNAL +hildon_window_stack_remove (HildonStackableWindow *win); + +gboolean G_GNUC_INTERNAL +_hildon_window_stack_do_push (HildonWindowStack *stack, + HildonStackableWindow *win); + +G_END_DECLS + +#endif /* __HILDON_WINDOW_STACK_PRIVATE_H__ */ diff --git a/hildon/hildon-window-stack.c b/hildon/hildon-window-stack.c new file mode 100644 index 0000000..925d9fd --- /dev/null +++ b/hildon/hildon-window-stack.c @@ -0,0 +1,679 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * 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, or (at your option) any later version. + * + * 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-window-stack + * @short_description: Object representing a stack of windows in the Hildon framework + * @see_also: #HildonStackableWindow + * + * The #HildonWindowStack is an object used to represent a stack of + * windows in the Hildon framework. + * + * Stacks contain all #HildonStackableWindows that are being + * shown. The user can only interact with the topmost window from each + * stack (as it covers all the others), but all of them are mapped and + * visible from the Gtk point of view. + * + * Each window can only be in one stack at a time. All stacked windows + * are visible and all visible windows are stacked. + * + * Each application has a default stack, and windows are automatically + * added to it when they are shown with gtk_widget_show(). + * + * Additional stacks can be created at any time using + * hildon_window_stack_new(). To add a window to a specific stack, use + * hildon_window_stack_push_1() (remember that, for the default stack, + * gtk_widget_show() can be used instead). + * + * To remove a window from a stack use hildon_window_stack_pop_1(), or + * simply gtk_widget_hide(). + * + * For more complex layout changes, applications can push and/or pop + * several windows at the same time in a single step. See + * hildon_window_stack_push(), hildon_window_stack_pop() and + * hildon_window_stack_pop_and_push() for more details. + */ + +#include "hildon-window-stack.h" +#include "hildon-window-stack-private.h" +#include "hildon-stackable-window-private.h" + +struct _HildonWindowStackPrivate +{ + GList *list; + GtkWindowGroup *group; + GdkWindow *leader; /* X Window group hint for all windows in a group */ +}; + +#define HILDON_WINDOW_STACK_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ + HILDON_TYPE_WINDOW_STACK, HildonWindowStackPrivate)) + +G_DEFINE_TYPE (HildonWindowStack, hildon_window_stack, G_TYPE_OBJECT); + +enum { + PROP_GROUP = 1, +}; + +static void +hildon_window_stack_set_window_group (HildonWindowStack *stack, + GtkWindowGroup *group) +{ + g_return_if_fail (HILDON_IS_WINDOW_STACK (stack)); + g_return_if_fail (!group || GTK_IS_WINDOW_GROUP (group)); + + /* The window group is only to be set once during construction */ + g_return_if_fail (stack->priv->group == NULL); + + if (!group) + group = gtk_window_group_new (); + + stack->priv->group = group; +} + +static GtkWindowGroup * +hildon_window_stack_get_window_group (HildonWindowStack *stack) +{ + g_return_val_if_fail (HILDON_IS_WINDOW_STACK (stack), NULL); + + return stack->priv->group; +} + +/** + * hildon_window_stack_get_default: + * + * Returns the default window stack. This stack always exists and + * doesn't need to be created by the application. + * + * Return value: the default #HildonWindowStack + * + * Since: 2.2 + **/ +HildonWindowStack * +hildon_window_stack_get_default (void) +{ + static HildonWindowStack *stack = NULL; + if (G_UNLIKELY (stack == NULL)) { + stack = g_object_new (HILDON_TYPE_WINDOW_STACK, + "window-group", gtk_window_get_group (NULL), + NULL); + } + return stack; +} + +/** + * hildon_window_stack_new: + * + * Creates a new #HildonWindowStack. The stack is initially empty. + * + * Return value: a new #HildonWindowStack + * + * Since: 2.2 + **/ +HildonWindowStack * +hildon_window_stack_new (void) +{ + HildonWindowStack *stack = g_object_new (HILDON_TYPE_WINDOW_STACK, NULL); + return stack; +} + +/** + * hildon_window_stack_size: + * @stack: A #HildonWindowStack + * + * Returns the number of windows in @stack + * + * Return value: Number of windows in @stack + * + * Since: 2.2 + **/ +gint +hildon_window_stack_size (HildonWindowStack *stack) +{ + g_return_val_if_fail (HILDON_IS_WINDOW_STACK (stack), 0); + + return g_list_length (stack->priv->list); +} + +static GdkWindow * +hildon_window_stack_get_leader_window (HildonWindowStack *stack, + GtkWidget *win) +{ + /* Create the X Window group (leader) if we haven't. */ + if (!stack->priv->leader) { + if (stack == hildon_window_stack_get_default ()) { + GdkDisplay *dpy; + + /* We're the default stack, use the default group. */ + dpy = gtk_widget_get_display (win); + stack->priv->leader = gdk_display_get_default_group (dpy); + } else { + static GdkWindowAttr attr = { + .window_type = GDK_WINDOW_TOPLEVEL, + .x = 10, .y = 10, .width = 10, .height = 10, + .wclass = GDK_INPUT_OUTPUT, .event_mask = 0, + }; + GdkWindow *root; + + /* Create a new X Window group. */ + root = gtk_widget_get_root_window (win); + stack->priv->leader = gdk_window_new (root, &attr, GDK_WA_X | GDK_WA_Y); + } + } + + return stack->priv->leader; +} + +/* Set the X Window group of a window when it is realized. */ +static void +hildon_window_stack_window_realized (GtkWidget *win, + HildonWindowStack *stack) +{ + GdkWindow *leader = hildon_window_stack_get_leader_window (stack, win); + gdk_window_set_group (win->window, leader); +} + +/* Remove a window from its stack, no matter its position */ +void G_GNUC_INTERNAL +hildon_window_stack_remove (HildonStackableWindow *win) +{ + HildonWindowStack *stack = hildon_stackable_window_get_stack (win); + + /* If the window is stacked */ + if (stack) { + GList *pos; + + hildon_stackable_window_set_stack (win, NULL, -1); + gtk_window_set_transient_for (GTK_WINDOW (win), NULL); + if (GTK_WIDGET (win)->window) { + gdk_window_set_group (GTK_WIDGET (win)->window, NULL); + } + + /* If the window removed is in the middle of the stack, update + * transiency of other windows */ + pos = g_list_find (stack->priv->list, win); + g_assert (pos != NULL); + if (pos->prev) { + GtkWindow *upper = GTK_WINDOW (pos->prev->data); + GtkWindow *lower = pos->next ? GTK_WINDOW (pos->next->data) : NULL; + gtk_window_set_transient_for (upper, lower); + } + + stack->priv->list = g_list_remove (stack->priv->list, win); + + g_signal_handlers_disconnect_by_func (win, hildon_window_stack_window_realized, stack); + } +} + +/** + * hildon_window_stack_get_windows: + * @stack: a #HildonWindowStack + * + * Returns the list of windows on this stack (topmost first). The + * widgets in the list are not individually referenced. Once you are + * done with the list you must call g_list_free(). + * + * Returns: a newly-allocated list of #HildonStackableWindows + * + * Since: 2.2 + **/ +GList * +hildon_window_stack_get_windows (HildonWindowStack *stack) +{ + g_return_val_if_fail (HILDON_IS_WINDOW_STACK (stack), NULL); + + return g_list_copy (stack->priv->list); +} + +/** + * hildon_window_stack_peek: + * @stack: A %HildonWindowStack + * + * Returns the window on top of @stack. The stack is never modified. + * + * Return value: the window on top of the stack, or %NULL if the stack + * is empty. + * + * Since: 2.2 + **/ +GtkWidget * +hildon_window_stack_peek (HildonWindowStack *stack) +{ + GtkWidget *win = NULL; + + g_return_val_if_fail (HILDON_IS_WINDOW_STACK (stack), NULL); + + if (stack->priv->list != NULL) { + win = GTK_WIDGET (stack->priv->list->data); + } + + return win; +} + +/* This function does everything to push a window to the stack _but_ + * actually calling gtk_widget_show(). + * It's up to each specific push function to decide the order in which + * to show windows. */ +gboolean G_GNUC_INTERNAL +_hildon_window_stack_do_push (HildonWindowStack *stack, + HildonStackableWindow *win) +{ + HildonWindowStack *current_stack; + + g_return_val_if_fail (HILDON_IS_WINDOW_STACK (stack), FALSE); + g_return_val_if_fail (HILDON_IS_STACKABLE_WINDOW (win), FALSE); + + current_stack = hildon_stackable_window_get_stack (win); + + if (current_stack == NULL) { + GtkWidget *parent = hildon_window_stack_peek (stack); + + /* Push the window */ + hildon_stackable_window_set_stack (win, stack, g_list_length (stack->priv->list)); + stack->priv->list = g_list_prepend (stack->priv->list, win); + + /* Make the window part of the same group as its parent */ + if (parent) { + gtk_window_set_transient_for (GTK_WINDOW (win), GTK_WINDOW (parent)); + } else { + gtk_window_group_add_window (stack->priv->group, GTK_WINDOW (win)); + } + + /* Set win's group after it's been realized. */ + g_signal_connect (win, "realize", + G_CALLBACK (hildon_window_stack_window_realized), + stack); + + return TRUE; + } else { + g_warning ("Trying to push a window that is already on a stack"); + return FALSE; + } +} + +static GtkWidget * +_hildon_window_stack_do_pop (HildonWindowStack *stack) +{ + GtkWidget *win = hildon_window_stack_peek (stack); + + if (win) + hildon_window_stack_remove (HILDON_STACKABLE_WINDOW (win)); + + return win; +} + +/** + * hildon_window_stack_push_1: + * @stack: A %HildonWindowStack + * @win: A %HildonStackableWindow + * + * Adds @win to the top of @stack, and shows it. The window must not + * be already stacked. + * + * Since: 2.2 + **/ +void +hildon_window_stack_push_1 (HildonWindowStack *stack, + HildonStackableWindow *win) +{ + if (_hildon_window_stack_do_push (stack, win)) + gtk_widget_show (GTK_WIDGET (win)); +} + +/** + * hildon_window_stack_pop_1: + * @stack: A %HildonWindowStack + * + * Removes the window on top of @stack, and hides it. If the stack is + * empty nothing happens. + * + * Return value: the window on top of the stack, or %NULL if the stack + * is empty. + * + * Since: 2.2 + **/ +GtkWidget * +hildon_window_stack_pop_1 (HildonWindowStack *stack) +{ + GtkWidget *win = _hildon_window_stack_do_pop (stack); + if (win) + gtk_widget_hide (win); + return win; +} + +/** + * hildon_window_stack_push_list: + * @stack: A %HildonWindowStack + * @list: A list of %HildonStackableWindows to push + * + * Pushes all windows in @list to the top of @stack, and shows + * them. Everything is done in a single transition, so the user will + * only see the last window in @list during this operation. None of + * the windows must be already stacked. + * + * Since: 2.2 + **/ +void +hildon_window_stack_push_list (HildonWindowStack *stack, + GList *list) +{ + HildonStackableWindow *win; + GList *l; + GList *pushed = NULL; + + g_return_if_fail (HILDON_IS_WINDOW_STACK (stack)); + + /* Stack all windows */ + for (l = list; l != NULL; l = g_list_next (l)) { + win = HILDON_STACKABLE_WINDOW (l->data); + if (win) { + _hildon_window_stack_do_push (stack, win); + pushed = g_list_prepend (pushed, win); + } else { + g_warning ("Trying to stack a non-stackable window!"); + } + } + + /* Show windows in reverse order (topmost first) */ + g_list_foreach (pushed, (GFunc) gtk_widget_show, NULL); + + g_list_free (pushed); +} + +/** + * hildon_window_stack_push: + * @stack: A %HildonWindowStack + * @win1: The first window to push + * @Varargs: A %NULL-terminated list of additional #HildonStackableWindows to push. + * + * Pushes all windows to the top of @stack, and shows them. Everything + * is done in a single transition, so the user will only see the last + * window. None of the windows must be already stacked. + * + * Since: 2.2 + **/ +void +hildon_window_stack_push (HildonWindowStack *stack, + HildonStackableWindow *win1, + ...) +{ + HildonStackableWindow *win = win1; + GList *list = NULL; + va_list args; + + va_start (args, win1); + + while (win != NULL) { + list = g_list_prepend (list, win); + win = va_arg (args, HildonStackableWindow *); + } + + va_end (args); + + list = g_list_reverse (list); + + hildon_window_stack_push_list (stack, list); + g_list_free (list); +} + +/** + * hildon_window_stack_pop: + * @stack: A %HildonWindowStack + * @nwindows: Number of windows to pop + * @popped_windows: if non-%NULL, the list of popped windows is stored here + * + * Pops @nwindows windows from @stack, and hides them. Everything is + * done in a single transition, so the user will not see any of the + * windows being popped in this operation. + * + * If @popped_windows is not %NULL, the list of popped windows is + * stored there (ordered bottom-up). That list must be freed by the + * user. + * + * Since: 2.2 + **/ +void +hildon_window_stack_pop (HildonWindowStack *stack, + gint nwindows, + GList **popped_windows) +{ + gint i; + GList *popped = NULL; + + g_return_if_fail (HILDON_IS_WINDOW_STACK (stack)); + g_return_if_fail (nwindows > 0); + g_return_if_fail (g_list_length (stack->priv->list) >= nwindows); + + /* Pop windows */ + for (i = 0; i < nwindows; i++) { + GtkWidget *win = _hildon_window_stack_do_pop (stack); + popped = g_list_prepend (popped, win); + } + + /* Hide windows in reverse order (topmost last) */ + g_list_foreach (popped, (GFunc) gtk_widget_hide, NULL); + + if (popped_windows) { + *popped_windows = popped; + } else { + g_list_free (popped); + } +} + +/** + * hildon_window_stack_pop_and_push_list: + * @stack: A %HildonWindowStack + * @nwindows: Number of windows to pop. + * @popped_windows: if non-%NULL, the list of popped windows is stored here + * @list: A list of %HildonStackableWindows to push + * + * Pops @nwindows windows from @stack (and hides them), then pushes + * all windows in @list (and shows them). Everything is done in a + * single transition, so the user will only see the last window from + * @list. None of the pushed windows must be already stacked. + * + * If @popped_windows is not %NULL, the list of popped windows is + * stored there (ordered bottom-up). That list must be freed by the + * user. + * + * Since: 2.2 + **/ +void +hildon_window_stack_pop_and_push_list (HildonWindowStack *stack, + gint nwindows, + GList **popped_windows, + GList *list) +{ + gint i; + GList *l; + GList *popped = NULL; + GList *pushed = NULL; + + g_return_if_fail (HILDON_IS_WINDOW_STACK (stack)); + g_return_if_fail (nwindows > 0); + g_return_if_fail (g_list_length (stack->priv->list) >= nwindows); + + /* Pop windows */ + for (i = 0; i < nwindows; i++) { + GtkWidget *win = _hildon_window_stack_do_pop (stack); + popped = g_list_prepend (popped, win); + } + + /* Push windows */ + for (l = list; l != NULL; l = g_list_next (l)) { + HildonStackableWindow *win = HILDON_STACKABLE_WINDOW (l->data); + if (win) { + _hildon_window_stack_do_push (stack, win); + pushed = g_list_prepend (pushed, win); + } else { + g_warning ("Trying to stack a non-stackable window!"); + } + } + + /* Show windows in reverse order (topmost first) */ + g_list_foreach (pushed, (GFunc) gtk_widget_show, NULL); + + /* Hide windows in reverse order (topmost last) */ + g_list_foreach (popped, (GFunc) gtk_widget_hide, NULL); + + g_list_free (pushed); + if (popped_windows) { + *popped_windows = popped; + } else { + g_list_free (popped); + } +} + +/** + * hildon_window_stack_pop_and_push: + * @stack: A %HildonWindowStack + * @nwindows: Number of windows to pop. + * @popped_windows: if non-%NULL, the list of popped windows is stored here + * @win1: The first window to push + * @Varargs: A %NULL-terminated list of additional #HildonStackableWindows to push. + * + * Pops @nwindows windows from @stack (and hides them), then pushes + * all passed windows (and shows them). Everything is done in a single + * transition, so the user will only see the last pushed window. None + * of the pushed windows must be already stacked. + * + * If @popped_windows is not %NULL, the list of popped windows is + * stored there (ordered bottom-up). That list must be freed by the + * user. + * + * Since: 2.2 + **/ +void +hildon_window_stack_pop_and_push (HildonWindowStack *stack, + gint nwindows, + GList **popped_windows, + HildonStackableWindow *win1, + ...) +{ + HildonStackableWindow *win = win1; + GList *list = NULL; + va_list args; + + va_start (args, win1); + + while (win != NULL) { + list = g_list_prepend (list, win); + win = va_arg (args, HildonStackableWindow *); + } + + va_end (args); + + list = g_list_reverse (list); + + hildon_window_stack_pop_and_push_list (stack, nwindows, popped_windows, list); + g_list_free (list); +} + +static void +hildon_window_stack_finalize (GObject *object) +{ + HildonWindowStack *stack = HILDON_WINDOW_STACK (object); + + if (stack->priv->list) + hildon_window_stack_pop (stack, hildon_window_stack_size (stack), NULL); + + if (stack->priv->group) + g_object_unref (stack->priv->group); + + /* Since the default group stack shouldn't be finalized, + * it's safe to destroy the X Window group we created. */ + if (stack->priv->leader) + gdk_window_destroy (stack->priv->leader); + + G_OBJECT_CLASS (hildon_window_stack_parent_class)->finalize (object); +} + +static void +hildon_window_stack_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + HildonWindowStack *stack = HILDON_WINDOW_STACK (object); + + switch (prop_id) + { + case PROP_GROUP: + hildon_window_stack_set_window_group (stack, g_value_get_object (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +hildon_window_stack_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + HildonWindowStack *stack = HILDON_WINDOW_STACK (object); + + switch (prop_id) + { + case PROP_GROUP: + g_value_set_object (value, hildon_window_stack_get_window_group (stack)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +hildon_window_stack_class_init (HildonWindowStackClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass *)klass; + + gobject_class->set_property = hildon_window_stack_set_property; + gobject_class->get_property = hildon_window_stack_get_property; + gobject_class->finalize = hildon_window_stack_finalize; + + g_object_class_install_property ( + gobject_class, + PROP_GROUP, + g_param_spec_object ( + "window-group", + "GtkWindowGroup for this stack", + "GtkWindowGroup that all windows on this stack belong to", + GTK_TYPE_WINDOW_GROUP, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_type_class_add_private (klass, sizeof (HildonWindowStackPrivate)); +} + +static void +hildon_window_stack_init (HildonWindowStack *self) +{ + HildonWindowStackPrivate *priv; + + priv = self->priv = HILDON_WINDOW_STACK_GET_PRIVATE (self); + + priv->list = NULL; + priv->group = NULL; +} diff --git a/hildon/hildon-window-stack.h b/hildon/hildon-window-stack.h new file mode 100644 index 0000000..98219a6 --- /dev/null +++ b/hildon/hildon-window-stack.h @@ -0,0 +1,137 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2008 Nokia Corporation, all rights reserved. + * + * 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, or (at your option) any later version. + * + * 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_STACK_H__ +#define __HILDON_WINDOW_STACK_H__ + +#include "hildon-stackable-window.h" + +G_BEGIN_DECLS + +#define HILDON_TYPE_WINDOW_STACK \ + (hildon_window_stack_get_type()) + +#define HILDON_WINDOW_STACK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + HILDON_TYPE_WINDOW_STACK, \ + HildonWindowStack)) + +#define HILDON_WINDOW_STACK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + HILDON_TYPE_WINDOW_STACK, \ + HildonWindowStackClass)) + +#define HILDON_IS_WINDOW_STACK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + HILDON_TYPE_WINDOW_STACK)) + +#define HILDON_IS_WINDOW_STACK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + HILDON_TYPE_WINDOW_STACK)) + +#define HILDON_WINDOW_STACK_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + HILDON_TYPE_WINDOW_STACK, \ + HildonWindowStackClass)) + +typedef struct _HildonWindowStackPrivate HildonWindowStackPrivate; + +#ifndef _TYPEDEF_HILDON_WINDOW_STACK_ +#define _TYPEDEF_HILDON_WINDOW_STACK_ +typedef struct _HildonWindowStack HildonWindowStack; +#endif +typedef struct _HildonWindowStackClass HildonWindowStackClass; + +struct _HildonWindowStack +{ + GObject parent; + + /* private */ + HildonWindowStackPrivate *priv; +}; + +struct _HildonWindowStackClass +{ + GObjectClass parent_class; + + /* Padding for future extension */ + void (*_hildon_reserved1)(void); + void (*_hildon_reserved2)(void); + void (*_hildon_reserved3)(void); + void (*_hildon_reserved4)(void); +}; + +GType +hildon_window_stack_get_type (void) G_GNUC_CONST; + +HildonWindowStack * +hildon_window_stack_get_default (void); + +HildonWindowStack * +hildon_window_stack_new (void); + +gint +hildon_window_stack_size (HildonWindowStack *stack); + +GList * +hildon_window_stack_get_windows (HildonWindowStack *stack); + +GtkWidget * +hildon_window_stack_peek (HildonWindowStack *stack); + +void +hildon_window_stack_push (HildonWindowStack *stack, + HildonStackableWindow *win1, + ...); + +void +hildon_window_stack_push_list (HildonWindowStack *stack, + GList *list); + +void +hildon_window_stack_push_1 (HildonWindowStack *stack, + HildonStackableWindow *win); + +void +hildon_window_stack_pop (HildonWindowStack *stack, + gint nwindows, + GList **popped_windows); + +GtkWidget * +hildon_window_stack_pop_1 (HildonWindowStack *stack); + +void +hildon_window_stack_pop_and_push (HildonWindowStack *stack, + gint nwindows, + GList **popped_windows, + HildonStackableWindow *win1, + ...); + +void +hildon_window_stack_pop_and_push_list (HildonWindowStack *stack, + gint nwindows, + GList **popped_windows, + GList *list); + +G_END_DECLS + +#endif /* __HILDON_WINDOW_STACK_H__ */ diff --git a/hildon/hildon-window.c b/hildon/hildon-window.c new file mode 100644 index 0000000..8d8e2f5 --- /dev/null +++ b/hildon/hildon-window.c @@ -0,0 +1,2176 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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-window + * @short_description: Widget representing a top-level window in the Hildon framework. + * @see_also: #HildonProgram, #HildonStackableWindow + * + * #HildonWindow is a GTK widget which represents a top-level + * window in the Hildon framework. It is derived from #GtkWindow + * and provides additional commodities specific to the Hildon + * framework. + * + * #HildonWindows can have a menu attached, which is toggled + * with a hardware key or by tapping on the window frame. This menu + * can be either a #GtkMenu or a #HildonAppMenu (set with + * hildon_window_set_main_menu() and hildon_window_set_app_menu() + * respectively). Only one type of menu can be used at the same time. + * In Hildon 2.2, #HildonAppMenu is the recommended menu to use. + * + * Similarly, a #HildonWindow can have several toolbars + * attached. These can be added with hildon_window_add_toolbar(). In + * addition to those, a #HildonWindow can also have a + * #HildonEditToolbar. To add it to the window use + * hildon_window_set_edit_toolbar(). + * + * + * Creating a HildonWindow + * + * HildonWindow *window; + * GtkToolbar *toolbar; + * HildonAppMenu *menu; + * GdkPixbuf *icon_pixbuf; + * + * window = HILDON_WINDOW (hildon_window_new()); + * + * toolbar = create_toolbar(); + * + * menu = create_menu(); + * + * icon_pixbuf = create_icon(); + * + * hildon_window_set_app_menu (window, menu); + * + * hildon_window_add_toolbar (window, toolbar); + * + * // Can be used to set the window fullscreen + * gtk_window_fullscreen (GTK_WINDOW (window)); + * + * // Used to trigger the blinking of the window's icon in the task navigator + * gtk_window_set_urgency_hint (GTK_WINDOW (window), TRUE); + * + * // Change the window's icon in the task navigator + * gtk_window_set_icon (GTK_WINDOW (window), icon_pixbuf); + * + * + */ + +#undef HILDON_DISABLE_DEPRECATED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hildon-window.h" +#include "hildon-window-private.h" +#include "hildon-app-menu-private.h" +#include "hildon-find-toolbar.h" +#include "hildon-defines.h" + +#define _(String) gettext(String) + +#define TOOLBAR_HEIGHT 70 + +#define TOOLBAR_MIDDLE 0 + +/*FIXME*/ +#define CAN_HIBERNATE "CANKILL" + +#define CAN_HIBERNATE_LENGTH 7 + +#define CAN_HIBERNATE_PROPERTY "_HILDON_ABLE_TO_HIBERNATE" + +#define TITLE_SEPARATOR " - " + +typedef void (*HildonWindowSignal) (HildonWindow *, gint, gpointer); + +static void +hildon_window_init (HildonWindow * self); + +static void +hildon_window_class_init (HildonWindowClass * window_class); + +static void +hildon_window_menu_popup_func (GtkMenu *menu, + gint *x, + gint *y, + gboolean *push_in, + GtkWidget *widget); +static void +hildon_window_menu_popup_func_full (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_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static void +hildon_window_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); + +static void +hildon_window_update_markup (HildonWindow *window); + +static void +hildon_window_destroy (GtkObject *obj); + +static void +hildon_window_realize (GtkWidget *widget); + +static void +hildon_window_unrealize (GtkWidget *widget); + +static void +hildon_window_map (GtkWidget *widget); + +static void +hildon_window_unmap (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 gboolean +hildon_window_focus_out_event (GtkWidget *widget, + GdkEventFocus *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, + guint button, + guint32 time); + +static gboolean +hildon_window_toggle_menu_real (HildonWindow * self, + guint button, + guint32 time); + +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); + +static void +paint_edit_toolbar (GtkWidget *widget, + GtkWidget *toolbar, + GdkEventExpose *event, + gboolean fullscreen); + +enum +{ + PROP_0, + PROP_IS_TOPMOST, + PROP_MARKUP +}; + +enum +{ + WIN_TYPE = 0, + WIN_TYPE_MESSAGE, + MAX_WIN_MESSAGES +}; + +G_DEFINE_TYPE (HildonWindow, hildon_window, GTK_TYPE_WINDOW); + +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); + + object_class->get_property = hildon_window_get_property; + object_class->set_property = hildon_window_set_property; + object_class->notify = hildon_window_notify; + 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; + widget_class->focus_out_event = hildon_window_focus_out_event; + widget_class->map = hildon_window_map; + widget_class->unmap = hildon_window_unmap; + + /* now the object stuff */ + object_class->finalize = hildon_window_finalize; + + /* To the container */ + container_class->forall = hildon_window_forall; + + /* To this class */ + window_class->toggle_menu = hildon_window_toggle_menu_real; + + /* 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)); + + g_object_class_install_property (object_class, PROP_MARKUP, + g_param_spec_string ("markup", + "Marked up text for the window title", + "Marked up text for the window title", + NULL, + G_PARAM_READWRITE)); + + 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, + G_TYPE_INT); +} + +static void +hildon_window_init (HildonWindow *self) +{ + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (self); + g_assert (priv != NULL); + + priv->vbox = gtk_vbox_new (TRUE, TOOLBAR_MIDDLE); + gtk_widget_set_parent (priv->vbox, GTK_WIDGET(self)); + priv->menu = NULL; + priv->app_menu = NULL; + priv->edit_toolbar = NULL; + priv->visible_toolbars = 0; + priv->is_topmost = FALSE; + priv->borders = NULL; + priv->toolbar_borders = NULL; + priv->escape_timeout = 0; + priv->markup = NULL; + + 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) +{ + HildonWindowPrivate *priv; + + g_return_if_fail (HILDON_WINDOW (obj_self)); + + priv = HILDON_WINDOW_GET_PRIVATE (obj_self); + g_assert (priv != NULL); + + g_free (priv->markup); + + if (priv->escape_timeout) { + g_source_remove (priv->escape_timeout); + priv->escape_timeout = 0; + } + + if (priv->borders) + gtk_border_free (priv->borders); + + if (priv->toolbar_borders) + gtk_border_free (priv->toolbar_borders); + + if (G_OBJECT_CLASS (hildon_window_parent_class)->finalize) + G_OBJECT_CLASS (hildon_window_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; + HildonWindowPrivate *priv; + + GTK_WIDGET_CLASS (hildon_window_parent_class)->realize (widget); + + priv = HILDON_WINDOW_GET_PRIVATE (widget); + g_assert (priv != NULL); + + gtk_widget_realize (GTK_WIDGET (priv->vbox)); + + if (priv->edit_toolbar != NULL) + gtk_widget_realize (priv->edit_toolbar); + + /* 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 (priv->program) { + gboolean can_hibernate = hildon_program_get_can_hibernate (priv->program); + + hildon_window_set_can_hibernate_property (HILDON_WINDOW (widget), + &can_hibernate); + } + + if (priv->markup) + hildon_window_update_markup (HILDON_WINDOW (widget)); + + /* Update the topmost status */ + active_window = hildon_window_get_active_window(); + hildon_window_update_topmost (HILDON_WINDOW (widget), active_window); +} + +static void +hildon_window_unrealize (GtkWidget *widget) +{ + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (widget); + g_assert (priv != NULL); + + gdk_window_remove_filter (widget->window, hildon_window_event_filter, + widget); + + gtk_widget_unrealize (GTK_WIDGET (priv->vbox)); + + if (priv->edit_toolbar != NULL) + gtk_widget_unrealize (priv->edit_toolbar); + + GTK_WIDGET_CLASS(hildon_window_parent_class)->unrealize(widget); +} + +static void +hildon_window_map (GtkWidget *widget) +{ + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (widget); + g_assert (priv != NULL); + + if (GTK_WIDGET_CLASS (hildon_window_parent_class)->map) + GTK_WIDGET_CLASS (hildon_window_parent_class)->map (widget); + + if (priv->vbox != NULL && GTK_WIDGET_VISIBLE (priv->vbox)) + gtk_widget_map (priv->vbox); + + if (priv->edit_toolbar != NULL && GTK_WIDGET_VISIBLE (priv->edit_toolbar)) + gtk_widget_map (priv->edit_toolbar); +} + +static void +hildon_window_unmap (GtkWidget *widget) +{ + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (widget); + g_assert (priv != NULL); + + gtk_widget_unmap (priv->vbox); + + if (priv->edit_toolbar != NULL) + gtk_widget_unmap (priv->edit_toolbar); + + if (GTK_WIDGET_CLASS (hildon_window_parent_class)->unmap) + GTK_WIDGET_CLASS (hildon_window_parent_class)->unmap (widget); +} + +static void +hildon_window_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec * pspec) +{ + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (object); + g_assert (priv != NULL); + + switch (property_id) { + + case PROP_IS_TOPMOST: + g_value_set_boolean (value, priv->is_topmost); + break; + + case PROP_MARKUP: + g_value_set_string (value, priv->markup); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void +hildon_window_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + + case PROP_MARKUP: + hildon_window_set_markup (HILDON_WINDOW (object), g_value_get_string (value)); + 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) +{ + GtkBorder zero = {0, 0, 0, 0}; + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (window); + g_assert (priv); + + GtkBorder *borders = NULL; + GtkBorder *toolbar_borders = NULL; + + if (priv->borders) + gtk_border_free (priv->borders); + if (priv->toolbar_borders) + gtk_border_free (priv->toolbar_borders); + + priv->borders = NULL; + priv->toolbar_borders = NULL; + + gtk_widget_style_get (GTK_WIDGET (window), "borders",&borders, + "toolbar-borders", &toolbar_borders, + NULL); + + // We're doing a copy here instead of reusing the pointer, + // as we don't know where it comes from (has it been allocated using + // malloc or slices... and we want to free it sanely. Blowing on + // cold probbably. + + if (borders) { + priv->borders = gtk_border_copy (borders); + gtk_border_free (borders); + } else + priv->borders = g_boxed_copy (GTK_TYPE_BORDER, &zero); + + if (toolbar_borders) { + priv->toolbar_borders = gtk_border_copy (toolbar_borders); + gtk_border_free (toolbar_borders); + } else + priv->toolbar_borders = g_boxed_copy (GTK_TYPE_BORDER, &zero); +} + +static gboolean +hildon_window_expose (GtkWidget *widget, + GdkEventExpose * event) +{ + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (widget); + g_assert (priv); + + GtkWidget *bx = priv->vbox; + GtkBox *box = GTK_BOX(bx); + GtkBorder *b = priv->borders; + GtkBorder *tb = priv->toolbar_borders; + gint tb_height = 0; + + if (! priv->borders) { + hildon_window_get_borders (HILDON_WINDOW (widget)); + b = priv->borders; + tb = priv->toolbar_borders; + } + + tb_height = bx->allocation.height + tb->top + tb->bottom; + + paint_toolbar (widget, box, + event, priv->fullscreen); + + if (priv->edit_toolbar != NULL) + { + paint_edit_toolbar (widget, priv->edit_toolbar, + event, priv->fullscreen); + } + + if (! priv->fullscreen) { + + /* Draw the left and right window border */ + gint side_borders_height = widget->allocation.height - b->top; + + if (priv->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 (! priv->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 (hildon_window_parent_class))->expose_event (widget, event); + + /* FIXME Not sure why this is commented out + * GTK_WIDGET_CLASS (hildon_window_parent_class))-> + * expose_event (widget, event); + */ + + return FALSE; +} + +static void +hildon_window_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (widget); + g_assert (priv); + + GtkWidget *child = GTK_BIN (widget)->child; + GtkRequisition req2 = { 0 }; + 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 (priv->vbox != NULL) + gtk_widget_size_request (priv->vbox, &req2); + + requisition->height += req2.height; + requisition->width = MAX (requisition->width, req2.width); + + if (priv->edit_toolbar != NULL && GTK_WIDGET_VISIBLE (priv->edit_toolbar)) + { + GtkRequisition req; + gtk_widget_size_request (priv->edit_toolbar, &req); + requisition->height += req.height; + requisition->width = MAX (requisition->width, req.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_GET_PRIVATE (widget); + g_assert (priv); + + GtkAllocation box_alloc = { 0 }; + GtkAllocation edittb_alloc = { 0 }; + GtkAllocation alloc = *allocation; + + GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget)); + GtkBorder *tb; + + if (!priv->borders) + hildon_window_get_borders (HILDON_WINDOW (widget)); + + tb = priv->toolbar_borders; + + widget->allocation = *allocation; + + /* Calculate allocation of edit toolbar */ + if (priv->edit_toolbar != NULL && GTK_WIDGET_VISIBLE (priv->edit_toolbar)) + { + GtkRequisition req; + gtk_widget_get_child_requisition (priv->edit_toolbar, &req); + edittb_alloc.width = alloc.width - tb->left - tb->right; + edittb_alloc.height = MIN (req.height, alloc.height); + edittb_alloc.x = alloc.x + tb->left; + edittb_alloc.y = alloc.y + tb->top; + + if (edittb_alloc.height > 0) + { + alloc.y += tb->top + tb->bottom + edittb_alloc.height; + alloc.height -= tb->top + tb->bottom + edittb_alloc.height; + gtk_widget_size_allocate (priv->edit_toolbar, &edittb_alloc); + } + } + + /* Calculate allocation of normal toolbars */ + if (priv->vbox != NULL && GTK_WIDGET_VISIBLE (priv->vbox)) + { + GtkRequisition req; + gtk_widget_get_child_requisition (priv->vbox, &req); + box_alloc.width = alloc.width - tb->left - tb->right; + box_alloc.height = MIN (req.height, alloc.height); + box_alloc.x = alloc.x + tb->left; + box_alloc.y = alloc.y + alloc.height - box_alloc.height - tb->bottom; + + if (box_alloc.height > 0) + { + alloc.height -= tb->top + tb->bottom + box_alloc.height; + gtk_widget_size_allocate (priv->vbox, &box_alloc); + } + } + + /* Calculate allocation of the child widget */ + if (child != NULL && GTK_WIDGET_VISIBLE (child)) + { + guint border_width = gtk_container_get_border_width (GTK_CONTAINER (widget)); + alloc.x += border_width; + alloc.y += border_width; + alloc.width -= (border_width * 2); + alloc.height -= (border_width * 2); + + if (! priv->fullscreen) + { + GtkBorder *b = priv->borders; + alloc.x += b->left; + alloc.width -= (b->left + b->right); + + /* Use the top border if there's no edit toolbar */ + if (edittb_alloc.height <= 0) + { + alloc.y += b->top; + alloc.height -= b->top; + } + + /* Use the top border if there are no standard toolbars */ + if (box_alloc.height <= 0) + alloc.height -= b->bottom; + } + + gtk_widget_size_allocate (child, &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 = MIN (priv->previous_vbox_y, 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); + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (self); + + g_return_if_fail (callback != NULL); + g_assert (priv); + + GTK_CONTAINER_CLASS (hildon_window_parent_class)->forall (container, include_internals, + callback, callback_data); + + if (include_internals && priv->vbox != NULL) + (* callback)(GTK_WIDGET (priv->vbox), callback_data); + + if (include_internals && priv->edit_toolbar != NULL) + (* callback)(GTK_WIDGET (priv->edit_toolbar), callback_data); +} + +static void +hildon_window_show_all (GtkWidget *widget) +{ + HildonWindow *self = HILDON_WINDOW (widget); + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (self); + + g_assert (priv != NULL); + + GTK_WIDGET_CLASS (hildon_window_parent_class)->show_all (widget); + + gtk_widget_show_all (priv->vbox); + + if (priv->edit_toolbar) + gtk_widget_show_all (priv->edit_toolbar); +} + +static void +hildon_window_destroy (GtkObject *obj) +{ + HildonWindow *self = HILDON_WINDOW (obj); + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (obj); + GList *menu_list = NULL; + GList *menu_node = NULL; + + g_assert (priv != NULL); + + if (priv->vbox != NULL) + { + if (priv->program) + { + GtkWidget * common_toolbar = + GTK_WIDGET (hildon_program_get_common_toolbar (priv->program)); + if (common_toolbar && common_toolbar->parent == priv->vbox) + { + gtk_container_remove (GTK_CONTAINER (priv->vbox), + common_toolbar); + } + } + + gtk_widget_unparent (priv->vbox); + priv->vbox = NULL; + + } + + if (priv->edit_toolbar != NULL) + { + gtk_widget_unparent (priv->edit_toolbar); + priv->edit_toolbar = NULL; + } + + if (priv->app_menu) + { + hildon_app_menu_set_parent_window (priv->app_menu, NULL); + g_object_unref (priv->app_menu); + priv->app_menu = NULL; + } + + menu_list = g_list_copy (gtk_menu_get_for_attach_widget (GTK_WIDGET (obj))); + menu_node = menu_list; + + while (menu_node) + { + if (GTK_IS_MENU (menu_node->data)) + { + if (GTK_WIDGET_VISIBLE (GTK_WIDGET (menu_node->data))) + { + gtk_menu_popdown (GTK_MENU (menu_node->data)); + gtk_menu_shell_deactivate (GTK_MENU_SHELL (menu_node->data)); + } + gtk_menu_detach (GTK_MENU (menu_node->data)); + + /* Destroy it, but only if it's not a common menu */ + if (priv->program && + hildon_program_get_common_menu (priv->program) != menu_node->data) { + gtk_object_destroy (GTK_OBJECT (menu_node->data)); + g_object_unref (menu_node->data); + } + } + menu_node = menu_node->next; + } + + g_list_free (menu_list); + menu_list = NULL; + + if (priv->program) + { + hildon_program_remove_window (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 (hildon_window_parent_class)->destroy (obj); +} + +static void +hildon_window_notify (GObject *gobject, + GParamSpec *param) +{ + HildonWindow *window = HILDON_WINDOW (gobject); + + if (g_str_equal (param->name, "is-topmost")) + { + hildon_window_is_topmost_notify (window); + } + + if (G_OBJECT_CLASS(hildon_window_parent_class)->notify) + G_OBJECT_CLASS(hildon_window_parent_class)->notify (gobject, param); +} + + +static void +visible_toolbar (gpointer data, + gpointer user_data) +{ + if (GTK_WIDGET_VISIBLE (((GtkBoxChild *)data)->widget)) + (*((gint *)user_data))++; +} + +static void +paint_toolbar (GtkWidget *widget, + GtkBox *box, + GdkEventExpose * event, + gboolean fullscreen) +{ + gint toolbar_num = 0; + gint count; + + /* collect info to help on painting the boxes */ + g_list_foreach (box->children, visible_toolbar, + (gpointer) &toolbar_num); + + if(toolbar_num <= 0) + return; + + /*top most toolbar painting*/ + gtk_paint_box (widget->style, widget->window, + GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, + &event->area, widget, "toolbar-primary", + widget->allocation.x, + GTK_WIDGET(box)->allocation.y, + widget->allocation.width, + TOOLBAR_HEIGHT); + + /*multi toolbar painting*/ + for (count = 0; count < toolbar_num - 1; count++) + { + gtk_paint_box (widget->style, widget->window, + GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, + &event->area, widget, "toolbar-secondary", + widget->allocation.x, + GTK_WIDGET(box)->allocation.y + + (1 + count) * (TOOLBAR_HEIGHT), + widget->allocation.width, + TOOLBAR_HEIGHT); + } +} + +static void +paint_edit_toolbar (GtkWidget *widget, + GtkWidget *toolbar, + GdkEventExpose *event, + gboolean fullscreen) +{ + if (!GTK_WIDGET_VISIBLE (toolbar)) + return; + + gtk_paint_box (widget->style, widget->window, + GTK_WIDGET_STATE (widget), GTK_SHADOW_OUT, + &event->area, widget, "toolbar-edit-mode", + toolbar->allocation.x, + toolbar->allocation.y, + toolbar->allocation.width, + toolbar->allocation.height); +} + +/* + * Checks the root window to know which is the topped window + */ +Window +hildon_window_get_active_window (void) +{ + Atom realtype; + gint xerror; + 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; + + gdk_error_trap_push (); + status = XGetWindowProperty (GDK_DISPLAY(), GDK_ROOT_WINDOW(), + active_app_atom, 0L, 16L, + 0, XA_WINDOW, &realtype, &format, + &n, &extra, &win.char_pointer); + xerror = gdk_error_trap_pop (); + if (xerror || !(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); +} + +/* + * 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 ), cm->data.l[2], cm->data.l[0]); + 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; +} + +/* + * Handle the menu hardware key here + */ +static gboolean +hildon_window_key_press_event (GtkWidget *widget, + GdkEventKey *event) +{ + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (widget); + + g_return_val_if_fail (HILDON_IS_WINDOW (widget),FALSE); + g_assert (priv); + + switch (event->keyval) + { + case HILDON_HARDKEY_MENU: + if (hildon_window_toggle_menu (HILDON_WINDOW (widget), 0, GDK_CURRENT_TIME)) + 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 (hildon_window_parent_class)->key_press_event (widget, event); +} + +static gboolean +hildon_window_key_release_event (GtkWidget *widget, + GdkEventKey *event) +{ + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (widget); + + g_return_val_if_fail (HILDON_IS_WINDOW (widget), FALSE); + g_assert (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 (hildon_window_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) +{ + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (widget); + g_assert (priv != NULL); + + if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) + priv->fullscreen = event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN; + + if (GTK_WIDGET_CLASS (hildon_window_parent_class)->window_state_event) + { + return GTK_WIDGET_CLASS (hildon_window_parent_class)->window_state_event ( + widget, + event); + } + else + { + return FALSE; + } +} + +/* + * 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. + */ +static gboolean +hildon_window_focus_out_event (GtkWidget *widget, + GdkEventFocus *event) +{ + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (widget); + + if (priv->escape_timeout) + { + g_source_remove (priv->escape_timeout); + priv->escape_timeout = 0; + } + + return GTK_WIDGET_CLASS (hildon_window_parent_class)->focus_out_event (widget, event); +} + +/* + * The menu popuping needs a menu popup-function + */ +static void +hildon_window_menu_popup_func (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); + + if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) + { + *x = GTK_WIDGET (widget)->allocation.width + window_x - GTK_WIDGET (menu)->allocation.width - *x; + } + else + *x += window_x; + + *y += window_y; + +} + +static void +hildon_window_menu_popup_func_full (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); + + if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) + *x = GTK_WIDGET (widget)->allocation.width - GTK_WIDGET (menu)->allocation.width - *x; + else + *x = MAX (0, *x); + + *y = MAX (0, *y); +} + + +/* + * Takes the common toolbar when we acquire the top-most status + */ +static void +hildon_window_is_topmost_notify (HildonWindow *window) +{ + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (window); + + g_assert (priv); + + if (priv->is_topmost) + { + hildon_window_take_common_toolbar (window); + } +} + +/* + * Sets the program to which the window belongs. This should only be called + * by hildon_program_add_window + */ +void G_GNUC_INTERNAL +hildon_window_set_program (HildonWindow *self, + GObject *program) +{ + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (self); + + g_return_if_fail (HILDON_IS_WINDOW (self)); + g_assert (priv != NULL); + + if (priv->program) + { + g_object_unref (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); + + 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_remove_window + */ +void G_GNUC_INTERNAL +hildon_window_unset_program (HildonWindow *self) +{ + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (self); + + g_return_if_fail(HILDON_IS_WINDOW (self)); + g_assert (priv != NULL); + + if (priv->program) + { + g_object_unref (priv->program); + 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 ); + } + + 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 G_GNUC_INTERNAL +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 G_GNUC_INTERNAL +hildon_window_take_common_toolbar (HildonWindow *self) +{ + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (self); + + g_return_if_fail(HILDON_IS_WINDOW (self)); + g_assert (priv); + + if (priv->program) + { + GtkWidget *common_toolbar = + GTK_WIDGET (hildon_program_get_common_toolbar (priv->program)); + + if (common_toolbar && common_toolbar->parent != 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(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 (priv->vbox); + + } + } +} + +/* + * Compare the window that was last topped, and act consequently + */ +void +hildon_window_update_topmost (HildonWindow *self, + Window window_id) +{ + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (self); + + GdkWindow *my_window; + + g_return_if_fail (HILDON_IS_WINDOW (self)); + g_assert (priv); + + my_window = GTK_WIDGET (self)->window; + + if (my_window && window_id == GDK_WINDOW_XID (my_window)) + { + if (! priv->is_topmost) + { + priv->is_topmost = TRUE; + hildon_window_is_topmost_notify (self); + g_object_notify (G_OBJECT (self), "is-topmost"); + } + } + else if (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); + + priv->is_topmost = FALSE; + hildon_window_is_topmost_notify (self); + g_object_notify (G_OBJECT (self), "is-topmost"); + } +} + +static void +detach_menu_func (GtkWidget *attach_widget, + GtkMenu *menu) +{ + /* FIXME Why is this even needed here? */ +} + +static gboolean +hildon_window_toggle_menu (HildonWindow *self, + guint button, + guint32 time) +{ + g_return_val_if_fail (HILDON_IS_WINDOW (self), FALSE); + + if (HILDON_WINDOW_GET_CLASS (self)->toggle_menu != NULL) + { + return HILDON_WINDOW_GET_CLASS (self)->toggle_menu (self, button, time); + } + else + { + return FALSE; + } +} + + +static gboolean +hildon_window_toggle_gtk_menu (HildonWindow *self, + GtkMenu *menu, + guint button, + guint32 time) +{ + gboolean retvalue = FALSE; + + g_return_val_if_fail (HILDON_IS_WINDOW (self), FALSE); + g_return_val_if_fail (GTK_IS_MENU (menu), FALSE); + + if (gtk_menu_get_attach_widget (menu) != GTK_WIDGET (self)) + { + g_object_ref (menu); + if (gtk_menu_get_attach_widget (menu)) + { + gtk_menu_detach (menu); + } + gtk_menu_attach_to_widget (menu, GTK_WIDGET (self), &detach_menu_func); + g_object_unref (menu); + } + + if (GTK_WIDGET_MAPPED (menu)) + { + gtk_menu_popdown (menu); + gtk_menu_shell_deactivate (GTK_MENU_SHELL (menu)); + retvalue = TRUE; + } + else + { + /* Check if the menu has items */ + GList *menu_children = gtk_container_get_children (GTK_CONTAINER (menu)); + + if (menu_children) + { + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (self); + g_list_free (menu_children); + + /* Apply right theming */ + gtk_widget_set_name (GTK_WIDGET (menu), "menu_force_with_corners"); + + if (priv->fullscreen) + { + gtk_menu_popup (menu, NULL, NULL, + (GtkMenuPositionFunc) + hildon_window_menu_popup_func_full, + self, button, time); + } + else + { + gtk_menu_popup (menu, NULL, NULL, + (GtkMenuPositionFunc) + hildon_window_menu_popup_func, + self, button, time); + } + gtk_menu_shell_select_first (GTK_MENU_SHELL (menu), TRUE); + retvalue = TRUE; + } + } + + return retvalue; +} + +static gboolean +hildon_window_toggle_app_menu (HildonWindow *self, + HildonAppMenu *menu) +{ + g_return_val_if_fail (HILDON_IS_WINDOW (self), FALSE); + g_return_val_if_fail (HILDON_IS_APP_MENU (menu), FALSE); + + if (self != hildon_app_menu_get_parent_window (menu)) + { + gtk_widget_hide (GTK_WIDGET (menu)); + } + + if (GTK_WIDGET_MAPPED (menu)) + { + gtk_widget_hide (GTK_WIDGET (menu)); + } + else + { + hildon_app_menu_popup (menu, GTK_WINDOW (self)); + } + + return TRUE; +} + +/* + * 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_real (HildonWindow * self, + guint button, + guint32 time) +{ + gboolean retvalue = FALSE; + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (self); + + g_return_val_if_fail (HILDON_IS_WINDOW (self), FALSE); + + /* Select which menu to use, Window specific has highest priority, + * then program specific */ + if (priv->menu) + { + retvalue = hildon_window_toggle_gtk_menu (self, priv->menu, button, time); + } + else if (priv->app_menu) + { + retvalue = hildon_window_toggle_app_menu (self, priv->app_menu); + } + else if (priv->program) + { + GtkMenu *gtkmenu = hildon_program_get_common_menu (priv->program); + HildonAppMenu *appmenu = hildon_program_get_common_app_menu (priv->program); + + if (gtkmenu) + { + retvalue = hildon_window_toggle_gtk_menu (self, gtkmenu, button, time); + } + else if (appmenu) + { + retvalue = hildon_window_toggle_app_menu (self, appmenu); + } + } + + return retvalue; +} + +/* + * If the ESC key was not released when the timeout expires, + * close the window + */ +static gboolean +hildon_window_escape_timeout (gpointer data) +{ + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (data); + GdkEvent *event; + + g_assert (priv); + + GDK_THREADS_ENTER (); + + /* 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; +} + +/** + * hildon_window_new: + * + * Creates 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 @child to the #HildonWindow and creates a scrollbar for + * it. Similar to adding first a #GtkScrolledWindow and then @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)); +} + +static void +calculate_visible_toolbars (gpointer data, + gpointer user_data) +{ + if (GTK_WIDGET_VISIBLE (GTK_WIDGET (((GtkBoxChild *)data)->widget))) + (*((gint *)user_data)) ++; +} + +static void +toolbar_visible_notify (GtkWidget *toolbar, GParamSpec *pspec, + HildonWindow *window) +{ + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (window); + + g_assert (priv); + + /* Recalculate from scratch the value just in case */ + priv->visible_toolbars = 0; + + g_list_foreach (GTK_BOX (priv->vbox)->children, calculate_visible_toolbars, + &priv->visible_toolbars); + + if (priv->visible_toolbars == 0) + gtk_widget_hide (priv->vbox); + else + gtk_widget_show (priv->vbox); +} + +/** + * hildon_window_add_toolbar: + * @self: A #HildonWindow + * @toolbar: A #GtkToolbar to add to the #HildonWindow + * + * Adds a toolbar to the window. Note that the toolbar is not automatically + * shown. You need to call gtk_widget_show_all() on it to make it visible. + * It's also possible to hide the toolbar (without removing it) by calling + * gtk_widget_hide() + **/ +void +hildon_window_add_toolbar (HildonWindow *self, + GtkToolbar *toolbar) +{ + GtkBox *vbox; + HildonWindowPrivate *priv; + + g_return_if_fail (HILDON_IS_WINDOW (self)); + g_return_if_fail (toolbar && GTK_IS_TOOLBAR (toolbar)); + + priv = HILDON_WINDOW_GET_PRIVATE (self); + + vbox = GTK_BOX (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); + + g_signal_connect (G_OBJECT (toolbar), "notify::visible", + G_CALLBACK (toolbar_visible_notify), self); + + if (GTK_WIDGET_VISIBLE (toolbar)) + { + priv->visible_toolbars++; + gtk_widget_show (priv->vbox); + } + + 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. Note that this decreases the refference + * count on the widget. If you want to keep the toolbar alive call g_object_ref() + * before calling this function. + **/ +void +hildon_window_remove_toolbar (HildonWindow *self, + GtkToolbar *toolbar) +{ + HildonWindowPrivate *priv; + + g_return_if_fail (HILDON_IS_WINDOW (self)); + + priv = HILDON_WINDOW_GET_PRIVATE (self); + + if (GTK_WIDGET_VISIBLE (toolbar)) + { + if (--(priv->visible_toolbars) == 0) + gtk_widget_hide (priv->vbox); + } + + g_signal_handlers_disconnect_by_func (toolbar, toolbar_visible_notify, self); + + gtk_container_remove (GTK_CONTAINER (priv->vbox), GTK_WIDGET (toolbar)); +} + +/** + * hildon_window_set_edit_toolbar: + * @self: A #HildonWindow + * @toolbar: A #HildonEditToolbar, or %NULL to remove the current one. + * + * Adds a #HildonEditToolbar to the window. Note that the toolbar is + * not automatically shown. You need to call gtk_widget_show() on it + * to make it visible. It's also possible to hide the toolbar (without + * removing it) by calling gtk_widget_hide(). + * + * A window can only have at most one edit toolbar at a time, so the + * previous toolbar (if any) is replaced after calling this function. + * + * Since: 2.2 + **/ +void +hildon_window_set_edit_toolbar (HildonWindow *self, + HildonEditToolbar *toolbar) +{ + HildonWindowPrivate *priv; + + g_return_if_fail (HILDON_IS_WINDOW (self)); + g_return_if_fail (toolbar == NULL || HILDON_IS_EDIT_TOOLBAR (toolbar)); + + priv = HILDON_WINDOW_GET_PRIVATE (self); + + if (priv->edit_toolbar != GTK_WIDGET (toolbar)) + { + GtkWidget *old_toolbar = priv->edit_toolbar; + priv->edit_toolbar = GTK_WIDGET (toolbar); + + if (priv->edit_toolbar) + gtk_widget_set_parent (priv->edit_toolbar, GTK_WIDGET (self)); + + if (old_toolbar) + gtk_widget_unparent (old_toolbar); + } +} + +/** + * hildon_window_get_main_menu: + * @self: a #HildonWindow + * + * Gets the #GtkMenu assigned to the #HildonAppview. Note that the + * window is still the owner of the menu. + * + * Note that if you're using a #HildonAppMenu rather than a #GtkMenu + * you should use hildon_window_get_app_menu() instead. + * + * Return value: The #GtkMenu assigned to this application view. + * + * Since: 2.2 + **/ +GtkMenu* +hildon_window_get_main_menu (HildonWindow * self) +{ + HildonWindowPrivate *priv; + + g_return_val_if_fail (HILDON_IS_WINDOW (self), NULL); + + priv = HILDON_WINDOW_GET_PRIVATE (self); + + return priv->menu; +} + +/** + * hildon_window_get_menu: + * @self: a #HildonWindow + * + * Return value: a #GtkMenu + * + * Deprecated: In Hildon 2.2 this function has been renamed to + * hildon_window_get_main_menu() for consistency + **/ +GtkMenu* +hildon_window_get_menu (HildonWindow * self) +{ + return hildon_window_get_main_menu (self); +} + +/* Since we've been asking developers to call gtk_window_add_accel_group() + * themselves, do not trigger criticals by trying it again. + */ +static void +hildon_window_add_accel_group (HildonWindow *self, + GtkAccelGroup *accel_group) +{ + GSList *groups, *l; + + groups = gtk_accel_groups_from_object (G_OBJECT (self)); + for (l = groups; l != NULL; l = l->next) + if (l->data == (gpointer)accel_group) + /* Maybe print a warning here? */ + return; + + gtk_window_add_accel_group (GTK_WINDOW (self), accel_group); +} + +/** + * hildon_window_set_main_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. #HildonWindow takes ownership of the passed menu and you're + * not supposed to free it yourself anymore. + * + * Note that if you're using a #HildonAppMenu rather than a #GtkMenu + * you should use hildon_window_set_app_menu() instead. + **/ +void +hildon_window_set_main_menu (HildonWindow* self, + GtkMenu * menu) +{ + HildonWindowPrivate *priv; + GtkAccelGroup *accel_group; + + g_return_if_fail (HILDON_IS_WINDOW (self)); + + priv = HILDON_WINDOW_GET_PRIVATE (self); + + if (priv->menu != NULL) + { + accel_group = gtk_menu_get_accel_group (priv->menu); + if (accel_group != NULL) + gtk_window_remove_accel_group (GTK_WINDOW (self), accel_group); + + gtk_menu_detach (priv->menu); + g_object_unref (priv->menu); + } + + priv->menu = menu; + if (priv->menu != NULL) + { + gtk_widget_set_name (GTK_WIDGET (priv->menu), "menu_force_with_corners"); + gtk_menu_attach_to_widget (priv->menu, GTK_WIDGET (self), &detach_menu_func); + g_object_ref (priv->menu); + + accel_group = gtk_menu_get_accel_group (priv->menu); + if (accel_group != NULL) + hildon_window_add_accel_group (self, accel_group); + } +} + +/** + * 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. HildonWindow takes ownership of the passed menu and you're + * not supposed to free it yourself anymore. + * + * Note: hildon_window_set_menu() calls gtk_widget_show_all() for the + * #GtkMenu. To pass control about visibility to the application + * developer, hildon_window_set_main_menu() was introduced, which + * doesn't do this. + * + * Deprecated: Hildon 2.2: use hildon_window_set_main_menu() + **/ +void +hildon_window_set_menu (HildonWindow *self, + GtkMenu *menu) +{ + HildonWindowPrivate *priv; + + g_return_if_fail (HILDON_IS_WINDOW (self)); + + hildon_window_set_main_menu (self, menu); + + priv = HILDON_WINDOW_GET_PRIVATE (self); + + if (priv->menu != NULL) + gtk_widget_show_all (GTK_WIDGET (priv->menu)); +} + +/** + * hildon_window_get_is_topmost: + * @self: A #HildonWindow + * + * Returns whether the #HildonWindow is currenty activated by the + * window manager. + * + * Return value: %TRUE if @self is currently activated, %FALSE otherwise. + **/ +gboolean +hildon_window_get_is_topmost (HildonWindow *self) +{ + HildonWindowPrivate *priv; + + g_return_val_if_fail (HILDON_IS_WINDOW (self), FALSE); + + priv = HILDON_WINDOW_GET_PRIVATE (self); + return priv->is_topmost; +} + +/** + * hildon_window_set_app_menu: + * @self: a #HildonWindow + * @menu: a #HildonAppMenu to be used for this window + * + * Sets the menu to be used for this window. Pass %NULL to remove the + * current menu. Any reference to a previous menu will be dropped. + * #HildonWindow takes ownership of the passed menu and + * you're not supposed to free it yourself anymore. + * + * Note that if you're using a #GtkMenu rather than a #HildonAppMenu + * you should use hildon_window_set_main_menu() instead. + * + * Since: 2.2 + **/ +void +hildon_window_set_app_menu (HildonWindow *self, + HildonAppMenu *menu) +{ + HildonWindowPrivate *priv; + HildonAppMenu *old_menu; + + g_return_if_fail (HILDON_IS_WINDOW (self)); + g_return_if_fail (!menu || HILDON_IS_APP_MENU (menu)); + priv = HILDON_WINDOW_GET_PRIVATE (self); + + old_menu = priv->app_menu; + + /* Add new menu */ + priv->app_menu = menu; + if (menu) + g_object_ref_sink (menu); + + /* Unref old menu */ + if (old_menu) + g_object_unref (old_menu); +} + +/** + * hildon_window_get_app_menu: + * @self: a #HildonWindow + * + * Returns the #HildonAppMenu assigned to @self, or %NULL if it's + * unset. Note that the window is still the owner of the menu. + * + * Note that if you're using a #GtkMenu rather than a #HildonAppMenu + * you should use hildon_window_get_main_menu() instead. + * + * Returns: a #HildonAppMenu + * + * Since: 2.2 + **/ +HildonAppMenu * +hildon_window_get_app_menu (HildonWindow *self) +{ + HildonWindowPrivate *priv; + + g_return_val_if_fail (HILDON_IS_WINDOW (self), NULL); + + priv = HILDON_WINDOW_GET_PRIVATE (self); + + return priv->app_menu; +} + +static void +hildon_window_update_markup (HildonWindow *window) +{ + HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (window); + GdkAtom markup_atom = gdk_atom_intern ("_HILDON_WM_NAME", FALSE); + GdkAtom utf8_atom = gdk_atom_intern ("UTF8_STRING", FALSE); + GdkWindow *gdkwin = GTK_WIDGET (window)->window; + + if (priv->markup) { + gdk_property_change (gdkwin, markup_atom, utf8_atom, 8, + GDK_PROP_MODE_REPLACE, (const guchar *) priv->markup, + strlen (priv->markup)); + } else { + gdk_property_delete (gdkwin, markup_atom); + } +} + +/** + * hildon_window_get_markup: + * @window: a #HildonWindow + * + * Gets the marked up title of the window title. See hildon_window_set_markup() + * + * Returns: the marked up title of the window, or %NULL if none has + * been set explicitely. The returned string is owned by the widget + * and must not be modified or freed. + * + * Since: 2.2 + **/ +const gchar * +hildon_window_get_markup (HildonWindow *window) +{ + HildonWindowPrivate *priv; + + g_return_val_if_fail (HILDON_IS_WINDOW (window), NULL); + + priv = HILDON_WINDOW_GET_PRIVATE (window); + + return priv->markup; +} + +/** + * hildon_window_set_markup: + * @window: a #HildonWindow + * @markup: the marked up title of the window, or %NULL to unset the + * current one + * + * Sets the marked up title of @window. The accepted format is the one + * used in Pango (see #PangoMarkupFormat) with the exception of + * <span>. + * + * Note that you need support from the window manager for this title + * to be used. See gtk_window_set_title() for the standard way of + * setting the title of a window. + * + * Since: 2.2 + **/ +void +hildon_window_set_markup (HildonWindow *window, + const gchar *markup) +{ + HildonWindowPrivate *priv; + gchar *new_markup; + + g_return_if_fail (HILDON_IS_WINDOW (window)); + + priv = HILDON_WINDOW_GET_PRIVATE (window); + + new_markup = g_strdup (markup); + g_free (priv->markup); + priv->markup = new_markup; + + if (GTK_WIDGET_REALIZED (window)) + hildon_window_update_markup (window); + + g_object_notify (G_OBJECT (window), "markup"); +} diff --git a/hildon/hildon-window.h b/hildon/hildon-window.h new file mode 100644 index 0000000..e5d8d49 --- /dev/null +++ b/hildon/hildon-window.h @@ -0,0 +1,140 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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 "hildon-app-menu.h" +#include "hildon-edit-toolbar.h" + +G_BEGIN_DECLS + +#define HILDON_WINDOW_LONG_PRESS_TIME 800 /* 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)) + +#define HILDON_WINDOW_GET_CLASS(obj) \ + ((HildonWindowClass *) G_OBJECT_GET_CLASS(obj)) + +typedef struct _HildonWindow HildonWindow; + +typedef struct _HildonWindowClass HildonWindowClass; + +typedef enum +{ + HILDON_WINDOW_CO_COPY, + HILDON_WINDOW_CO_CUT, + HILDON_WINDOW_CO_PASTE +} HildonWindowClipboardOperation; + +struct _HildonWindow +{ + GtkWindow parent; +}; + +struct _HildonWindowClass +{ + GtkWindowClass parent_class; + + /* opera hacks for clip board operation */ + void (*clipboard_operation)(HildonWindow *hwindow, int operation); + gboolean (*toggle_menu)(HildonWindow * self, guint button, guint32 time); + /* Padding for future extension */ + void (*_hildon_reserved1)(void); + void (*_hildon_reserved2)(void); +}; + +GType G_GNUC_CONST +hildon_window_get_type (void); + +GtkWidget* +hildon_window_new (void); + +void +hildon_window_add_with_scrollbar (HildonWindow *self, + GtkWidget *child); + +void +hildon_window_set_main_menu (HildonWindow *self, + GtkMenu *menu); + +GtkMenu* +hildon_window_get_main_menu (HildonWindow *self); + +void +hildon_window_set_app_menu (HildonWindow *self, + HildonAppMenu *menu); + +HildonAppMenu * +hildon_window_get_app_menu (HildonWindow *self); + +#ifndef HILDON_DISABLE_DEPRECATED +void +hildon_window_set_menu (HildonWindow *self, + GtkMenu *menu); + +GtkMenu* +hildon_window_get_menu (HildonWindow *self); +#endif + +void +hildon_window_add_toolbar (HildonWindow *self, + GtkToolbar *toolbar); + +void +hildon_window_remove_toolbar (HildonWindow *self, + GtkToolbar *toolbar); + +void +hildon_window_set_edit_toolbar (HildonWindow *self, + HildonEditToolbar *toolbar); + +gboolean +hildon_window_get_is_topmost (HildonWindow *self); + +const gchar * +hildon_window_get_markup (HildonWindow *window); + +void +hildon_window_set_markup (HildonWindow *window, + const gchar *markup); + +G_END_DECLS + +#endif /* __HILDON_WINDOW_H__ */ diff --git a/hildon/hildon-wizard-dialog-private.h b/hildon/hildon-wizard-dialog-private.h new file mode 100644 index 0000000..deed7c9 --- /dev/null +++ b/hildon/hildon-wizard-dialog-private.h @@ -0,0 +1,52 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * 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, or (at your option) any later version. + * + * 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_PRIVATE_H__ +#define __HILDON_WIZARD_DIALOG_PRIVATE_H__ + +G_BEGIN_DECLS + +#define HILDON_WIZARD_DIALOG_GET_PRIVATE(obj)\ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + HILDON_TYPE_WIZARD_DIALOG, \ + HildonWizardDialogPrivate)); + +typedef struct _HildonWizardDialogPrivate HildonWizardDialogPrivate; + +struct _HildonWizardDialogPrivate +{ + gchar *wizard_name; + GtkNotebook *notebook; + gboolean autotitle; + + HildonWizardDialogPageFunc forward_function; + gpointer forward_function_data; + GDestroyNotify forward_data_destroy; +}; + +G_END_DECLS + +#endif /* __HILDON_WIZARD_DIALOG_PRIVATE_H__ */ + diff --git a/hildon/hildon-wizard-dialog.c b/hildon/hildon-wizard-dialog.c new file mode 100644 index 0000000..8a8ee83 --- /dev/null +++ b/hildon/hildon-wizard-dialog.c @@ -0,0 +1,555 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * 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, or (at your option) any later version. + * + * 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 three standard buttons, previous, next, + * finish, and contains several pages. + * + * Response buttons are dimmed/undimmed automatically. The notebook + * widget provided by users contains the actual wizard pages. + * + * Usage of the API is very simple, it has only one function to create it + * and the rest of it is handled by developers notebook. + * Also, the response is returned, either cancel or finish. + * Next and previous buttons are handled by the wizard dialog it self, by + * switching the page either forward or backward in the notebook. + * + * It is possible to determinate whether users can go to the next page + * by setting a #HildonWizardDialogPageFunc function with + * hildon_wizard_dialog_set_forward_page_func() + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "hildon-wizard-dialog.h" +#include "hildon-defines.h" +#include "hildon-wizard-dialog-private.h" + +#define _(String) dgettext("hildon-libs", String) + +static GtkDialogClass* parent_class; + +static void +hildon_wizard_dialog_class_init (HildonWizardDialogClass *wizard_dialog_class); + +static void +hildon_wizard_dialog_init (HildonWizardDialog *wizard_dialog); + +static void +create_title (HildonWizardDialog *wizard_dialog); + +static void +hildon_wizard_dialog_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); + +static void +hildon_wizard_dialog_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static void +finalize (GObject *object); + +static void +destroy (GtkObject *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_0, + PROP_NAME, + PROP_NOTEBOOK, + PROP_AUTOTITLE +}; + +/** + * hildon_wizard_dialog_get_type: + * + * Initializes and returns the type of a hildon wizard dialog. + * + * Returns: GType of #HildonWzardDialog + */ +GType G_GNUC_CONST +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) hildon_wizard_dialog_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (HildonWizardDialog), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_wizard_dialog_init, + }; + + wizard_dialog_type = g_type_register_static (GTK_TYPE_DIALOG, + "HildonWizardDialog", + &wizard_dialog_info, + 0); + } + + return wizard_dialog_type; +} + +static void +hildon_wizard_dialog_class_init (HildonWizardDialogClass *wizard_dialog_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (wizard_dialog_class); + GtkObjectClass *gtk_object_class = GTK_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 = hildon_wizard_dialog_set_property; + object_class->get_property = hildon_wizard_dialog_get_property; + object_class->finalize = finalize; + gtk_object_class->destroy = destroy; + + /** + * HildonWizardDialog:wizard-name: + * + * The name of the wizard. + */ + g_object_class_install_property (object_class, PROP_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_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_AUTOTITLE, + g_param_spec_boolean + ("autotitle", + "AutoTitle", + "If the wizard should autotitle itself", + TRUE, + G_PARAM_READWRITE)); +} + +static void +finalize (GObject *object) +{ + HildonWizardDialogPrivate *priv = HILDON_WIZARD_DIALOG_GET_PRIVATE (object); + + g_assert (priv); + + if (priv->wizard_name != NULL) + g_free (priv->wizard_name); + + if (G_OBJECT_CLASS (parent_class)->finalize) + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +destroy (GtkObject *object) +{ + HildonWizardDialogPrivate *priv = HILDON_WIZARD_DIALOG_GET_PRIVATE (object); + + g_assert (priv); + + if (priv->forward_function) + { + if (priv->forward_function_data && + priv->forward_data_destroy) + priv->forward_data_destroy (priv->forward_function_data); + + priv->forward_function = NULL; + priv->forward_function_data = NULL; + priv->forward_data_destroy = NULL; + } +} + +/* 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 +hildon_wizard_dialog_init (HildonWizardDialog *wizard_dialog) +{ + /* Initialize private structure for faster member access */ + HildonWizardDialogPrivate *priv = HILDON_WIZARD_DIALOG_GET_PRIVATE (wizard_dialog); + g_assert (priv); + + GtkDialog *dialog = GTK_DIALOG (wizard_dialog); + + /* Init internal widgets */ + gtk_dialog_set_has_separator (dialog, FALSE); + + /* Default values for user provided properties */ + priv->notebook = NULL; + priv->wizard_name = NULL; + priv->autotitle = TRUE; + + priv->forward_function = NULL; + priv->forward_function_data = NULL; + priv->forward_data_destroy = NULL; + + /* Add response buttons: finish, previous, next */ + gtk_dialog_add_button (dialog, _("wdgt_bd_finish"), HILDON_WIZARD_DIALOG_FINISH); + gtk_dialog_add_button (dialog, _("wdgt_bd_previous"), HILDON_WIZARD_DIALOG_PREVIOUS); + gtk_dialog_add_button (dialog, _("wdgt_bd_next"), HILDON_WIZARD_DIALOG_NEXT); + + /* 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 +hildon_wizard_dialog_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + HildonWizardDialogPrivate *priv = HILDON_WIZARD_DIALOG_GET_PRIVATE (object); + GtkDialog *dialog = GTK_DIALOG (object); + + g_assert (priv); + + switch (property_id) { + + case PROP_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_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_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 (dialog->vbox), 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 (GTK_WIDGET (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 +hildon_wizard_dialog_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + HildonWizardDialogPrivate *priv = HILDON_WIZARD_DIALOG_GET_PRIVATE (object); + g_assert (priv); + + switch (property_id) { + + case PROP_NAME: + g_value_set_string (value, priv->wizard_name); + break; + + case PROP_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 = HILDON_WIZARD_DIALOG_GET_PRIVATE (wizard_dialog); + GtkNotebook *notebook; + + g_assert (priv); + 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); + } else { + const gchar *steps = gtk_notebook_get_tab_label_text (notebook, + gtk_notebook_get_nth_page (notebook, current)); + + if (steps) { + str = g_strdup_printf ("%s: %s", priv->wizard_name, steps); + } else { + str = g_strdup (priv->wizard_name); + } + } + + /* 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 = HILDON_WIZARD_DIALOG_GET_PRIVATE (wizard_dialog); + GtkNotebook *notebook = priv->notebook; + gint current = 0; + gint last = gtk_notebook_get_n_pages (notebook) - 1; + gboolean is_first, is_last; + + g_assert (priv); + + current = gtk_notebook_current_page (notebook); + + switch (response_id) { + + case HILDON_WIZARD_DIALOG_PREVIOUS: + --current; + is_last = (current == last); + is_first = (current == 0); + make_buttons_sensitive (wizard_dialog, + !is_first, !is_first, !is_last); + gtk_notebook_prev_page (notebook); /* go to previous page */ + break; + + case HILDON_WIZARD_DIALOG_NEXT: + + if (!priv->forward_function || + (*priv->forward_function) (priv->notebook, current, priv->forward_function_data)) { + ++current; + is_last = (current == last); + is_first = (current == 0); + make_buttons_sensitive (wizard_dialog, + !is_first, !is_first, !is_last); + gtk_notebook_next_page (notebook); /* go to next page */ + } + break; + + case HILDON_WIZARD_DIALOG_FINISH: + return; + + } + + current = gtk_notebook_get_current_page (notebook); + is_last = current == last; + is_first = current == 0; + + /* Don't let the dialog close */ + g_signal_stop_emission_by_name (wizard_dialog, "response"); + + /* 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; +} + +/** + * hildon_wizard_dialog_set_forward_page_func: + * @wizard_dialog: a #HildonWizardDialog + * @page_func: the #HildonWizardDialogPageFunc + * @data: user data for @page_func + * @destroy: destroy notifier for @data + * + * Sets the page forwarding function to be @page_func. This function + * will be used to determine whether it is possible to go to the next page + * when the user presses the forward button. Setting @page_func to %NULL + * wil make the wizard to simply go always to the next page. + * + * Since: 2.2 + **/ +void +hildon_wizard_dialog_set_forward_page_func (HildonWizardDialog *wizard_dialog, + HildonWizardDialogPageFunc page_func, + gpointer data, + GDestroyNotify destroy) +{ + g_return_if_fail (HILDON_IS_WIZARD_DIALOG (wizard_dialog)); + + HildonWizardDialogPrivate *priv = HILDON_WIZARD_DIALOG_GET_PRIVATE (wizard_dialog); + + if (priv->forward_data_destroy && + priv->forward_function_data) { + (*priv->forward_data_destroy) (priv->forward_function_data); + } + + priv->forward_function = page_func; + priv->forward_function_data = data; + priv->forward_data_destroy = destroy; +} diff --git a/hildon/hildon-wizard-dialog.h b/hildon/hildon-wizard-dialog.h new file mode 100644 index 0000000..a39abe4 --- /dev/null +++ b/hildon/hildon-wizard-dialog.h @@ -0,0 +1,109 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * 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, or (at your option) any later version. + * + * 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 + +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; + +/* HILDON_WIZARD_DIALOG_CANCEL should be marked as deprecated */ + +/** + * HildonWizardDialogResponse: + * @HILDON_WIZARD_DIALOG_CANCEL: Returned by the 'Cancel' button. + * @HILDON_WIZARD_DIALOG_PREVIOUS: Returned by the 'Previous' button. + * @HILDON_WIZARD_DIALOG_NEXT: Returned by the 'Next' button. + * @HILDON_WIZARD_DIALOG_FINISH: Returned by the 'Finish' button. + * + * Predefined values for use as response ids for #HildonWizardDialog. + * + * + * + * HILDON_WIZARD_DIALOG_CANCEL is deprecated and should not be used in newly-written code. + * + * + **/ +typedef enum +{ + HILDON_WIZARD_DIALOG_CANCEL = GTK_RESPONSE_CANCEL, + HILDON_WIZARD_DIALOG_PREVIOUS = 0, + HILDON_WIZARD_DIALOG_NEXT, + HILDON_WIZARD_DIALOG_FINISH +} HildonWizardDialogResponse; + +struct _HildonWizardDialog +{ + GtkDialog parent; +}; + +struct _HildonWizardDialogClass +{ + GtkDialogClass parent_class; +}; + +typedef gboolean (*HildonWizardDialogPageFunc) (GtkNotebook *notebook, gint current_page, gpointer data); + +GType G_GNUC_CONST +hildon_wizard_dialog_get_type (void); + +GtkWidget* +hildon_wizard_dialog_new (GtkWindow *parent, + const char *wizard_name, + GtkNotebook *notebook); + +void +hildon_wizard_dialog_set_forward_page_func (HildonWizardDialog *wizard_dialog, + HildonWizardDialogPageFunc page_func, + gpointer data, + GDestroyNotify destroy); + +G_END_DECLS + +#endif /* __HILDON_WIZARD_DIALOG_H__ */ + diff --git a/hildon/hildon.h b/hildon/hildon.h new file mode 100644 index 0000000..b593c0e --- /dev/null +++ b/hildon/hildon.h @@ -0,0 +1,87 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo + * + * 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, or (at your option) any later version. + * + * 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_H__ +#define __HILDON_H__ + +#include "hildon-version.h" +#include "hildon-banner.h" +#include "hildon-calendar-popup.h" +#include "hildon-caption.h" +#include "hildon-code-dialog.h" +#include "hildon-color-button.h" +#include "hildon-color-chooser-dialog.h" +#include "hildon-color-chooser.h" +#include "hildon-controlbar.h" +#include "hildon-date-editor.h" +#include "hildon-defines.h" +#include "hildon-helper.h" +#include "hildon-enum-types.h" +#include "hildon-find-toolbar.h" +#include "hildon-edit-toolbar.h" +#include "hildon-font-selection-dialog.h" +#include "hildon-get-password-dialog.h" +#include "hildon-hvolumebar.h" +#include "hildon-login-dialog.h" +#include "hildon-marshalers.h" +#include "hildon-note.h" +#include "hildon-number-editor.h" +#include "hildon-program.h" +#include "hildon-range-editor.h" +#include "hildon-seekbar.h" +#include "hildon-set-password-dialog.h" +#include "hildon-sort-dialog.h" +#include "hildon-sound.h" +#include "hildon-time-editor.h" +#include "hildon-time-picker.h" +#include "hildon-date-selector.h" +#include "hildon-time-selector.h" +#include "hildon-touch-selector.h" +#include "hildon-touch-selector-entry.h" +#include "hildon-picker-dialog.h" +#include "hildon-picker-button.h" +#include "hildon-date-button.h" +#include "hildon-time-button.h" +#include "hildon-volumebar-range.h" +#include "hildon-volumebar.h" +#include "hildon-vvolumebar.h" +#include "hildon-weekday-picker.h" +#include "hildon-window.h" +#include "hildon-stackable-window.h" +#include "hildon-window-stack.h" +#include "hildon-animation-actor.h" +#include "hildon-wizard-dialog.h" +#include "hildon-calendar.h" +#include "hildon-bread-crumb-trail.h" +#include "hildon-pannable-area.h" +#include "hildon-entry.h" +#include "hildon-text-view.h" +#include "hildon-app-menu.h" +#include "hildon-button.h" +#include "hildon-check-button.h" +#include "hildon-gtk.h" +#include "hildon-dialog.h" +#include "hildon-main.h" + +#endif diff --git a/po/POTFILES.in b/po/POTFILES.in index 2e88f6e..4992e92 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,97 +1,97 @@ -src/hildon-code-dialog-private.h -src/hildon-window-private.h -src/hildon-find-toolbar.h -src/hildon-seekbar-private.h -src/hildon-volumebar.c -src/hildon-time-editor-private.h -src/hildon-sort-dialog-private.h -src/hildon-volumebar.h -src/hildon-font-selection-dialog-private.h -src/hildon-color-button-private.h -src/hildon-weekday-picker.c -src/hildon-time-picker.c -src/hildon-weekday-picker.h -src/hildon-note.h -src/hildon-banner-private.h -src/hildon-time-picker.h -src/hildon-calendar.c -src/hildon-calendar-popup.c -src/hildon-controlbar-private.h -src/hildon-vvolumebar.c -src/hildon-range-editor.h -src/hildon-volumebar-range.c -src/hildon-vvolumebar.h -src/hildon-get-password-dialog-private.h -src/hildon-color-chooser-private.h -src/hildon-volumebar-range.h -src/hildon-set-password-dialog-private.h -src/hildon-code-dialog.c -src/hildon.h -src/hildon-caption-private.h -src/hildon-wizard-dialog-private.h -src/hildon-code-dialog.h -src/hildon-window.h -src/hildon-date-editor-private.h -src/hildon-date-selector.c -src/hildon-time-selector.c -src/hildon-seekbar.h -src/hildon-login-dialog-private.h -src/hildon-time-editor.c -src/hildon-program-private.h -src/hildon-helper.h -src/hildon-sort-dialog.c -src/hildon-font-selection-dialog.c -src/hildon-color-button.c -src/hildon-time-editor.h -src/hildon-color-chooser-dialog-private.h -src/hildon-sound.c -src/hildon-number-editor-private.h -src/hildon-sort-dialog.h -src/hildon-font-selection-dialog.h -src/hildon-color-button.h -src/hildon-find-toolbar-private.h -src/hildon-sound.h -src/hildon-range-editor.c -src/hildon-hvolumebar.h -src/hildon-volumebar-private.h -src/hildon-controlbar.h -src/hildon-color-chooser.c -src/hildon-get-password-dialog.h -src/hildon-weekday-picker-private.h -src/hildon-note-private.h -src/hildon-color-chooser.h -src/hildon-time-picker-private.h -src/hildon-banner.h -src/hildon-set-password-dialog.c -src/hildon-range-editor-private.h -src/hildon-window.c -src/hildon-set-password-dialog.h -src/hildon-wizard-dialog.c -src/hildon-date-editor.c -src/hildon-caption.h -src/hildon-wizard-dialog.h -src/hildon-login-dialog.c -src/hildon-date-editor.h -src/hildon-private.c -src/hildon-login-dialog.h -src/hildon-color-chooser-dialog.c -src/hildon-program.h -src/hildon-seekbar.c -src/hildon-defines.c -src/hildon-private.h -src/hildon-color-chooser-dialog.h -src/hildon-find-toolbar.c -src/hildon-number-editor.h -src/hildon-defines.h -src/hildon-caption.c -src/hildon-calendar-popup-private.h -src/hildon-get-password-dialog.c -src/hildon-helper.c -src/hildon-hvolumebar.c -src/hildon-banner.c -src/hildon-note.c -src/hildon-calendar-popup.h -src/hildon-number-editor.c -src/hildon-controlbar.c -src/hildon-program.c +hildon/hildon-code-dialog-private.h +hildon/hildon-window-private.h +hildon/hildon-find-toolbar.h +hildon/hildon-seekbar-private.h +hildon/hildon-volumebar.c +hildon/hildon-time-editor-private.h +hildon/hildon-sort-dialog-private.h +hildon/hildon-volumebar.h +hildon/hildon-font-selection-dialog-private.h +hildon/hildon-color-button-private.h +hildon/hildon-weekday-picker.c +hildon/hildon-time-picker.c +hildon/hildon-weekday-picker.h +hildon/hildon-note.h +hildon/hildon-banner-private.h +hildon/hildon-time-picker.h +hildon/hildon-calendar.c +hildon/hildon-calendar-popup.c +hildon/hildon-controlbar-private.h +hildon/hildon-vvolumebar.c +hildon/hildon-range-editor.h +hildon/hildon-volumebar-range.c +hildon/hildon-vvolumebar.h +hildon/hildon-get-password-dialog-private.h +hildon/hildon-color-chooser-private.h +hildon/hildon-volumebar-range.h +hildon/hildon-set-password-dialog-private.h +hildon/hildon-code-dialog.c +hildon/hildon.h +hildon/hildon-caption-private.h +hildon/hildon-wizard-dialog-private.h +hildon/hildon-code-dialog.h +hildon/hildon-window.h +hildon/hildon-date-editor-private.h +hildon/hildon-date-selector.c +hildon/hildon-time-selector.c +hildon/hildon-seekbar.h +hildon/hildon-login-dialog-private.h +hildon/hildon-time-editor.c +hildon/hildon-program-private.h +hildon/hildon-helper.h +hildon/hildon-sort-dialog.c +hildon/hildon-font-selection-dialog.c +hildon/hildon-color-button.c +hildon/hildon-time-editor.h +hildon/hildon-color-chooser-dialog-private.h +hildon/hildon-sound.c +hildon/hildon-number-editor-private.h +hildon/hildon-sort-dialog.h +hildon/hildon-font-selection-dialog.h +hildon/hildon-color-button.h +hildon/hildon-find-toolbar-private.h +hildon/hildon-sound.h +hildon/hildon-range-editor.c +hildon/hildon-hvolumebar.h +hildon/hildon-volumebar-private.h +hildon/hildon-controlbar.h +hildon/hildon-color-chooser.c +hildon/hildon-get-password-dialog.h +hildon/hildon-weekday-picker-private.h +hildon/hildon-note-private.h +hildon/hildon-color-chooser.h +hildon/hildon-time-picker-private.h +hildon/hildon-banner.h +hildon/hildon-set-password-dialog.c +hildon/hildon-range-editor-private.h +hildon/hildon-window.c +hildon/hildon-set-password-dialog.h +hildon/hildon-wizard-dialog.c +hildon/hildon-date-editor.c +hildon/hildon-caption.h +hildon/hildon-wizard-dialog.h +hildon/hildon-login-dialog.c +hildon/hildon-date-editor.h +hildon/hildon-private.c +hildon/hildon-login-dialog.h +hildon/hildon-color-chooser-dialog.c +hildon/hildon-program.h +hildon/hildon-seekbar.c +hildon/hildon-defines.c +hildon/hildon-private.h +hildon/hildon-color-chooser-dialog.h +hildon/hildon-find-toolbar.c +hildon/hildon-number-editor.h +hildon/hildon-defines.h +hildon/hildon-caption.c +hildon/hildon-calendar-popup-private.h +hildon/hildon-get-password-dialog.c +hildon/hildon-helper.c +hildon/hildon-hvolumebar.c +hildon/hildon-banner.c +hildon/hildon-note.c +hildon/hildon-calendar-popup.h +hildon/hildon-number-editor.c +hildon/hildon-controlbar.c +hildon/hildon-program.c tests/check-hildon-caption.c \ No newline at end of file diff --git a/src/Makefile.am b/src/Makefile.am deleted file mode 100644 index 5b8ddee..0000000 --- a/src/Makefile.am +++ /dev/null @@ -1,235 +0,0 @@ -INCLUDES = -DG_LOG_DOMAIN=\"hildon-@API_VERSION_MAJOR@\" \ - -DLOCALEDIR=\"$(localedir)\" - -CLEANFILES = \ - hildon-enum-types.c \ - hildon-enum-types.h \ - hildon-marshalers.h \ - hildon-marshalers.c - -EXTRA_DIST = hildon-marshalers.list - -lib_LTLIBRARIES = libhildon-@API_VERSION_MAJOR@.la - -libhildon_@API_VERSION_MAJOR@_la_LDFLAGS = $(HILDON_WIDGETS_LT_LDFLAGS) - -libhildon_@API_VERSION_MAJOR@_la_LIBADD = \ - $(GTK_LIBS) \ - $(GCONF_LIBS) \ - $(CANBERRA_LIBS) \ - @HILDON_LT_LDFLAGS@ - -libhildon_@API_VERSION_MAJOR@_la_CFLAGS = \ - $(GTK_CFLAGS) \ - $(GCONF_CFLAGS) \ - $(EXTRA_CFLAGS) \ - $(CANBERRA_CFLAGS) - -libhildon_@API_VERSION_MAJOR@_la_SOURCES = \ - hildon-private.c \ - hildon-controlbar.c \ - hildon-seekbar.c \ - hildon-note.c \ - hildon-volumebar.c \ - hildon-sound.c \ - hildon-volumebar-range.c \ - hildon-hvolumebar.c \ - hildon-vvolumebar.c \ - hildon-calendar-popup.c \ - hildon-date-editor.c \ - hildon-time-editor.c \ - hildon-time-picker.c \ - hildon-date-selector.c \ - hildon-time-selector.c \ - hildon-touch-selector.c \ - hildon-touch-selector-entry.c \ - hildon-picker-dialog.c \ - hildon-picker-button.c \ - hildon-date-button.c \ - hildon-time-button.c \ - hildon-helper.c \ - hildon-weekday-picker.c \ - hildon-number-editor.c \ - hildon-range-editor.c \ - hildon-get-password-dialog.c \ - hildon-set-password-dialog.c \ - hildon-sort-dialog.c \ - hildon-font-selection-dialog.c \ - hildon-login-dialog.c \ - hildon-wizard-dialog.c \ - hildon-color-chooser.c \ - hildon-color-button.c \ - hildon-color-chooser-dialog.c \ - hildon-defines.c \ - hildon-find-toolbar.c \ - hildon-edit-toolbar.c \ - hildon-banner.c \ - hildon-caption.c \ - hildon-window.c \ - hildon-stackable-window.c \ - hildon-window-stack.c \ - hildon-animation-actor.c \ - hildon-remote-texture.c \ - hildon-program.c \ - hildon-code-dialog.c \ - hildon-enum-types.c \ - hildon-marshalers.c \ - hildon-calendar.c \ - hildon-pannable-area.c \ - hildon-entry.c \ - hildon-text-view.c \ - hildon-bread-crumb-trail.c \ - hildon-bread-crumb.c \ - hildon-bread-crumb-widget.c \ - hildon-app-menu.c \ - hildon-button.c \ - hildon-check-button.c \ - hildon-gtk.c \ - hildon-dialog.c \ - hildon-main.c - -libhildon_@API_VERSION_MAJOR@_built_public_headers = \ - hildon-enum-types.h \ - hildon-marshalers.h - -libhildon_@API_VERSION_MAJOR@_includedir = \ - $(includedir)/$(PACKAGE)-$(API_VERSION_MAJOR)/$(PACKAGE) - -libhildon_@API_VERSION_MAJOR@_public_headers = \ - hildon-banner.h \ - hildon-calendar-popup.h \ - hildon-caption.h \ - hildon-code-dialog.h \ - hildon-color-button.h \ - hildon-color-chooser-dialog.h \ - hildon-color-chooser.h \ - hildon-controlbar.h \ - hildon-date-editor.h \ - hildon-defines.h \ - hildon-find-toolbar.h \ - hildon-edit-toolbar.h \ - hildon-helper.h \ - hildon-font-selection-dialog.h \ - hildon-get-password-dialog.h \ - hildon-hvolumebar.h \ - hildon-login-dialog.h \ - hildon-note.h \ - hildon-number-editor.h \ - hildon-program.h \ - hildon-range-editor.h \ - hildon-seekbar.h \ - hildon-set-password-dialog.h \ - hildon-sort-dialog.h \ - hildon-sound.h \ - hildon-time-editor.h \ - hildon-time-picker.h \ - hildon-date-selector.h \ - hildon-time-selector.h \ - hildon-touch-selector.h \ - hildon-touch-selector-column.h \ - hildon-touch-selector-entry.h \ - hildon-picker-dialog.h \ - hildon-picker-button.h \ - hildon-date-button.h \ - hildon-time-button.h \ - hildon-volumebar-range.h \ - hildon-volumebar.h \ - hildon-vvolumebar.h \ - hildon-weekday-picker.h \ - hildon.h \ - hildon-window.h \ - hildon-stackable-window.h \ - hildon-window-stack.h \ - hildon-animation-actor.h \ - hildon-remote-texture.h \ - hildon-wizard-dialog.h \ - hildon-calendar.h \ - hildon-pannable-area.h \ - hildon-entry.h \ - hildon-text-view.h \ - hildon-bread-crumb-trail.h \ - hildon-bread-crumb.h \ - hildon-app-menu.h \ - hildon-dialog.h \ - hildon-button.h \ - hildon-check-button.h \ - hildon-gtk.h \ - hildon-version.h \ - hildon-main.h - -libhildon_@API_VERSION_MAJOR@_include_HEADERS = \ - $(libhildon_@API_VERSION_MAJOR@_public_headers) \ - $(libhildon_@API_VERSION_MAJOR@_built_public_headers) - -noinst_HEADERS = hildon-banner-private.h \ - hildon-calendar-popup-private.h \ - hildon-private.h \ - hildon-caption-private.h \ - hildon-code-dialog-private.h \ - hildon-picker-button-private.h \ - hildon-color-button-private.h \ - hildon-color-chooser-dialog-private.h \ - hildon-color-chooser-private.h \ - hildon-controlbar-private.h \ - hildon-date-editor-private.h \ - hildon-find-toolbar-private.h \ - hildon-font-selection-dialog-private.h \ - hildon-get-password-dialog-private.h \ - hildon-login-dialog-private.h \ - hildon-note-private.h \ - hildon-number-editor-private.h \ - hildon-program-private.h \ - hildon-range-editor-private.h \ - hildon-seekbar-private.h \ - hildon-set-password-dialog-private.h \ - hildon-sort-dialog-private.h \ - hildon-time-editor-private.h \ - hildon-time-picker-private.h \ - hildon-volumebar-private.h \ - hildon-weekday-picker-private.h \ - hildon-window-private.h \ - hildon-stackable-window-private.h \ - hildon-window-stack-private.h \ - hildon-animation-actor-private.h \ - hildon-remote-texture-private.h \ - hildon-wizard-dialog-private.h \ - hildon-calendar-private.h \ - hildon-app-menu-private.h \ - hildon-bread-crumb-widget.h \ - hildon-touch-selector-private.h - -# Don't build the library until we have built the header that it needs: -$(OBJECTS) $(libhildon_$(API_VERSION_MAJOR)_la_OBJECTS): hildon-enum-types.h hildon-marshalers.c hildon-marshalers.h - -hildon-enum-types.h: @REBUILD@ $(libhildon_$(API_VERSION_MAJOR)_public_headers) Makefile - (cd $(srcdir) && glib-mkenums \ - --fhead "#ifndef __HILDON_ENUM_TYPES_H__\n" \ - --fhead "#define __HILDON_ENUM_TYPES_H__\n" \ - --fhead "\n" \ - --fhead "#include \n" \ - --fhead "\n" \ - --fhead "G_BEGIN_DECLS\n" \ - --fhead "\n" \ - --fprod "/* Enumerations from \"@filename@\" */\n" \ - --vhead "GType @enum_name@_get_type (void);\n#define HILDON_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \ - --ftail "\nG_END_DECLS\n\n#endif /* __HILDON_ENUM_TYPES_H__ */" \ - $(libhildon_$(API_VERSION_MAJOR)_public_headers)) > $@ - -hildon-enum-types.c: @REBUILD@ $(libhildon_$(API_VERSION_MAJOR)_public_headers) Makefile - (cd $(srcdir) && glib-mkenums \ - --fhead "#undef HILDON_DISABLE_DEPRECATED\n" \ - --fhead "#include \"hildon.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" \ - $(libhildon_$(API_VERSION_MAJOR)_public_headers)) > $@ - -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.h"' >hildon-marshalers.c - glib-genmarshal --prefix _hildon_marshal --body hildon-marshalers.list >>hildon-marshalers.c - diff --git a/src/hildon-animation-actor-private.h b/src/hildon-animation-actor-private.h deleted file mode 100644 index 6ab3763..0000000 --- a/src/hildon-animation-actor-private.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_ANIMATION_ACTOR_PRIVATE_H__ -#define __HILDON_ANIMATION_ACTOR_PRIVATE_H__ - -G_BEGIN_DECLS - -typedef struct _HildonAnimationActorPrivate HildonAnimationActorPrivate; - -#define HILDON_ANIMATION_ACTOR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_ANIMATION_ACTOR, HildonAnimationActorPrivate)); - -struct _HildonAnimationActorPrivate -{ - guint ready : 1; - - guint set_show : 1; - guint set_position : 1; - guint set_rotation : 3; - guint set_scale : 1; - guint set_anchor : 1; - guint set_parent : 1; - - guint show; - guint opacity; - - guint gravity; - guint anchor_x; - guint anchor_y; - - guint position_x; - guint position_y; - guint depth; - - guint32 x_rotation_angle; - guint x_rotation_y; - guint x_rotation_z; - - guint32 y_rotation_angle; - guint y_rotation_x; - guint y_rotation_z; - - guint32 z_rotation_angle; - guint z_rotation_x; - guint z_rotation_y; - - guint32 scale_x; - guint32 scale_y; - - GtkWindow* parent; - gulong parent_map_event_cb_id; - - gulong map_event_cb_id; -}; - -G_END_DECLS - -#endif /* __HILDON_ANIMATION_ACTOR_PRIVATE_H__ */ diff --git a/src/hildon-animation-actor.c b/src/hildon-animation-actor.c deleted file mode 100644 index 0d623d8..0000000 --- a/src/hildon-animation-actor.c +++ /dev/null @@ -1,1198 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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-animation-window - * @short_description: Widget representing an animation actor for - * WM-assisted animation effects in the Hildon framework. - * - * The #HildonAnimationActor is a GTK+ widget which represents an - * animation actor for WM-assisted animation effects in the Hildon - * framework. It derives from #GtkWindow and can host any widgets much - * like a normal window. The special features available to the - * animation actor is the ability to set its position, scale factor - * and rotation. These parameters are interpreted by Hildon's - * compositing window manager to alter the on-screen representation of - * the animation actor window. Bear in mind, however, that by design - * decision, animation actors are not reactive -- the widgets placed - * in such window will not receive keyboard, motion or button - * events. Animation actors are input-transparent -- the input events - * will be sent to the underlying real windows and widgets. - * - * The animation actors may exist in a parented or an unparented - * state. To be displayed, animations actors must be parented to - * another top-level window widget. Animation actors display on top - * (in front) of the standard window contents unless the position - * (depth, z-coordinate) is specifically adjusted. Animation actors in - * an unparented state do not display at all. - * - * Parented animation actors are placed in the coordinate space of the - * parent window and visually become a part of the parent window - * iteslf -- they inherit the transformations and effects enforced by - * the window manager on the parent window (task switcher animations, - * minimize events, etc.). - * - * All animation actor settings (position, scale, rotation, opacity, - * depth) can be applied to unparented actors, but will only take - * effect as the actor is parented to a top-level window and that - * window is shown. All settings are preserved during - * unparenting/reparenting. - * - * The #HildonAnimationActor API closely follows the #ClutterActor - * API. Please take a look at the #ClutterActor description for the - * modelview transformations order that applies to - * HildonAnimationActor and ClutterActor alike. - * - * Animation actor widget controls the animation actor as it is - * transformed by the window manager using ClientMessage X11 - * events. It tries to minimize the amount of such events and couples - * conceptually related parameters (visibility and opacity, position - * and depth) to the same message. The API, however, offers - * convenience functions for the programmer to be able to modify every - * parameter individually. - * - * - * Basic HildonAnimationActor example - * - * static void - * animation_cb (void *obj) - * { - * HildonAnimationActor *actor = HILDON_ANIMATION_ACTOR (obj); - * - * static int x_inc = 1; - * static int y_inc = 1; - * static int x = 0; - * static int y = 0; - * static int r = 0; - * - * if (((x_inc > 0) && (x > 800)) || - * ((x_inc < 0) && (x < 1))) - * x_inc = -x_inc; - * if (((y_inc > 0) && (y > 480)) || - * ((y_inc < 0) && (y < 1))) - * y_inc = -y_inc; - * - * x += x_inc; - * y += y_inc; - * r ++; - * - * // Set animation actor position and rotation - * hildon_animation_actor_set_position (actor, x, y); - * hildon_animation_actor_set_rotation (actor, - * HILDON_AA_Z_AXIS, - * r, - * 0, 0, 0); - * } - * - * int - * main (int argc, char **argv) - * { - * GtkWidget *win; - * GtkWidget *image; - * GtkWidget *actor; - * - * gtk_init (&argc, &argv); - * - * // ... set up a normal window - * win = hildon_window_new (); - * g_signal_connect (win, "destroy", G_CALLBACK (gtk_main_quit), NULL); - * gtk_widget_show_all (win); - * - * // ... load an image - * image = gtk_image_new_from_file ("image.jpg"); - * - * actor = hildon_animation_actor_new(); - * gtk_container_add (GTK_CONTAINER (actor), image); - * - * // Parent the animation actor - * hildon_animation_actor_set_parent (HILDON_ANIMATION_ACTOR (actor), win); - * - * // Set anchor point to the actor center - * hildon_animation_actor_set_anchor_from_gravity (HILDON_ANIMATION_ACTOR (actor), - HILDON_AA_CENTER_GRAVITY); - * - * gtk_widget_show_all (actor); - * - * // Set up animation - * g_timeout_add (100, (GSourceFunc)animation_cb, actor); - * - * gtk_main (); - * - * return 0; - * } - * - * - */ - -#include -#include - -#include "hildon-animation-actor.h" -#include "hildon-animation-actor-private.h" - -G_DEFINE_TYPE (HildonAnimationActor, hildon_animation_actor, GTK_TYPE_WINDOW); - -static GdkFilterReturn -hildon_animation_actor_event_filter (GdkXEvent *xevent, - GdkEvent *event, - gpointer data); -static void -hildon_animation_actor_update_ready (HildonAnimationActor *self); -static void -hildon_animation_actor_send_pending_messages (HildonAnimationActor *self); -static void -hildon_animation_actor_send_all_messages (HildonAnimationActor *self); -static gboolean -hildon_animation_actor_parent_map_event (GtkWidget *parent, - GdkEvent *event, - gpointer user_data); -static gboolean -hildon_animation_actor_map_event (GtkWidget *widget, - GdkEvent *event, - gpointer user_data); - -static guint32 show_atom; -static guint32 position_atom; -static guint32 rotation_atom; -static guint32 scale_atom; -static guint32 anchor_atom; -static guint32 parent_atom; -static guint32 ready_atom; - -static gboolean atoms_initialized = FALSE; - -static void -hildon_animation_actor_realize (GtkWidget *widget) -{ - GdkDisplay *display; - Atom wm_type, applet_type; - - GTK_WIDGET_CLASS (hildon_animation_actor_parent_class)->realize (widget); - - /* Set animation actor window type. */ - - display = gdk_drawable_get_display (widget->window); - - wm_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"); - applet_type = gdk_x11_get_xatom_by_name_for_display (display, "_HILDON_WM_WINDOW_TYPE_ANIMATION_ACTOR"); - - XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (widget->window), wm_type, - XA_ATOM, 32, PropModeReplace, - (unsigned char *) &applet_type, 1); - - /* This is a bit of a hack, but for the sake of speed (it is assumed that - * once HildonAnimationActor is created, a lot of ClientMessages will - * follow), we cache all ClientMessages atoms in static variables. */ - - if (!atoms_initialized) - { - show_atom = - gdk_x11_get_xatom_by_name_for_display - (display, "_HILDON_ANIMATION_CLIENT_MESSAGE_SHOW"); - position_atom = - gdk_x11_get_xatom_by_name_for_display - (display, "_HILDON_ANIMATION_CLIENT_MESSAGE_POSITION"); - rotation_atom = - gdk_x11_get_xatom_by_name_for_display - (display, "_HILDON_ANIMATION_CLIENT_MESSAGE_ROTATION"); - scale_atom = - gdk_x11_get_xatom_by_name_for_display - (display, "_HILDON_ANIMATION_CLIENT_MESSAGE_SCALE"); - anchor_atom = - gdk_x11_get_xatom_by_name_for_display - (display, "_HILDON_ANIMATION_CLIENT_MESSAGE_ANCHOR"); - parent_atom = - gdk_x11_get_xatom_by_name_for_display - (display, "_HILDON_ANIMATION_CLIENT_MESSAGE_PARENT"); - ready_atom = - gdk_x11_get_xatom_by_name_for_display - (display, "_HILDON_ANIMATION_CLIENT_READY"); -#if 0 - g_debug ("show atom = %lu\n", show_atom); - g_debug ("position atom = %lu\n", position_atom); - g_debug ("rotation atom = %lu\n", rotation_atom); - g_debug ("scale atom = %lu\n", scale_atom); - g_debug ("anchor atom = %lu\n", anchor_atom); - g_debug ("parent atom = %lu\n", parent_atom); - g_debug ("ready atom = %lu\n", ready_atom); -#endif - - atoms_initialized = TRUE; - } - - /* Wait for a ready message */ - - gdk_window_add_filter (widget->window, - hildon_animation_actor_event_filter, - widget); -} - -static void -hildon_animation_actor_unrealize (GtkWidget *widget) -{ - gdk_window_remove_filter (widget->window, - hildon_animation_actor_event_filter, - widget); - - GTK_WIDGET_CLASS (hildon_animation_actor_parent_class)->unrealize (widget); -} - -static void -hildon_animation_actor_show (GtkWidget *widget) -{ - HildonAnimationActor *self = HILDON_ANIMATION_ACTOR (widget); - - GTK_WIDGET_CLASS (hildon_animation_actor_parent_class)->show (widget); - hildon_animation_actor_set_show (self, 1); -} - -static void -hildon_animation_actor_hide (GtkWidget *widget) -{ - HildonAnimationActor *self = HILDON_ANIMATION_ACTOR (widget); - - hildon_animation_actor_set_show (self, 0); - GTK_WIDGET_CLASS (hildon_animation_actor_parent_class)->hide (widget); -} - -static void -hildon_animation_actor_class_init (HildonAnimationActorClass *klass) -{ - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - - widget_class->realize = hildon_animation_actor_realize; - widget_class->unrealize = hildon_animation_actor_unrealize; - widget_class->show = hildon_animation_actor_show; - widget_class->hide = hildon_animation_actor_hide; - - g_type_class_add_private (klass, sizeof (HildonAnimationActorPrivate)); -} - -static void -hildon_animation_actor_init (HildonAnimationActor *self) -{ - HildonAnimationActorPrivate - *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); - - /* Default non-zero values for the private variables */ - - priv->scale_x = 1 << 16; - priv->scale_y = 1 << 16; - priv->opacity = 0xff; -} - -/** - * hildon_animation_actor_new: - * - * Creates a new #HildonAnimationActor. - * - * Return value: A #HildonAnimationActor - * - * Since: 2.2 - **/ -GtkWidget* -hildon_animation_actor_new (void) -{ - HildonAnimationActor *newwindow = g_object_new (HILDON_TYPE_ANIMATION_ACTOR, NULL); - - gtk_window_set_decorated (GTK_WINDOW (newwindow), FALSE); - - return GTK_WIDGET (newwindow); -} - -/* - * An filter for GDK X11 events, waiting for PropertyNotify (window property - * changes) events, keeping track of animation actor ready atom. - * Having the ready atom set on the window by the window manager will trigger - * updates of actor parameters (position/rotation/etc...) to be sent off - * to the window manager for processing. - */ -static GdkFilterReturn -hildon_animation_actor_event_filter (GdkXEvent *xevent, - GdkEvent *event, - gpointer data) -{ - HildonAnimationActor *self = HILDON_ANIMATION_ACTOR (data); - XAnyEvent *any = xevent; - - if (any->type == PropertyNotify) - { - XPropertyEvent *property = xevent; - - if (property->atom == ready_atom) - { - hildon_animation_actor_update_ready (self); - } - } - - return GDK_FILTER_CONTINUE; -} - -/* - * Check for the ready atom on the animation actor X11 window. - * If present, send all pending animation actor messages to the - * window manager. - */ -static void -hildon_animation_actor_update_ready (HildonAnimationActor *self) -{ - HildonAnimationActorPrivate - *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); - GtkWidget *widget = GTK_WIDGET (self); - Display *display = GDK_WINDOW_XDISPLAY (widget->window); - Window window = GDK_WINDOW_XID (widget->window); - - int status; - gint xerror; - - Atom actual_type; - int actual_format; - unsigned long nitems, bytes_after; - unsigned char *prop = NULL; - - /* Check for the "ready" property */ - - gdk_error_trap_push (); - status = XGetWindowProperty (display, window, - ready_atom, 0, 32, - False, XA_ATOM, - &actual_type, &actual_format, - &nitems, &bytes_after, &prop); - xerror = gdk_error_trap_pop(); - - if (prop) - { - /* We do not actually use the property value for anything, - * it is enough that the property is set. */ - - XFree (prop); - } - - if (xerror || - (status != Success) || (actual_type != XA_ATOM) || - (actual_format != 32) || (nitems != 1)) - { - priv->ready = 0; - return; - } - - if (priv->ready) - { - /* The ready flag has been set once already. This means that - * the WM has restarted. Trigger re-mapping of the widget to - * update the texture actor first. Then push all animation - * actor settings anew. */ - - priv->map_event_cb_id = - g_signal_connect (G_OBJECT (self), - "map-event", - G_CALLBACK(hildon_animation_actor_map_event), - self); - - if (GTK_WIDGET_MAPPED (GTK_WIDGET (self))) - { - gtk_widget_unmap (GTK_WIDGET (self)); - gtk_widget_map (GTK_WIDGET (self)); - } - - return; - } - - priv->ready = 1; - - /* Send all pending messages */ - - hildon_animation_actor_send_pending_messages (self); -} - -static void -hildon_animation_actor_send_pending_messages (HildonAnimationActor *self) -{ - HildonAnimationActorPrivate - *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); - - if (priv->set_anchor) - { - if (priv->gravity == 0) - hildon_animation_actor_set_anchor (self, - priv->anchor_x, - priv->anchor_y); - else - hildon_animation_actor_set_anchor_from_gravity (self, - priv->gravity); - } - - if (priv->set_position) - hildon_animation_actor_set_position_full (self, - priv->position_x, - priv->position_y, - priv->depth); - - if (priv->set_rotation & (1 << HILDON_AA_X_AXIS)) - hildon_animation_actor_set_rotationx (self, - HILDON_AA_X_AXIS, - priv->x_rotation_angle, - 0, - priv->x_rotation_y, - priv->x_rotation_z); - - if (priv->set_rotation & (1 << HILDON_AA_Y_AXIS)) - hildon_animation_actor_set_rotationx (self, - HILDON_AA_Y_AXIS, - priv->y_rotation_angle, - priv->y_rotation_x, - 0, - priv->y_rotation_z); - - if (priv->set_rotation & (1 << HILDON_AA_Z_AXIS)) - hildon_animation_actor_set_rotationx (self, - HILDON_AA_Z_AXIS, - priv->z_rotation_angle, - priv->z_rotation_x, - priv->z_rotation_y, - 0); - - if (priv->set_scale) - hildon_animation_actor_set_scalex (self, - priv->scale_x, - priv->scale_y); - - if (priv->set_parent) - hildon_animation_actor_set_parent (self, - priv->parent); - - if (priv->set_show) - hildon_animation_actor_set_show_full (self, - priv->show, priv->opacity); -} - -static void -hildon_animation_actor_send_all_messages (HildonAnimationActor *self) -{ - HildonAnimationActorPrivate - *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); - - priv->set_anchor = 1; - priv->set_position = 1; - priv->set_rotation = (1 << HILDON_AA_X_AXIS) | - (1 << HILDON_AA_Y_AXIS) | - (1 << HILDON_AA_Z_AXIS); - priv->set_scale = 1; - priv->set_parent = 1; - priv->set_show = 1; - - hildon_animation_actor_send_pending_messages (self); -} - -/* ------------------------------------------------------------- */ - -/** - * hildon_animation_actor_send_message: - * @self: A #HildonAnimationActor - * @message_type: Message id for the animation actor message. - * @l0: 1st animation actor message parameter. - * @l1: 2nd animation actor message parameter. - * @l2: 3rd animation actor message parameter. - * @l3: 4th animation actor message parameter. - * @l4: 5th animation actor message parameter. - * - * Sends an X11 ClientMessage event to the window manager with - * the specified parameters -- id (@message_type) and data (@l0, - * @l1, @l2, @l3, @l4). - * - * This is an internal utility function that application will - * not need to call directly. - * - * Since: 2.2 - **/ -void -hildon_animation_actor_send_message (HildonAnimationActor *self, - guint32 message_type, - guint32 l0, - guint32 l1, - guint32 l2, - guint32 l3, - guint32 l4) -{ - GtkWidget *widget = GTK_WIDGET (self); - Display *display = GDK_WINDOW_XDISPLAY (widget->window); - Window window = GDK_WINDOW_XID (widget->window); -#if 0 - XClientMessageEvent event; - - event.type = ClientMessage; - event.window = window; - event.message_type = (Atom)message_type; - event.format = 32; - event.data.l[0] = l0; - event.data.l[1] = l1; - event.data.l[2] = l2; - event.data.l[3] = l3; - event.data.l[4] = l4; -#else - XEvent event = { 0 }; - - event.xclient.type = ClientMessage; - event.xclient.window = window; - event.xclient.message_type = (Atom)message_type; - event.xclient.format = 32; - event.xclient.data.l[0] = l0; - event.xclient.data.l[1] = l1; - event.xclient.data.l[2] = l2; - event.xclient.data.l[3] = l3; - event.xclient.data.l[4] = l4; -#endif - -#if 0 - g_debug ("%lu (%lu %lu %lu %lu %lu) -> %lu\n", - message_type, - l0, l1, l2, l3, l4, - window); -#endif - - XSendEvent (display, window, True, - StructureNotifyMask, - (XEvent *)&event); -} - -/** - * hildon_animation_actor_set_show_full: - * @self: A #HildonAnimationActor - * @show: A boolean flag setting the visibility of the animation actor. - * @opacity: Desired opacity setting - * - * Send a message to the window manager setting the visibility of - * the animation actor. This will only affect the visibility of - * the animation actor set by the compositing window manager in its own - * rendering pipeline, after X has drawn the window to the off-screen - * buffer. This setting, naturally, has no effect if the #HildonAnimationActor - * widget is not visible in X11 terms (i.e. realized and mapped). - * - * Furthermore, if a widget is parented, its final visibility will be - * affected by that of the parent window. - * - * The opacity setting ranges from zero (0), being completely transparent - * to 255 (0xff) being fully opaque. - * - * If the animation actor WM-counterpart is not ready, the show message - * will be queued until the WM is ready for it. - * - * Since: 2.2 - **/ -void -hildon_animation_actor_set_show_full (HildonAnimationActor *self, - gint show, - gint opacity) -{ - HildonAnimationActorPrivate - *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); - GtkWidget *widget = GTK_WIDGET (self); - - if (opacity > 255) - opacity = 255; - - if (opacity < 0) - opacity = 0; - - priv->show = show; - priv->opacity = opacity; - priv->set_show = 1; - - if (GTK_WIDGET_MAPPED (widget) && priv->ready) - { - /* Defer show messages until the animation actor is parented - * and the parent window is mapped */ - - if (!priv->parent || !GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent))) - return; - - hildon_animation_actor_send_message (self, - show_atom, - show, opacity, - 0, 0, 0); - priv->set_show = 0; - } -} - -/** - * hildon_animation_actor_set_show: - * @self: A #HildonAnimationActor - * @show: A boolean flag setting the visibility of the animation actor. - * - * This function is a shortcut for hildon_animation_actor_set_show_full(), - * setting the overall actor visibility without changing it's opacity - * setting. - * - * Since: 2.2 - **/ -void -hildon_animation_actor_set_show (HildonAnimationActor *self, - gint show) -{ - HildonAnimationActorPrivate - *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); - - hildon_animation_actor_set_show_full (self, - show, priv->opacity); -} - -/** - * hildon_animation_actor_set_opacity: - * @self: A #HildonAnimationActor - * @opacity: Desired opacity setting - * - * This function is a shortcut for hildon_animation_actor_set_show_full(), - * setting actor opacity without changing it's overall visibility. - * - * See hildon_animation_actor_set_show_full() for description of the range - * of values @opacity argument takes. - * - * Since: 2.2 - **/ -void -hildon_animation_actor_set_opacity (HildonAnimationActor *self, - gint opacity) -{ - HildonAnimationActorPrivate - *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); - - hildon_animation_actor_set_show_full (self, - priv->show, opacity); -} - -/** - * hildon_animation_actor_set_position_full: - * @self: A #HildonAnimationActor - * @x: Desired X coordinate - * @y: Desired Y coordinate - * @depth: Desired window depth (Z coordinate) - * - * Send a message to the window manager setting the position of the - * animation actor. This will set the position of the animation - * actor off-screen bitmap as it is rendered to the screen. The - * position of the actor is relative to the parent window. The actor - * is also subject to the animation effects rendered by the compositing - * window manager on that window (like those by task switcher). - * - * The window depth affects the stacking of animation actors within - * a parent window and, more generally, the stacking of clutter actors - * within a stage/container. The default depth is 0 and a parent - * window's container will have it's window texture stacked at that level. - * The stacking at any depth level is sequential -- animation actor B - * created/parented after animation actor A will obscure the latter - * if they overlap. - * - * Animation actors with non-zero depth settings are subject to scaling as - * per the global scene perspective setup, which limits the depth setting - * as the primary parameter to control the stacking order. Since the - * stacking order follows the parenting order, it may be better to use - * hildon_animation_actor_set_parent() for setting the stacking. - * - * If the animation actor WM-counterpart is not ready, the show message - * will be queued until the WM is ready for it. - * - * Since: 2.2 - **/ -void -hildon_animation_actor_set_position_full (HildonAnimationActor *self, - gint x, - gint y, - gint depth) -{ - HildonAnimationActorPrivate - *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); - GtkWidget *widget = GTK_WIDGET (self); - - priv->position_x = x; - priv->position_y = y; - priv->depth = depth; - priv->set_position = 1; - - if (GTK_WIDGET_MAPPED (widget) && priv->ready) - { - hildon_animation_actor_send_message (self, - position_atom, - x, y, depth, - 0, 0); - priv->set_position = 0; - } -} - -/** - * hildon_animation_actor_set_position: - * @self: A #HildonAnimationActor - * @x: Desired window X coordinate - * @y: Desired window Y coordinate - * - * A shortcut for hildon_animation_actor_set_position_full(), - * changing the window position, but preserving it's depth setting. - * - * Since: 2.2 - **/ -void -hildon_animation_actor_set_position (HildonAnimationActor *self, - gint x, - gint y) -{ - HildonAnimationActorPrivate - *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); - - hildon_animation_actor_set_position_full (self, - x, y, priv->depth); -} - -/** - * hildon_animation_actor_set_depth: - * @self: A #HildonAnimationActor - * @depth: Desired window depth (Z coordinate) - * - * A shortcut for hildon_animation_actor_set_position_full(), - * changing the window depth, but preserving it's position. - * - * Since: 2.2 - **/ -void -hildon_animation_actor_set_depth (HildonAnimationActor *self, - gint depth) -{ - HildonAnimationActorPrivate - *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); - - hildon_animation_actor_set_position_full (self, - priv->position_x, - priv->position_y, - depth); -} - -/** - * hildon_animation_actor_set_scalex: - * @self: A #HildonAnimationActor - * @x_scale: Window's desired scale factor along the X-axis - * @y_scale: Window's desired scale factor along the Y-axis - * - * This function is just like hildon_animation_actor_set_scale(), - * but the scale factors are given as 16-bit fixed-point number. - * - * Since: 2.2 - **/ -void -hildon_animation_actor_set_scalex (HildonAnimationActor *self, - gint32 x_scale, - gint32 y_scale) -{ - HildonAnimationActorPrivate - *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); - GtkWidget *widget = GTK_WIDGET (self); - - priv->scale_x = x_scale; - priv->scale_y = y_scale; - priv->set_scale = 1; - - if (GTK_WIDGET_MAPPED (widget) && priv->ready) - { - hildon_animation_actor_send_message (self, - scale_atom, - x_scale, y_scale, - 0, 0, 0); - priv->set_scale = 0; - } -} - -/** - * hildon_animation_actor_set_scale: - * @self: A #HildonAnimationActor - * @x_scale: Window's desired scale factor along the X-axis - * @y_scale: Window's desired scale factor along the Y-axis - * - * Send a message to the window manager setting the scale factors of the - * animation actor. This will set the scale factors on the animation - * actor off-screen bitmap as it is rendered to the screen. If the - * animation actor is parented to another top-level window, the - * animation effects rendered by the compositing window manager - * on that top-level window (like those by task switcher) will - * also affect the animation actor. - * - * If the animation actor WM-counterpart is not ready, the show message - * will be queued until the WM is ready for it. - * - * Since: 2.2 - **/ -void -hildon_animation_actor_set_scale (HildonAnimationActor *self, - double x_scale, - double y_scale) -{ - gint32 f_x_scale = x_scale * (1 << 16); - gint32 f_y_scale = y_scale * (1 << 16); - - hildon_animation_actor_set_scalex (self, f_x_scale, f_y_scale); -} - -/** - * hildon_animation_actor_set_rotationx: - * @self: A #HildonAnimationActor - * @axis: The rotation axis. - * @degrees: The rotation angle in degrees. - * @x: Center of the rotation, X coordinate. - * @y: Center of the rotation, Y coordinate. - * @z: Center of the rotation, Z coordinate. - * - * This function is just like hildon_animation_actor_set_rotation(), - * but the rotation angle is given as 16-bit fixed-point number. - * - * Since: 2.2 - **/ -void -hildon_animation_actor_set_rotationx (HildonAnimationActor *self, - gint axis, - gint32 degrees, - gint x, - gint y, - gint z) -{ - HildonAnimationActorPrivate - *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); - GtkWidget *widget = GTK_WIDGET (self); - - guint mask = 0; - - switch (axis) - { - case HILDON_AA_X_AXIS: - priv->x_rotation_angle = degrees; - priv->x_rotation_y = y; - priv->x_rotation_z = z; - mask = (1 << HILDON_AA_X_AXIS); - break; - case HILDON_AA_Y_AXIS: - priv->y_rotation_angle = degrees; - priv->y_rotation_x = x; - priv->y_rotation_z = z; - mask = (1 << HILDON_AA_Y_AXIS); - break; - case HILDON_AA_Z_AXIS: - priv->z_rotation_angle = degrees; - priv->z_rotation_x = x; - priv->z_rotation_y = y; - mask = (1 << HILDON_AA_Z_AXIS); - break; - default: - return; - } - - priv->set_rotation |= mask; - - if (GTK_WIDGET_MAPPED (widget) && priv->ready) - { - hildon_animation_actor_send_message (self, - rotation_atom, - axis, degrees, x, y, z); - priv->set_rotation &= ~mask; - } -} - -/** - * hildon_animation_actor_set_rotation: - * @self: A #HildonAnimationActor - * @axis: The rotation axis. - * @degrees: The rotation angle in degrees. - * @x: Center of the rotation, X coordinate. - * @y: Center of the rotation, Y coordinate. - * @z: Center of the rotation, Z coordinate. - * - * Send a message to the window manager setting the animation actor - * rotation around one of the three axes. The rotation center coordinates - * depend on the axis of rotation: - * - * * %HILDON_AA_X_AXIS requires @y and @z coordinates. - * * %HILDON_AA_Y_AXIS requires @x and @z coordinates. - * * %HILDON_AA_Z_AXIS requires @x and @y coordinates. - * - * If the animation actor WM-counterpart is not ready, the show message - * will be queued until the WM is ready for it. - * - * Since: 2.2 - **/ -void -hildon_animation_actor_set_rotation (HildonAnimationActor *self, - gint axis, - double degrees, - gint x, - gint y, - gint z) -{ - gint32 f_degrees = degrees * (1 << 16); - - hildon_animation_actor_set_rotationx (self, axis, f_degrees, x, y, z); -} - -/** - * hildon_animation_actor_set_anchor: - * @self: A #HildonAnimationActor - * @x: The X coordinate of the anchor point. - * @y: The Y coordinate of the anchor point. - * - * Send a message to the window manager setting the anchor point for - * the animation actor. The anchor point is the point to which the - * actor position within its parent it is relative. - * - * If the animation actor WM-counterpart is not ready, the show message - * will be queued until the WM is ready for it. - * - * Since: 2.2 - **/ -void -hildon_animation_actor_set_anchor (HildonAnimationActor *self, - gint x, - gint y) -{ - HildonAnimationActorPrivate - *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); - GtkWidget *widget = GTK_WIDGET (self); - - priv->gravity = 0; - priv->anchor_x = x; - priv->anchor_y = y; - priv->set_anchor = 1; - - if (GTK_WIDGET_MAPPED (widget) && priv->ready) - { - hildon_animation_actor_send_message (self, - anchor_atom, - 0, x, y, - 0, 0); - priv->set_anchor = 0; - } -} - -/** - * hildon_animation_actor_set_anchor_from_gravity: - * @self: A #HildonAnimationActor - * @gravity: The gravity constant. - * - * Send a message to the window manager setting the anchor point for - * the animation actor. The anchor point is the point to which the - * actor position within its parent it is relative. Instead of being - * defined in (x, y)-coordinates, the anchor point is defined in the - * relative "gravity" constant as: - * - * * %HILDON_AA_N_GRAVITY translates to (width / 2, 0) coordinate - * * %HILDON_AA_NE_GRAVITY translates to (width, 0) coordinate - * * %HILDON_AA_E_GRAVITY translates to (width, height / 2) coordinate - * * %HILDON_AA_SE_GRAVITY translates to (width, height) coordinate - * * %HILDON_AA_S_GRAVITY translates to (width / 2, height) coordinate - * * %HILDON_AA_SW_GRAVITY translates to (0, height) coordinate - * * %HILDON_AA_W_GRAVITY translates to (0, height / 2) coordinate - * * %HILDON_AA_NW_GRAVITY translates to (0, 0) coordinate - * * %HILDON_AA_CENTER_GRAVITY translates to (width / 2, height / 2) coordinate - * - * If the animation actor WM-counterpart is not ready, the show message - * will be queued until the WM is ready for it. - * - * Since: 2.2 - **/ -void -hildon_animation_actor_set_anchor_from_gravity (HildonAnimationActor *self, - guint gravity) -{ - HildonAnimationActorPrivate - *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); - GtkWidget *widget = GTK_WIDGET (self); - - priv->gravity = gravity; - priv->set_anchor = 1; - - if (GTK_WIDGET_MAPPED (widget) && priv->ready) - { - hildon_animation_actor_send_message (self, - anchor_atom, - gravity, 0, 0, - 0, 0); - priv->set_anchor = 0; - } -} - -/* - * This callback will be triggered by the parent widget of - * an animation actor when it is mapped. The compositing - * window manager is now ready to parent the animation actor - * into the target parent window. - */ -static gboolean -hildon_animation_actor_parent_map_event (GtkWidget *parent, - GdkEvent *event, - gpointer user_data) -{ - hildon_animation_actor_set_parent (HILDON_ANIMATION_ACTOR (user_data), - GTK_WINDOW (parent)); - return FALSE; -} - -/* - * This callback will be triggered by the widget re-mapping - * itself in case of WM restarting. The point is to push all - * animation actor parameters anew to the WM. - */ -static gboolean -hildon_animation_actor_map_event (GtkWidget *widget, - GdkEvent *event, - gpointer user_data) -{ - HildonAnimationActor - *self = HILDON_ANIMATION_ACTOR (user_data); - HildonAnimationActorPrivate - *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); - - hildon_animation_actor_send_all_messages (self); - - /* Disconnect the "map-event" handler after the "emergency resend all - * actor parameters" drill is over. */ - - if (priv->map_event_cb_id) - { - g_signal_handler_disconnect (self, - priv->map_event_cb_id); - priv->map_event_cb_id = 0; - } - - return FALSE; -} - -/** - * hildon_animation_actor_set_parent: - * @self: A #HildonAnimationActor - * @parent: A #GtkWindow that the actor will be parented to. - * - * Send a message to the window manager setting the parent window - * for the animation actor. Parenting an actor will not affect the - * X window that the HildonAnimationActor represents, but it's off-screen - * bitmap as it is handled by the compositing window manager. - * - * Parenting an animation actor will affect its visibility as set - * by the gtk_widget_show(), gtk_widget_hide() and - * hildon_animation_actor_set_show(). The animation actor will only be - * visible when the top-level window it is parented is visible. - * - * Passing %NULL as a @parent argument will unparent the animation actor. - * This will restore the actor's visibility if it was suppressed by - * being unparented or parented to an unmapped window. - * - * If the animation actor WM-counterpart is not ready, the show message - * will be queued until the WM is ready for it. - * - * Since: 2.2 - **/ -void -hildon_animation_actor_set_parent (HildonAnimationActor *self, - GtkWindow *parent) -{ - HildonAnimationActorPrivate - *priv = HILDON_ANIMATION_ACTOR_GET_PRIVATE (self); - GtkWidget *widget = GTK_WIDGET (self); - - gtk_window_set_transient_for (GTK_WINDOW (self), parent); - - if (priv->parent != parent) - { - /* Setting a new parent */ - - if (priv->parent) - { - if (priv->parent_map_event_cb_id) - g_signal_handler_disconnect (priv->parent, - priv->parent_map_event_cb_id); - - /* Might need a synchronized "parent(0)" or "parent(new parent)" - * message here before we can safely decrease the reference count. */ - - g_object_unref (priv->parent); - } - - priv->parent = parent; - priv->set_parent = 1; - - if (parent != 0) - { - /* The widget is being (re)parented, not unparented. */ - - g_object_ref (parent); - - priv->parent_map_event_cb_id = - g_signal_connect (G_OBJECT (priv->parent), - "map-event", - G_CALLBACK(hildon_animation_actor_parent_map_event), - self); - } - else - { - priv->parent_map_event_cb_id = 0; - } - } - - if (GTK_WIDGET_MAPPED (widget) && priv->ready) - { - Window win = 0; - - /* If the animation actor is being unparented or parented to an - * unmapped widget, force its visibility to "hidden". */ - - if (!priv->parent || !GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent))) - { - hildon_animation_actor_send_message (self, - show_atom, - 0, priv->opacity, - 0, 0, 0); - } - - /* If the widget is being parented (parent != 0), only proceed when - * the parent widget is realized, since we need the X window id of - * the parent. If the widget is being unparented (parent == 0), pass - * the "special" window id of 0 in the message. */ - - if (priv->parent) - { - if (!GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent))) - return; - - GdkWindow *gdk = GTK_WIDGET (parent)->window; - win = GDK_WINDOW_XID (gdk); - } - - hildon_animation_actor_send_message (self, - parent_atom, - win, - 0, 0, 0, 0); - priv->set_parent = 0; - - /* Set animation actor visibility to desired value (in case it was - * forced off when the actor was parented into an unmapped widget). */ - - hildon_animation_actor_send_message (self, - show_atom, - priv->show, priv->opacity, - 0, 0, 0); - priv->set_show = 0; - } -} - diff --git a/src/hildon-animation-actor.h b/src/hildon-animation-actor.h deleted file mode 100644 index a92e5c2..0000000 --- a/src/hildon-animation-actor.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_ANIMATION_ACTOR_H__ -#define __HILDON_ANIMATION_ACTOR_H__ - -#include "hildon-window.h" - -G_BEGIN_DECLS - -#define HILDON_TYPE_ANIMATION_ACTOR \ - (hildon_animation_actor_get_type()) - -#define HILDON_ANIMATION_ACTOR(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - HILDON_TYPE_ANIMATION_ACTOR, \ - HildonAnimationActor)) - -#define HILDON_ANIMATION_ACTOR_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - HILDON_TYPE_ANIMATION_ACTOR, \ - HildonAnimationActorClass)) - -#define HILDON_IS_ANIMATION_ACTOR(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ - HILDON_TYPE_ANIMATION_ACTOR)) - -#define HILDON_IS_ANIMATION_ACTOR_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), \ - HILDON_TYPE_ANIMATION_ACTOR)) - -#define HILDON_ANIMATION_ACTOR_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - HILDON_TYPE_ANIMATION_ACTOR, \ - HildonAnimationActorClass)) - -typedef struct _HildonAnimationActor HildonAnimationActor; -typedef struct _HildonAnimationActorClass HildonAnimationActorClass; - -struct _HildonAnimationActorClass -{ - GtkWindowClass parent_class; - - /* Padding for future extension */ - void (*_hildon_reserved1)(void); - void (*_hildon_reserved2)(void); - void (*_hildon_reserved3)(void); - void (*_hildon_reserved4)(void); -}; - -struct _HildonAnimationActor -{ - GtkWindow parent; -}; - -#define HILDON_AA_X_AXIS 0 -#define HILDON_AA_Y_AXIS 1 -#define HILDON_AA_Z_AXIS 2 - -#define HILDON_AA_N_GRAVITY 1 -#define HILDON_AA_NE_GRAVITY 2 -#define HILDON_AA_E_GRAVITY 3 -#define HILDON_AA_SE_GRAVITY 4 -#define HILDON_AA_S_GRAVITY 5 -#define HILDON_AA_SW_GRAVITY 6 -#define HILDON_AA_W_GRAVITY 7 -#define HILDON_AA_NW_GRAVITY 8 -#define HILDON_AA_CENTER_GRAVITY 9 - -GType -hildon_animation_actor_get_type (void) G_GNUC_CONST; - -GtkWidget* -hildon_animation_actor_new (void); - -void -hildon_animation_actor_send_message (HildonAnimationActor *self, - guint32 message_type, - guint32 l0, - guint32 l1, - guint32 l2, - guint32 l3, - guint32 l4); -void -hildon_animation_actor_set_show_full (HildonAnimationActor *self, - gint show, - gint opacity); -void -hildon_animation_actor_set_show (HildonAnimationActor *self, - gint show); -void -hildon_animation_actor_set_opacity (HildonAnimationActor *self, - gint opacity); -void -hildon_animation_actor_set_position_full (HildonAnimationActor *self, - gint x, - gint y, - gint depth); -void -hildon_animation_actor_set_position (HildonAnimationActor *self, - gint x, - gint y); -void -hildon_animation_actor_set_depth (HildonAnimationActor *self, - gint depth); -void -hildon_animation_actor_set_scalex (HildonAnimationActor *self, - gint32 x_scale, - gint32 y_scale); -void -hildon_animation_actor_set_scale (HildonAnimationActor *self, - double x_scale, - double y_scale); -void -hildon_animation_actor_set_rotationx (HildonAnimationActor *self, - gint axis, - gint32 degrees, - gint x, - gint y, - gint z); -void -hildon_animation_actor_set_rotation (HildonAnimationActor *self, - gint axis, - double degrees, - gint x, - gint y, - gint z); -void -hildon_animation_actor_set_anchor (HildonAnimationActor *self, - gint x, - gint y); -void -hildon_animation_actor_set_anchor_from_gravity (HildonAnimationActor *self, - guint gravity); -void -hildon_animation_actor_set_parent (HildonAnimationActor *self, - GtkWindow *parent); - -G_END_DECLS - -#endif /* __HILDON_ANIMATION_ACTOR_H__ */ diff --git a/src/hildon-app-menu-private.h b/src/hildon-app-menu-private.h deleted file mode 100644 index dc9ba07..0000000 --- a/src/hildon-app-menu-private.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser Public License as published by - * the Free Software Foundation; version 2 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser Public License for more details. - * - */ - -#ifndef __HILDON_APP_MENU_PRIVATE_H__ -#define __HILDON_APP_MENU_PRIVATE_H__ - -G_BEGIN_DECLS - -#define HILDON_APP_MENU_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_APP_MENU, HildonAppMenuPrivate)); - -struct _HildonAppMenuPrivate -{ - GtkBox *filters_hbox; - GtkBox *vbox; - GtkTable *table; - GtkWindow *parent_window; - GdkWindow *transfer_window; - gboolean pressed_outside; - GList *buttons; - GList *filters; - guint columns; - gint width_request; - guint find_intruder_idle_id; - guint hide_idle_id; -}; - -void G_GNUC_INTERNAL -hildon_app_menu_set_parent_window (HildonAppMenu *self, - GtkWindow *parent_window); - -gpointer G_GNUC_INTERNAL -hildon_app_menu_get_parent_window (HildonAppMenu *self); - -G_END_DECLS - -#endif /* __HILDON_APP_MENU_PRIVATE_H__ */ diff --git a/src/hildon-app-menu.c b/src/hildon-app-menu.c deleted file mode 100644 index 5aa56f0..0000000 --- a/src/hildon-app-menu.c +++ /dev/null @@ -1,1123 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser Public License as published by - * the Free Software Foundation; version 2 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser Public License for more details. - * - */ - -/** - * SECTION:hildon-app-menu - * @short_description: Widget representing the application menu in the Hildon framework. - * - * The #HildonAppMenu is a GTK widget which represents an application - * menu in the Hildon framework. - * - * This menu opens from the top of the screen and contains a number of - * entries (#GtkButton) organized in one or two columns, depending on - * the size of the screen (the number of columns changes automatically - * if the screen is resized). Entries are added left to right and top - * to bottom. - * - * Besides that, the #HildonAppMenu can contain a group of filter buttons - * (#GtkToggleButton or #GtkRadioButton). - * - * To use a #HildonAppMenu, add it to a #HildonWindow using - * hildon_window_set_app_menu(). The menu will appear when the user - * presses the window title bar. Alternatively, you can show it by - * hand using hildon_app_menu_popup(). - * - * The menu will be automatically hidden when one of its buttons is - * clicked. Use g_signal_connect_after() when connecting callbacks to - * buttons to make sure that they're called after the menu - * disappears. Alternatively, you can add the button to the menu - * before connecting any callback. - * - * Although implemented with a #GtkWindow, #HildonAppMenu behaves like - * a normal ref-counted widget, so g_object_ref(), g_object_unref(), - * g_object_ref_sink() and friends will behave just like with any - * other non-toplevel widget. - * - * - * Creating a HildonAppMenu - * - * GtkWidget *win; - * HildonAppMenu *menu; - * GtkWidget *button; - * GtkWidget *filter; - * - * win = hildon_stackable_window_new (); - * menu = HILDON_APP_MENU (hildon_app_menu_new ()); - * - * // Create a button and add it to the menu - * button = gtk_button_new_with_label ("Menu command one"); - * g_signal_connect_after (button, "clicked", G_CALLBACK (button_one_clicked), userdata); - * hildon_app_menu_append (menu, GTK_BUTTON (button)); - * - * // Another button - * button = gtk_button_new_with_label ("Menu command two"); - * g_signal_connect_after (button, "clicked", G_CALLBACK (button_two_clicked), userdata); - * hildon_app_menu_append (menu, GTK_BUTTON (button)); - * - * // Create a filter and add it to the menu - * filter = gtk_radio_button_new_with_label (NULL, "Filter one"); - * gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (filter), FALSE); - * g_signal_connect_after (filter, "clicked", G_CALLBACK (filter_one_clicked), userdata); - * hildon_app_menu_add_filter (menu, GTK_BUTTON (filter)); - * - * // Add a new filter - * filter = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (filter), "Filter two"); - * gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (filter), FALSE); - * g_signal_connect_after (filter, "clicked", G_CALLBACK (filter_two_clicked), userdata); - * hildon_app_menu_add_filter (menu, GTK_BUTTON (filter)); - * - * // Show all menu items - * gtk_widget_show_all (GTK_WIDGET (menu)); - * - * // Add the menu to the window - * hildon_window_set_app_menu (HILDON_WINDOW (win), menu); - * - * - * - */ - -#include -#include -#include - -#include "hildon-gtk.h" -#include "hildon-app-menu.h" -#include "hildon-app-menu-private.h" -#include "hildon-window.h" -#include "hildon-banner.h" - -static GdkWindow * -grab_transfer_window_get (GtkWidget *widget); - -static void -hildon_app_menu_repack_items (HildonAppMenu *menu, - gint start_from); - -static void -hildon_app_menu_repack_filters (HildonAppMenu *menu); - -static gboolean -can_activate_accel (GtkWidget *widget, - guint signal_id, - gpointer user_data); - -static void -item_visibility_changed (GtkWidget *item, - GParamSpec *arg1, - HildonAppMenu *menu); - -static void -filter_visibility_changed (GtkWidget *item, - GParamSpec *arg1, - HildonAppMenu *menu); - -static void -remove_item_from_list (GList **list, - gpointer item); - -static void -hildon_app_menu_apply_style (GtkWidget *widget); - -G_DEFINE_TYPE (HildonAppMenu, hildon_app_menu, GTK_TYPE_WINDOW); - -/** - * hildon_app_menu_new: - * - * Creates a new #HildonAppMenu. - * - * Return value: A #HildonAppMenu. - * - * Since: 2.2 - **/ -GtkWidget * -hildon_app_menu_new (void) -{ - GtkWidget *menu = g_object_new (HILDON_TYPE_APP_MENU, NULL); - return menu; -} - -/** - * hildon_app_menu_insert: - * @menu : A #HildonAppMenu - * @item : A #GtkButton to add to the #HildonAppMenu - * @position : The position in the item list where @item is added (from 0 to n-1). - * - * Adds @item to @menu at the position indicated by @position. - * - * Since: 2.2 - */ -void -hildon_app_menu_insert (HildonAppMenu *menu, - GtkButton *item, - gint position) -{ - HildonAppMenuPrivate *priv; - - g_return_if_fail (HILDON_IS_APP_MENU (menu)); - g_return_if_fail (GTK_IS_BUTTON (item)); - - priv = HILDON_APP_MENU_GET_PRIVATE(menu); - - /* Force widget size */ - hildon_gtk_widget_set_theme_size (GTK_WIDGET (item), - HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH); - - /* Add the item to the menu */ - gtk_widget_show (GTK_WIDGET (item)); - g_object_ref_sink (item); - priv->buttons = g_list_insert (priv->buttons, item, position); - hildon_app_menu_repack_items (menu, position); - - /* Enable accelerators */ - g_signal_connect (item, "can-activate-accel", G_CALLBACK (can_activate_accel), NULL); - - /* Close the menu when the button is clicked */ - g_signal_connect_swapped (item, "clicked", G_CALLBACK (gtk_widget_hide), menu); - g_signal_connect (item, "notify::visible", G_CALLBACK (item_visibility_changed), menu); - - /* Remove item from list when it is destroyed */ - g_object_weak_ref (G_OBJECT (item), (GWeakNotify) remove_item_from_list, &(priv->buttons)); -} - -/** - * hildon_app_menu_append: - * @menu : A #HildonAppMenu - * @item : A #GtkButton to add to the #HildonAppMenu - * - * Adds @item to the end of the menu's item list. - * - * Since: 2.2 - */ -void -hildon_app_menu_append (HildonAppMenu *menu, - GtkButton *item) -{ - hildon_app_menu_insert (menu, item, -1); -} - -/** - * hildon_app_menu_prepend: - * @menu : A #HildonAppMenu - * @item : A #GtkButton to add to the #HildonAppMenu - * - * Adds @item to the beginning of the menu's item list. - * - * Since: 2.2 - */ -void -hildon_app_menu_prepend (HildonAppMenu *menu, - GtkButton *item) -{ - hildon_app_menu_insert (menu, item, 0); -} - -/** - * hildon_app_menu_reorder_child: - * @menu : A #HildonAppMenu - * @item : A #GtkButton to move - * @position : The new position to place @item (from 0 to n-1). - * - * Moves a #GtkButton to a new position within #HildonAppMenu. - * - * Since: 2.2 - */ -void -hildon_app_menu_reorder_child (HildonAppMenu *menu, - GtkButton *item, - gint position) -{ - HildonAppMenuPrivate *priv; - gint old_position; - - g_return_if_fail (HILDON_IS_APP_MENU (menu)); - g_return_if_fail (GTK_IS_BUTTON (item)); - g_return_if_fail (position >= 0); - - priv = HILDON_APP_MENU_GET_PRIVATE (menu); - old_position = g_list_index (priv->buttons, item); - - g_return_if_fail (old_position >= 0); - - /* Move the item */ - priv->buttons = g_list_remove (priv->buttons, item); - priv->buttons = g_list_insert (priv->buttons, item, position); - - hildon_app_menu_repack_items (menu, MIN (old_position, position)); -} - -/** - * hildon_app_menu_add_filter: - * @menu : A #HildonAppMenu - * @filter : A #GtkButton to add to the #HildonAppMenu. - * - * Adds the @filter to @menu. - * - * Since: 2.2 - */ -void -hildon_app_menu_add_filter (HildonAppMenu *menu, - GtkButton *filter) -{ - HildonAppMenuPrivate *priv; - - g_return_if_fail (HILDON_IS_APP_MENU (menu)); - g_return_if_fail (GTK_IS_BUTTON (filter)); - - priv = HILDON_APP_MENU_GET_PRIVATE(menu); - - /* Force widget size */ - hildon_gtk_widget_set_theme_size (GTK_WIDGET (filter), - HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH); - - /* Add the filter to the menu */ - gtk_widget_show (GTK_WIDGET (filter)); - g_object_ref_sink (filter); - priv->filters = g_list_append (priv->filters, filter); - hildon_app_menu_repack_filters (menu); - - /* Enable accelerators */ - g_signal_connect (filter, "can-activate-accel", G_CALLBACK (can_activate_accel), NULL); - - /* Close the menu when the button is clicked */ - g_signal_connect_swapped (filter, "clicked", G_CALLBACK (gtk_widget_hide), menu); - g_signal_connect (filter, "notify::visible", G_CALLBACK (filter_visibility_changed), menu); - - /* Remove filter from list when it is destroyed */ - g_object_weak_ref (G_OBJECT (filter), (GWeakNotify) remove_item_from_list, &(priv->filters)); -} - -static void -hildon_app_menu_set_columns (HildonAppMenu *menu, - guint columns) -{ - HildonAppMenuPrivate *priv; - - g_return_if_fail (HILDON_IS_APP_MENU (menu)); - g_return_if_fail (columns > 0); - - priv = HILDON_APP_MENU_GET_PRIVATE (menu); - - if (columns != priv->columns) { - priv->columns = columns; - hildon_app_menu_repack_items (menu, 0); - } -} - -static void -parent_window_topmost_notify (HildonWindow *parent_win, - GParamSpec *arg1, - GtkWidget *menu) -{ - if (!hildon_window_get_is_topmost (parent_win)) - gtk_widget_hide (menu); -} - -static void -parent_window_unmapped (HildonWindow *parent_win, - GtkWidget *menu) -{ - gtk_widget_hide (menu); -} - -void G_GNUC_INTERNAL -hildon_app_menu_set_parent_window (HildonAppMenu *self, - GtkWindow *parent_window) -{ - HildonAppMenuPrivate *priv; - - g_return_if_fail (HILDON_IS_APP_MENU (self)); - g_return_if_fail (parent_window == NULL || GTK_IS_WINDOW (parent_window)); - - priv = HILDON_APP_MENU_GET_PRIVATE(self); - - /* Disconnect old handlers, if any */ - if (priv->parent_window) { - g_signal_handlers_disconnect_by_func (priv->parent_window, parent_window_topmost_notify, self); - g_signal_handlers_disconnect_by_func (priv->parent_window, parent_window_unmapped, self); - } - - /* Connect a new handler */ - if (parent_window) { - g_signal_connect (parent_window, "notify::is-topmost", G_CALLBACK (parent_window_topmost_notify), self); - g_signal_connect (parent_window, "unmap", G_CALLBACK (parent_window_unmapped), self); - } - - priv->parent_window = parent_window; - - if (parent_window == NULL && GTK_WIDGET_VISIBLE (self)) - gtk_widget_hide (GTK_WIDGET (self)); -} - -gpointer G_GNUC_INTERNAL -hildon_app_menu_get_parent_window (HildonAppMenu *self) -{ - HildonAppMenuPrivate *priv; - - g_return_val_if_fail (HILDON_IS_APP_MENU (self), NULL); - - priv = HILDON_APP_MENU_GET_PRIVATE (self); - - return priv->parent_window; -} - -static void -screen_size_changed (GdkScreen *screen, - HildonAppMenu *menu) -{ - hildon_app_menu_apply_style (GTK_WIDGET (menu)); - - if (gdk_screen_get_width (screen) > gdk_screen_get_height (screen)) { - hildon_app_menu_set_columns (menu, 2); - } else { - hildon_app_menu_set_columns (menu, 1); - } -} - -static gboolean -can_activate_accel (GtkWidget *widget, - guint signal_id, - gpointer user_data) -{ - return GTK_WIDGET_VISIBLE (widget); -} - -static void -item_visibility_changed (GtkWidget *item, - GParamSpec *arg1, - HildonAppMenu *menu) -{ - HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE (menu); - - hildon_app_menu_repack_items (menu, g_list_index (priv->buttons, item)); -} - -static void -filter_visibility_changed (GtkWidget *item, - GParamSpec *arg1, - HildonAppMenu *menu) -{ - hildon_app_menu_repack_filters (menu); -} - -static void -remove_item_from_list (GList **list, - gpointer item) -{ - *list = g_list_remove (*list, item); -} - -static void -hildon_app_menu_show_all (GtkWidget *widget) -{ - HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE (widget); - - /* Show children, but not self. */ - g_list_foreach (priv->buttons, (GFunc) gtk_widget_show_all, NULL); - g_list_foreach (priv->filters, (GFunc) gtk_widget_show_all, NULL); -} - - -static void -hildon_app_menu_hide_all (GtkWidget *widget) -{ - HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE (widget); - - /* Hide children, but not self. */ - g_list_foreach (priv->buttons, (GFunc) gtk_widget_hide_all, NULL); - g_list_foreach (priv->filters, (GFunc) gtk_widget_hide_all, NULL); -} - -/* - * There's a race condition that can freeze the UI if a dialog appears - * between a HildonAppMenu and its parent window, see NB#100468 - */ -static gboolean -hildon_app_menu_find_intruder (gpointer data) -{ - GtkWidget *widget = GTK_WIDGET (data); - HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE (widget); - - priv->find_intruder_idle_id = 0; - - /* If there's a window between the menu and its parent window, hide the menu */ - if (priv->parent_window) { - gboolean intruder_found = FALSE; - GdkScreen *screen = gtk_widget_get_screen (widget); - GList *stack = gdk_screen_get_window_stack (screen); - GList *parent_pos = g_list_find (stack, GTK_WIDGET (priv->parent_window)->window); - GList *toplevels = gtk_window_list_toplevels (); - GList *i; - - for (i = toplevels; i != NULL && !intruder_found; i = i->next) { - if (i->data != widget && i->data != priv->parent_window) { - if (g_list_find (parent_pos, GTK_WIDGET (i->data)->window)) { - /* HildonBanners are not closed automatically when - * a new window appears, so we must close them by - * hand to make the AppMenu work as expected. - * Yes, this is a hack. See NB#111027 */ - if (HILDON_IS_BANNER (i->data)) { - gtk_widget_hide (i->data); - } else { - intruder_found = TRUE; - } - } - } - } - - g_list_foreach (stack, (GFunc) g_object_unref, NULL); - g_list_free (stack); - g_list_free (toplevels); - - if (intruder_found) - gtk_widget_hide (widget); - } - - return FALSE; -} - -static void -hildon_app_menu_map (GtkWidget *widget) -{ - HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE(widget); - - GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->map (widget); - - /* Grab pointer and keyboard */ - if (priv->transfer_window == NULL) { - gboolean has_grab = FALSE; - - priv->transfer_window = grab_transfer_window_get (widget); - - if (gdk_pointer_grab (priv->transfer_window, TRUE, - GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | - GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | - GDK_POINTER_MOTION_MASK, NULL, NULL, - GDK_CURRENT_TIME) == GDK_GRAB_SUCCESS) { - if (gdk_keyboard_grab (priv->transfer_window, TRUE, - GDK_CURRENT_TIME) == GDK_GRAB_SUCCESS) { - has_grab = TRUE; - } else { - gdk_display_pointer_ungrab (gtk_widget_get_display (widget), - GDK_CURRENT_TIME); - } - } - - if (has_grab) { - gtk_grab_add (widget); - } else { - gdk_window_destroy (priv->transfer_window); - priv->transfer_window = NULL; - } - } - - /* Make the menu temporary when it's mapped, so it's closed if a - * new window appears */ - gtk_window_set_is_temporary (GTK_WINDOW (widget), TRUE); - - priv->find_intruder_idle_id = gdk_threads_add_idle (hildon_app_menu_find_intruder, widget); -} - -static void -hildon_app_menu_unmap (GtkWidget *widget) -{ - HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE(widget); - - /* Remove the grab */ - if (priv->transfer_window != NULL) { - gdk_display_pointer_ungrab (gtk_widget_get_display (widget), - GDK_CURRENT_TIME); - gtk_grab_remove (widget); - - gdk_window_destroy (priv->transfer_window); - priv->transfer_window = NULL; - } - - GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->unmap (widget); - - gtk_window_set_is_temporary (GTK_WINDOW (widget), FALSE); -} - -static void -hildon_app_menu_grab_notify (GtkWidget *widget, - gboolean was_grabbed) -{ - if (GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->grab_notify) - GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->grab_notify (widget, was_grabbed); - - if (!was_grabbed && GTK_WIDGET_VISIBLE (widget)) - gtk_widget_hide (widget); -} - -static gboolean -hildon_app_menu_hide_idle (gpointer widget) -{ - HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE (widget); - gtk_widget_hide (GTK_WIDGET (widget)); - priv->hide_idle_id = 0; - return FALSE; -} - -/* Send keyboard accelerators to the parent window, if necessary. - * This code is heavily based on gtk_menu_key_press () - */ -static gboolean -hildon_app_menu_key_press (GtkWidget *widget, - GdkEventKey *event) -{ - GtkWindow *parent_window; - HildonAppMenuPrivate *priv; - - g_return_val_if_fail (HILDON_IS_APP_MENU (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); - - if (GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->key_press_event (widget, event)) - return TRUE; - - priv = HILDON_APP_MENU_GET_PRIVATE (widget); - parent_window = priv->parent_window; - - if (parent_window) { - guint accel_key, accel_mods; - GdkModifierType consumed_modifiers; - GdkDisplay *display; - GSList *accel_groups; - GSList *list; - - display = gtk_widget_get_display (widget); - - /* Figure out what modifiers went into determining the key symbol */ - gdk_keymap_translate_keyboard_state (gdk_keymap_get_for_display (display), - event->hardware_keycode, event->state, event->group, - NULL, NULL, NULL, &consumed_modifiers); - - accel_key = gdk_keyval_to_lower (event->keyval); - accel_mods = event->state & gtk_accelerator_get_default_mod_mask () & ~consumed_modifiers; - - /* If lowercasing affects the keysym, then we need to include SHIFT in the modifiers, - * We re-upper case when we match against the keyval, but display and save in caseless form. - */ - if (accel_key != event->keyval) - accel_mods |= GDK_SHIFT_MASK; - - accel_groups = gtk_accel_groups_from_object (G_OBJECT (parent_window)); - - for (list = accel_groups; list; list = list->next) { - GtkAccelGroup *accel_group = list->data; - - if (gtk_accel_group_query (accel_group, accel_key, accel_mods, NULL)) { - gtk_window_activate_key (parent_window, event); - priv->hide_idle_id = gdk_threads_add_idle (hildon_app_menu_hide_idle, widget); - break; - } - } - } - - return TRUE; -} - -static gboolean -hildon_app_menu_button_press (GtkWidget *widget, - GdkEventButton *event) -{ - int x, y; - HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE(widget); - - gdk_window_get_position (widget->window, &x, &y); - - /* Whether the button has been pressed outside the widget */ - priv->pressed_outside = (event->x_root < x || event->x_root > x + widget->allocation.width || - event->y_root < y || event->y_root > y + widget->allocation.height); - - if (GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->button_press_event) { - return GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->button_press_event (widget, event); - } else { - return FALSE; - } -} - -static gboolean -hildon_app_menu_button_release (GtkWidget *widget, - GdkEventButton *event) -{ - HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE(widget); - - if (priv->pressed_outside) { - int x, y; - gboolean released_outside; - - gdk_window_get_position (widget->window, &x, &y); - - /* Whether the button has been released outside the widget */ - released_outside = (event->x_root < x || event->x_root > x + widget->allocation.width || - event->y_root < y || event->y_root > y + widget->allocation.height); - - if (released_outside) { - gtk_widget_hide (widget); - } - - priv->pressed_outside = FALSE; /* Always reset pressed_outside to FALSE */ - } - - if (GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->button_release_event) { - return GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->button_release_event (widget, event); - } else { - return FALSE; - } -} - -static gboolean -hildon_app_menu_delete_event_handler (GtkWidget *widget, - GdkEventAny *event) -{ - /* Hide the menu if it receives a delete-event, but don't destroy it */ - gtk_widget_hide (widget); - return TRUE; -} - -/* Grab transfer window (based on the one from GtkMenu) */ -static GdkWindow * -grab_transfer_window_get (GtkWidget *widget) -{ - GdkWindow *window; - GdkWindowAttr attributes; - gint attributes_mask; - - attributes.x = 0; - attributes.y = 0; - attributes.width = 10; - attributes.height = 10; - attributes.window_type = GDK_WINDOW_TEMP; - attributes.wclass = GDK_INPUT_ONLY; - attributes.override_redirect = TRUE; - attributes.event_mask = 0; - - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR; - - window = gdk_window_new (gtk_widget_get_root_window (widget), - &attributes, attributes_mask); - gdk_window_set_user_data (window, widget); - - gdk_window_show (window); - - return window; -} - -static void -hildon_app_menu_size_request (GtkWidget *widget, - GtkRequisition *requisition) -{ - HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE (widget); - - GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->size_request (widget, requisition); - - requisition->width = priv->width_request; -} - -static void -hildon_app_menu_realize (GtkWidget *widget) -{ - Atom property, window_type; - Display *xdisplay; - GdkDisplay *gdkdisplay; - GdkScreen *screen; - - GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->realize (widget); - - gdk_window_set_decorations (widget->window, GDK_DECOR_BORDER); - - gdkdisplay = gdk_drawable_get_display (widget->window); - xdisplay = GDK_WINDOW_XDISPLAY (widget->window); - - property = gdk_x11_get_xatom_by_name_for_display (gdkdisplay, "_NET_WM_WINDOW_TYPE"); - window_type = XInternAtom (xdisplay, "_HILDON_WM_WINDOW_TYPE_APP_MENU", False); - XChangeProperty (xdisplay, GDK_WINDOW_XID (widget->window), property, - XA_ATOM, 32, PropModeReplace, (guchar *) &window_type, 1); - - /* Detect any screen changes */ - screen = gtk_widget_get_screen (widget); - g_signal_connect (screen, "size-changed", G_CALLBACK (screen_size_changed), widget); - - /* Force menu to set the initial layout */ - screen_size_changed (screen, HILDON_APP_MENU (widget)); -} - -static void -hildon_app_menu_unrealize (GtkWidget *widget) -{ - GdkScreen *screen = gtk_widget_get_screen (widget); - /* Disconnect "size-changed" signal handler */ - g_signal_handlers_disconnect_by_func (screen, G_CALLBACK (screen_size_changed), widget); - - GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->unrealize (widget); -} - -static void -hildon_app_menu_apply_style (GtkWidget *widget) -{ - GdkScreen *screen; - guint horizontal_spacing, vertical_spacing, filter_vertical_spacing; - guint inner_border, external_border; - HildonAppMenuPrivate *priv; - - priv = HILDON_APP_MENU_GET_PRIVATE (widget); - - gtk_widget_style_get (widget, - "horizontal-spacing", &horizontal_spacing, - "vertical-spacing", &vertical_spacing, - "filter-vertical-spacing", &filter_vertical_spacing, - "inner-border", &inner_border, - "external-border", &external_border, - NULL); - - /* Set spacings */ - gtk_table_set_row_spacings (priv->table, vertical_spacing); - gtk_table_set_col_spacings (priv->table, horizontal_spacing); - gtk_box_set_spacing (priv->vbox, filter_vertical_spacing); - - /* Set inner border */ - gtk_container_set_border_width (GTK_CONTAINER (widget), inner_border); - - /* Compute width request */ - screen = gtk_widget_get_screen (widget); - if (gdk_screen_get_width (screen) < gdk_screen_get_height (screen)) { - external_border = 0; - } - priv->width_request = gdk_screen_get_width (screen) - external_border * 2; - gtk_window_move (GTK_WINDOW (widget), external_border, 0); - gtk_widget_queue_resize (widget); -} - -static void -hildon_app_menu_style_set (GtkWidget *widget, - GtkStyle *previous_style) -{ - if (GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->style_set) - GTK_WIDGET_CLASS (hildon_app_menu_parent_class)->style_set (widget, previous_style); - - hildon_app_menu_apply_style (widget); -} - -static void -hildon_app_menu_repack_filters (HildonAppMenu *menu) -{ - HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE(menu); - GList *iter; - - for (iter = priv->filters; iter != NULL; iter = iter->next) { - GtkWidget *filter = GTK_WIDGET (iter->data); - GtkWidget *parent = gtk_widget_get_parent (filter); - if (parent) { - g_object_ref (filter); - gtk_container_remove (GTK_CONTAINER (parent), filter); - } - } - - for (iter = priv->filters; iter != NULL; iter = iter->next) { - GtkWidget *filter = GTK_WIDGET (iter->data); - if (GTK_WIDGET_VISIBLE (filter)) { - gtk_box_pack_start (GTK_BOX (priv->filters_hbox), filter, TRUE, TRUE, 0); - g_object_unref (filter); - /* GtkButton must be realized for accelerators to work */ - gtk_widget_realize (filter); - } - } -} - -/* - * When items displayed in the menu change (e.g, a new item is added, - * an item is hidden or the list is reordered), the layout must be - * updated. To do this we repack all items starting from a given one. - */ -static void -hildon_app_menu_repack_items (HildonAppMenu *menu, - gint start_from) -{ - HildonAppMenuPrivate *priv; - gint row, col; - GList *iter; - - priv = HILDON_APP_MENU_GET_PRIVATE(menu); - - /* Remove buttons from their parent */ - if (start_from != -1) { - for (iter = g_list_nth (priv->buttons, start_from); iter != NULL; iter = iter->next) { - GtkWidget *item = GTK_WIDGET (iter->data); - GtkWidget *parent = gtk_widget_get_parent (item); - if (parent) { - g_object_ref (item); - gtk_container_remove (GTK_CONTAINER (parent), item); - } - } - - /* If items have been removed, recalculate the size of the menu */ - gtk_window_resize (GTK_WINDOW (menu), 1, 1); - } - - /* Add buttons */ - row = col = 0; - for (iter = priv->buttons; iter != NULL; iter = iter->next) { - GtkWidget *item = GTK_WIDGET (iter->data); - if (GTK_WIDGET_VISIBLE (item)) { - /* Don't add an item to the table if it's already there */ - if (gtk_widget_get_parent (item) == NULL) { - gtk_table_attach_defaults (priv->table, item, col, col + 1, row, row + 1); - g_object_unref (item); - /* GtkButton must be realized for accelerators to work */ - gtk_widget_realize (item); - } - if (++col == priv->columns) { - col = 0; - row++; - } - } - } - - /* The number of rows/columns might have changed, so we have to - * resize the table */ - if (col == 0) { - gtk_table_resize (priv->table, MAX (row, 1), priv->columns); - } else { - gtk_table_resize (priv->table, row + 1, priv->columns); - } -} - -/** - * hildon_app_menu_popup: - * @menu: a #HildonAppMenu - * @parent_window: a #GtkWindow - * - * Displays a menu on top of a window and makes it available for - * selection. - * - * Since: 2.2 - **/ -void -hildon_app_menu_popup (HildonAppMenu *menu, - GtkWindow *parent_window) -{ - HildonAppMenuPrivate *priv; - gboolean show_menu = FALSE; - GList *i; - - g_return_if_fail (HILDON_IS_APP_MENU (menu)); - g_return_if_fail (GTK_IS_WINDOW (parent_window)); - - priv = HILDON_APP_MENU_GET_PRIVATE (menu); - - /* Don't show menu if it doesn't contain visible items */ - for (i = priv->buttons; i && !show_menu; i = i->next) - show_menu = GTK_WIDGET_VISIBLE (i->data); - - for (i = priv->filters; i && !show_menu; i = i->next) - show_menu = GTK_WIDGET_VISIBLE (i->data); - - if (show_menu) { - hildon_app_menu_set_parent_window (menu, parent_window); - gtk_widget_show (GTK_WIDGET (menu)); - } - -} - -/** - * hildon_app_menu_get_items: - * @menu: a #HildonAppMenu - * - * Returns a list of all items (regular items, not filters) contained - * in @menu. - * - * Returns: a newly-allocated list containing the items in @menu - * - * Since: 2.2 - **/ -GList * -hildon_app_menu_get_items (HildonAppMenu *menu) -{ - HildonAppMenuPrivate *priv; - - g_return_val_if_fail (HILDON_IS_APP_MENU (menu), NULL); - - priv = HILDON_APP_MENU_GET_PRIVATE (menu); - - return g_list_copy (priv->buttons); -} - -/** - * hildon_app_menu_get_filters: - * @menu: a #HildonAppMenu - * - * Returns a list of all filters contained in @menu. - * - * Returns: a newly-allocated list containing the filters in @menu - * - * Since: 2.2 - **/ -GList * -hildon_app_menu_get_filters (HildonAppMenu *menu) -{ - HildonAppMenuPrivate *priv; - - g_return_val_if_fail (HILDON_IS_APP_MENU (menu), NULL); - - priv = HILDON_APP_MENU_GET_PRIVATE (menu); - - return g_list_copy (priv->filters); -} - -static void -hildon_app_menu_init (HildonAppMenu *menu) -{ - GtkWidget *alignment; - HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE(menu); - - /* Initialize private variables */ - priv->parent_window = NULL; - priv->transfer_window = NULL; - priv->pressed_outside = FALSE; - priv->buttons = NULL; - priv->filters = NULL; - priv->columns = 2; - priv->width_request = -1; - priv->find_intruder_idle_id = 0; - priv->hide_idle_id = 0; - - /* Create boxes and tables */ - priv->filters_hbox = GTK_BOX (gtk_hbox_new (TRUE, 0)); - priv->vbox = GTK_BOX (gtk_vbox_new (FALSE, 0)); - priv->table = GTK_TABLE (gtk_table_new (1, priv->columns, TRUE)); - - /* Align the filters to the center */ - alignment = gtk_alignment_new (0.5, 0.5, 0, 0); - gtk_container_add (GTK_CONTAINER (alignment), GTK_WIDGET (priv->filters_hbox)); - - /* Pack everything */ - gtk_container_add (GTK_CONTAINER (menu), GTK_WIDGET (priv->vbox)); - gtk_box_pack_start (priv->vbox, alignment, TRUE, TRUE, 0); - gtk_box_pack_start (priv->vbox, GTK_WIDGET (priv->table), TRUE, TRUE, 0); - - /* Make menu a modal window */ - gtk_window_set_modal (GTK_WINDOW (menu), TRUE); - - /* This should be treated like a normal, ref-counted widget */ - g_object_force_floating (G_OBJECT (menu)); - GTK_WINDOW (menu)->has_user_ref_count = FALSE; - - gtk_widget_show_all (GTK_WIDGET (priv->vbox)); -} - -static void -hildon_app_menu_finalize (GObject *object) -{ - HildonAppMenuPrivate *priv = HILDON_APP_MENU_GET_PRIVATE(object); - - if (priv->find_intruder_idle_id) { - g_source_remove (priv->find_intruder_idle_id); - priv->find_intruder_idle_id = 0; - } - - if (priv->hide_idle_id) { - g_source_remove (priv->hide_idle_id); - priv->hide_idle_id = 0; - } - - if (priv->parent_window) { - g_signal_handlers_disconnect_by_func (priv->parent_window, parent_window_topmost_notify, object); - g_signal_handlers_disconnect_by_func (priv->parent_window, parent_window_unmapped, object); - } - - if (priv->transfer_window) - gdk_window_destroy (priv->transfer_window); - - g_list_foreach (priv->buttons, (GFunc) g_object_unref, NULL); - g_list_foreach (priv->filters, (GFunc) g_object_unref, NULL); - - g_list_free (priv->buttons); - g_list_free (priv->filters); - - g_signal_handlers_destroy (object); - G_OBJECT_CLASS (hildon_app_menu_parent_class)->finalize (object); -} - -static void -hildon_app_menu_class_init (HildonAppMenuClass *klass) -{ - GObjectClass *gobject_class = (GObjectClass *)klass; - GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; - - gobject_class->finalize = hildon_app_menu_finalize; - widget_class->show_all = hildon_app_menu_show_all; - widget_class->hide_all = hildon_app_menu_hide_all; - widget_class->map = hildon_app_menu_map; - widget_class->unmap = hildon_app_menu_unmap; - widget_class->realize = hildon_app_menu_realize; - widget_class->unrealize = hildon_app_menu_unrealize; - widget_class->grab_notify = hildon_app_menu_grab_notify; - widget_class->key_press_event = hildon_app_menu_key_press; - widget_class->button_press_event = hildon_app_menu_button_press; - widget_class->button_release_event = hildon_app_menu_button_release; - widget_class->style_set = hildon_app_menu_style_set; - widget_class->delete_event = hildon_app_menu_delete_event_handler; - widget_class->size_request = hildon_app_menu_size_request; - - g_type_class_add_private (klass, sizeof (HildonAppMenuPrivate)); - - gtk_widget_class_install_style_property ( - widget_class, - g_param_spec_uint ( - "horizontal-spacing", - "Horizontal spacing on menu items", - "Horizontal spacing between each menu item. Does not apply to filter buttons.", - 0, G_MAXUINT, 16, - G_PARAM_READABLE)); - - gtk_widget_class_install_style_property ( - widget_class, - g_param_spec_uint ( - "vertical-spacing", - "Vertical spacing on menu items", - "Vertical spacing between each menu item. Does not apply to filter buttons.", - 0, G_MAXUINT, 16, - G_PARAM_READABLE)); - - gtk_widget_class_install_style_property ( - widget_class, - g_param_spec_uint ( - "filter-vertical-spacing", - "Vertical spacing between filters and menu items", - "Vertical spacing between filters and menu items", - 0, G_MAXUINT, 8, - G_PARAM_READABLE)); - - gtk_widget_class_install_style_property ( - widget_class, - g_param_spec_uint ( - "inner-border", - "Border between menu edges and buttons", - "Border between menu edges and buttons", - 0, G_MAXUINT, 16, - G_PARAM_READABLE)); - - gtk_widget_class_install_style_property ( - widget_class, - g_param_spec_uint ( - "external-border", - "Border between menu and screen edges (in horizontal mode)", - "Border between the right and left edges of the menu and " - "the screen edges (in horizontal mode)", - 0, G_MAXUINT, 50, - G_PARAM_READABLE)); -} diff --git a/src/hildon-app-menu.h b/src/hildon-app-menu.h deleted file mode 100644 index f0a20bb..0000000 --- a/src/hildon-app-menu.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser Public License as published by - * the Free Software Foundation; version 2 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser Public License for more details. - * - */ - -#ifndef __HILDON_APP_MENU_H__ -#define __HILDON_APP_MENU_H__ - -#include - -G_BEGIN_DECLS - -#define HILDON_TYPE_APP_MENU \ - (hildon_app_menu_get_type()) - -#define HILDON_APP_MENU(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - HILDON_TYPE_APP_MENU, HildonAppMenu)) - -#define HILDON_APP_MENU_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - HILDON_TYPE_APP_MENU, HildonAppMenuClass)) - -#define HILDON_IS_APP_MENU(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_APP_MENU)) - -#define HILDON_IS_APP_MENU_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_APP_MENU)) - -#define HILDON_APP_MENU_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - HILDON_TYPE_APP_MENU, HildonAppMenuClass)) - -typedef struct _HildonAppMenu HildonAppMenu; - -typedef struct _HildonAppMenuClass HildonAppMenuClass; - -typedef struct _HildonAppMenuPrivate HildonAppMenuPrivate; - -struct _HildonAppMenuClass -{ - GtkWindowClass parent_class; -}; - -struct _HildonAppMenu -{ - GtkWindow parent; -}; - -GType -hildon_app_menu_get_type (void) G_GNUC_CONST; - -GtkWidget * -hildon_app_menu_new (void); - -void -hildon_app_menu_append (HildonAppMenu *menu, - GtkButton *item); - -void -hildon_app_menu_prepend (HildonAppMenu *menu, - GtkButton *item); - -void -hildon_app_menu_insert (HildonAppMenu *menu, - GtkButton *item, - gint position); - -void -hildon_app_menu_reorder_child (HildonAppMenu *menu, - GtkButton *item, - gint position); - -void -hildon_app_menu_add_filter (HildonAppMenu *menu, - GtkButton *filter); - -void -hildon_app_menu_popup (HildonAppMenu *menu, - GtkWindow *parent_window); - -GList * -hildon_app_menu_get_items (HildonAppMenu *menu); - -GList * -hildon_app_menu_get_filters (HildonAppMenu *menu); - -G_END_DECLS - -#endif /* __HILDON_APP_MENU_H__ */ diff --git a/src/hildon-banner-private.h b/src/hildon-banner-private.h deleted file mode 100644 index 8f4f581..0000000 --- a/src/hildon-banner-private.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_PRIVATE_H__ -#define __HILDON_BANNER_PRIVATE_H__ - -G_BEGIN_DECLS - -typedef struct _HildonBannerPrivate HildonBannerPrivate; - -#define HILDON_BANNER_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_BANNER, HildonBannerPrivate)); - -struct _HildonBannerPrivate -{ - GtkWidget *main_item; - GtkWidget *label; - GtkWidget *layout; - guint timeout_id; - guint is_timed : 1, has_been_wrapped : 1, has_been_truncated : 1; - guint timeout; - GtkWindow *parent; -}; - -/* For internal use of hildon libraries only */ -void G_GNUC_INTERNAL -hildon_gtk_label_set_text_n_lines (GtkLabel *label, - const gchar *text, - gint max_lines); - -G_END_DECLS - -#endif /* __HILDON_BANNER_PRIVATE_H__ */ diff --git a/src/hildon-banner.c b/src/hildon-banner.c deleted file mode 100644 index 0d65edc..0000000 --- a/src/hildon-banner.c +++ /dev/null @@ -1,1238 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006, 2007 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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-banner - * @short_description: A widget used to display timed notifications. - * - * #HildonBanner is a small, pop-up window that can be used to display - * a short, timed notification or information to the user. It can - * communicate that a task has been finished or that the application - * state has changed. - * - * Hildon provides convenient funtions to create and show banners. To - * create and show information banners you can use - * hildon_banner_show_information(), hildon_banner_show_informationf() - * or hildon_banner_show_information_with_markup(). - * - * Two more kinds of banners are maintained for backward compatibility - * but are no longer recommended in Hildon 2.2. These are the animated - * banner (created with hildon_banner_show_animation()) and the - * progress banner (created with hildon_banner_show_progress()). See - * hildon_gtk_window_set_progress_indicator() for the preferred way of - * showing progress notifications in Hildon 2.2. - * - * Information banners dissapear automatically after a certain - * period. This is stored in the #HildonBanner:timeout property (in - * miliseconds), and can be changed using hildon_banner_set_timeout(). - * - * Note that #HildonBanners should only be used to display - * non-critical pieces of information. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#undef HILDON_DISABLE_DEPRECATED - -#include "hildon-banner.h" -#include "hildon-banner-private.h" -#include "hildon-defines.h" - -/* position relative to the screen */ - -#define HILDON_BANNER_WINDOW_X 0 - -#define HILDON_BANNER_WINDOW_Y HILDON_WINDOW_TITLEBAR_HEIGHT - -/* max widths */ - -#define HILDON_BANNER_PROGRESS_WIDTH 104 - -#define HILDON_BANNER_LABEL_MAX_TIMED \ - (800 - ((HILDON_MARGIN_TRIPLE) * 2)) - -#define HILDON_BANNER_LABEL_MAX_PROGRESS 375 /*265*/ - -/* default timeout */ - -#define HILDON_BANNER_DEFAULT_TIMEOUT 3000 - -/* default icons */ - -#define HILDON_BANNER_DEFAULT_PROGRESS_ANIMATION "indicator_update" - -/* animation related stuff */ - -#define HILDON_BANNER_ANIMATION_FRAMERATE ((float)1000/150) - -#define HILDON_BANNER_ANIMATION_TMPL "indicator_update%d" - -#define HILDON_BANNER_ANIMATION_NFRAMES 8 - -enum -{ - PROP_0, - PROP_PARENT_WINDOW, - PROP_IS_TIMED, - PROP_TIMEOUT -}; - -static GtkWidget* global_timed_banner = NULL; - -static GQuark -hildon_banner_timed_quark (void); - -static void -hildon_banner_bind_style (HildonBanner *self, - const gchar *name); - -static gboolean -hildon_banner_timeout (gpointer data); - -static gboolean -hildon_banner_clear_timeout (HildonBanner *self); - -static void -hildon_banner_ensure_timeout (HildonBanner *self); - -static void -hildon_banner_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); - -static void -hildon_banner_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); - -static void -hildon_banner_destroy (GtkObject *object); - -static GObject* -hildon_banner_real_get_instance (GObject *window, - gboolean timed); - -static GObject* -hildon_banner_constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params); - -static void -hildon_banner_finalize (GObject *object); - -static gboolean -hildon_banner_button_press_event (GtkWidget* widget, - GdkEventButton* event); - -static gboolean -hildon_banner_map_event (GtkWidget *widget, - GdkEventAny *event); -static void -hildon_banner_reset_wrap_state (HildonBanner *banner); - -static void -force_to_wrap_truncated (HildonBanner *banner); - -static void -hildon_banner_check_position (GtkWidget *widget); - -static void -hildon_banner_realize (GtkWidget *widget); - -static void -hildon_banner_class_init (HildonBannerClass *klass); - -static void -hildon_banner_init (HildonBanner *self); - -static void -hildon_banner_ensure_child (HildonBanner *self, - GtkWidget *user_widget, - guint pos, - GType type, - const gchar *first_property, - ...); - -static HildonBanner* -hildon_banner_get_instance_for_widget (GtkWidget *widget, - gboolean timed); - -G_DEFINE_TYPE (HildonBanner, hildon_banner, GTK_TYPE_WINDOW) - -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 widget and label name to make the correct rc-style attached into them */ -static void -hildon_banner_bind_style (HildonBanner *self, - const gchar *name_sufix) -{ - HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self); - gchar *name; - - g_assert (priv); - - name = g_strconcat ("HildonBannerLabel-", name_sufix, NULL); - gtk_widget_set_name (priv->label, name); - g_free (name); - - name = g_strconcat ("HildonBanner-", name_sufix, NULL); - gtk_widget_set_name (GTK_WIDGET (self), name); - g_free (name); -} - -/* In timeout function we automatically destroy timed banners */ -static gboolean -simulate_close (GtkWidget* widget) -{ - gboolean result = FALSE; - - /* 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)) - { - GdkEvent *event = gdk_event_new (GDK_DELETE); - event->any.window = g_object_ref (widget->window); - event->any.send_event = FALSE; - result = gtk_widget_event (widget, event); - gdk_event_free (event); - } - - return result; -} - -static gboolean -hildon_banner_timeout (gpointer data) -{ - GtkWidget *widget; - gboolean continue_timeout = FALSE; - - GDK_THREADS_ENTER (); - - g_assert (HILDON_IS_BANNER (data)); - - widget = GTK_WIDGET (data); - g_object_ref (widget); - - continue_timeout = simulate_close (widget); - - if (! continue_timeout) { - HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (data); - priv->timeout_id = 0; - gtk_widget_destroy (widget); - } - - g_object_unref (widget); - - GDK_THREADS_LEAVE (); - - return continue_timeout; -} - -static gboolean -hildon_banner_clear_timeout (HildonBanner *self) -{ - HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self); - g_assert (priv); - - if (priv->timeout_id != 0) { - g_source_remove (priv->timeout_id); - priv->timeout_id = 0; - return TRUE; - } - - return FALSE; -} - -static void -hildon_banner_ensure_timeout (HildonBanner *self) -{ - HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self); - g_assert (priv); - - if (priv->timeout_id == 0 && priv->is_timed && priv->timeout > 0) - priv->timeout_id = g_timeout_add (priv->timeout, - hildon_banner_timeout, self); -} - -static void -hildon_banner_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GtkWidget *window; - HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object); - g_assert (priv); - - switch (prop_id) { - - case PROP_TIMEOUT: - priv->timeout = g_value_get_uint (value); - break; - - case PROP_IS_TIMED: - priv->is_timed = g_value_get_boolean (value); - break; - - case PROP_PARENT_WINDOW: - window = g_value_get_object (value); - if (priv->parent) { - g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent); - } - - gtk_window_set_transient_for (GTK_WINDOW (object), (GtkWindow *) window); - priv->parent = (GtkWindow *) window; - - if (window) { - gtk_window_set_destroy_with_parent (GTK_WINDOW (object), TRUE); - g_object_add_weak_pointer(G_OBJECT (window), (gpointer) &priv->parent); - } - - 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) -{ - HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object); - g_assert (priv); - - switch (prop_id) - { - case PROP_TIMEOUT: - g_value_set_uint (value, priv->timeout); - break; - - case PROP_IS_TIMED: - g_value_set_boolean (value, 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) -{ - HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object); - g_assert (priv); - - HildonBanner *self; - GObject *parent_window = (GObject *) priv->parent; - - 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 (priv->is_timed && parent_window != 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) -{ - 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); - hildon_banner_reset_wrap_state (HILDON_BANNER (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; -} - -static void -hildon_banner_finalize (GObject *object) -{ - HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (object); - - if (priv->parent) { - g_object_remove_weak_pointer(G_OBJECT (priv->parent), (gpointer) &priv->parent); - } - - G_OBJECT_CLASS (hildon_banner_parent_class)->finalize (object); -} - -static gboolean -hildon_banner_button_press_event (GtkWidget* widget, - GdkEventButton* event) -{ - gboolean result = simulate_close (widget); - - if (!result) { - /* signal emission not stopped - basically behave like - * gtk_main_do_event() for a delete event, but just hide the - * banner instead of destroying it, as it is already meant to - * be destroyed by hildon_banner_timeout() (if it's timed) or - * the application (if it's not). */ - gtk_widget_hide (widget); - } - - return result; -} - -#if defined(MAEMO_GTK) -static void -hildon_banner_map (GtkWidget *widget) -{ - if (GTK_WIDGET_CLASS (hildon_banner_parent_class)->map) { - /* Make the banner temporary _before_ mapping it, to avoid closing - * other temporary windows */ - gtk_window_set_is_temporary (GTK_WINDOW (widget), TRUE); - - GTK_WIDGET_CLASS (hildon_banner_parent_class)->map (widget); - - /* Make the banner non-temporary _after_ mapping it, to avoid - * being closed by other non-temporary windows */ - gtk_window_set_is_temporary (GTK_WINDOW (widget), FALSE); - - hildon_banner_check_position (widget); - } -} -#endif - -/* 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; -} - -static void -hildon_banner_reset_wrap_state (HildonBanner *banner) -{ - PangoLayout *layout; - HildonBannerPrivate *priv; - - priv = HILDON_BANNER_GET_PRIVATE (banner); - g_assert (priv); - - layout = gtk_label_get_layout (GTK_LABEL (priv->label)); - - pango_layout_set_width (layout, -1); - priv->has_been_wrapped = FALSE; - priv->has_been_truncated = FALSE; - - gtk_widget_set_size_request (priv->label, -1, -1); - gtk_widget_set_size_request (GTK_WIDGET (banner), -1, -1); -} - -/* 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; - int height = -1; - PangoRectangle logical; - GtkRequisition requisition; - HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (banner); - - g_return_if_fail (priv); - - label = GTK_LABEL (priv->label); - - layout = gtk_label_get_layout (label); - - pango_layout_get_extents (layout, NULL, &logical); - width_text = PANGO_PIXELS (logical.width); - - width_max = priv->is_timed ? HILDON_BANNER_LABEL_MAX_TIMED - : HILDON_BANNER_LABEL_MAX_PROGRESS; - - /* If the width of the label is going to exceed the maximum allowed - * width, enforce the maximum allowed width now. - */ - if (priv->has_been_wrapped - || width_text >= width_max - || pango_layout_is_wrapped (layout)) { - /* Force wrapping by setting the maximum size */ - width = width_max; - - priv->has_been_wrapped = TRUE; - } - - /* Make the label update its layout; and update our layout pointer - * because the layout will be cleared and refreshed. - */ - gtk_widget_set_size_request (GTK_WIDGET (label), width, height); - gtk_widget_size_request (GTK_WIDGET (label), &requisition); - - layout = gtk_label_get_layout (label); - - /* If the layout has now been wrapped and exceeds 3 lines, we truncate - * the rest of the label according to spec. - */ - if (priv->has_been_truncated - || (pango_layout_is_wrapped (layout) - && pango_layout_get_line_count (layout) > 3)) { - int lines; - - pango_layout_get_extents (layout, NULL, &logical); - lines = pango_layout_get_line_count (layout); - - /* This calculation assumes that the same font is used - * throughout the banner -- this is usually the case on maemo - * - * FIXME: Pango >= 1.20 has pango_layout_set_height(). - */ - height = (PANGO_PIXELS (logical.height) * 3) / lines + 1; - priv->has_been_truncated = TRUE; - } - - /* Set the new width/height if applicable */ - gtk_widget_set_size_request (GTK_WIDGET (label), width, height); -} - - -static void -hildon_banner_check_position (GtkWidget *widget) -{ - gint x, y; - GtkRequisition req; - - gtk_widget_set_size_request (widget, gdk_screen_width (), -1); - - 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 = HILDON_BANNER_WINDOW_X; - - y = HILDON_BANNER_WINDOW_Y; - - gtk_window_move (GTK_WINDOW (widget), x, y); -} - -static void -hildon_banner_realize (GtkWidget *widget) -{ - GdkWindow *gdkwin; - GdkAtom atom; - guint32 portrait = 1; - const gchar *notification_type = "_HILDON_NOTIFICATION_TYPE_BANNER"; - HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (widget); - g_assert (priv); - - /* 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_NOTIFICATION); - gtk_window_set_transient_for (GTK_WINDOW (widget), (GtkWindow *) priv->parent); - - hildon_banner_check_position (widget); - - gdkwin = widget->window; - - /* Set the _HILDON_NOTIFICATION_TYPE property so Matchbox places the window correctly */ - atom = gdk_atom_intern ("_HILDON_NOTIFICATION_TYPE", FALSE); - gdk_property_change (gdkwin, atom, gdk_x11_xatom_to_atom (XA_STRING), 8, GDK_PROP_MODE_REPLACE, - (gpointer) notification_type, strlen (notification_type)); - - /* HildonBanner supports portrait mode */ - atom = gdk_atom_intern ("_HILDON_PORTRAIT_MODE_SUPPORT", FALSE); - gdk_property_change (gdkwin, atom, gdk_x11_xatom_to_atom (XA_CARDINAL), 32, - GDK_PROP_MODE_REPLACE, (gpointer) &portrait, 1); -} - -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->finalize = hildon_banner_finalize; - 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; - widget_class->button_press_event = hildon_banner_button_press_event; -#if defined(MAEMO_GTK) - widget_class->map = hildon_banner_map; -#endif - - /* Install properties. - We need construct properties for singleton purposes */ - - /** - * HildonBanner:parent-window: - * - * The window for which the banner will be singleton. - * - */ - 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)); - - /** - * HildonBanner:is-timed: - * - * Whether the banner is timed and goes away automatically. - * - */ - 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)); - - /** - * HildonBanner:timeout: - * - * The time before making the banner banner go away. This needs - * to be adjusted before the banner is mapped to the screen. - * - */ - g_object_class_install_property (object_class, PROP_TIMEOUT, - g_param_spec_uint ("timeout", - "Timeout", - "The time before making the banner banner go away", - 0, - 10000, - HILDON_BANNER_DEFAULT_TIMEOUT, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); -} - -static void -hildon_banner_init (HildonBanner *self) -{ - HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self); - g_assert (priv); - - priv->parent = NULL; - - /* Initialize the common layout inside banner */ - 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_label_set_line_wrap_mode (GTK_LABEL (priv->label), PANGO_WRAP_WORD_CHAR); - - gtk_container_set_border_width (GTK_CONTAINER (priv->layout), HILDON_MARGIN_DEFAULT); - gtk_container_add (GTK_CONTAINER (self), priv->layout); - gtk_box_pack_start (GTK_BOX (priv->layout), priv->label, TRUE, TRUE, 0); - - gtk_window_set_accept_focus (GTK_WINDOW (self), FALSE); - - hildon_banner_reset_wrap_state (self); - - gtk_widget_add_events (GTK_WIDGET (self), GDK_BUTTON_PRESS_MASK); -} - -/* 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; - HildonBannerPrivate *priv = HILDON_BANNER_GET_PRIVATE (self); - - g_assert (priv); - - widget = 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 (priv->layout), widget); - - /* Use user provided widget or create a new one */ - priv->main_item = widget = user_widget ? - user_widget : GTK_WIDGET (g_object_new_valist(type, first_property, args)); - gtk_box_pack_start (GTK_BOX (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 (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; - - 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); -} - -static GtkWidget * -hildon_banner_create_animation (void) -{ - GtkWidget *image; - GdkPixbufSimpleAnim *anim; - GdkPixbuf *frame; - GtkIconTheme *theme; - GError *error = NULL; - gchar *icon_name; - gint i; - - anim = gdk_pixbuf_simple_anim_new (HILDON_ICON_PIXEL_SIZE_STYLUS, - HILDON_ICON_PIXEL_SIZE_STYLUS, - HILDON_BANNER_ANIMATION_FRAMERATE); - gdk_pixbuf_simple_anim_set_loop (anim, TRUE); - theme = gtk_icon_theme_get_default (); - - for (i = 1; i <= HILDON_BANNER_ANIMATION_NFRAMES; i++) { - icon_name = g_strdup_printf (HILDON_BANNER_ANIMATION_TMPL, i); - frame = gtk_icon_theme_load_icon (theme, icon_name, HILDON_ICON_PIXEL_SIZE_STYLUS, - 0, &error); - - if (error) { - g_warning ("Icon theme lookup for icon `%s' failed: %s", - icon_name, error->message); - g_error_free (error); - error = NULL; - } else { - gdk_pixbuf_simple_anim_add_frame (anim, frame); - } - - g_object_unref (frame); - g_free (icon_name); - } - - image = gtk_image_new_from_animation (GDK_PIXBUF_ANIMATION (anim)); - g_object_unref (anim); - - return image; -} - -/** - * hildon_banner_show_information: - * @widget: the #GtkWidget that is the owner of the banner - * @icon_name: since Hildon 2.2 this parameter is not used anymore and - * any value that you pass will be ignored - * @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. - * - * Returns: The newly created banner - * - */ -GtkWidget* -hildon_banner_show_information (GtkWidget *widget, - const gchar *icon_name, - const gchar *text) -{ - HildonBanner *banner; - - g_return_val_if_fail (text != NULL, NULL); - - /* Prepare banner */ - banner = hildon_banner_get_instance_for_widget (widget, TRUE); - - hildon_banner_set_text (banner, text); - hildon_banner_bind_style (banner, "information"); - - /* Show the banner, since caller cannot do that */ - gtk_widget_show_all (GTK_WIDGET (banner)); - - return (GtkWidget *) banner; -} - -/** - * hildon_banner_show_informationf: - * @widget: the #GtkWidget that is the owner of the banner - * @icon_name: since Hildon 2.2 this parameter is not used anymore and - * any value that you pass will be ignored - * @format: a printf-like format string - * @Varargs: arguments for the format string - * - * A helper function for #hildon_banner_show_information with - * string formatting. - * - * Returns: the newly created banner - */ -GtkWidget* -hildon_banner_show_informationf (GtkWidget *widget, - const gchar *icon_name, - const gchar *format, - ...) -{ - g_return_val_if_fail (format != NULL, NULL); - - gchar *message; - va_list args; - GtkWidget *banner; - - va_start (args, format); - message = g_strdup_vprintf (format, args); - va_end (args); - - banner = hildon_banner_show_information (widget, icon_name, message); - - g_free (message); - - return banner; -} - -/** - * hildon_banner_show_information_with_markup: - * @widget: the #GtkWidget that wants to display banner - * @icon_name: since Hildon 2.2 this parameter is not used anymore and - * any value that you pass will be ignored - * @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. - * - * Returns: the newly created banner - * - */ -GtkWidget* -hildon_banner_show_information_with_markup (GtkWidget *widget, - const gchar *icon_name, - const gchar *markup) -{ - HildonBanner *banner; - - g_return_val_if_fail (icon_name == NULL || icon_name[0] != 0, NULL); - g_return_val_if_fail (markup != NULL, NULL); - - /* Prepare banner */ - banner = hildon_banner_get_instance_for_widget (widget, TRUE); - - hildon_banner_set_markup (banner, markup); - hildon_banner_bind_style (banner, "information"); - - /* Show the banner, since caller cannot do that */ - gtk_widget_show_all (GTK_WIDGET (banner)); - - return (GtkWidget *) banner; -} - -/** - * hildon_banner_show_animation: - * @widget: the #GtkWidget that wants to display banner - * @animation_name: since Hildon 2.2 this parameter is not used - * anymore and any value that you pass will be - * ignored - * @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 does 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 does not disappear - * automatically, you can separately ref the return value (this - * doesn't prevent the banner from disappearing, just the object from - * being 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 done with the banner. - * - * Deprecated: Hildon 2.2: use - * hildon_gtk_window_set_progress_indicator() instead. - */ -GtkWidget* -hildon_banner_show_animation (GtkWidget *widget, - const gchar *animation_name, - const gchar *text) -{ - HildonBanner *banner; - GtkWidget *image_widget; - - g_return_val_if_fail (text != NULL, NULL); - - image_widget = hildon_banner_create_animation (); - - /* 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_style (banner, "animation"); - - /* And show it */ - gtk_widget_show_all (GTK_WIDGET (banner)); - - return (GtkWidget *) 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 done with the banner. - * - * Deprecated: Hildon 2.2: use hildon_gtk_window_set_progress_indicator() instead. - */ -GtkWidget* -hildon_banner_show_progress (GtkWidget *widget, - GtkProgressBar *bar, - const gchar *text) -{ - HildonBanner *banner; - HildonBannerPrivate *priv; - - 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); - priv = HILDON_BANNER_GET_PRIVATE (banner); - g_assert (priv); - hildon_banner_ensure_child (banner, (GtkWidget *) bar, -1, GTK_TYPE_PROGRESS_BAR, NULL); - - gtk_widget_set_size_request (priv->main_item, - HILDON_BANNER_PROGRESS_WIDTH, -1); - - hildon_banner_set_text (banner, text); - hildon_banner_bind_style (banner, "progress"); - - /* 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. - * - */ -void -hildon_banner_set_text (HildonBanner *self, - const gchar *text) -{ - GtkLabel *label; - HildonBannerPrivate *priv; - const gchar *existing_text; - - g_return_if_fail (HILDON_IS_BANNER (self)); - - priv = HILDON_BANNER_GET_PRIVATE (self); - g_assert (priv); - - label = GTK_LABEL (priv->label); - existing_text = gtk_label_get_text (label); - - if (existing_text != NULL && - text != NULL && - strcmp (existing_text, text) != 0) { - gtk_label_set_text (label, text); - hildon_banner_reset_wrap_state (self); - } - - 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. - * - */ -void -hildon_banner_set_markup (HildonBanner *self, - const gchar *markup) -{ - GtkLabel *label; - HildonBannerPrivate *priv; - - g_return_if_fail (HILDON_IS_BANNER (self)); - - priv = HILDON_BANNER_GET_PRIVATE (self); - g_assert (priv); - - label = GTK_LABEL (priv->label); - gtk_label_set_markup (label, markup); - - hildon_banner_reset_wrap_state (self); - - 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. - * - * Note that this method only has effect if @self was created with - * hildon_banner_show_progress() - * - */ -void -hildon_banner_set_fraction (HildonBanner *self, - gdouble fraction) -{ - HildonBannerPrivate *priv; - - g_return_if_fail (HILDON_IS_BANNER (self)); - priv = HILDON_BANNER_GET_PRIVATE (self); - g_assert (priv); - - g_return_if_fail (GTK_IS_PROGRESS_BAR (priv->main_item)); - gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->main_item), fraction); -} - -/** - * hildon_banner_set_timeout: - * @self: a #HildonBanner widget - * @timeout: timeout to set in miliseconds. - * - * Sets the timeout on the banner. After the given amount of miliseconds - * has elapsed the banner will go away. Note that settings this only makes - * sense on the banners that are timed and that have not been yet displayed - * on the screen. - * - * Note that this method only has effect if @self is an information - * banner (created using hildon_banner_show_information() and - * friends). - */ -void -hildon_banner_set_timeout (HildonBanner *self, - guint timeout) -{ - HildonBannerPrivate *priv; - - g_return_if_fail (HILDON_IS_BANNER (self)); - priv = HILDON_BANNER_GET_PRIVATE (self); - g_assert (priv); - - priv->timeout = timeout; -} - -/** - * hildon_banner_set_icon: - * @self: a #HildonBanner widget - * @icon_name: the name of icon to use. Can be %NULL for default icon - * - * Sets the icon to be used in the banner. - * - * Deprecated: This function does nothing. As of hildon 2.2, hildon - * banners don't allow changing their icons. - */ -void -hildon_banner_set_icon (HildonBanner *self, - const gchar *icon_name) -{ -} - -/** - * hildon_banner_set_icon_from_file: - * @self: a #HildonBanner widget - * @icon_file: the filename of icon to use. Can be %NULL for default icon - * - * Sets the icon from its filename to be used in the banner. - * - * Deprecated: This function does nothing. As of hildon 2.2, hildon - * banners don't allow changing their icons. - */ -void -hildon_banner_set_icon_from_file (HildonBanner *self, - const gchar *icon_file) -{ -} diff --git a/src/hildon-banner.h b/src/hildon-banner.h deleted file mode 100644 index bdd16a5..0000000 --- a/src/hildon-banner.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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 - -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; - -struct _HildonBanner -{ - GtkWindow parent; -}; - -struct _HildonBannerClass -{ - GtkWindowClass parent_class; -}; - -GType G_GNUC_CONST -hildon_banner_get_type (void); - -GtkWidget* -hildon_banner_show_information (GtkWidget *widget, - const gchar *icon_name, - const gchar *text); - -GtkWidget* -hildon_banner_show_informationf (GtkWidget *widget, - const gchar *icon_name, - const gchar *format, - ...); - -GtkWidget* -hildon_banner_show_information_with_markup (GtkWidget *widget, - const gchar *icon_name, - const gchar *markup); - -#ifndef HILDON_DISABLE_DEPRECATED -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); -#endif /* HILDON_DISABLE_DEPRECATED */ - -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); - -#ifndef HILDON_DISABLE_DEPRECATED -void -hildon_banner_set_icon (HildonBanner *self, - const gchar *icon_name); - -void -hildon_banner_set_icon_from_file (HildonBanner *self, - const gchar *icon_file); -#endif /* HILDON_DISABLE_DEPRECATED */ - -void -hildon_banner_set_timeout (HildonBanner *self, - guint timeout); - -G_END_DECLS - -#endif /* __HILDON_BANNER_H__ */ diff --git a/src/hildon-bread-crumb-trail.c b/src/hildon-bread-crumb-trail.c deleted file mode 100644 index 5ed23e0..0000000 --- a/src/hildon-bread-crumb-trail.c +++ /dev/null @@ -1,791 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2007 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * Author: Xan Lopez - * - * 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, or (at your option) any later version. - * - * 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-bread-crumb-trail - * @short_description: Widget used to represent a specific path in a hierarchical tree. - * Stability: Unstable - * - * HildonBreadCrumbTrail is a GTK widget used to represent the currently active path in - * some kind of hierarchical structure (file system, media library, structured document, etc). - * - * It has built-in support for text and icon bread crumbs, but the trail only requires a very - * simple interface to be implemented for its children and thus new types of items can be - * implemented if needed. See #HildonBreadCrumb for more details. - */ - -#undef HILDON_DISABLE_DEPRECATED - -#include - -#include "hildon-marshalers.h" -#include "hildon-bread-crumb-trail.h" -#include "hildon-bread-crumb-widget.h" - -#define HILDON_BREAD_CRUMB_TRAIL_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_BREAD_CRUMB_TRAIL, HildonBreadCrumbTrailPrivate)) - -struct _HildonBreadCrumbTrailPrivate -{ - GtkWidget *back_button; - GList *item_list; - GtkWidget *arrow; -}; - -/* Signals */ - -enum { - CRUMB_CLICKED, - MOVE_PARENT, - LAST_SIGNAL -}; - -/* Properties */ - -enum { - PROP_0 -}; - -static void hildon_bread_crumb_trail_size_request (GtkWidget *widget, - GtkRequisition *requisition); -static void hildon_bread_crumb_trail_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); -static void hildon_bread_crumb_trail_add (GtkContainer *container, - GtkWidget *widget); -static void hildon_bread_crumb_trail_forall (GtkContainer *container, - gboolean include_internals, - GtkCallback callback, - gpointer callback_data); -static void hildon_bread_crumb_trail_remove (GtkContainer *container, - GtkWidget *widget); -static void hildon_bread_crumb_trail_finalize (GObject *object); -static void hildon_bread_crumb_trail_scroll_back (GtkWidget *button, - HildonBreadCrumbTrail *bct); -static void hildon_bread_crumb_trail_update_back_button_sensitivity (HildonBreadCrumbTrail *bct); -static void hildon_bread_crumb_trail_move_parent (HildonBreadCrumbTrail *bct); - -static gpointer get_bread_crumb_id (HildonBreadCrumb *item); - -static guint bread_crumb_trail_signals[LAST_SIGNAL] = { 0 }; - -/* GType methods */ - -G_DEFINE_TYPE (HildonBreadCrumbTrail, hildon_bread_crumb_trail, GTK_TYPE_CONTAINER) - -static void -hildon_bread_crumb_trail_class_init (HildonBreadCrumbTrailClass *klass) -{ - GObjectClass *gobject_class = (GObjectClass*)klass; - GtkObjectClass *object_class = (GtkObjectClass*)klass; - GtkWidgetClass *widget_class = (GtkWidgetClass*)klass; - GtkContainerClass *container_class = (GtkContainerClass*)klass; - GtkBindingSet *binding_set; - - /* GObject signals */ - gobject_class->finalize = hildon_bread_crumb_trail_finalize; - - /* GtkWidget signals */ - widget_class->size_request = hildon_bread_crumb_trail_size_request; - widget_class->size_allocate = hildon_bread_crumb_trail_size_allocate; - - /* GtkContainer signals */ - container_class->add = hildon_bread_crumb_trail_add; - container_class->forall = hildon_bread_crumb_trail_forall; - container_class->remove = hildon_bread_crumb_trail_remove; - - /* HildonBreadCrumbTrail signals */ - klass->move_parent = hildon_bread_crumb_trail_move_parent; - - /* Style properties */ - -#define _BREAD_CRUMB_TRAIL_MINIMUM_WIDTH 10 - - /* FIXME: is this the best way to do it? */ - gtk_widget_class_install_style_property (widget_class, - g_param_spec_int ("minimum-width", - "Minimum width", - "The minimum width in characters the children widgets will request", - 0, - G_MAXINT, - _BREAD_CRUMB_TRAIL_MINIMUM_WIDTH, - G_PARAM_READABLE)); - -#define _BREAD_CRUMB_TRAIL_ARROW_SIZE 34 - - gtk_widget_class_install_style_property (widget_class, - g_param_spec_int ("arrow-size", - "Arrow size", - "Size of the back button arrow", - 0, - G_MAXINT, - _BREAD_CRUMB_TRAIL_ARROW_SIZE, - G_PARAM_READABLE)); - /* Signals */ - bread_crumb_trail_signals[CRUMB_CLICKED] = - g_signal_new ("crumb-clicked", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (HildonBreadCrumbTrailClass, crumb_clicked), - g_signal_accumulator_true_handled, NULL, - _hildon_marshal_BOOLEAN__POINTER, - G_TYPE_BOOLEAN, 1, - G_TYPE_POINTER); - - bread_crumb_trail_signals[MOVE_PARENT] = - g_signal_new ("move-parent", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (HildonBreadCrumbTrailClass, move_parent), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, - 0); - - - /* Binding set */ - binding_set = gtk_binding_set_by_class (widget_class); - - gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0, - "move-parent", 0); - gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, 0, - "move-parent", 0); - - /* Private data */ - g_type_class_add_private (gobject_class, sizeof (HildonBreadCrumbTrailPrivate)); -} - -static void -hildon_bread_crumb_trail_finalize (GObject *object) -{ - HildonBreadCrumbTrailPrivate *priv = HILDON_BREAD_CRUMB_TRAIL (object)->priv; - - g_list_free (priv->item_list); - - G_OBJECT_CLASS (hildon_bread_crumb_trail_parent_class)->finalize (object); -} - -static void -hildon_bread_crumb_trail_move_parent (HildonBreadCrumbTrail *bct) -{ - if (g_list_length (bct->priv->item_list) > 1) - { - g_signal_emit_by_name (HILDON_BREAD_CRUMB (bct->priv->item_list->next->data), - "crumb-activated"); - } -} - -static void -hildon_bread_crumb_trail_size_request (GtkWidget *widget, - GtkRequisition *requisition) -{ - GList *p; - GtkRequisition child_requisition; - HildonBreadCrumbTrail *bct; - HildonBreadCrumbTrailPrivate *priv; - gint minimum_width, width = 0; - PangoLayout *layout; - gchar *tmp = NULL; - - bct= HILDON_BREAD_CRUMB_TRAIL (widget); - priv = bct->priv; - - requisition->height = 0; - requisition->width = 0; - - gtk_widget_size_request (priv->back_button, &child_requisition); - requisition->width = child_requisition.width; - requisition->height = child_requisition.height; - - if (priv->item_list) - { - /* Add minimum width for one item */ - /* TODO: this can be probably cached */ - gtk_widget_style_get (widget, - "minimum-width", &minimum_width, - NULL); - - tmp = g_strnfill ((gsize)minimum_width, 'm'); - layout = gtk_widget_create_pango_layout (widget, tmp); - g_free (tmp); - pango_layout_get_size (layout, &width, NULL); - requisition->width += PANGO_PIXELS (width); - g_object_unref (layout); - } - - /* Button requisitions */ - for (p = priv->item_list; p; p = p->next) - { - GtkWidget *child = GTK_WIDGET (p->data); - - if (GTK_WIDGET_VISIBLE (child)) - gtk_widget_size_request (child, &child_requisition); - } - - /* Border width */ - requisition->width += GTK_CONTAINER (widget)->border_width * 2; - requisition->height += GTK_CONTAINER (widget)->border_width * 2; - - widget->requisition = *requisition; -} - -/* Document me please */ - -static void -hildon_bread_crumb_trail_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - GtkRequisition req; - gint natural_width, natural_height; - HildonBreadCrumb *item; - GtkAllocation child_allocation; - GtkRequisition child_requisition; - GtkWidget *child; - gint allocation_width; - gint border_width, width; - gint extra_space; - GList *p, *first_show, *first_hide; - gint back_button_size; - HildonBreadCrumbTrailPrivate *priv = HILDON_BREAD_CRUMB_TRAIL (widget)->priv; - gboolean rtl; - - /* Get the rtl status */ - rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL); - - widget->allocation = *allocation; - - border_width = (gint) GTK_CONTAINER (widget)->border_width; - allocation_width = allocation->width - 2 * border_width; - - /* Allocate the back button */ - if (rtl) - child_allocation.x = allocation->width - border_width; - else - child_allocation.x = allocation->x + border_width; - - child_allocation.y = allocation->y + border_width; - gtk_widget_get_child_requisition (priv->back_button, &child_requisition); - /* We want the back button to be a square */ - back_button_size = MAX (child_requisition.width, child_requisition.height); - child_allocation.width = child_allocation.height = back_button_size; - - if (rtl) - child_allocation.x -= back_button_size; - - gtk_widget_size_allocate (priv->back_button, &child_allocation); - - if (!rtl) - child_allocation.x += back_button_size; - - /* If there are no buttons there's nothing else to do */ - if (priv->item_list == NULL) - return; - - /* We find out how many buttons can we show, starting from the - the last one in the logical path (the first item in the list) */ - - width = back_button_size; - p = priv->item_list; - first_show = NULL; - first_hide = NULL; - extra_space = 0; - - for (p = priv->item_list; p; p = p->next) - { - item = HILDON_BREAD_CRUMB (p->data); - child = GTK_WIDGET (item); - - /* Does the widget fit with its natural size? */ - hildon_bread_crumb_get_natural_size (item, - &natural_width, - &natural_height); - - if (width + natural_width <= allocation_width) - { - /* Yes, it does */ - first_show = p; - first_hide = p->next; - width += natural_width; - } - else - { - /* No, it doesn't. Allocate as much as possible - and stop */ - child_allocation.width = allocation_width - width; - - gtk_widget_size_request (child, &req); - - if (child_allocation.width > req.width) - { - first_hide = p->next; - gtk_widget_set_child_visible (child, TRUE); - - if (rtl) - child_allocation.x -= child_allocation.width; - - gtk_widget_size_allocate (child, &child_allocation); - - if (!rtl) - child_allocation.x += child_allocation.width; - } - else - { - extra_space = child_allocation.width; - } - - break; - } - } - - /* Not enough items to fill the breadcrumb? */ - if (p == NULL && width < allocation_width) - { - extra_space = allocation_width - width; - } - - /* Allocate the other buttons */ - for (p = first_show; p; p = p->prev) - { - item = HILDON_BREAD_CRUMB (p->data); - child = GTK_WIDGET (item); - - /* Does the widget fit with its natural size? */ - hildon_bread_crumb_get_natural_size (item, - &natural_width, - &natural_height); - - /* If I'm the last and there's extra space, use it */ - if (p->prev == NULL && extra_space != 0) - { - natural_width += extra_space; - } - - child_allocation.width = natural_width; - gtk_widget_set_child_visible (child, TRUE); - - if (rtl) - child_allocation.x -= child_allocation.width; - - gtk_widget_size_allocate (child, &child_allocation); - - if (!rtl) - child_allocation.x += child_allocation.width; - } - - for (p = first_hide; p; p = p->next) - { - item = HILDON_BREAD_CRUMB (p->data); - gtk_widget_set_child_visible (GTK_WIDGET (item), FALSE); - } -} - -static gpointer -get_bread_crumb_id (HildonBreadCrumb *item) -{ - return g_object_get_data (G_OBJECT (item), "bread-crumb-id"); -} - -static void -crumb_activated_cb (GtkWidget *button, - HildonBreadCrumbTrail *bct) -{ - gboolean signal_handled = FALSE; - - g_signal_emit (bct, bread_crumb_trail_signals[CRUMB_CLICKED], 0, - get_bread_crumb_id (HILDON_BREAD_CRUMB (button)), - &signal_handled); - - if (signal_handled == FALSE) - { - GtkWidget *child; - gboolean focus_last_item = FALSE; - HildonBreadCrumbTrailPrivate *priv; - - priv = bct->priv; - - child = GTK_WIDGET (priv->item_list->data); - - /* We remove the tip of the list until we hit the clicked button */ - while (child && child != button) - { - if (GTK_WIDGET_HAS_FOCUS (child)) - focus_last_item = TRUE; - - gtk_container_remove (GTK_CONTAINER (bct), child); - - if (priv->item_list == NULL) - return; - - child = GTK_WIDGET (priv->item_list->data); - } - - if (focus_last_item) - gtk_widget_grab_focus (GTK_WIDGET (bct->priv->item_list->data)); - } -} - -static void -hildon_bread_crumb_trail_add (GtkContainer *container, - GtkWidget *widget) -{ - gtk_widget_set_parent (widget, GTK_WIDGET (container)); - - if (HILDON_IS_BREAD_CRUMB (widget)) - { - HildonBreadCrumbTrail *bct = HILDON_BREAD_CRUMB_TRAIL (container); - - g_signal_connect (G_OBJECT (widget), "crumb-activated", - G_CALLBACK (crumb_activated_cb), container); - - bct->priv->item_list = g_list_prepend (bct->priv->item_list, widget); - - hildon_bread_crumb_trail_update_back_button_sensitivity (bct); - } -} - -static void -hildon_bread_crumb_trail_forall (GtkContainer *container, - gboolean include_internals, - GtkCallback callback, - gpointer callback_data) -{ - g_return_if_fail (callback != NULL); - g_return_if_fail (HILDON_IS_BREAD_CRUMB_TRAIL (container)); - - GList *children; - HildonBreadCrumbTrailPrivate *priv = HILDON_BREAD_CRUMB_TRAIL (container)->priv; - - children = priv->item_list; - - while (children) - { - GtkWidget *child; - child = GTK_WIDGET (children->data); - children = children->next; - - (*callback) (child, callback_data); - } - - if (include_internals && priv->back_button) - { - (*callback) (priv->back_button, callback_data); - } -} - -static void -hildon_bread_crumb_trail_remove (GtkContainer *container, - GtkWidget *widget) -{ - GList *p, *next; - HildonBreadCrumbTrailPrivate *priv; - gboolean was_visible = GTK_WIDGET_VISIBLE (widget); - - priv = HILDON_BREAD_CRUMB_TRAIL (container)->priv; - - p = priv->item_list; - - while (p) - { - next = p->next; - - if (widget == GTK_WIDGET (p->data)) - { - g_signal_handlers_disconnect_by_func (widget, G_CALLBACK (crumb_activated_cb), - HILDON_BREAD_CRUMB_TRAIL (container)); - gtk_widget_unparent (widget); - - priv->item_list = g_list_delete_link (priv->item_list, p); - - hildon_bread_crumb_trail_update_back_button_sensitivity (HILDON_BREAD_CRUMB_TRAIL (container)); - - if (was_visible) - { - gtk_widget_queue_resize (GTK_WIDGET (container)); - } - } - - p = next; - } -} - -static void -hildon_bread_crumb_trail_update_back_button_sensitivity (HildonBreadCrumbTrail *bct) -{ - guint list_length; - HildonBreadCrumbTrailPrivate *priv = bct->priv; - - list_length = g_list_length (priv->item_list); - - if (list_length <= 1) - { - gtk_widget_set_sensitive (priv->back_button, FALSE); - } - else - { - gtk_widget_set_sensitive (priv->back_button, TRUE); - } -} - -static GtkWidget* -create_back_button (HildonBreadCrumbTrail *bct) -{ - GtkWidget *button; - GtkWidget *arrow; - gint arrow_size; - - gtk_widget_push_composite_child (); - - button = gtk_button_new (); - gtk_widget_set_name (button, "hildon-bread-crumb-back-button"); - gtk_widget_set_sensitive (button, FALSE); - - arrow = gtk_arrow_new (GTK_ARROW_LEFT, GTK_SHADOW_NONE); - bct->priv->arrow = arrow; - gtk_widget_style_get (GTK_WIDGET (bct), - "arrow-size", &arrow_size, - NULL); - gtk_widget_set_size_request (arrow, arrow_size, arrow_size); - - gtk_container_add (GTK_CONTAINER (button), arrow); - gtk_container_add (GTK_CONTAINER (bct), button); - gtk_widget_show_all (button); - - gtk_widget_pop_composite_child (); - - return button; -} - -static void -hildon_bread_crumb_trail_init (HildonBreadCrumbTrail *bct) -{ - HildonBreadCrumbTrailPrivate *priv = HILDON_BREAD_CRUMB_TRAIL_GET_PRIVATE (bct); - - GTK_WIDGET_SET_FLAGS (bct, GTK_NO_WINDOW); - gtk_widget_set_redraw_on_allocate (GTK_WIDGET (bct), FALSE); - - bct->priv = priv; - priv->item_list = NULL; - - priv->back_button = create_back_button (bct); - g_signal_connect (priv->back_button, "clicked", - G_CALLBACK (hildon_bread_crumb_trail_scroll_back), - bct); -} - -static void -hildon_bread_crumb_trail_scroll_back (GtkWidget *button, - HildonBreadCrumbTrail *bct) -{ - hildon_bread_crumb_trail_move_parent (bct); -} - -static void -attach_bread_crumb (HildonBreadCrumbTrail *bct, - GtkWidget *bread_crumb, - gpointer id, - GDestroyNotify destroy) -{ - g_object_set_data_full (G_OBJECT (bread_crumb), "bread-crumb-id", id, destroy); - - gtk_container_add (GTK_CONTAINER (bct), bread_crumb); - - gtk_widget_show (bread_crumb); -} - -/* PUBLIC API */ - -/** - * hildon_bread_crumb_trail_new: - * - * Creates a new #HildonBreadCrumbTrail widget. - * - * Returns: a #GtkWidget pointer of newly created bread crumb trail - * widget - * - * Stability: Unstable - */ - -GtkWidget* -hildon_bread_crumb_trail_new (void) -{ - return GTK_WIDGET (g_object_new (HILDON_TYPE_BREAD_CRUMB_TRAIL, NULL)); -} - -/** - * hildon_bread_crumb_trail_push: - * @bct: pointer to #HildonBreadCrumbTrail - * @item: the #HildonBreadCrumb to be added to the trail - * @id: optional id for the bread crumb - * @destroy: GDestroyNotify callback to be called when the bread crumb is destroyed - * - * Adds a new bread crumb to the end of the trail. - * - * Stability: Unstable - */ - -void -hildon_bread_crumb_trail_push (HildonBreadCrumbTrail *bct, - HildonBreadCrumb *item, - gpointer id, - GDestroyNotify destroy) -{ - GtkWidget *widget; - - g_return_if_fail (HILDON_IS_BREAD_CRUMB_TRAIL (bct)); - g_return_if_fail (HILDON_IS_BREAD_CRUMB (item)); - - widget = GTK_WIDGET (item); - - attach_bread_crumb (bct, widget, id, destroy); -} - -/** - * hildon_bread_crumb_trail_push_text: - * @bct: pointer to #HildonBreadCrumbTrail - * @text: content of the new bread crumb - * @id: optional id for the bread crumb - * @destroy: GDestroyNotify callback to be called when the bread crumb is destroyed - * - * Adds a new bread crumb to the end of the trail containing the specified text. - * - * Stability: Unstable - */ - -void -hildon_bread_crumb_trail_push_text (HildonBreadCrumbTrail *bct, - const gchar *text, - gpointer id, - GDestroyNotify destroy) -{ - GtkWidget *widget; - - g_return_if_fail (HILDON_IS_BREAD_CRUMB_TRAIL (bct)); - g_return_if_fail (text != NULL); - - widget = _hildon_bread_crumb_widget_new_with_text (text); - if (bct->priv->item_list == NULL) - { - g_object_set (G_OBJECT (widget), "show-separator", FALSE, NULL); - } - attach_bread_crumb (bct, widget, id, destroy); -} - -/** - * hildon_bread_crumb_trail_push_icon: - * @bct: pointer to #HildonBreadCrumbTrail - * @text: content of the new bread crumb - * @icon: a widget to set as the icon in the bread crumb - * @id: optional id for the bread crumb - * @destroy: GDestroyNotify callback to be called when the bread crumb is destroyed - * - * Adds a new bread crumb to the end of the trail containing the specified text and - * icon. - * - * Stability: Unstable - */ - -void -hildon_bread_crumb_trail_push_icon (HildonBreadCrumbTrail *bct, - const gchar *text, - GtkWidget *icon, - gpointer id, - GDestroyNotify destroy) -{ - GtkWidget *widget; - - g_return_if_fail (HILDON_IS_BREAD_CRUMB_TRAIL (bct)); - g_return_if_fail (text != NULL); - g_return_if_fail (GTK_IS_WIDGET (icon)); - - widget = _hildon_bread_crumb_widget_new_with_icon (icon, text); - if (bct->priv->item_list == NULL) - { - g_object_set (G_OBJECT (widget), "show-separator", FALSE, NULL); - } - attach_bread_crumb (bct, widget, id, destroy); -} - -/** - * hildon_bread_crumb_trail_pop: - * @bct: pointer to #HildonBreadCrumbTrail - * - * Removes the last bread crumb from the trail. - * - * Stability: Unstable - */ - -void -hildon_bread_crumb_trail_pop (HildonBreadCrumbTrail *bct) -{ - GtkWidget *child; - HildonBreadCrumbTrailPrivate *priv; - - g_return_if_fail (HILDON_IS_BREAD_CRUMB_TRAIL (bct)); - - priv = bct->priv; - - if (priv->item_list == NULL) - return; - - if (priv->item_list) - { - child = GTK_WIDGET (priv->item_list->data); - gtk_container_remove (GTK_CONTAINER (bct), child); - } - - hildon_bread_crumb_trail_update_back_button_sensitivity (bct); -} - -/** - * hildon_bread_crumb_trail_clear: - * @bct: pointer to #HildonBreadCrumbTrail - * - * Removes all the bread crumbs from the bread crumb trail. - * - * Stability: Unstable - */ - -void -hildon_bread_crumb_trail_clear (HildonBreadCrumbTrail *bct) -{ - HildonBreadCrumbTrailPrivate *priv; - - g_return_if_fail (HILDON_IS_BREAD_CRUMB_TRAIL (bct)); - - priv = bct->priv; - - while (priv->item_list) - { - hildon_bread_crumb_trail_pop (bct); - } - - /* - Sensitivity hack from hell. We need to do this while - http://bugzilla.gnome.org/show_bug.cgi?id=56070 is not - fixed to allow repeated clicking on the back button if - someone clears and rebuilds the trail when it's clicked - */ - gtk_widget_hide (priv->back_button); - gtk_widget_show (priv->back_button); -} diff --git a/src/hildon-bread-crumb-trail.h b/src/hildon-bread-crumb-trail.h deleted file mode 100644 index 71695ce..0000000 --- a/src/hildon-bread-crumb-trail.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2007 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * Author: Xan Lopez - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#ifndef __HILDON_BREAD_CRUMB_TRAIL_H__ -#define __HILDON_BREAD_CRUMB_TRAIL_H__ - -#include - -#include "hildon-bread-crumb.h" - -G_BEGIN_DECLS - -typedef struct _HildonBreadCrumbTrail HildonBreadCrumbTrail; -typedef struct _HildonBreadCrumbTrailClass HildonBreadCrumbTrailClass; -typedef struct _HildonBreadCrumbTrailPrivate HildonBreadCrumbTrailPrivate; - -#define HILDON_TYPE_BREAD_CRUMB_TRAIL (hildon_bread_crumb_trail_get_type ()) -#define HILDON_BREAD_CRUMB_TRAIL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HILDON_TYPE_BREAD_CRUMB_TRAIL, HildonBreadCrumbTrail)) -#define HILDON_BREAD_CRUMB_TRAIL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), HILDON_TYPE_BREAD_CRUMB_TRAIL, HildonBreadCrumbTrailClass)) -#define HILDON_IS_BREAD_CRUMB_TRAIL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_BREAD_CRUMB_TRAIL)) -#define HILDON_IS_BREAD_CRUMB_TRAIL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_BREAD_CRUMB_TRAIL)) -#define HILDON_BREAD_CRUMB_TRAIL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), HILDON_TYPE_BREAD_CRUMB_TRAIL, HildonBreadCrumbTrailClass)) - -struct _HildonBreadCrumbTrail -{ - GtkContainer parent; - - HildonBreadCrumbTrailPrivate *priv; -}; - -struct _HildonBreadCrumbTrailClass -{ - GtkContainerClass parent_class; - - void (*crumb_clicked) (HildonBreadCrumbTrail *bct, - gpointer id); - - /* Signals used for keybindings */ - void (*move_parent) (HildonBreadCrumbTrail *bct); - - /* Padding for future expansion */ - void (*_hildon_bct_reserved1) (void); - void (*_hildon_bct_reserved2) (void); - void (*_hildon_bct_reserved3) (void); - void (*_hildon_bct_reserved4) (void); -}; - -GType hildon_bread_crumb_trail_get_type (void) G_GNUC_CONST; -GtkWidget *hildon_bread_crumb_trail_new (void); -void hildon_bread_crumb_trail_push (HildonBreadCrumbTrail *bct, HildonBreadCrumb *item, - gpointer id, GDestroyNotify destroy); -void hildon_bread_crumb_trail_push_text (HildonBreadCrumbTrail *bct, const gchar *text, - gpointer id, GDestroyNotify destroy); -void hildon_bread_crumb_trail_push_icon (HildonBreadCrumbTrail *bct, - const gchar *text, - GtkWidget *icon, - gpointer id, - GDestroyNotify destroy); -void hildon_bread_crumb_trail_pop (HildonBreadCrumbTrail *bct); -void hildon_bread_crumb_trail_clear (HildonBreadCrumbTrail *bct); - -G_END_DECLS - -#endif - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-bread-crumb-widget.c b/src/hildon-bread-crumb-widget.c deleted file mode 100644 index 22e4411..0000000 --- a/src/hildon-bread-crumb-widget.c +++ /dev/null @@ -1,517 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2007 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * Author: Xan Lopez - * - * 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, or (at your option) any later version. - * - * 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 - * - */ - -#undef HILDON_DISABLE_DEPRECATED - -#include "hildon-bread-crumb-widget.h" -#include "hildon-defines.h" - -#define HILDON_BREAD_CRUMB_WIDGET_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_BREAD_CRUMB_WIDGET, HildonBreadCrumbWidgetPrivate)) - -struct _HildonBreadCrumbWidgetPrivate -{ - GtkWidget *hbox; - GtkWidget *label; - GtkWidget *icon; - GtkWidget *arrow; - gchar *text; - - GtkPositionType icon_position; - gboolean constructed; - gboolean show_separator; -}; - -/* Signals */ - -enum { - LAST_SIGNAL -}; - -/* Properties */ - -enum { - PROP_0, - PROP_TEXT, - PROP_ICON, - PROP_ICON_POSITION, - PROP_SHOW_SEPARATOR -}; - -/* -static guint bread_crumb_item_signals[LAST_SIGNAL] = { 0 }; -*/ - -/* GType methods */ - -static void hildon_bread_crumb_widget_finalize (GObject *object); -static void hildon_bread_crumb_widget_set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec); -static void hildon_bread_crumb_widget_get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec); -static GObject* hildon_bread_crumb_widget_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_params); -static void hildon_bread_crumb_widget_set_contents (HildonBreadCrumbWidget *bread_crumb); - -static void hildon_bread_crumb_widget_clicked (GtkButton *button); - -static void hildon_bread_crumb_widget_bread_crumb_init (HildonBreadCrumbIface *iface); - -static void hildon_bread_crumb_widget_get_natural_size (HildonBreadCrumb *bread_crumb, - gint *width, - gint *height); - -G_DEFINE_TYPE_WITH_CODE (HildonBreadCrumbWidget, hildon_bread_crumb_widget, GTK_TYPE_BUTTON, - G_IMPLEMENT_INTERFACE (HILDON_TYPE_BREAD_CRUMB, - hildon_bread_crumb_widget_bread_crumb_init)) - -static void -hildon_bread_crumb_widget_class_init (HildonBreadCrumbWidgetClass *klass) -{ - GObjectClass *gobject_class = (GObjectClass*)klass; - GtkButtonClass *button_class = (GtkButtonClass*)klass; - - /* GObject signals */ - gobject_class->constructor = hildon_bread_crumb_widget_constructor; - gobject_class->finalize = hildon_bread_crumb_widget_finalize; - gobject_class->set_property = hildon_bread_crumb_widget_set_property; - gobject_class->get_property = hildon_bread_crumb_widget_get_property; - - /* GtkButton signals */ - button_class->clicked = hildon_bread_crumb_widget_clicked; - - /* Properties */ - g_object_class_install_property (gobject_class, - PROP_TEXT, - g_param_spec_string ("text", - "Text", - "Text of the label widget inside the bread crumb", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - g_object_class_install_property (gobject_class, - PROP_ICON, - g_param_spec_object ("icon", - "Icon", - "Image that will appear next to the bread crumb text", - GTK_TYPE_WIDGET, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - g_object_class_install_property (gobject_class, - PROP_ICON_POSITION, - g_param_spec_enum ("icon-position", - "Icon position", - "The position of the image relative to the text", - GTK_TYPE_POSITION_TYPE, - GTK_POS_LEFT, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - g_object_class_install_property (gobject_class, - PROP_SHOW_SEPARATOR, - g_param_spec_boolean ("show-separator", - "Show separator", - "Show the separator attached to the item", - TRUE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - /* Private data */ - g_type_class_add_private (gobject_class, sizeof (HildonBreadCrumbWidgetPrivate)); -} - -static void -hildon_bread_crumb_widget_bread_crumb_init (HildonBreadCrumbIface *iface) -{ - iface->get_natural_size = hildon_bread_crumb_widget_get_natural_size; -} - -static GObject* -hildon_bread_crumb_widget_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_params) -{ - GObject *object; - HildonBreadCrumbWidget *bread_crumb; - HildonBreadCrumbWidgetPrivate *priv; - - object = (* G_OBJECT_CLASS (hildon_bread_crumb_widget_parent_class)->constructor) (type, - n_construct_properties, - construct_params); - - bread_crumb = HILDON_BREAD_CRUMB_WIDGET (object); - priv = bread_crumb->priv; - priv->constructed = TRUE; - - priv->hbox = gtk_hbox_new (FALSE, 6); - gtk_container_add (GTK_CONTAINER (bread_crumb), priv->hbox); - - /* Separator */ - priv->arrow = gtk_arrow_new (GTK_ARROW_RIGHT, GTK_SHADOW_NONE); - gtk_widget_set_name (priv->arrow, "hildon-bread-crumb-separator-arrow"); - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->arrow, FALSE, FALSE, 0); - - if (priv->show_separator) - gtk_widget_show (priv->arrow); - - gtk_widget_set_no_show_all (priv->arrow, TRUE); - - /* Contents base container */ - bread_crumb->contents = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT); - gtk_container_add (GTK_CONTAINER (priv->hbox), bread_crumb->contents); - gtk_widget_show (bread_crumb->contents); - - if (priv->text || priv->icon) - hildon_bread_crumb_widget_set_contents (bread_crumb); - - /* Show everything */ - gtk_widget_show (priv->hbox); - - return object; -} - -static void -hildon_bread_crumb_widget_init (HildonBreadCrumbWidget *item) -{ - HildonBreadCrumbWidgetPrivate *priv = HILDON_BREAD_CRUMB_WIDGET_GET_PRIVATE (item); - - item->priv = priv; - - item->contents = NULL; - - priv->constructed = FALSE; - priv->text = NULL; - priv->icon = NULL; - priv->icon_position = GTK_POS_LEFT; - priv->show_separator = TRUE; -} - -static void -hildon_bread_crumb_widget_finalize (GObject *object) -{ - HildonBreadCrumbWidgetPrivate *priv = HILDON_BREAD_CRUMB_WIDGET (object)->priv; - - g_free (priv->text); - - G_OBJECT_CLASS (hildon_bread_crumb_widget_parent_class)->finalize (object); -} - -static void -hildon_bread_crumb_widget_clicked (GtkButton *button) -{ - hildon_bread_crumb_activated (HILDON_BREAD_CRUMB (button)); -} - -static void -hildon_bread_crumb_widget_set_contents (HildonBreadCrumbWidget *bread_crumb) -{ - GtkWidget *icon = NULL; - HildonBreadCrumbWidgetPrivate *priv = bread_crumb->priv; - - if (!priv->constructed) - return; - - if (!priv->text && !priv->icon) - return; - - /* If the icon exists, keep it */ - if (priv->icon) - { - icon = g_object_ref (priv->icon); - if (icon->parent) - gtk_container_remove (GTK_CONTAINER (icon->parent), icon); - priv->icon = NULL; - } - - /* Reset contents */ - if (bread_crumb->contents) - gtk_container_remove (GTK_CONTAINER (priv->hbox), - bread_crumb->contents); - - if (icon) - { - priv->icon = icon; - if (priv->icon_position == GTK_POS_LEFT || - priv->icon_position == GTK_POS_RIGHT) - bread_crumb->contents = gtk_hbox_new (FALSE, HILDON_MARGIN_DEFAULT); - else - bread_crumb->contents = gtk_vbox_new (FALSE, HILDON_MARGIN_DEFAULT); - - if (priv->icon_position == GTK_POS_LEFT || - priv->icon_position == GTK_POS_TOP) - gtk_box_pack_start (GTK_BOX (bread_crumb->contents), priv->icon, - FALSE, FALSE, 0); - else - gtk_box_pack_end (GTK_BOX (bread_crumb->contents), priv->icon, - FALSE, FALSE, 0); - - if (priv->text) - { - priv->label = gtk_label_new (priv->text); - g_object_set (G_OBJECT (priv->label), "xalign", 0.0, NULL); - gtk_label_set_ellipsize (GTK_LABEL (priv->label), - PANGO_ELLIPSIZE_END); - - if (priv->icon_position == GTK_POS_RIGHT || - priv->icon_position == GTK_POS_BOTTOM) - gtk_box_pack_start (GTK_BOX (bread_crumb->contents), priv->label, - TRUE, TRUE, 0); - else - gtk_box_pack_end (GTK_BOX (bread_crumb->contents), priv->label, - TRUE, TRUE, 0); - - } - - gtk_box_pack_start (GTK_BOX (priv->hbox), bread_crumb->contents, - TRUE, TRUE, 0); - gtk_widget_show_all (bread_crumb->contents); - - g_object_unref (icon); - } - else - { - /* Only text */ - bread_crumb->contents = gtk_hbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (priv->hbox), bread_crumb->contents, - TRUE, TRUE, 0); - - priv->label = gtk_label_new (priv->text); - g_object_set (G_OBJECT (priv->label), "xalign", 0.0, NULL); - gtk_label_set_ellipsize (GTK_LABEL (priv->label), - PANGO_ELLIPSIZE_END); - gtk_box_pack_start (GTK_BOX (bread_crumb->contents), priv->label, TRUE, TRUE, 0); - - gtk_widget_show_all (bread_crumb->contents); - } -} - -static void -hildon_bread_crumb_widget_set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - HildonBreadCrumbWidget *item = HILDON_BREAD_CRUMB_WIDGET (object); - - switch (prop_id) - { - case PROP_TEXT: - _hildon_bread_crumb_widget_set_text (item, g_value_get_string (value)); - break; - case PROP_ICON: - _hildon_bread_crumb_widget_set_icon (item, (GtkWidget*)g_value_get_object (value)); - break; - case PROP_ICON_POSITION: - _hildon_bread_crumb_widget_set_icon_position (item, g_value_get_enum (value)); - break; - case PROP_SHOW_SEPARATOR: - _hildon_bread_crumb_widget_set_show_separator (item, g_value_get_boolean (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -hildon_bread_crumb_widget_get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - HildonBreadCrumbWidget *item = HILDON_BREAD_CRUMB_WIDGET (object); - - switch (prop_id) - { - case PROP_TEXT: - g_value_set_string (value, item->priv->text); - break; - case PROP_ICON: - g_value_set_object (value, (GObject *)item->priv->icon); - break; - case PROP_ICON_POSITION: - g_value_set_enum (value, item->priv->icon_position); - break; - case PROP_SHOW_SEPARATOR: - g_value_set_boolean (value, item->priv->show_separator); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -void -_hildon_bread_crumb_widget_set_text (HildonBreadCrumbWidget *item, - const gchar *text) -{ - HildonBreadCrumbWidgetPrivate *priv; - - g_return_if_fail (HILDON_IS_BREAD_CRUMB_WIDGET (item)); - - priv = item->priv; - - if (priv->text) - g_free (priv->text); - - priv->text = g_strdup (text); - - hildon_bread_crumb_widget_set_contents (item); - - g_object_notify (G_OBJECT (item), "text"); -} - -const gchar* -_hildon_bread_crumb_widget_get_text (HildonBreadCrumbWidget *item) -{ - HildonBreadCrumbWidgetPrivate *priv; - - g_return_val_if_fail (HILDON_IS_BREAD_CRUMB_WIDGET (item), NULL); - - priv = item->priv; - - return priv->text; -} - -void -_hildon_bread_crumb_widget_set_show_separator (HildonBreadCrumbWidget *item, - gboolean show_separator) -{ - HildonBreadCrumbWidgetPrivate *priv; - - g_return_if_fail (HILDON_IS_BREAD_CRUMB_WIDGET (item)); - - priv = item->priv; - - if (priv->show_separator == show_separator) - return; - - priv->show_separator = show_separator; - - if (!priv->constructed) - return; - - if (show_separator) - gtk_widget_show (priv->arrow); - else - gtk_widget_hide (priv->arrow); - - g_object_notify (G_OBJECT (item), "show-separator"); -} - -static void -hildon_bread_crumb_widget_get_natural_size (HildonBreadCrumb *bread_crumb, - gint *natural_width, - gint *natural_height) -{ - GtkRequisition widget_req, label_req; - gint width, height; - PangoLayout *layout; - HildonBreadCrumbWidget *item; - HildonBreadCrumbWidgetPrivate *priv; - - g_return_if_fail (HILDON_IS_BREAD_CRUMB_WIDGET (bread_crumb)); - - item = HILDON_BREAD_CRUMB_WIDGET (bread_crumb); - priv = item->priv; - - gtk_widget_size_request (GTK_WIDGET (item), &widget_req); - - layout = gtk_widget_create_pango_layout (priv->label, priv->text); - pango_layout_get_pixel_size (layout, &width, &height); - g_object_unref (layout); - - if (natural_width) - { - *natural_width = widget_req.width; - /* Substract the size request of the label */ - gtk_widget_size_request (priv->label, &label_req); - *natural_width -= label_req.width; - - /* Add the "natural" width for the label */ - *natural_width += width; - *natural_width += GTK_CONTAINER (item)->border_width * 2; - } - - if (natural_height) - { - *natural_height = widget_req.height; - *natural_height += GTK_CONTAINER (item)->border_width * 2; - } -} - -GtkWidget* -_hildon_bread_crumb_widget_new () -{ - return GTK_WIDGET (g_object_new (HILDON_TYPE_BREAD_CRUMB_WIDGET, NULL)); -} - -GtkWidget* -_hildon_bread_crumb_widget_new_with_text (const gchar *text) -{ - return GTK_WIDGET (g_object_new (HILDON_TYPE_BREAD_CRUMB_WIDGET, - "text", text, - NULL)); -} - -GtkWidget* -_hildon_bread_crumb_widget_new_with_icon (GtkWidget *icon, const gchar *text) -{ - return GTK_WIDGET (g_object_new (HILDON_TYPE_BREAD_CRUMB_WIDGET, - "icon", icon, - "text", text, - NULL)); -} - -void -_hildon_bread_crumb_widget_set_icon (HildonBreadCrumbWidget *bread_crumb, - GtkWidget *icon) -{ - HildonBreadCrumbWidgetPrivate *priv; - - g_return_if_fail (HILDON_IS_BREAD_CRUMB_WIDGET (bread_crumb)); - - priv = bread_crumb->priv; - - priv->icon = icon; - - hildon_bread_crumb_widget_set_contents (bread_crumb); - - g_object_notify (G_OBJECT (bread_crumb), "icon"); -} - -void -_hildon_bread_crumb_widget_set_icon_position (HildonBreadCrumbWidget *bread_crumb, - GtkPositionType icon_position) -{ - HildonBreadCrumbWidgetPrivate *priv; - - g_return_if_fail (HILDON_IS_BREAD_CRUMB_WIDGET (bread_crumb)); - - priv = bread_crumb->priv; - - if (priv->icon_position == icon_position) - return; - - priv->icon_position = icon_position; - - hildon_bread_crumb_widget_set_contents (bread_crumb); - - g_object_notify (G_OBJECT (bread_crumb), "icon-position"); -} diff --git a/src/hildon-bread-crumb-widget.h b/src/hildon-bread-crumb-widget.h deleted file mode 100644 index 4c04c23..0000000 --- a/src/hildon-bread-crumb-widget.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2007 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * Author: Xan Lopez - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#ifndef __HILDON_BREAD_CRUMB_WIDGET_H__ -#define __HILDON_BREAD_CRUMB_WIDGET_H__ - -#include - -#include "hildon-bread-crumb.h" - -G_BEGIN_DECLS - -typedef struct _HildonBreadCrumbWidget HildonBreadCrumbWidget; -typedef struct _HildonBreadCrumbWidgetClass HildonBreadCrumbWidgetClass; -typedef struct _HildonBreadCrumbWidgetPrivate HildonBreadCrumbWidgetPrivate; - -#define HILDON_TYPE_BREAD_CRUMB_WIDGET (hildon_bread_crumb_widget_get_type ()) -#define HILDON_BREAD_CRUMB_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HILDON_TYPE_BREAD_CRUMB_WIDGET, HildonBreadCrumbWidget)) -#define HILDON_BREAD_CRUMB_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), HILDON_TYPE_BREAD_CRUMB_WIDGET, HildonBreadCrumbWidgetClass)) -#define HILDON_IS_BREAD_CRUMB_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_BREAD_CRUMB_WIDGET)) -#define HILDON_IS_BREAD_CRUMB_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_BREAD_CRUMB_WIDGET)) -#define HILDON_BREAD_CRUMB_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), HILDON_TYPE_BREAD_CRUMB_WIDGET, HildonBreadCrumbWidgetClass)) - -struct _HildonBreadCrumbWidget -{ - GtkButton parent; - - GtkWidget *contents; - - HildonBreadCrumbWidgetPrivate *priv; -}; - -struct _HildonBreadCrumbWidgetClass -{ - GtkButtonClass parent_class; -}; - -GType hildon_bread_crumb_widget_get_type (void) G_GNUC_CONST; -GtkWidget *_hildon_bread_crumb_widget_new (void); -GtkWidget *_hildon_bread_crumb_widget_new_with_text (const gchar *label); -GtkWidget *_hildon_bread_crumb_widget_new_with_icon (GtkWidget *icon, const gchar *text); -void _hildon_bread_crumb_widget_set_text (HildonBreadCrumbWidget *item, const gchar *text); -const gchar *_hildon_bread_crumb_widget_get_text (HildonBreadCrumbWidget *item); -void _hildon_bread_crumb_widget_set_show_separator (HildonBreadCrumbWidget *item, - gboolean show_separator); -void _hildon_bread_crumb_widget_set_icon (HildonBreadCrumbWidget *bread_crumb_widget, - GtkWidget *icon); -void _hildon_bread_crumb_widget_set_icon_position (HildonBreadCrumbWidget *bread_crumb, - GtkPositionType icon_position); - -G_END_DECLS - -#endif - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-bread-crumb.c b/src/hildon-bread-crumb.c deleted file mode 100644 index e9bc4f0..0000000 --- a/src/hildon-bread-crumb.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2007 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * Author: Xan Lopez - * - * 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, or (at your option) any later version. - * - * 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-bread-crumb - * @short_description: Interface for elements in a #HildonBreadCrumbTrail - * - * #HildonBreadCrumb is an interface for creating new types of items - * for the #HildonBreadCrumbTrail widget. - */ - -#undef HILDON_DISABLE_DEPRECATED - -#include "hildon-bread-crumb.h" - -static void hildon_bread_crumb_base_init (gpointer g_class); - -GType -hildon_bread_crumb_get_type (void) -{ - static GType bread_crumb_type = 0; - - if (G_UNLIKELY (bread_crumb_type == 0)) - { - const GTypeInfo bread_crumb_info = - { - sizeof (HildonBreadCrumbIface), /* class_size */ - hildon_bread_crumb_base_init, /* base_init */ - NULL, /* base_finalize */ - NULL, - NULL, /* class_finalize */ - NULL, /* class_data */ - 0, - 0, - NULL - }; - - bread_crumb_type = - g_type_register_static (G_TYPE_INTERFACE, "HildonBreadCrumb", - &bread_crumb_info, 0); - - g_type_interface_add_prerequisite (bread_crumb_type, GTK_TYPE_WIDGET); - } - - return bread_crumb_type; -} - -static void -hildon_bread_crumb_base_init (gpointer g_class) -{ - static gboolean initialized = FALSE; - - if (initialized == FALSE) - { - g_signal_new ("crumb-activated", - HILDON_TYPE_BREAD_CRUMB, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (HildonBreadCrumbIface, crumb_activated), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - initialized = TRUE; - } -} - -/** - * hildon_bread_crumb_get_natural_size: - * @bread_crumb: A #HildonBreadCrumb - * @width: location to store the natural width request of the @bread_crumb - * @height: location to store the natural height request of the @bread_crumb - * - * Function to ask the @bread_crumb its preferred width and height requisition. - * Natural size is different to size_request in that it's not the minimum space - * the widget needs, but the ideal space it'd like to be allocated. For example, - * in the case of a label the natural size would be the width and height needed - * to show the full label without line breaks. - * - **/ - -void -hildon_bread_crumb_get_natural_size (HildonBreadCrumb *bread_crumb, - gint *width, - gint *height) -{ - g_return_if_fail (HILDON_IS_BREAD_CRUMB (bread_crumb)); - - (* HILDON_BREAD_CRUMB_GET_IFACE (bread_crumb)->get_natural_size) (bread_crumb, width, height); -} - -/** - * hildon_bread_crumb_activated: - * @bread_crumb: a #HildonBreadCrumb - * - * Emits the "crumb-activated" signal. The signal is meant to indicate that - * the user has interacted with the bread crumb. - **/ - -void -hildon_bread_crumb_activated (HildonBreadCrumb *bread_crumb) -{ - g_return_if_fail (HILDON_IS_BREAD_CRUMB (bread_crumb)); - - g_signal_emit_by_name (bread_crumb, "crumb-activated"); -} - - diff --git a/src/hildon-bread-crumb.h b/src/hildon-bread-crumb.h deleted file mode 100644 index 8ce0c83..0000000 --- a/src/hildon-bread-crumb.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2007 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * Author: Xan Lopez - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#ifndef __HILDON_BREAD_CRUMB_H__ -#define __HILDON_BREAD_CRUMB_H__ - -#include - -G_BEGIN_DECLS - -typedef struct _HildonBreadCrumb HildonBreadCrumb; -typedef struct _HildonBreadCrumbIface HildonBreadCrumbIface; - -#define HILDON_TYPE_BREAD_CRUMB (hildon_bread_crumb_get_type ()) -#define HILDON_BREAD_CRUMB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HILDON_TYPE_BREAD_CRUMB, HildonBreadCrumb)) -#define HILDON_BREAD_CRUMB_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), HILDON_TYPE_BREAD_CRUMB, HildonBreadCrumbIface)) -#define HILDON_IS_BREAD_CRUMB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_BREAD_CRUMB)) -#define HILDON_BREAD_CRUMB_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), HILDON_TYPE_BREAD_CRUMB, HildonBreadCrumbIface)) - -struct _HildonBreadCrumbIface -{ - GTypeInterface g_iface; - - /* virtual table */ - void (* get_natural_size) (HildonBreadCrumb *bread_crumb, - gint *natural_width, gint *natural_height); - /* signals */ - void (* crumb_activated) (HildonBreadCrumb *bread_crumb); -}; - -GType hildon_bread_crumb_get_type (void) G_GNUC_CONST; -void hildon_bread_crumb_get_natural_size (HildonBreadCrumb *bread_crumb, - gint *width, gint *height); -void hildon_bread_crumb_activated (HildonBreadCrumb *bread_crumb); - -G_END_DECLS - -#endif - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-button.c b/src/hildon-button.c deleted file mode 100644 index 7123152..0000000 --- a/src/hildon-button.c +++ /dev/null @@ -1,1022 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser Public License as published by - * the Free Software Foundation; version 2 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser Public License for more details. - * - */ - -/** - * SECTION:hildon-button - * @short_description: Widget representing a button in the Hildon framework. - * - * The #HildonButton is a GTK widget which represents a clickable - * button. It is derived from the #GtkButton widget and provides - * additional commodities specific to the Hildon framework. - * - * The height of a #HildonButton can be set to either "finger" height - * or "thumb" height. It can also be configured to use halfscreen or - * fullscreen width. Alternatively, either dimension can be set to - * "auto" so it behaves like a standard #GtkButton. - * - * The #HildonButton can hold any valid child widget, but it usually - * contains two labels, named title and value, and it can also contain - * an image. The contents of the button are packed together inside a - * #GtkAlignment and they do not expand by default (they don't use the - * full space of the button). - * - * To change the alignment of both labels, use gtk_button_set_alignment() - * - * To make them expand and use the full space of the button, use - * hildon_button_set_alignment(). - * - * To change the relative alignment of each label, use - * hildon_button_set_title_alignment() and - * hildon_button_set_value_alignment(). - * - * In hildon-button-example.c included in the Hildon distribution you - * can see examples of how to create the most common button - * layouts. - * - * If only one label is needed, #GtkButton can be used as well, see - * also hildon_gtk_button_new(). - * - * - * Creating a HildonButton - * - * void - * button_clicked (HildonButton *button, gpointer user_data) - * { - * const gchar *title, *value; - * - * title = hildon_button_get_title (button); - * value = hildon_button_get_value (button); - * g_debug ("Button clicked with title '%s' and value '%s'", title, value); - * } - * - * GtkWidget * - * create_button (void) - * { - * GtkWidget *button; - * GtkWidget *image; - * - * button = hildon_button_new (HILDON_SIZE_AUTO_WIDTH | HILDON_SIZE_FINGER_HEIGHT, - * HILDON_BUTTON_ARRANGEMENT_VERTICAL); - * hildon_button_set_text (HILDON_BUTTON (button), "Some title", "Some value"); - * - * image = gtk_image_new_from_stock (GTK_STOCK_INFO, GTK_ICON_SIZE_BUTTON); - * hildon_button_set_image (HILDON_BUTTON (button), image); - * hildon_button_set_image_position (HILDON_BUTTON (button), GTK_POS_RIGHT); - * - * gtk_button_set_alignment (GTK_BUTTON (button), 0.0, 0.5); - * - * g_signal_connect (button, "clicked", G_CALLBACK (button_clicked), NULL); - * - * return button; - * } - * - * - */ - -#include "hildon-button.h" -#include "hildon-enum-types.h" -#include "hildon-gtk.h" -#include "hildon-helper.h" - -G_DEFINE_TYPE (HildonButton, hildon_button, GTK_TYPE_BUTTON); - -#define HILDON_BUTTON_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_BUTTON, HildonButtonPrivate)); - -typedef struct _HildonButtonPrivate HildonButtonPrivate; - -struct _HildonButtonPrivate -{ - GtkLabel *title; - GtkLabel *value; - GtkBox *hbox; - GtkWidget *label_box; - GtkWidget *alignment; - GtkWidget *image; - GtkPositionType image_position; - gfloat image_xalign; - gfloat image_yalign; - HildonButtonStyle style; -}; - -enum { - PROP_TITLE = 1, - PROP_VALUE, - PROP_SIZE, - PROP_ARRANGEMENT, - PROP_STYLE -}; - -static void -hildon_button_set_arrangement (HildonButton *button, - HildonButtonArrangement arrangement); - -static void -hildon_button_construct_child (HildonButton *button); - -static void -hildon_button_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - HildonButton *button = HILDON_BUTTON (object); - - switch (prop_id) - { - case PROP_TITLE: - hildon_button_set_title (button, g_value_get_string (value)); - break; - case PROP_VALUE: - hildon_button_set_value (button, g_value_get_string (value)); - break; - case PROP_SIZE: - hildon_gtk_widget_set_theme_size (GTK_WIDGET (button), g_value_get_flags (value)); - break; - case PROP_ARRANGEMENT: - hildon_button_set_arrangement (button, g_value_get_enum (value)); - break; - case PROP_STYLE: - hildon_button_set_style (button, g_value_get_enum (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -hildon_button_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - HildonButton *button = HILDON_BUTTON (object); - - switch (prop_id) - { - case PROP_TITLE: - g_value_set_string (value, hildon_button_get_title (button)); - break; - case PROP_VALUE: - g_value_set_string (value, hildon_button_get_value (button)); - break; - case PROP_STYLE: - g_value_set_enum (value, hildon_button_get_style (button)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -hildon_button_style_set (GtkWidget *widget, - GtkStyle *previous_style) -{ - guint horizontal_spacing, vertical_spacing, image_spacing; - HildonButtonPrivate *priv = HILDON_BUTTON_GET_PRIVATE (widget); - - if (GTK_WIDGET_CLASS (hildon_button_parent_class)->style_set) - GTK_WIDGET_CLASS (hildon_button_parent_class)->style_set (widget, previous_style); - - gtk_widget_style_get (widget, - "horizontal-spacing", &horizontal_spacing, - "vertical-spacing", &vertical_spacing, - "image-spacing", &image_spacing, - NULL); - - if (GTK_IS_HBOX (priv->label_box)) { - gtk_box_set_spacing (GTK_BOX (priv->label_box), horizontal_spacing); - } else { - gtk_box_set_spacing (GTK_BOX (priv->label_box), vertical_spacing); - } - - if (GTK_IS_BOX (priv->hbox)) { - gtk_box_set_spacing (priv->hbox, image_spacing); - } -} - -static void -hildon_button_finalize (GObject *object) -{ - HildonButtonPrivate *priv = HILDON_BUTTON_GET_PRIVATE (object); - - g_object_unref (priv->alignment); - g_object_unref (priv->label_box); - - G_OBJECT_CLASS (hildon_button_parent_class)->finalize (object); -} - -static void -hildon_button_class_init (HildonButtonClass *klass) -{ - GObjectClass *gobject_class = (GObjectClass *)klass; - GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; - - gobject_class->set_property = hildon_button_set_property; - gobject_class->get_property = hildon_button_get_property; - gobject_class->finalize = hildon_button_finalize; - widget_class->style_set = hildon_button_style_set; - - g_object_class_install_property ( - gobject_class, - PROP_TITLE, - g_param_spec_string ( - "title", - "Title", - "Text of the title label inside the button", - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - gobject_class, - PROP_VALUE, - g_param_spec_string ( - "value", - "Value", - "Text of the value label inside the button", - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - gobject_class, - PROP_SIZE, - g_param_spec_flags ( - "size", - "Size", - "Size request for the button", - HILDON_TYPE_SIZE_TYPE, - HILDON_SIZE_AUTO, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property ( - gobject_class, - PROP_ARRANGEMENT, - g_param_spec_enum ( - "arrangement", - "Arrangement", - "How the button contents must be arranged", - HILDON_TYPE_BUTTON_ARRANGEMENT, - HILDON_BUTTON_ARRANGEMENT_HORIZONTAL, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property ( - gobject_class, - PROP_STYLE, - g_param_spec_enum ( - "style", - "Style", - "Visual style of the button", - HILDON_TYPE_BUTTON_STYLE, - HILDON_BUTTON_STYLE_NORMAL, - G_PARAM_READWRITE)); - - gtk_widget_class_install_style_property ( - widget_class, - g_param_spec_uint ( - "horizontal-spacing", - "Horizontal spacing between labels", - "Horizontal spacing between the title and value labels, when in horizontal mode", - 0, G_MAXUINT, 25, - G_PARAM_READABLE)); - - gtk_widget_class_install_style_property ( - widget_class, - g_param_spec_uint ( - "vertical-spacing", - "Vertical spacing between labels", - "Vertical spacing between the title and value labels, when in vertical mode", - 0, G_MAXUINT, 5, - G_PARAM_READABLE)); - - g_type_class_add_private (klass, sizeof (HildonButtonPrivate)); -} - -static void -hildon_button_init (HildonButton *self) -{ - HildonButtonPrivate *priv = HILDON_BUTTON_GET_PRIVATE (self); - - priv->title = GTK_LABEL (gtk_label_new (NULL)); - priv->value = GTK_LABEL (gtk_label_new (NULL)); - priv->alignment = gtk_alignment_new (0.5, 0.5, 0, 0); - priv->image = NULL; - priv->image_position = GTK_POS_LEFT; - priv->image_xalign = 0.5; - priv->image_yalign = 0.5; - priv->hbox = NULL; - priv->label_box = NULL; - - gtk_widget_set_name (GTK_WIDGET (priv->title), "hildon-button-title"); - gtk_widget_set_name (GTK_WIDGET (priv->value), "hildon-button-value"); - - hildon_button_set_style (self, HILDON_BUTTON_STYLE_NORMAL); - - gtk_misc_set_alignment (GTK_MISC (priv->title), 0, 0.5); - gtk_misc_set_alignment (GTK_MISC (priv->value), 0, 0.5); - - g_object_ref_sink (priv->alignment); - - /* The labels are not shown automatically, see hildon_button_set_(title|value) */ - gtk_widget_set_no_show_all (GTK_WIDGET (priv->title), TRUE); - gtk_widget_set_no_show_all (GTK_WIDGET (priv->value), TRUE); - - gtk_button_set_focus_on_click (GTK_BUTTON (self), FALSE); -} - -/** - * hildon_button_add_title_size_group: - * @button: a #HildonButton - * @size_group: A #GtkSizeGroup for the button title (main label) - * - * Adds the title label of @button to @size_group. - * - * Since: 2.2 - **/ -void -hildon_button_add_title_size_group (HildonButton *button, - GtkSizeGroup *size_group) -{ - HildonButtonPrivate *priv; - - g_return_if_fail (HILDON_IS_BUTTON (button)); - g_return_if_fail (GTK_IS_SIZE_GROUP (size_group)); - - priv = HILDON_BUTTON_GET_PRIVATE (button); - - gtk_size_group_add_widget (size_group, GTK_WIDGET (priv->title)); -} - -/** - * hildon_button_add_value_size_group: - * @button: a #HildonButton - * @size_group: A #GtkSizeGroup for the button value (secondary label) - * - * Adds the value label of @button to @size_group. - * - * Since: 2.2 - **/ -void -hildon_button_add_value_size_group (HildonButton *button, - GtkSizeGroup *size_group) -{ - HildonButtonPrivate *priv; - - g_return_if_fail (HILDON_IS_BUTTON (button)); - g_return_if_fail (GTK_IS_SIZE_GROUP (size_group)); - - priv = HILDON_BUTTON_GET_PRIVATE (button); - - gtk_size_group_add_widget (size_group, GTK_WIDGET (priv->value)); -} - -/** - * hildon_button_add_image_size_group: - * @button: a #HildonButton - * @size_group: A #GtkSizeGroup for the button image - * - * Adds the image of @button to @size_group. You must add an image - * using hildon_button_set_image() before calling this function. - * - * Since: 2.2 - **/ -void -hildon_button_add_image_size_group (HildonButton *button, - GtkSizeGroup *size_group) -{ - HildonButtonPrivate *priv; - - g_return_if_fail (HILDON_IS_BUTTON (button)); - g_return_if_fail (GTK_IS_SIZE_GROUP (size_group)); - - priv = HILDON_BUTTON_GET_PRIVATE (button); - - g_return_if_fail (GTK_IS_WIDGET (priv->image)); - - gtk_size_group_add_widget (size_group, GTK_WIDGET (priv->image)); -} - -/** - * hildon_button_add_size_groups: - * @button: a #HildonButton - * @title_size_group: A #GtkSizeGroup for the button title (main label), or %NULL - * @value_size_group: A #GtkSizeGroup group for the button value (secondary label), or %NULL - * @image_size_group: A #GtkSizeGroup group for the button image, or %NULL - * - * Convenience function to add title, value and image to size - * groups. %NULL size groups will be ignored. - * - * Since: 2.2 - **/ -void -hildon_button_add_size_groups (HildonButton *button, - GtkSizeGroup *title_size_group, - GtkSizeGroup *value_size_group, - GtkSizeGroup *image_size_group) -{ - if (title_size_group) - hildon_button_add_title_size_group (button, title_size_group); - - if (value_size_group) - hildon_button_add_value_size_group (button, value_size_group); - - if (image_size_group) - hildon_button_add_image_size_group (button, image_size_group); -} - -/** - * hildon_button_new: - * @size: Flags to set the size of the button. - * @arrangement: How the labels must be arranged. - * - * Creates a new #HildonButton. To set text in the labels, use - * hildon_button_set_title() and - * hildon_button_set_value(). Alternatively, you can add a custom - * child widget using gtk_container_add(). - * - * Returns: a new #HildonButton - * - * Since: 2.2 - **/ -GtkWidget * -hildon_button_new (HildonSizeType size, - HildonButtonArrangement arrangement) -{ - return hildon_button_new_with_text (size, arrangement, NULL, NULL); -} - -/** - * hildon_button_new_with_text: - * @size: Flags to set the size of the button. - * @arrangement: How the labels must be arranged. - * @title: Title of the button (main label), or %NULL - * @value: Value of the button (secondary label), or %NULL - * - * Creates a new #HildonButton with two labels, @title and @value. - * - * If you just don't want to use one of the labels, set it to - * %NULL. You can set it to a non-%NULL value at any time later using - * hildon_button_set_title() or hildon_button_set_value() . - * - * Returns: a new #HildonButton - * - * Since: 2.2 - **/ -GtkWidget * -hildon_button_new_with_text (HildonSizeType size, - HildonButtonArrangement arrangement, - const gchar *title, - const gchar *value) -{ - GtkWidget *button; - - /* Create widget */ - button = g_object_new (HILDON_TYPE_BUTTON, - "size", size, - "title", title, - "value", value, - "arrangement", arrangement, - NULL); - - return button; -} - -static void -hildon_button_set_arrangement (HildonButton *button, - HildonButtonArrangement arrangement) -{ - HildonButtonPrivate *priv; - - priv = HILDON_BUTTON_GET_PRIVATE (button); - - /* Pack everything */ - if (arrangement == HILDON_BUTTON_ARRANGEMENT_VERTICAL) { - priv->label_box = gtk_vbox_new (FALSE, 0); - hildon_helper_set_logical_font (GTK_WIDGET (priv->value), "SmallSystemFont"); - } else { - priv->label_box = gtk_hbox_new (FALSE, 0); - } - - g_object_ref_sink (priv->label_box); - - /* If we pack both labels with (TRUE, TRUE) or (FALSE, FALSE) they - * can be painted outside of the button in some situations, see - * NB#88126 and NB#110689 */ - gtk_box_pack_start (GTK_BOX (priv->label_box), GTK_WIDGET (priv->title), FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (priv->label_box), GTK_WIDGET (priv->value), TRUE, TRUE, 0); - - hildon_button_construct_child (button); -} - -/** - * hildon_button_set_title: - * @button: a #HildonButton - * @title: a new title (main label) for the button, or %NULL - * - * Sets the title (main label) of @button to @title. - * - * This will clear any previously set title. - * - * If @title is set to %NULL, the title label will be hidden and the - * value label will be realigned. - * - * Since: 2.2 - **/ -void -hildon_button_set_title (HildonButton *button, - const gchar *title) -{ - HildonButtonPrivate *priv; - - g_return_if_fail (HILDON_IS_BUTTON (button)); - - priv = HILDON_BUTTON_GET_PRIVATE (button); - gtk_label_set_text (priv->title, title); - - /* If the button has no title, hide the label so the value is - * properly aligned */ - if (title) { - hildon_button_construct_child (button); - gtk_widget_show (GTK_WIDGET (priv->title)); - } else { - gtk_widget_hide (GTK_WIDGET (priv->title)); - } - - g_object_notify (G_OBJECT (button), "title"); -} - -/** - * hildon_button_set_value: - * @button: a #HildonButton - * @value: a new value (secondary label) for the button, or %NULL - * - * Sets the value (secondary label) of @button to @value. - * - * This will clear any previously set value. - * - * If @value is set to %NULL, the value label will be hidden and the - * title label will be realigned. - * - * Since: 2.2 - **/ -void -hildon_button_set_value (HildonButton *button, - const gchar *value) -{ - HildonButtonPrivate *priv; - - g_return_if_fail (HILDON_IS_BUTTON (button)); - - priv = HILDON_BUTTON_GET_PRIVATE (button); - gtk_label_set_text (priv->value, value); - - /* If the button has no value, hide the label so the title is - * properly aligned */ - if (value) { - hildon_button_construct_child (button); - gtk_widget_show (GTK_WIDGET (priv->value)); - } else { - gtk_widget_hide (GTK_WIDGET (priv->value)); - } - - g_object_notify (G_OBJECT (button), "value"); -} - -/** - * hildon_button_get_title: - * @button: a #HildonButton - * - * Fetches the text from the main label (title) of @button, - * as set by hildon_button_set_title() or hildon_button_set_text(). - * If the label text has not been set the return value will be %NULL. - * This will be the case if you create an empty button with - * hildon_button_new() to use as a container. - * - * Returns: The text of the title label. This string is owned by the - * widget and must not be modified or freed. - * - * Since: 2.2 - **/ -const gchar * -hildon_button_get_title (HildonButton *button) -{ - HildonButtonPrivate *priv; - - g_return_val_if_fail (HILDON_IS_BUTTON (button), NULL); - - priv = HILDON_BUTTON_GET_PRIVATE (button); - - return gtk_label_get_text (priv->title); -} - -/** - * hildon_button_get_value: - * @button: a #HildonButton - * - * Fetches the text from the secondary label (value) of @button, - * as set by hildon_button_set_value() or hildon_button_set_text(). - * If the label text has not been set the return value will be %NULL. - * This will be the case if you create an empty button with hildon_button_new() - * to use as a container. - * - * Returns: The text of the value label. This string is owned by the - * widget and must not be modified or freed. - * - * Since: 2.2 - **/ -const gchar * -hildon_button_get_value (HildonButton *button) -{ - HildonButtonPrivate *priv; - - g_return_val_if_fail (HILDON_IS_BUTTON (button), NULL); - - priv = HILDON_BUTTON_GET_PRIVATE (button); - - return gtk_label_get_text (priv->value); -} - -/** - * hildon_button_set_text: - * @button: a #HildonButton - * @title: new text for the button title (main label) - * @value: new text for the button value (secondary label) - * - * Convenience function to change both labels of a #HildonButton - * - * Since: 2.2 - **/ -void -hildon_button_set_text (HildonButton *button, - const gchar *title, - const gchar *value) -{ - hildon_button_set_title (button, title); - hildon_button_set_value (button, value); -} - -/** - * hildon_button_set_image: - * @button: a #HildonButton - * @image: a widget to set as the button image - * - * Sets the image of @button to the given widget. The previous image - * (if any) will be removed. - * - * Since: 2.2 - **/ -void -hildon_button_set_image (HildonButton *button, - GtkWidget *image) -{ - HildonButtonPrivate *priv; - - g_return_if_fail (HILDON_IS_BUTTON (button)); - g_return_if_fail (!image || GTK_IS_WIDGET (image)); - - priv = HILDON_BUTTON_GET_PRIVATE (button); - - /* Return if there's nothing to do */ - if (image == priv->image) - return; - - if (priv->image && priv->image->parent) - gtk_container_remove (GTK_CONTAINER (priv->image->parent), priv->image); - - priv->image = image; - - hildon_button_construct_child (button); -} - -/** - * hildon_button_get_image: - * @button: a #HildonButton - * - * Gets the widget that is currenty set as the image of @button, - * previously set with hildon_button_set_image() - * - * Returns: a #GtkWidget or %NULL in case there is no image - * - * Since: 2.2 - **/ -GtkWidget * -hildon_button_get_image (HildonButton *button) -{ - HildonButtonPrivate *priv; - - g_return_val_if_fail (HILDON_IS_BUTTON (button), NULL); - - priv = HILDON_BUTTON_GET_PRIVATE (button); - - return priv->image; -} - -/** - * hildon_button_set_image_position: - * @button: a #HildonButton - * @position: the position of the image (%GTK_POS_LEFT or %GTK_POS_RIGHT) - * - * Sets the position of the image inside @button. Only %GTK_POS_LEFT - * and %GTK_POS_RIGHT are currently supported. - * - * Since: 2.2 - **/ -void -hildon_button_set_image_position (HildonButton *button, - GtkPositionType position) -{ - HildonButtonPrivate *priv; - - g_return_if_fail (HILDON_IS_BUTTON (button)); - g_return_if_fail (position == GTK_POS_LEFT || position == GTK_POS_RIGHT); - - priv = HILDON_BUTTON_GET_PRIVATE (button); - - /* Return if there's nothing to do */ - if (priv->image_position == position) - return; - - priv->image_position = position; - - hildon_button_construct_child (button); -} - -/** - * hildon_button_set_alignment: - * @button: a #HildonButton - * @xalign: the horizontal alignment of the contents, from 0 (left) to 1 (right). - * @yalign: the vertical alignment of the contents, from 0 (top) to 1 (bottom). - * @xscale: the amount that the child widget expands horizontally to fill up unused space, from 0 to 1 - * @yscale: the amount that the child widget expands vertically to fill up unused space, from 0 to 1 - * - * Sets the alignment of the contents of the widget. If you don't need - * to change @xscale or @yscale you can just use - * gtk_button_set_alignment() instead. - * - * Note that for this method to work properly the, child widget of - * @button must be a #GtkAlignment. That's what #HildonButton uses by - * default, so this function will work unless you add a custom widget - * to @button. - * - * Since: 2.2 - **/ -void -hildon_button_set_alignment (HildonButton *button, - gfloat xalign, - gfloat yalign, - gfloat xscale, - gfloat yscale) -{ - HildonButtonPrivate *priv; - GtkWidget *child; - - g_return_if_fail (HILDON_IS_BUTTON (button)); - - priv = HILDON_BUTTON_GET_PRIVATE (button); - - child = gtk_bin_get_child (GTK_BIN (button)); - - /* If the button has no child, use priv->alignment, which is the default one */ - if (child == NULL) - child = priv->alignment; - - if (GTK_IS_ALIGNMENT (child)) { - gtk_alignment_set (GTK_ALIGNMENT (priv->alignment), xalign, yalign, xscale, yscale); - } -} - -/** - * hildon_button_set_title_alignment: - * @button: a #HildonButton - * @xalign: the horizontal alignment of the title label, from 0 (left) to 1 (right). - * @yalign: the vertical alignment of the title label, from 0 (top) to 1 (bottom). - * - * Sets the alignment of the title label. See also - * hildon_button_set_alignment() to set the alignment of the whole - * contents of the button. - * - * Since: 2.2 - **/ -void -hildon_button_set_title_alignment (HildonButton *button, - gfloat xalign, - gfloat yalign) -{ - HildonButtonPrivate *priv; - - g_return_if_fail (HILDON_IS_BUTTON (button)); - - priv = HILDON_BUTTON_GET_PRIVATE (button); - - gtk_misc_set_alignment (GTK_MISC (priv->title), xalign, yalign); -} - -/** - * hildon_button_set_value_alignment: - * @button: a #HildonButton - * @xalign: the horizontal alignment of the value label, from 0 (left) to 1 (right). - * @yalign: the vertical alignment of the value label, from 0 (top) to 1 (bottom). - * - * Sets the alignment of the value label. See also - * hildon_button_set_alignment() to set the alignment of the whole - * contents of the button. - * - * Since: 2.2 - **/ -void -hildon_button_set_value_alignment (HildonButton *button, - gfloat xalign, - gfloat yalign) -{ - HildonButtonPrivate *priv; - - g_return_if_fail (HILDON_IS_BUTTON (button)); - - priv = HILDON_BUTTON_GET_PRIVATE (button); - - gtk_misc_set_alignment (GTK_MISC (priv->value), xalign, yalign); -} - -/** - * hildon_button_set_image_alignment: - * @button: a #HildonButton - * @xalign: the horizontal alignment of the image, from 0 (left) to 1 (right). - * @yalign: the vertical alignment of the image, from 0 (top) to 1 (bottom). - * - * Sets the alignment of the image. See also - * hildon_button_set_alignment() to set the alignment of the whole - * contents of the button. - * - * Since: 2.2 - **/ -void -hildon_button_set_image_alignment (HildonButton *button, - gfloat xalign, - gfloat yalign) -{ - HildonButtonPrivate *priv; - - g_return_if_fail (HILDON_IS_BUTTON (button)); - - priv = HILDON_BUTTON_GET_PRIVATE (button); - - /* Return if there's nothing to do */ - if (priv->image_xalign == xalign && priv->image_yalign == yalign) - return; - - priv->image_xalign = xalign; - priv->image_yalign = yalign; - - hildon_button_construct_child (button); -} - -/** - * hildon_button_set_style: - * @button: A #HildonButton - * @style: A #HildonButtonStyle for @button - * - * Sets the style of @button to @style. This changes the visual - * appearance of the button (colors, font sizes) according to the - * particular style chosen, but the general layout is not altered. - * - * Use %HILDON_BUTTON_STYLE_NORMAL to make it look like a normal - * #HildonButton, or %HILDON_BUTTON_STYLE_PICKER to make it look like - * a #HildonPickerButton. - * - * Since: 2.2 - */ -void -hildon_button_set_style (HildonButton *button, - HildonButtonStyle style) -{ - HildonButtonPrivate *priv; - const gchar *color; - - g_return_if_fail (HILDON_IS_BUTTON (button)); - - switch (style) { - case HILDON_BUTTON_STYLE_NORMAL: - color = "SecondaryTextColor"; - break; - case HILDON_BUTTON_STYLE_PICKER: - color = "ActiveTextColor"; - break; - default: - g_return_if_reached (); - } - - priv = HILDON_BUTTON_GET_PRIVATE (button); - - hildon_helper_set_logical_color (GTK_WIDGET (priv->value), GTK_RC_FG, GTK_STATE_NORMAL, color); - hildon_helper_set_logical_color (GTK_WIDGET (priv->value), GTK_RC_FG, GTK_STATE_PRELIGHT, color); - - priv->style = style; - - g_object_notify (G_OBJECT (button), "style"); -} - -/** - * hildon_button_get_style: - * @button: A #HildonButton - * - * Gets the visual style of the button. - * - * Returns: a #HildonButtonStyle - * - * Since: 2.2 - */ -HildonButtonStyle -hildon_button_get_style (HildonButton *button) -{ - HildonButtonPrivate *priv; - - g_return_val_if_fail (HILDON_IS_BUTTON (button), HILDON_BUTTON_STYLE_NORMAL); - - priv = HILDON_BUTTON_GET_PRIVATE (button); - - return priv->style; -} - -static void -hildon_button_construct_child (HildonButton *button) -{ - HildonButtonPrivate *priv = HILDON_BUTTON_GET_PRIVATE (button); - GtkWidget *child; - gint image_spacing; - const gchar *title, *value; - - /* Don't do anything if the button is not constructed yet */ - if (G_UNLIKELY (priv->label_box == NULL)) - return; - - /* Don't do anything if the button has no contents */ - title = gtk_label_get_text (priv->title); - value = gtk_label_get_text (priv->value); - if (!priv->image && !title[0] && !value[0]) - return; - - /* Save a ref to the image, and remove it from its container if necessary */ - if (priv->image) { - g_object_ref (priv->image); - if (priv->image->parent != NULL) - gtk_container_remove (GTK_CONTAINER (priv->image->parent), priv->image); - } - - if (priv->label_box->parent != NULL) { - gtk_container_remove (GTK_CONTAINER (priv->label_box->parent), priv->label_box); - } - - /* Remove the child from the container and add priv->alignment */ - child = gtk_bin_get_child (GTK_BIN (button)); - if (child != NULL && child != priv->alignment) { - gtk_container_remove (GTK_CONTAINER (button), child); - child = NULL; - } - - if (child == NULL) { - gtk_container_add (GTK_CONTAINER (button), GTK_WIDGET (priv->alignment)); - } - - /* Create a new hbox */ - if (priv->hbox) { - gtk_container_remove (GTK_CONTAINER (priv->alignment), GTK_WIDGET (priv->hbox)); - } - gtk_widget_style_get (GTK_WIDGET (button), "image-spacing", &image_spacing, NULL); - priv->hbox = GTK_BOX (gtk_hbox_new (FALSE, image_spacing)); - gtk_container_add (GTK_CONTAINER (priv->alignment), GTK_WIDGET (priv->hbox)); - - /* Pack the image and the alignment in the new hbox */ - if (priv->image && priv->image_position == GTK_POS_LEFT) - gtk_box_pack_start (priv->hbox, priv->image, FALSE, FALSE, 0); - - gtk_box_pack_start (priv->hbox, priv->label_box, TRUE, TRUE, 0); - - if (priv->image && priv->image_position == GTK_POS_RIGHT) - gtk_box_pack_start (priv->hbox, priv->image, FALSE, FALSE, 0); - - /* Set image alignment and remove previously set ref */ - if (priv->image) { - gtk_misc_set_alignment (GTK_MISC (priv->image), priv->image_xalign, priv->image_yalign); - g_object_unref (priv->image); - } - - /* Show everything */ - gtk_widget_show_all (GTK_WIDGET (priv->alignment)); -} diff --git a/src/hildon-button.h b/src/hildon-button.h deleted file mode 100644 index d3b703c..0000000 --- a/src/hildon-button.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser Public License as published by - * the Free Software Foundation; version 2 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser Public License for more details. - * - */ - -#ifndef __HILDON_BUTTON_H__ -#define __HILDON_BUTTON_H__ - -#include "hildon-gtk.h" - -G_BEGIN_DECLS - -#define HILDON_TYPE_BUTTON \ - (hildon_button_get_type()) - -#define HILDON_BUTTON(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - HILDON_TYPE_BUTTON, HildonButton)) - -#define HILDON_BUTTON_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - HILDON_TYPE_BUTTON, HildonButtonClass)) - -#define HILDON_IS_BUTTON(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_BUTTON)) - -#define HILDON_IS_BUTTON_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_BUTTON)) - -#define HILDON_BUTTON_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - HILDON_TYPE_BUTTON, HildonButtonClass)) - -typedef struct _HildonButton HildonButton; - -typedef struct _HildonButtonClass HildonButtonClass; - -struct _HildonButtonClass -{ - GtkButtonClass parent_class; -}; - -struct _HildonButton -{ - GtkButton parent; -}; - - -/** - * HildonButtonArrangement: - * @HILDON_BUTTON_ARRANGEMENT_HORIZONTAL: Labels are arranged from left to right - * @HILDON_BUTTON_ARRANGEMENT_VERTICAL: Labels are arranged from top to bottom - * - * Describes the arrangement of labels inside a #HildonButton - * - **/ -typedef enum { - HILDON_BUTTON_ARRANGEMENT_HORIZONTAL, - HILDON_BUTTON_ARRANGEMENT_VERTICAL -} HildonButtonArrangement; - -/** - * HildonButtonStyle: - * @HILDON_BUTTON_STYLE_NORMAL: The button will look like a normal #HildonButton - * @HILDON_BUTTON_STYLE_PICKER: The button will look like a #HildonPickerButton - * - * Describes the visual style of a #HildonButton - **/ -typedef enum { - HILDON_BUTTON_STYLE_NORMAL, - HILDON_BUTTON_STYLE_PICKER -} HildonButtonStyle; - -GType -hildon_button_get_type (void) G_GNUC_CONST; - -GtkWidget * -hildon_button_new (HildonSizeType size, - HildonButtonArrangement arrangement); - -GtkWidget * -hildon_button_new_with_text (HildonSizeType size, - HildonButtonArrangement arrangement, - const gchar *title, - const gchar *value); - -void -hildon_button_set_title (HildonButton *button, - const gchar *title); - -void -hildon_button_set_value (HildonButton *button, - const gchar *value); - -const gchar * -hildon_button_get_title (HildonButton *button); - -const gchar * -hildon_button_get_value (HildonButton *button); - -void -hildon_button_set_text (HildonButton *button, - const gchar *title, - const gchar *value); - -void -hildon_button_set_image (HildonButton *button, - GtkWidget *image); - -GtkWidget * -hildon_button_get_image (HildonButton *button); - -void -hildon_button_set_image_position (HildonButton *button, - GtkPositionType position); - -void -hildon_button_set_alignment (HildonButton *button, - gfloat xalign, - gfloat yalign, - gfloat xscale, - gfloat yscale); -void -hildon_button_set_title_alignment (HildonButton *button, - gfloat xalign, - gfloat yalign); - -void -hildon_button_set_value_alignment (HildonButton *button, - gfloat xalign, - gfloat yalign); - -void -hildon_button_set_image_alignment (HildonButton *button, - gfloat xalign, - gfloat yalign); - -void -hildon_button_add_title_size_group (HildonButton *button, - GtkSizeGroup *size_group); -void -hildon_button_add_value_size_group (HildonButton *button, - GtkSizeGroup *size_group); - -void -hildon_button_add_image_size_group (HildonButton *button, - GtkSizeGroup *size_group); - -void -hildon_button_add_size_groups (HildonButton *button, - GtkSizeGroup *title_size_group, - GtkSizeGroup *value_size_group, - GtkSizeGroup *image_size_group); - -void -hildon_button_set_style (HildonButton *button, - HildonButtonStyle style); - -HildonButtonStyle -hildon_button_get_style (HildonButton *button); - -G_END_DECLS - -#endif /* __HILDON_BUTTON_H__ */ diff --git a/src/hildon-calendar-popup-private.h b/src/hildon-calendar-popup-private.h deleted file mode 100644 index b237576..0000000 --- a/src/hildon-calendar-popup-private.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_PRIVATE_H__ -#define __HILDON_CALENDAR_POPUP_PRIVATE_H__ - -#include - -G_BEGIN_DECLS - -typedef struct _HildonCalendarPopupPrivate HildonCalendarPopupPrivate; - -#define HILDON_CALENDAR_POPUP_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), HILDON_TYPE_CALENDAR_POPUP, HildonCalendarPopupPrivate)); - -struct _HildonCalendarPopupPrivate -{ - GtkWidget *cal; -}; - -G_END_DECLS - -#endif /* __HILDON_CALENDAR_POPUP_PRIVATE_H__ */ diff --git a/src/hildon-calendar-popup.c b/src/hildon-calendar-popup.c deleted file mode 100644 index 1396a31..0000000 --- a/src/hildon-calendar-popup.c +++ /dev/null @@ -1,528 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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 - * @short_description: CalendarPopup allows choosing a date from a popup calendar. - * @see_also: #HildonDateEditor, #HildonTimeEditor - * - * HildonCalendarPopup is a dialog which contains a HildonCalendar. It - * also contains arrow buttons for changing the month/year. If an - * entered date is invalid, an information message will be shown. - * - * - * - * #HildonCalendarPopup has been deprecated since Hildon 2.2 and should not - * be used in newly written code. - * See Migrating Date Widgets - * section to know how to migrate this deprecated widget. - * - * - * - * - * HildonCalendarPopup example - * - * ... - * gint y, m, d; - * GtkWidget *parent, *popup; - * - * // get current date into &y, &m, &d... - * - * gtk_widget_get_ancestor (GTK_WIDGET (data), GTK_TYPE_WINDOW); - * popup = hildon_calendar_popup_new (GTK_WINDOW (parent), y, m, d); - * - * 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); - * - * // here set the new date - * } - * gtk_widget_destroy(popup); - * ... - * - * - * - */ - - -#undef HILDON_DISABLE_DEPRECATED - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include -#include - -#include "hildon-calendar-popup.h" -#include "hildon-calendar-popup-private.h" -#include "hildon-calendar.h" - -#define _(String)\ - dgettext("hildon-libs", String) - -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); - -static GtkDialog* parent_class; - -enum -{ - PROP_0, - PROP_DAY, - PROP_MONTH, - PROP_YEAR, - PROP_MIN_YEAR, - PROP_MAX_YEAR -}; - -GType G_GNUC_CONST -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); - g_assert (priv); - - /* Choose current date if the date is invalid: */ - init_dmy (year, month, day, &dtmp, &mtmp, &ytmp); - - /* Remove all visual markers */ - hildon_calendar_clear_marks (HILDON_CALENDAR (priv->cal)); - - /* Set a new date */ - hildon_calendar_select_month (HILDON_CALENDAR (priv->cal), mtmp - 1, ytmp); - hildon_calendar_select_day (HILDON_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. - * It's possible to pass NULL to any of the pointers if you don't need that data. - */ -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); - g_assert (priv); - - hildon_calendar_get_date (HILDON_CALENDAR (priv->cal), year, month, day); - if (month != NULL) - *month = *month + 1; - - if (day != NULL && - month != NULL && - year != NULL && - ! 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, 10000, - 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, 10000, - 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); - g_assert (priv); - - /* set the domain directory for different language */ - /* FIXME I can't exactly figure out why is this here... */ - if (set_domain) { - (void) bindtextdomain ("hildon-libs", LOCALEDIR); - set_domain = 0; - } - - priv->cal = hildon_calendar_new (); - - /* dialog options and packing */ - hildon_calendar_set_display_options (HILDON_CALENDAR (priv->cal), - HILDON_CALENDAR_SHOW_HEADING | - HILDON_CALENDAR_SHOW_DAY_NAMES | - HILDON_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), _("wdgt_bd_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 */ - /* FIXME That should be moved to on_realize */ - 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) -{ - g_assert (d != NULL); - g_assert (m != NULL); - g_assert (y != NULL); - - 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. */ -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)); - g_assert (priv); - - 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)); - g_assert (priv); - - 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 deleted file mode 100644 index 99810e5..0000000 --- a/src/hildon-calendar-popup.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#ifndef __HILDON_CALENDAR_POPUP_H__ -#define __HILDON_CALENDAR_POPUP_H__ - -#include - -G_BEGIN_DECLS - -typedef struct _HildonCalendarPopup HildonCalendarPopup; - -typedef struct _HildonCalendarPopupClass HildonCalendarPopupClass; - -#define HILDON_TYPE_CALENDAR_POPUP \ - (hildon_calendar_popup_get_type()) - -#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)) - -#define HILDON_CALENDAR_POPUP_GET_CLASS(obj) \ - ((HildonCalendarPopupClass *) G_OBJECT_GET_CLASS(obj)) - -struct _HildonCalendarPopup -{ - GtkDialog parent; -}; - -struct _HildonCalendarPopupClass -{ - GtkDialogClass parent_class; -}; - -GType G_GNUC_CONST -hildon_calendar_popup_get_type (void); - -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__ */ - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-calendar-private.h b/src/hildon-calendar-private.h deleted file mode 100644 index 4d01ac4..0000000 --- a/src/hildon-calendar-private.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_PRIVATE_H__ -#define __HILDON_CALENDAR_PRIVATE_H__ - -#include - -G_BEGIN_DECLS - -#define HILDON_CALENDAR_GET_PRIVATE(widget) \ - (((HildonCalendarPrivate*)(HILDON_CALENDAR (widget)->private_data))) - -typedef struct _HildonCalendarPrivate HildonCalendarPrivate; - -struct _HildonCalendarPrivate -{ - GdkWindow *header_win; - GdkWindow *footer_win; - GdkWindow *day_name_win; - GdkWindow *main_win; - GdkWindow *week_win; - GdkWindow *arrow_win[4]; - - gint year_before; - guint header_h; - guint day_name_h; - guint main_h; - - guint arrow_state[4]; - /* guint arrow_width; This is now defined constant. Even normal Gtk don't allow to change this */ - guint arrow_width; - guint max_month_width; - guint max_year_width; - - guint day_width; - guint week_width; - - guint min_day_width; - guint max_day_char_width; - guint max_day_char_ascent; - guint max_day_char_descent; - guint max_label_char_ascent; - guint max_label_char_descent; - guint max_week_char_width; - - guint freeze_count; - - /* flags */ - guint dirty_header : 1; - guint dirty_day_names : 1; - guint dirty_main : 1; - guint dirty_week : 1; - - /* guint year_before : 1;*/ - - guint need_timer : 1; - - guint in_drag : 1; - guint drag_highlight : 1; - - guint32 timer; - gint click_child; - - /* Following variables are for current date */ - guint current_day; - guint current_month; - guint current_year; - - /* Keep track of day and month - * where mouse button was pressed - */ - guint pressed_day; - guint pressed_month; - - /* Boolean value to indicate if - * out of bound day was selected - */ - gboolean is_bad_day; - - /* Must check if we are sliding stylus */ - gboolean slide_stylus; - gint prev_row; - gint prev_col; - - gint week_start; - - gint drag_start_x; - gint drag_start_y; - - gint min_year; - gint max_year; - - char *abbreviated_dayname[7]; - char *monthname[12]; -}; - -G_END_DECLS - -#endif /* __HILDON_CALENDAR_PRIVATE_H__ */ diff --git a/src/hildon-calendar.c b/src/hildon-calendar.c deleted file mode 100644 index bb4416c..0000000 --- a/src/hildon-calendar.c +++ /dev/null @@ -1,4307 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald - * - * GTK Calendar Widget - * Copyright (C) 1998 Cesar Miquel, Shawn T. Amundson and Mattias Groenlund - * - * lib_date routines - * Copyright (C) 1995, 1996, 1997, 1998 by Steffen Beyer - * - * HldonCalendar modifications - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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; either - * version 2 of the License, or (at your option) any later version. or (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS - * file for a list of people on the GTK+ Team. See the ChangeLog - * files for a list of changes. These files are distributed with - * GTK+ at ftp://ftp.gtk.org/pub/gtk/. - */ - -/** - * SECTION:hildon-calendar - * @short_description: A calendar widget - * - * #HildonCalendar is a slightly modified #GtkCalendar. It has an almost same API - * but a slightly different look and behaviour. Use this widget instead of - * standard #GtkCalendar or use #HildonDateEditor for more higher-level date setting - * operations. - * - * - * - * #HildonCalendar has been deprecated since Hildon 2.2 - * See Migrating Date Widgets - * section to know how to migrate this deprecated widget. - * - * - */ - -#undef HILDON_DISABLE_DEPRECATED - -#ifdef HAVE_CONFIG_H -#include -#endif - -#define _GNU_SOURCE /* needed for GNU nl_langinfo_l */ - -#include - -#ifdef HAVE_SYS_TIME_H -#include -#endif - -#include -#include -#include -#include - -#include -#include -#include - -#include "hildon-calendar.h" -#include "hildon-marshalers.h" -#include "hildon-calendar-private.h" - -/***************************************************************************/ -/* The following date routines are taken from the lib_date package. Keep - * them separate in case we want to update them if a newer lib_date comes - * out with fixes. */ - -typedef unsigned int N_int; - -typedef unsigned long N_long; - -typedef signed long Z_long; - -typedef enum { false = FALSE , true = TRUE } boolean; - -#define and && /* logical (boolean) operators: lower case */ - -#define or || - -static const N_int month_length [2][13] = -{ - { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, - { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } -}; - -static const N_int days_in_months[2][14] = -{ - { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, - { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } -}; - -static Z_long calc_days (N_int year, N_int mm, N_int dd); - -static N_int day_of_week (N_int year, N_int mm, N_int dd); - -static Z_long dates_difference (N_int year1, N_int mm1, N_int dd1, - N_int year2, N_int mm2, N_int dd2); - -static N_int weeks_in_year (N_int year); - -static boolean -leap (N_int year) -{ - return ((((year % 4) == 0) and ((year % 100) != 0)) or ((year % 400) == 0)); -} - -static N_int -day_of_week (N_int year, - N_int mm, - N_int dd) -{ - Z_long days; - - days = calc_days (year, mm, dd); - if (days > 0L) - { - days--; - days %= 7L; - days++; - } - return( (N_int) days ); -} - -static N_int -weeks_in_year (N_int year) -{ - return (52 + ((day_of_week(year,1,1)==4) or (day_of_week(year,12,31)==4))); -} - -static boolean -check_date (N_int year, - N_int mm, - N_int dd) -{ - if (year < 1) return(false); - if ((mm < 1) or (mm > 12)) return(false); - if ((dd < 1) or (dd > month_length[leap(year)][mm])) return(false); - return(true); -} - -static N_int -week_number (N_int year, - N_int mm, - N_int dd) -{ - N_int first; - - first = day_of_week (year,1,1) - 1; - return( (N_int) ( (dates_difference(year,1,1, year,mm,dd) + first) / 7L ) + - (first < 4) ); -} - -static Z_long -year_to_days (N_int year) -{ - return ( year * 365L + (year / 4) - (year / 100) + (year / 400) ); -} - -static Z_long -calc_days (N_int year, - N_int mm, - N_int dd) -{ - boolean lp; - - if (year < 1) return(0L); - if ((mm < 1) or (mm > 12)) return(0L); - if ((dd < 1) or (dd > month_length[(lp = leap(year))][mm])) return(0L); - return( year_to_days(--year) + days_in_months[lp][mm] + dd ); -} - -static boolean -week_of_year (N_int *week, - N_int *year, - N_int mm, - N_int dd) -{ - if (check_date(*year,mm,dd)) - { - *week = week_number(*year,mm,dd); - if (*week == 0) - *week = weeks_in_year(--(*year)); - else if (*week > weeks_in_year(*year)) - { - *week = 1; - (*year)++; - } - return(true); - } - return(false); -} - -static Z_long -dates_difference (N_int year1, - N_int mm1, - N_int dd1, - N_int year2, - N_int mm2, - N_int dd2) -{ - return (calc_days (year2, mm2, dd2) - calc_days (year1, mm1, dd1)); -} - -/*** END OF lib_date routines ********************************************/ - -/* HILDON: Spacings modified */ -#define HILDON_ARROW_SEP 5 /* Space between arrows and data */ - -#define HILDON_DAY_WIDTH 26 - -#define HILDON_DAY_HEIGHT 25 - -/* additional widths given to week number and day windows */ - -#define HILDON_WEEKS_EXTRA_WIDTH 8 - -#define HILDON_DAYS_EXTRA_WIDTH 8 - -/* Spacing around day/week headers and main area, inside those windows */ - -#define CALENDAR_MARGIN 0 - -/* Spacing around day/week headers and main area, outside those windows */ - -#define INNER_BORDER 0 /* 4 */ - -/* Separation between day headers and main area */ - -#define CALENDAR_YSEP 3 /* 4 */ - -/* Separation between week headers and main area */ - -#define CALENDAR_XSEP 6 /* 4 */ - -#define DAY_XSEP 0 /* not really good for small calendar */ - -#define DAY_YSEP 0 /* not really good for small calendar */ - -/* Color usage */ -#define HEADER_FG_COLOR(widget) \ - (& (widget)->style->fg[GTK_WIDGET_STATE (widget)]) - -#define HEADER_BG_COLOR(widget) \ - (& (widget)->style->bg[GTK_WIDGET_STATE (widget)]) - -#define SELECTED_BG_COLOR(widget) \ - (& (widget)->style->base[GTK_WIDGET_HAS_FOCUS (widget) ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE]) - -#define SELECTED_FG_COLOR(widget) \ - (& (widget)->style->text[GTK_WIDGET_HAS_FOCUS (widget) ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE]) - -#define NORMAL_DAY_COLOR(widget) \ - (& (widget)->style->fg[GTK_WIDGET_STATE (widget)]) - -#define PREV_MONTH_COLOR(widget) \ - (& (widget)->style->mid[GTK_WIDGET_STATE (widget)]) - -#define NEXT_MONTH_COLOR(widget) \ - (& (widget)->style->mid[GTK_WIDGET_STATE (widget)]) - -#define MARKED_COLOR(widget) \ - (& (widget)->style->fg[GTK_WIDGET_STATE (widget)]) - -#define BACKGROUND_COLOR(widget) \ - (& (widget)->style->base[GTK_WIDGET_STATE (widget)]) - -#define HIGHLIGHT_BACK_COLOR(widget) \ - (& (widget)->style->mid[GTK_WIDGET_STATE (widget)]) - -#define CALENDAR_INITIAL_TIMER_DELAY 200 - -#define CALENDAR_TIMER_DELAY 20 - -enum { - ARROW_YEAR_LEFT, - ARROW_YEAR_RIGHT, - ARROW_MONTH_LEFT, - ARROW_MONTH_RIGHT -}; - -enum { - MONTH_PREV, - MONTH_CURRENT, - MONTH_NEXT -}; - -enum { - MONTH_CHANGED_SIGNAL, - DAY_SELECTED_SIGNAL, - DAY_SELECTED_DOUBLE_CLICK_SIGNAL, - PREV_MONTH_SIGNAL, - NEXT_MONTH_SIGNAL, - PREV_YEAR_SIGNAL, - NEXT_YEAR_SIGNAL, - ERRONEOUS_DATE_SIGNAL, - SELECTED_DATE_SIGNAL, - LAST_SIGNAL -}; - -enum -{ - PROP_0, - PROP_YEAR, - PROP_MONTH, - PROP_DAY, - PROP_SHOW_HEADING, - PROP_SHOW_DAY_NAMES, - PROP_NO_MONTH_CHANGE, - PROP_SHOW_WEEK_NUMBERS, - PROP_WEEK_START, - PROP_MIN_YEAR, - PROP_MAX_YEAR, - PROP_LAST -}; - -static gint hildon_calendar_signals [LAST_SIGNAL] = { 0 }; - -static GtkWidgetClass* parent_class = NULL; - -typedef void (*HildonCalendarSignalDate) (GtkObject *object, guint arg1, guint arg2, guint arg3, gpointer data); - -static void -hildon_calendar_class_init (HildonCalendarClass *class); - -static void -hildon_calendar_init (HildonCalendar *calendar); - -static void -hildon_calendar_finalize (GObject *calendar); - -static void -hildon_calendar_destroy (GtkObject *calendar); - -static void -hildon_calendar_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); - -static void -hildon_calendar_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); - -static void -hildon_calendar_realize (GtkWidget *widget); - -static void -hildon_calendar_unrealize (GtkWidget *widget); - -static void -hildon_calendar_size_request (GtkWidget *widget, - GtkRequisition *requisition); - -static void -hildon_calendar_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); - -static gint -hildon_calendar_expose (GtkWidget *widget, - GdkEventExpose *event); - -static gint -hildon_calendar_button_press (GtkWidget *widget, - GdkEventButton *event); - -static gint -hildon_calendar_button_release (GtkWidget *widget, - GdkEventButton *event); - -static void -hildon_calendar_main_button (GtkWidget *widget, - GdkEventButton *event); - -static gint -hildon_calendar_motion_notify (GtkWidget *widget, - GdkEventMotion *event); - -static gint -hildon_calendar_enter_notify (GtkWidget *widget, - GdkEventCrossing *event); - -static gint -hildon_calendar_leave_notify (GtkWidget *widget, - GdkEventCrossing *event); - -static gint -hildon_calendar_key_press (GtkWidget *widget, - GdkEventKey *event); - -static gint -hildon_calendar_scroll (GtkWidget *widget, - GdkEventScroll *event); - -static void -hildon_calendar_grab_notify (GtkWidget *widget, - gboolean was_grabbed); - -static gboolean -hildon_calendar_focus_out (GtkWidget *widget, - GdkEventFocus *event); - -static void -hildon_calendar_state_changed (GtkWidget *widget, - GtkStateType previous_state); - -static void -hildon_calendar_style_set (GtkWidget *widget, - GtkStyle *previous_style); - -static void -hildon_calendar_paint_header (GtkWidget *widget); - -static void -hildon_calendar_paint_footer (GtkWidget *widget); - -static void -hildon_calendar_paint_day_names (GtkWidget *widget); - -static void -hildon_calendar_paint_week_numbers (GtkWidget *widget); - -static void -hildon_calendar_paint_main (GtkWidget *widget); - -static void -hildon_calendar_select_and_focus_day (HildonCalendar *calendar, - guint day); - -static void -hildon_calendar_paint_arrow (GtkWidget *widget, - guint arrow); - -static void -hildon_calendar_paint_day_num (GtkWidget *widget, - gint day); - -static void -hildon_calendar_paint_day (GtkWidget *widget, - gint row, - gint col); - -static void -hildon_calendar_compute_days (HildonCalendar *calendar); - -static gint -left_x_for_column (HildonCalendar *calendar, - gint column); - -static gint -top_y_for_row (HildonCalendar *calendar, - gint row); - -static void -hildon_calendar_drag_data_get (GtkWidget *widget, - GdkDragContext *context, - GtkSelectionData *selection_data, - guint info, - guint time); - -static void -hildon_calendar_drag_data_received (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - GtkSelectionData *selection_data, - guint info, - guint time); - -static gboolean -hildon_calendar_drag_motion (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - guint time); - -static void -hildon_calendar_drag_leave (GtkWidget *widget, - GdkDragContext *context, - guint time); - -static gboolean -hildon_calendar_drag_drop (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - guint time); - -/* This function was added because we need to mark current day according to - * specifications - */ - -static void -hildon_calendar_check_current_date (HildonCalendar *calendar, - gint x, - gint y); - -GType G_GNUC_CONST -hildon_calendar_get_type (void) -{ - static GType calendar_type = 0; - - if (!calendar_type) - { - static const GTypeInfo calendar_info = - { - sizeof (HildonCalendarClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_calendar_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (HildonCalendar), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_calendar_init, - }; - - calendar_type = g_type_register_static (GTK_TYPE_WIDGET, "HildonCalendar", - &calendar_info, 0); - } - - return calendar_type; -} - -static void -locales_init (HildonCalendarPrivate *priv) -{ - /* Hildon: This is not exactly portable, see - * http://bugzilla.gnome.org/show_bug.cgi?id=343415 - * The labels need to be instance variables as the startup wizard changes - * locale on runtime. - */ - locale_t l; - - l = newlocale (LC_TIME_MASK, setlocale (LC_MESSAGES, NULL), NULL); - - priv->abbreviated_dayname[0] = g_locale_to_utf8 (nl_langinfo_l(ABDAY_1, l), - -1, NULL, NULL, NULL); - priv->abbreviated_dayname[1] = g_locale_to_utf8 (nl_langinfo_l(ABDAY_2, l), - -1, NULL, NULL, NULL); - priv->abbreviated_dayname[2] = g_locale_to_utf8 (nl_langinfo_l(ABDAY_3, l), - -1, NULL, NULL, NULL) ; - priv->abbreviated_dayname[3] = g_locale_to_utf8 (nl_langinfo_l(ABDAY_4, l), - -1, NULL, NULL, NULL); - priv->abbreviated_dayname[4] = g_locale_to_utf8 (nl_langinfo_l(ABDAY_5, l), - -1, NULL, NULL, NULL); - priv->abbreviated_dayname[5] = g_locale_to_utf8 (nl_langinfo_l(ABDAY_6, l), - -1, NULL, NULL, NULL); - priv->abbreviated_dayname[6] = g_locale_to_utf8 (nl_langinfo_l(ABDAY_7, l), - -1, NULL, NULL, NULL); - priv->monthname[0] = g_locale_to_utf8 (nl_langinfo_l(MON_1, l), - -1, NULL, NULL, NULL); - priv->monthname[1] = g_locale_to_utf8 (nl_langinfo_l(MON_2, l), - -1, NULL, NULL, NULL); - priv->monthname[2] = g_locale_to_utf8 (nl_langinfo_l(MON_3, l), - -1, NULL, NULL, NULL); - priv->monthname[3] = g_locale_to_utf8 (nl_langinfo_l(MON_4, l), - -1, NULL, NULL, NULL); - priv->monthname[4] = g_locale_to_utf8 (nl_langinfo_l(MON_5, l), - -1, NULL, NULL, NULL); - priv->monthname[5] = g_locale_to_utf8 (nl_langinfo_l(MON_6, l), - -1, NULL, NULL, NULL); - priv->monthname[6] = g_locale_to_utf8 (nl_langinfo_l(MON_7, l), - -1, NULL, NULL, NULL); - priv->monthname[7] = g_locale_to_utf8 (nl_langinfo_l(MON_8, l), - -1, NULL, NULL, NULL); - priv->monthname[8] = g_locale_to_utf8 (nl_langinfo_l(MON_9, l), - -1, NULL, NULL, NULL); - priv->monthname[9] = g_locale_to_utf8 (nl_langinfo_l(MON_10, l), - -1, NULL, NULL, NULL); - priv->monthname[10] = g_locale_to_utf8 (nl_langinfo_l(MON_11, l), - -1, NULL, NULL, NULL); - priv->monthname[11] = g_locale_to_utf8 (nl_langinfo_l(MON_12, l), - -1, NULL, NULL, NULL); - - freelocale (l); -} - -static void -hildon_calendar_class_init (HildonCalendarClass *class) -{ - GObjectClass *gobject_class; - GtkObjectClass *object_class; - GtkWidgetClass *widget_class; - - gobject_class = (GObjectClass*) class; - object_class = (GtkObjectClass*) class; - widget_class = (GtkWidgetClass*) class; - - parent_class = g_type_class_peek_parent (class); - - gobject_class->set_property = hildon_calendar_set_property; - gobject_class->get_property = hildon_calendar_get_property; - gobject_class->finalize = hildon_calendar_finalize; - - object_class->destroy = hildon_calendar_destroy; - - widget_class->realize = hildon_calendar_realize; - widget_class->unrealize = hildon_calendar_unrealize; - widget_class->expose_event = hildon_calendar_expose; - widget_class->size_request = hildon_calendar_size_request; - widget_class->size_allocate = hildon_calendar_size_allocate; - widget_class->button_press_event = hildon_calendar_button_press; - widget_class->button_release_event = hildon_calendar_button_release; - widget_class->motion_notify_event = hildon_calendar_motion_notify; - widget_class->enter_notify_event = hildon_calendar_enter_notify; - widget_class->leave_notify_event = hildon_calendar_leave_notify; - widget_class->key_press_event = hildon_calendar_key_press; - widget_class->scroll_event = hildon_calendar_scroll; - widget_class->style_set = hildon_calendar_style_set; - widget_class->state_changed = hildon_calendar_state_changed; - widget_class->grab_notify = hildon_calendar_grab_notify; - widget_class->focus_out_event = hildon_calendar_focus_out; - - widget_class->drag_data_get = hildon_calendar_drag_data_get; - widget_class->drag_motion = hildon_calendar_drag_motion; - widget_class->drag_leave = hildon_calendar_drag_leave; - widget_class->drag_drop = hildon_calendar_drag_drop; - widget_class->drag_data_received = hildon_calendar_drag_data_received; - - class->month_changed = NULL; - class->day_selected = NULL; - class->day_selected_double_click = NULL; - class->prev_month = NULL; - class->next_month = NULL; - class->prev_year = NULL; - class->next_year = NULL; - - /** - * HildonCalendar:year: - * - * The selected year. - */ - g_object_class_install_property (gobject_class, - PROP_YEAR, - g_param_spec_int ("year", - "Year", - "The selected year", - 0, G_MAXINT, 0, - GTK_PARAM_READWRITE)); - - /** - * HildonCalendar:month: - * - * The selected month as number between 0 and 11. - */ - g_object_class_install_property (gobject_class, - PROP_MONTH, - g_param_spec_int ("month", - "Month", - "The selected month (as a number between 0 and 11)", - 0, 11, 0, - GTK_PARAM_READWRITE)); - - /** - * HildonCalendar:day: - * - * The selected day as number between 1 and 31 or 0 to unselect the currently selected day. - */ - g_object_class_install_property (gobject_class, - PROP_DAY, - g_param_spec_int ("day", - "Day", - "The selected day (as a number between 1 and 31, or 0 to unselect the currently selected day)", - 0, 31, 0, - GTK_PARAM_READWRITE)); - - /** - * HildonCalendar:show-heading: - * - * Determines whether a heading is displayed. - * - */ - g_object_class_install_property (gobject_class, - PROP_SHOW_HEADING, - g_param_spec_boolean ("show-heading", - "Show Heading", - "If TRUE, a heading is displayed", - TRUE, - GTK_PARAM_READWRITE)); - - /** - * HildonCalendar:show-day-names: - * - * Determines whether day names are displayed. - * - */ - g_object_class_install_property (gobject_class, - PROP_SHOW_DAY_NAMES, - g_param_spec_boolean ("show-day-names", - "Show Day Names", - "If TRUE, day names are displayed", - TRUE, - GTK_PARAM_READWRITE)); - /** - * HildonCalendar:no-month-change: - * - * Determines whether the selected month can be changed. - * - */ - g_object_class_install_property (gobject_class, - PROP_NO_MONTH_CHANGE, - g_param_spec_boolean ("no-month-change", - "No Month Change", - "If TRUE, the selected month cannot be changed", - FALSE, - GTK_PARAM_READWRITE)); - - /** - * HildonCalendar:show-week-numbers: - * - * Determines whether week numbers are displayed. - * - */ - g_object_class_install_property (gobject_class, - PROP_SHOW_WEEK_NUMBERS, - g_param_spec_boolean ("show-week-numbers", - "Show Week Numbers", - "If TRUE, week numbers are displayed", - FALSE, - GTK_PARAM_READWRITE)); - - /** - * HildonCalendar:week-start: - * - * Determines the start day of the week (0 for Sunday, 1 for Monday etc.) - * - */ - g_object_class_install_property (gobject_class, - PROP_WEEK_START, - g_param_spec_int ("week-start", - "Week start day", - "First day of the week; 0 for Sunday, 1 for Monday etc.", - 0, 6, 0, - GTK_PARAM_READWRITE)); - - /** - * HildonCalendar:min-year: - * - * Minimum valid year (0 if no limit). - * - */ - g_object_class_install_property (gobject_class, - PROP_MIN_YEAR, - g_param_spec_int ("min-year", - "Minimum valid year", - "Minimum valid year (0 if no limit)", - 0, 10000, 0, - GTK_PARAM_READWRITE)); - - /** - * HildonCalendar:max-year: - * - * Maximum valid year (0 if no limit). - * - */ - g_object_class_install_property (gobject_class, - PROP_MAX_YEAR, - g_param_spec_int ("max-year", - "Maximum valid year", - "Maximum valid year (0 if no limit)", - 0, 10000, 0, - GTK_PARAM_READWRITE)); - - hildon_calendar_signals[MONTH_CHANGED_SIGNAL] = - g_signal_new ("month_changed", - G_OBJECT_CLASS_TYPE (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (HildonCalendarClass, month_changed), - NULL, NULL, - _hildon_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - hildon_calendar_signals[DAY_SELECTED_SIGNAL] = - g_signal_new ("day_selected", - G_OBJECT_CLASS_TYPE (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (HildonCalendarClass, day_selected), - NULL, NULL, - _hildon_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - hildon_calendar_signals[DAY_SELECTED_DOUBLE_CLICK_SIGNAL] = - g_signal_new ("day_selected_double_click", - G_OBJECT_CLASS_TYPE (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (HildonCalendarClass, day_selected_double_click), - NULL, NULL, - _hildon_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - hildon_calendar_signals[PREV_MONTH_SIGNAL] = - g_signal_new ("prev_month", - G_OBJECT_CLASS_TYPE (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (HildonCalendarClass, prev_month), - NULL, NULL, - _hildon_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - hildon_calendar_signals[NEXT_MONTH_SIGNAL] = - g_signal_new ("next_month", - G_OBJECT_CLASS_TYPE (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (HildonCalendarClass, next_month), - NULL, NULL, - _hildon_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - hildon_calendar_signals[PREV_YEAR_SIGNAL] = - g_signal_new ("prev_year", - G_OBJECT_CLASS_TYPE (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (HildonCalendarClass, prev_year), - NULL, NULL, - _hildon_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - hildon_calendar_signals[NEXT_YEAR_SIGNAL] = - g_signal_new ("next_year", - G_OBJECT_CLASS_TYPE (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (HildonCalendarClass, next_year), - NULL, NULL, - _hildon_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - /** - * HildonCalendar::erroneous-date: - * - * Emitted when the user tries to set a date which is outside the boundaries - * set by min-year and max-year properties. - * - */ - hildon_calendar_signals[ERRONEOUS_DATE_SIGNAL] = - g_signal_new ("erroneous_date", - G_OBJECT_CLASS_TYPE (gobject_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, NULL, - _hildon_marshal_VOID__VOID, - G_TYPE_NONE, 0); - /** - * HildonCalendar::selected-date: - * - * Emitted on button-release when the user has selected a date. - * - */ - hildon_calendar_signals[SELECTED_DATE_SIGNAL] = - g_signal_new ("selected_date", - G_OBJECT_CLASS_TYPE(gobject_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, NULL, - _hildon_marshal_VOID__VOID, - G_TYPE_NONE, 0); -} - -static void -hildon_calendar_init (HildonCalendar *calendar) -{ - time_t secs; - struct tm *tm; - gint i; - /* char buffer[255];*/ - /* time_t tmp_time;*/ - GtkWidget *widget; - HildonCalendarPrivate *private_data; - /* gchar *year_before;*/ - /* gint row; - gint col; */ - gchar *langinfo; - GDateWeekday week_1stday; - gint first_weekday; - guint week_origin; - - widget = GTK_WIDGET (calendar); - GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS); - - calendar->private_data = g_malloc (sizeof (HildonCalendarPrivate)); - private_data = HILDON_CALENDAR_GET_PRIVATE (calendar); - - /* Set defaults */ - secs = time (NULL); - tm = localtime (&secs); - calendar->month = tm->tm_mon; - calendar->year = 1900 + tm->tm_year; - - for (i=0;i<31;i++) - calendar->marked_date[i] = FALSE; - calendar->num_marked_dates = 0; - calendar->selected_day = tm->tm_mday; - - calendar->display_flags = ( HILDON_CALENDAR_SHOW_HEADING | - HILDON_CALENDAR_SHOW_DAY_NAMES ); - - /* Hildon: we should mark current day and we need to store current date */ - private_data->current_day = tm->tm_mday; - private_data->current_month = tm->tm_mon; - private_data->current_year = tm->tm_year + 1900; - - /* Hildon: following lines are for stylus sliding */ - private_data->slide_stylus = FALSE; - private_data->prev_row = -1; - private_data->prev_col = -1; - - /* Hildon: is_bad_day indicate if day was selected out of legal range */ - private_data->is_bad_day = FALSE; - - calendar->highlight_row = -1; - calendar->highlight_col = -1; - - calendar->focus_row = -1; - calendar->focus_col = -1; - calendar->xor_gc = NULL; - - private_data->max_year_width = 0; - private_data->max_month_width = 0; - private_data->max_day_char_width = 0; - private_data->max_week_char_width = 0; - - private_data->max_day_char_ascent = 0; - private_data->max_day_char_descent = 0; - private_data->max_label_char_ascent = 0; - private_data->max_label_char_descent = 0; - - /* private_data->arrow_width = 10;*/ - - private_data->freeze_count = 0; - - private_data->dirty_header = 0; - private_data->dirty_day_names = 0; - private_data->dirty_week = 0; - private_data->dirty_main = 0; - - private_data->need_timer = 0; - private_data->timer = 0; - private_data->click_child = -1; - - private_data->in_drag = 0; - private_data->drag_highlight = 0; - - private_data->min_year = 0; - private_data->max_year = 0; - - gtk_drag_dest_set (widget, 0, NULL, 0, GDK_ACTION_COPY); - gtk_drag_dest_add_text_targets (widget); - -#if 0 - private_data->year_before = 0; - - /* Translate to calendar:YM if you want years to be displayed - * before months; otherwise translate to calendar:MY. - * Do *not* translate it to anything else, if it - * it isn't calendar:YM or calendar:MY it will not work. - * - * Note that this flipping is in top the text direction flipping, - * so if you have a default text direction of RTL and YM, then - * the year will appear on the right. - */ - year_before = _("calendar:MY"); - if (strcmp (year_before, "calendar:YM") == 0) - private_data->year_before = 1; - else if (strcmp (year_before, "calendar:MY") != 0) - g_warning ("Whoever translated calendar:MY did so wrongly.\n"); -#endif - langinfo = nl_langinfo (_NL_TIME_FIRST_WEEKDAY); - first_weekday = langinfo[0]; - langinfo = nl_langinfo (_NL_TIME_WEEK_1STDAY); - week_origin = GPOINTER_TO_UINT (langinfo); - if (week_origin == 19971130) - week_1stday = G_DATE_SUNDAY; - else if (week_origin == 19971201) - week_1stday = G_DATE_MONDAY; - else if (g_date_valid_dmy ((week_origin % 100), - (week_origin / 100) % 100, - (week_origin / 10000))) - { - GDate *date; - date = g_date_new_dmy ((week_origin % 100), - (week_origin / 100) % 100, - (week_origin / 10000)); - week_1stday = g_date_get_weekday (date); - g_date_free (date); - } - else - { - g_warning ("Invalid value set for _NL_TIME_WEEK_1STDAY"); - week_1stday = G_DATE_SUNDAY; - } - - private_data->week_start = (week_1stday + first_weekday - 1) % 7; - - locales_init (private_data); -} - -GtkWidget* -hildon_calendar_new (void) -{ - return g_object_new (HILDON_TYPE_CALENDAR, NULL); -} - -/* column_from_x: returns the column 0-6 that the - * x pixel of the xwindow is in */ -static gint -column_from_x (HildonCalendar *calendar, - gint event_x) -{ - gint c, column; - gint x_left, x_right; - - column = -1; - - for (c = 0; c < 7; c++) - { - x_left = left_x_for_column (calendar, c); - x_right = x_left + HILDON_CALENDAR_GET_PRIVATE (calendar)->day_width; - - if (event_x >= x_left && event_x < x_right) - { - column = c; - break; - } - } - - return column; -} -#if 0 - static gint -row_height (HildonCalendar *calendar) -{ - return (HILDON_CALENDAR_GET_PRIVATE (calendar)->main_h - CALENDAR_MARGIN - - ((calendar->display_flags & HILDON_CALENDAR_SHOW_DAY_NAMES) - ? CALENDAR_YSEP : CALENDAR_MARGIN)) / 6; -} -#endif - -/* row_from_y: returns the row 0-5 that the - * y pixel of the xwindow is in */ -static gint -row_from_y (HildonCalendar *calendar, - gint event_y) -{ - gint r, row; - /*gint height;*/ - gint y_top, y_bottom; - - row = -1; - - for (r = 0; r < 6; r++) - { - y_top = top_y_for_row (calendar, r); - y_bottom = y_top + HILDON_DAY_HEIGHT /*height*/; - - if (event_y >= y_top && event_y < y_bottom) - { - row = r; - break; - } - } - - return row; -} - -/* left_x_for_column: returns the x coordinate - * for the left of the column */ -static gint -left_x_for_column (HildonCalendar *calendar, - gint column) -{ - gint width; - gint x_left; - - if (gtk_widget_get_direction (GTK_WIDGET (calendar)) == GTK_TEXT_DIR_RTL) - column = 6 - column; - - width = HILDON_CALENDAR_GET_PRIVATE (calendar)->day_width; - if (calendar->display_flags & HILDON_CALENDAR_SHOW_WEEK_NUMBERS) - x_left = CALENDAR_XSEP + (width + DAY_XSEP) * column; - else - x_left = CALENDAR_MARGIN + (width + DAY_XSEP) * column; - - return x_left; -} - -/* top_y_for_row: returns the y coordinate - * for the top of the row */ -static gint -top_y_for_row (HildonCalendar *calendar, - gint row) -{ - return (HILDON_CALENDAR_GET_PRIVATE (calendar)->main_h - - (CALENDAR_MARGIN + (6 - row) - * HILDON_DAY_HEIGHT)); -} - -static void -hildon_calendar_set_month_prev (HildonCalendar *calendar) -{ - HildonCalendarPrivate *priv = HILDON_CALENDAR_GET_PRIVATE (calendar); - gint month_len; - - if (calendar->display_flags & HILDON_CALENDAR_NO_MONTH_CHANGE) - return; - - if (calendar->month == 0) - { - if (!priv->min_year || calendar->year > priv->min_year) - { - calendar->month = 11; - calendar->year--; - } - } - else - calendar->month--; - - month_len = month_length[leap (calendar->year)][calendar->month + 1]; - - hildon_calendar_freeze (calendar); - hildon_calendar_compute_days (calendar); - - g_signal_emit (calendar, - hildon_calendar_signals[PREV_MONTH_SIGNAL], - 0); - g_signal_emit (calendar, - hildon_calendar_signals[MONTH_CHANGED_SIGNAL], - 0); - - if (month_len < calendar->selected_day) - { - calendar->selected_day = 0; - hildon_calendar_select_day (calendar, month_len); - } - else - { - if (calendar->selected_day < 0) - calendar->selected_day = calendar->selected_day + 1 + month_length[leap (calendar->year)][calendar->month + 1]; - hildon_calendar_select_day (calendar, calendar->selected_day); - } - - gtk_widget_queue_draw (GTK_WIDGET (calendar)); - hildon_calendar_thaw (calendar); -} - -static void -hildon_calendar_set_month_next (HildonCalendar *calendar) -{ - HildonCalendarPrivate *priv; - gint month_len; - - g_return_if_fail (GTK_IS_WIDGET (calendar)); - - priv = HILDON_CALENDAR_GET_PRIVATE (calendar); - - if (calendar->display_flags & HILDON_CALENDAR_NO_MONTH_CHANGE) - return; - - if (calendar->month == 11) - { - if (!priv->max_year || calendar->year < priv->max_year) - { - calendar->month = 0; - calendar->year++; - } - } - else - calendar->month++; - - hildon_calendar_freeze (calendar); - hildon_calendar_compute_days (calendar); - g_signal_emit (calendar, - hildon_calendar_signals[NEXT_MONTH_SIGNAL], - 0); - g_signal_emit (calendar, - hildon_calendar_signals[MONTH_CHANGED_SIGNAL], - 0); - - month_len = month_length[leap (calendar->year)][calendar->month + 1]; - - if (month_len < calendar->selected_day) - { - calendar->selected_day = 0; - hildon_calendar_select_day (calendar, month_len); - } - else - hildon_calendar_select_day (calendar, calendar->selected_day); - - gtk_widget_queue_draw (GTK_WIDGET (calendar)); - hildon_calendar_thaw (calendar); -} - -static void -hildon_calendar_set_year_prev (HildonCalendar *calendar) -{ - HildonCalendarPrivate *priv; - gint month_len; - - g_return_if_fail (GTK_IS_WIDGET (calendar)); - - priv = HILDON_CALENDAR_GET_PRIVATE (calendar); - - if (!priv->min_year || priv->min_year < calendar->year) - calendar->year--; - - hildon_calendar_freeze (calendar); - hildon_calendar_compute_days (calendar); - g_signal_emit (calendar, - hildon_calendar_signals[PREV_YEAR_SIGNAL], - 0); - g_signal_emit (calendar, - hildon_calendar_signals[MONTH_CHANGED_SIGNAL], - 0); - - month_len = month_length[leap (calendar->year)][calendar->month + 1]; - - if (month_len < calendar->selected_day) - { - calendar->selected_day = 0; - hildon_calendar_select_day (calendar, month_len); - } - else - hildon_calendar_select_day (calendar, calendar->selected_day); - - gtk_widget_queue_draw (GTK_WIDGET (calendar)); - hildon_calendar_thaw (calendar); -} - -static void -hildon_calendar_set_year_next (HildonCalendar *calendar) -{ - HildonCalendarPrivate *priv; - gint month_len; - - g_return_if_fail (GTK_IS_WIDGET (calendar)); - priv = HILDON_CALENDAR_GET_PRIVATE (calendar); - - hildon_calendar_freeze (calendar); - - if (!priv->max_year || priv->max_year > calendar->year) - calendar->year++; - - hildon_calendar_compute_days (calendar); - g_signal_emit (calendar, - hildon_calendar_signals[NEXT_YEAR_SIGNAL], - 0); - g_signal_emit (calendar, - hildon_calendar_signals[MONTH_CHANGED_SIGNAL], - 0); - - month_len = month_length[leap (calendar->year)][calendar->month + 1]; - - if (month_len < calendar->selected_day) - { - calendar->selected_day = 0; - hildon_calendar_select_day (calendar, month_len); - } - else - hildon_calendar_select_day (calendar, calendar->selected_day); - gtk_widget_queue_draw (GTK_WIDGET (calendar)); - hildon_calendar_thaw (calendar); -} - -static void -hildon_calendar_main_button (GtkWidget *widget, - GdkEventButton *event) -{ - HildonCalendar *calendar; - HildonCalendarPrivate *private_data; - gint x, y; - gint row, col; - gint day_month; - gint day; - - calendar = HILDON_CALENDAR (widget); - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - - x = (gint) (event->x); - y = (gint) (event->y); - - row = row_from_y (calendar, y); - col = column_from_x (calendar, x); - - /* If row or column isn't found, just return. */ - if (row == -1 || col == -1) - return; - - day_month = calendar->day_month[row][col]; - - if ((calendar->year == private_data->min_year && - calendar->month == 0 && day_month == MONTH_PREV) || - (calendar->year == private_data->max_year && - calendar->month == 11 && day_month == MONTH_NEXT)) - { - private_data->is_bad_day = TRUE; - g_signal_emit (calendar, hildon_calendar_signals[ERRONEOUS_DATE_SIGNAL], 0); - return; - } - - if (event->type == GDK_BUTTON_RELEASE) - { - day = calendar->day[row][col]; - - if (day_month == MONTH_PREV) - { - hildon_calendar_set_month_prev (calendar); - } - else if (day_month == MONTH_NEXT) - { - hildon_calendar_set_month_next (calendar); - } - - if (!GTK_WIDGET_HAS_FOCUS (widget)) - gtk_widget_grab_focus (widget); - - if (event->button == 1) - { - private_data->in_drag = 1; - private_data->drag_start_x = x; - private_data->drag_start_y = y; - } - - hildon_calendar_select_and_focus_day (calendar, day); - } - else if (event->type == GDK_2BUTTON_PRESS) - { - private_data->in_drag = 0; - private_data->slide_stylus = FALSE; - if (day_month == MONTH_CURRENT) - g_signal_emit (calendar, - hildon_calendar_signals[DAY_SELECTED_DOUBLE_CLICK_SIGNAL], 0); - } -} - -static void -hildon_calendar_realize_arrows (GtkWidget *widget) -{ - HildonCalendar *calendar; - HildonCalendarPrivate *private_data; - GdkWindowAttr attributes; - gint attributes_mask; - gint i; - guint arrow_vlength, arrow_hlength; - /*gboolean year_left;*/ - - g_return_if_fail (HILDON_IS_CALENDAR (widget)); - - calendar = HILDON_CALENDAR (widget); - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - - gtk_widget_style_get (widget, - "scroll-arrow-hlength", &arrow_hlength, - "scroll-arrow-vlength", &arrow_vlength, - NULL); - /* - if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) - year_left = private_data->year_before; - else - year_left = !private_data->year_before; - */ - /* Arrow windows ------------------------------------- */ - if (! (calendar->display_flags & HILDON_CALENDAR_NO_MONTH_CHANGE) - && (calendar->display_flags & HILDON_CALENDAR_SHOW_HEADING)) - { - attributes.wclass = GDK_INPUT_OUTPUT; - attributes.window_type = GDK_WINDOW_CHILD; - attributes.visual = gtk_widget_get_visual (widget); - attributes.colormap = gtk_widget_get_colormap (widget); - attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK - | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - attributes.y = 0; - attributes.width = arrow_vlength; - attributes.height = arrow_hlength; - - attributes.x = (widget->allocation.width - private_data->max_year_width) / 2 - arrow_vlength - HILDON_ARROW_SEP; - private_data->arrow_win[ARROW_YEAR_LEFT] = gdk_window_new (private_data->header_win, - &attributes, attributes_mask); - - attributes.x = (widget->allocation.width + private_data->max_year_width) / 2 + HILDON_ARROW_SEP; - private_data->arrow_win[ARROW_YEAR_RIGHT] = gdk_window_new (private_data->header_win, - &attributes, attributes_mask); - attributes.x = (widget->allocation.width - private_data->max_month_width) / 2 - arrow_vlength - HILDON_ARROW_SEP; - private_data->arrow_win[ARROW_MONTH_LEFT] = gdk_window_new (private_data->footer_win, - &attributes, attributes_mask); - attributes.x = (widget->allocation.width + private_data->max_month_width) / 2 + HILDON_ARROW_SEP; - private_data->arrow_win[ARROW_MONTH_RIGHT] = gdk_window_new (private_data->footer_win, - &attributes, attributes_mask); - - /* - for (i = 0; i < 4; i++) - { - switch (i) - { - case ARROW_MONTH_LEFT: - if (year_left) - attributes.x = (widget->allocation.width - 2 * widget->style->xthickness - - (3 + 2*private_data->arrow_width - + private_data->max_month_width)); - else - attributes.x = 3; - break; - case ARROW_MONTH_RIGHT: - if (year_left) - attributes.x = (widget->allocation.width - 2 * widget->style->xthickness - - 3 - private_data->arrow_width); - else - attributes.x = (private_data->arrow_width - + private_data->max_month_width); - break; - case ARROW_YEAR_LEFT: - if (year_left) - attributes.x = 3; - else - attributes.x = (widget->allocation.width - 2 * widget->style->xthickness - - (3 + 2*private_data->arrow_width - + private_data->max_year_width)); - break; - case ARROW_YEAR_RIGHT: - if (year_left) - attributes.x = (private_data->arrow_width - + private_data->max_year_width); - else - attributes.x = (widget->allocation.width - 2 * widget->style->xthickness - - 3 - private_data->arrow_width); - break; - } - private_data->arrow_win[i] = gdk_window_new (private_data->header_win, - &attributes, - attributes_mask);*/ - - for (i = 0; i < 4; i++) - { - if (GTK_WIDGET_IS_SENSITIVE (widget)) - private_data->arrow_state[i] = GTK_STATE_NORMAL; - else - private_data->arrow_state[i] = GTK_STATE_INSENSITIVE; - gdk_window_set_background (private_data->arrow_win[i], - HEADER_BG_COLOR (GTK_WIDGET (calendar))); - gdk_window_show (private_data->arrow_win[i]); - gdk_window_set_user_data (private_data->arrow_win[i], widget); - } - } - else - { - for (i = 0; i < 4; i++) - private_data->arrow_win[i] = NULL; - } -} - -static void -hildon_calendar_realize_header (GtkWidget *widget) -{ - HildonCalendar *calendar; - HildonCalendarPrivate *private_data; - GdkWindowAttr attributes; - gint attributes_mask; - guint arrow_hlength; - - g_return_if_fail (HILDON_IS_CALENDAR (widget)); - - calendar = HILDON_CALENDAR (widget); - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - - gtk_widget_style_get (widget, - "scroll-arrow-hlength", &arrow_hlength, - NULL); - /* Header window ------------------------------------- */ - if (calendar->display_flags & HILDON_CALENDAR_SHOW_HEADING) - { - attributes.wclass = GDK_INPUT_OUTPUT; - attributes.window_type = GDK_WINDOW_CHILD; - attributes.visual = gtk_widget_get_visual (widget); - attributes.colormap = gtk_widget_get_colormap (widget); - attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK; - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - attributes.x = 0 /*widget->style->xthickness*/; - attributes.y = 0 /*widget->style->ythickness*/; - attributes.width = widget->allocation.width; /* - 2 * attributes.x */; - attributes.height = arrow_hlength /*private_data->header_h - 2 * attributes.y*/; - private_data->header_win = gdk_window_new (widget->window, - &attributes, attributes_mask); - - attributes.y = arrow_hlength + 2 * CALENDAR_YSEP + private_data->main_h + private_data->day_name_h; - - private_data->footer_win = gdk_window_new(widget->window, - &attributes, attributes_mask); - - gdk_window_set_background (private_data->header_win, - HEADER_BG_COLOR (widget)); - gdk_window_set_background (private_data->footer_win, - HEADER_BG_COLOR (widget)); - - gdk_window_show (private_data->header_win); - gdk_window_show (private_data->footer_win); - gdk_window_set_user_data (private_data->header_win, widget); - gdk_window_set_user_data (private_data->footer_win, widget); - } - else - { - private_data->header_win = NULL; - private_data->footer_win = NULL; - } - hildon_calendar_realize_arrows (widget); -} - -static void -hildon_calendar_realize_day_names (GtkWidget *widget) -{ - HildonCalendar *calendar; - HildonCalendarPrivate *private_data; - GdkWindowAttr attributes; - gint attributes_mask; - - g_return_if_fail (HILDON_IS_CALENDAR (widget)); - - calendar = HILDON_CALENDAR (widget); - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - - /* Day names window --------------------------------- */ - if ( calendar->display_flags & HILDON_CALENDAR_SHOW_DAY_NAMES) - { - attributes.wclass = GDK_INPUT_OUTPUT; - attributes.window_type = GDK_WINDOW_CHILD; - attributes.visual = gtk_widget_get_visual (widget); - attributes.colormap = gtk_widget_get_colormap (widget); - attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK; - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - attributes.x = HILDON_DAY_WIDTH + HILDON_WEEKS_EXTRA_WIDTH/*(widget->style->xthickness + INNER_BORDER)*/; - attributes.y = private_data->header_h; - attributes.width = widget->allocation.width - attributes.x; - attributes.height = private_data->day_name_h; - private_data->day_name_win = gdk_window_new (widget->window, - &attributes, - attributes_mask); - gdk_window_set_background (private_data->day_name_win, - BACKGROUND_COLOR ( GTK_WIDGET (calendar))); - - gdk_window_show (private_data->day_name_win); - gdk_window_set_user_data (private_data->day_name_win, widget); - } - else - { - private_data->day_name_win = NULL; - } -} - -static void -hildon_calendar_realize_week_numbers (GtkWidget *widget) -{ - HildonCalendar *calendar; - HildonCalendarPrivate *private_data; - GdkWindowAttr attributes; - gint attributes_mask; - - g_return_if_fail (HILDON_IS_CALENDAR (widget)); - - calendar = HILDON_CALENDAR (widget); - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - - /* Week number window -------------------------------- */ - if (calendar->display_flags & HILDON_CALENDAR_SHOW_WEEK_NUMBERS) - { - attributes.wclass = GDK_INPUT_OUTPUT; - attributes.window_type = GDK_WINDOW_CHILD; - attributes.visual = gtk_widget_get_visual (widget); - attributes.colormap = gtk_widget_get_colormap (widget); - attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK; - - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - attributes.x = 0 /*widget->style->xthickness + INNER_BORDER*/; - attributes.y = private_data->header_h; - /*+ (widget->style->ythickness + INNER_BORDER))*/; - attributes.width = HILDON_DAY_WIDTH + HILDON_WEEKS_EXTRA_WIDTH; - attributes.height = private_data->main_h + private_data->day_name_h; - private_data->week_win = gdk_window_new (widget->window, - &attributes, attributes_mask); - gdk_window_set_background (private_data->week_win, - BACKGROUND_COLOR (GTK_WIDGET (calendar))); - gdk_window_show (private_data->week_win); - gdk_window_set_user_data (private_data->week_win, widget); - } - else - { - private_data->week_win = NULL; - } -} - -static void -hildon_calendar_realize (GtkWidget *widget) -{ - HildonCalendar *calendar; - HildonCalendarPrivate *private_data; - GdkWindowAttr attributes; - gint attributes_mask; - GdkGCValues values; - - calendar = HILDON_CALENDAR (widget); - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - - GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); - hildon_calendar_compute_days (calendar); - - attributes.x = widget->allocation.x; - attributes.y = widget->allocation.y; - attributes.width = widget->allocation.width; - attributes.height = widget->allocation.height; - attributes.wclass = GDK_INPUT_OUTPUT; - attributes.window_type = GDK_WINDOW_CHILD; - attributes.event_mask = (gtk_widget_get_events (widget) - | GDK_EXPOSURE_MASK |GDK_KEY_PRESS_MASK | GDK_SCROLL_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_COLORMAP; - widget->window = gdk_window_new (widget->parent->window, - &attributes, attributes_mask); - - widget->style = gtk_style_attach (widget->style, widget->window); - - /* Header window ------------------------------------- */ - hildon_calendar_realize_header (widget); - /* Day names window --------------------------------- */ - hildon_calendar_realize_day_names (widget); - /* Week number window -------------------------------- */ - hildon_calendar_realize_week_numbers (widget); - /* Main Window -------------------------------------- */ - attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK - | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK); - - attributes.x = HILDON_DAY_WIDTH + HILDON_WEEKS_EXTRA_WIDTH /*private_data->week_width + (widget->style->ythickness + INNER_BORDER)*/; - attributes.y = (private_data->header_h + private_data->day_name_h - + (widget->style->ythickness + INNER_BORDER)); - attributes.width = (widget->allocation.width - attributes.x - /*- (widget->style->xthickness + INNER_BORDER)*/); - attributes.height = private_data->main_h; - private_data->main_win = gdk_window_new (widget->window, - &attributes, attributes_mask); - gdk_window_set_background (private_data->main_win, - BACKGROUND_COLOR ( GTK_WIDGET ( calendar))); - gdk_window_show (private_data->main_win); - gdk_window_set_user_data (private_data->main_win, widget); - gdk_window_set_background (widget->window, BACKGROUND_COLOR (widget)); - gdk_window_show (widget->window); - gdk_window_set_user_data (widget->window, widget); - - /* Set widgets gc */ - calendar->gc = gdk_gc_new (widget->window); - - values.foreground = widget->style->white; - values.function = GDK_XOR; - calendar->xor_gc = gdk_gc_new_with_values (widget->window, - &values, - GDK_GC_FOREGROUND | - GDK_GC_FUNCTION); -} - -static void -hildon_calendar_unrealize (GtkWidget *widget) -{ - HildonCalendar *calendar; - HildonCalendarPrivate *private_data; - gint i; - - calendar = HILDON_CALENDAR (widget); - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - - if (private_data->header_win) - { - for (i = 0; i < 4; i++) - { - if (private_data->arrow_win[i]) - { - gdk_window_set_user_data (private_data->arrow_win[i], NULL); - gdk_window_destroy (private_data->arrow_win[i]); - private_data->arrow_win[i] = NULL; - } - } - gdk_window_set_user_data (private_data->header_win, NULL); - gdk_window_destroy (private_data->header_win); - private_data->header_win = NULL; - gdk_window_set_user_data (private_data->footer_win, NULL); - gdk_window_destroy (private_data->footer_win); - private_data->footer_win = NULL; - } - - if (private_data->week_win) - { - gdk_window_set_user_data (private_data->week_win, NULL); - gdk_window_destroy (private_data->week_win); - private_data->week_win = NULL; - } - - if (private_data->main_win) - { - gdk_window_set_user_data (private_data->main_win, NULL); - gdk_window_destroy (private_data->main_win); - private_data->main_win = NULL; - } - if (private_data->day_name_win) - { - gdk_window_set_user_data (private_data->day_name_win, NULL); - gdk_window_destroy (private_data->day_name_win); - private_data->day_name_win = NULL; - } - if (calendar->xor_gc) - g_object_unref (calendar->xor_gc); - if (calendar->gc) - g_object_unref (calendar->gc); - - if (GTK_WIDGET_CLASS (parent_class)->unrealize) - (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); -} - -static void -hildon_calendar_size_request (GtkWidget *widget, - GtkRequisition *requisition) -{ - HildonCalendar *calendar; - HildonCalendarPrivate *private_data; - PangoLayout *layout; - PangoRectangle logical_rect; - - /*gint height;*/ - gint i; - gchar buffer[255]; - /*gint calendar_margin = CALENDAR_MARGIN;*/ - gint header_width, main_width; - gint max_header_height = 0; - gint focus_width; - gint focus_padding; - gint arrow_hlength; - - calendar = HILDON_CALENDAR (widget); - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - gtk_widget_style_get (GTK_WIDGET (widget), - "focus-line-width", &focus_width, - "focus-padding", &focus_padding, - "scroll-arrow-hlength", &arrow_hlength, - NULL); - - layout = gtk_widget_create_pango_layout (widget, NULL); - - /* - * Calculate the requisition width for the widget. - */ - - /* Header width */ - - if (calendar->display_flags & HILDON_CALENDAR_SHOW_HEADING) - { - private_data->max_month_width = 0; - for (i = 0; i < 12; i++) - { - pango_layout_set_text (layout, private_data->monthname[i], -1); - pango_layout_get_pixel_extents (layout, NULL, &logical_rect); - private_data->max_month_width = MAX (private_data->max_month_width, - logical_rect.width + 8); - max_header_height = MAX (max_header_height, logical_rect.height); - } - private_data->max_year_width = 0; - for (i=0; i<10; i++) - { - g_snprintf (buffer, sizeof (buffer), "%d%d%d%d", i,i,i,i); - pango_layout_set_text (layout, buffer, -1); - pango_layout_get_pixel_extents (layout, NULL, &logical_rect); - private_data->max_year_width = MAX (private_data->max_year_width, - logical_rect.width + 8); - max_header_height = MAX (max_header_height, logical_rect.height); - } - } - else - { - private_data->max_month_width = 0; - private_data->max_year_width = 0; - } - - if (calendar->display_flags & HILDON_CALENDAR_NO_MONTH_CHANGE) - header_width = (private_data->max_month_width - + private_data->max_year_width - + 3 * 3); - else - header_width = (private_data->max_month_width - + private_data->max_year_width - + 4 * private_data->arrow_width + 3 * 3); - - /* Mainwindow labels width */ - - private_data->max_day_char_width = 0; - private_data->min_day_width = 0; - private_data->max_label_char_ascent = 0; - private_data->max_label_char_descent = 0; - - for (i = 0; i < 9; i++) - { - g_snprintf (buffer, sizeof (buffer), "%d%d", i, i); - pango_layout_set_text (layout, buffer, -1); - pango_layout_get_pixel_extents (layout, NULL, &logical_rect); - private_data->min_day_width = MAX (private_data->min_day_width, - logical_rect.width); - - private_data->max_day_char_ascent = MAX (private_data->max_label_char_ascent, - PANGO_ASCENT (logical_rect)); - private_data->max_day_char_descent = MAX (private_data->max_label_char_descent, - PANGO_DESCENT (logical_rect)); - } - /* We add one to max_day_char_width to be able to make the marked day "bold" */ - private_data->max_day_char_width = private_data->min_day_width / 2 + 1; - - if (calendar->display_flags & HILDON_CALENDAR_SHOW_DAY_NAMES) - for (i = 0; i < 7; i++) - { - pango_layout_set_text (layout, private_data->abbreviated_dayname[i], -1); - pango_layout_line_get_pixel_extents (pango_layout_get_lines (layout)->data, NULL, &logical_rect); - - /* Hildon: add 4 so that passive focus wouldn't overlap day names */ - private_data->min_day_width = MAX (private_data->min_day_width, logical_rect.width + 4); - private_data->max_label_char_ascent = MAX (private_data->max_label_char_ascent, - PANGO_ASCENT (logical_rect)); - private_data->max_label_char_descent = MAX (private_data->max_label_char_descent, - PANGO_DESCENT (logical_rect)); - } - - private_data->max_week_char_width = 0; - if (calendar->display_flags & HILDON_CALENDAR_SHOW_WEEK_NUMBERS) - for (i = 0; i < 9; i++) - { - g_snprintf (buffer, sizeof (buffer), "%d%d", i, i); - pango_layout_set_text (layout, buffer, -1); - pango_layout_get_pixel_extents (layout, NULL, &logical_rect); - private_data->max_week_char_width = MAX (private_data->max_week_char_width, - logical_rect.width / 2); - } - - main_width = (7 * (private_data->min_day_width + (focus_padding + focus_width) * 2) + (DAY_XSEP * 6) + CALENDAR_MARGIN * 2 - + (private_data->max_week_char_width - ? private_data->max_week_char_width * 2 + (focus_padding + focus_width) * 2 + CALENDAR_XSEP * 2 - : 0)); - - /* requisition->width = MAX (header_width, main_width + INNER_BORDER * 2) + widget->style->xthickness * 2; - * - * FIXME: header_width is broken, when Calendar is themed ! - * Next line is workaround for this bug - */ - requisition->width = (main_width + INNER_BORDER * 2) + widget->style->xthickness * 2 + HILDON_WEEKS_EXTRA_WIDTH + HILDON_DAYS_EXTRA_WIDTH; - - /* - * Calculate the requisition height for the widget. - * This is Hildon calculation - */ - - if (calendar->display_flags & HILDON_CALENDAR_SHOW_HEADING) - private_data->header_h = arrow_hlength + CALENDAR_YSEP; - else - private_data->header_h = 0; - - if (calendar->display_flags & HILDON_CALENDAR_SHOW_DAY_NAMES) - private_data->day_name_h = HILDON_DAY_HEIGHT; - else - private_data->day_name_h = 0; - - private_data->main_h = 6 * HILDON_DAY_HEIGHT; - requisition->height = 2 * private_data->header_h + private_data->day_name_h + private_data->main_h; - - g_object_unref (layout); -} - -static void -hildon_calendar_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - HildonCalendar *calendar; - HildonCalendarPrivate *private_data; - gint xthickness = widget->style->xthickness; - /*gint ythickness = widget->style->xthickness;*/ - gboolean year_left; - gint arrow_vlength, arrow_hlength; - - widget->allocation = *allocation; - - calendar = HILDON_CALENDAR (widget); - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - - if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) - year_left = private_data->year_before; - else - year_left = !private_data->year_before; - - gtk_widget_style_get (widget, - "scroll-arrow-vlength", &arrow_vlength, - "scroll-arrow-hlength", &arrow_hlength, - NULL); - - if (calendar->display_flags & HILDON_CALENDAR_SHOW_WEEK_NUMBERS) - { - /* this variable is introduced to avoid breaking week_width because - of HILDON_WEEKS_EXTRA_WIDTH and HILDON_DAYS_EXTRA_WIDTH appearing - in calculation of day_width */ - int real_day_width = (private_data->min_day_width - * ((allocation->width - - (xthickness + INNER_BORDER) * 2 - - (CALENDAR_MARGIN * 2) - (DAY_XSEP * 6) - CALENDAR_XSEP * 2)) - / (7 * private_data->min_day_width + private_data->max_week_char_width * 2)); - - private_data->day_width = (private_data->min_day_width - * ((allocation->width - - (HILDON_WEEKS_EXTRA_WIDTH + HILDON_DAYS_EXTRA_WIDTH) - - (xthickness + INNER_BORDER) * 2 - - (CALENDAR_MARGIN * 2) - (DAY_XSEP * 6) - CALENDAR_XSEP * 2)) - / (7 * private_data->min_day_width + private_data->max_week_char_width * 2)); - private_data->week_width = ((allocation->width - (xthickness + INNER_BORDER) * 2 - - (CALENDAR_MARGIN * 2) - (DAY_XSEP * 6) - CALENDAR_XSEP * 2 ) - - real_day_width * 7 + CALENDAR_MARGIN + CALENDAR_XSEP); - } - else - { - private_data->day_width = (allocation->width - - (xthickness + INNER_BORDER) * 2 - - (CALENDAR_MARGIN * 2) - - (DAY_XSEP * 6))/7; - private_data->week_width = 0; - } - - if (GTK_WIDGET_REALIZED (widget)) - { - gdk_window_move_resize (widget->window, - allocation->x, allocation->y, - allocation->width, allocation->height); - if (private_data->header_win) - gdk_window_move_resize (private_data->header_win, - 0, 0, widget->allocation.width, arrow_hlength); - if (private_data->arrow_win[ARROW_YEAR_LEFT]) - { - /* if (year_left) - gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_LEFT], - 3, 3, - private_data->arrow_width, - private_data->header_h - 7); - else - gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_LEFT], - (allocation->width - 2 * xthickness - - (3 + 2*private_data->arrow_width - + private_data->max_year_width)), - 3, - private_data->arrow_width, - private_data->header_h - 7);*/ - - gdk_window_move (private_data->arrow_win[ARROW_YEAR_LEFT], - (widget->allocation.width - private_data->max_year_width) / 2 - arrow_vlength - HILDON_ARROW_SEP, 0); - } - if (private_data->arrow_win[ARROW_YEAR_RIGHT]) - { - /* if (year_left) - gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_RIGHT], - (private_data->arrow_width - + private_data->max_year_width), - 3, - private_data->arrow_width, - private_data->header_h - 7); - else - gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_RIGHT], - (allocation->width - 2 * xthickness - - 3 - private_data->arrow_width), - 3, - private_data->arrow_width, - private_data->header_h - 7);*/ - gdk_window_move (private_data->arrow_win[ARROW_YEAR_RIGHT], - (widget->allocation.width + private_data->max_year_width) / 2 + HILDON_ARROW_SEP, 0); - } - if (private_data->footer_win) - gdk_window_move_resize (private_data->footer_win, - 0, private_data->header_h + private_data->day_name_h + private_data->main_h + CALENDAR_YSEP, - widget->allocation.width, arrow_hlength); - - if (private_data->arrow_win[ARROW_MONTH_LEFT]) - { - /* if (year_left) - gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_LEFT], - (allocation->width - 2 * xthickness - - (3 + 2*private_data->arrow_width - + private_data->max_month_width)), - 3, - private_data->arrow_width, - private_data->header_h - 7); - else - gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_LEFT], - 3, 3, - private_data->arrow_width, - private_data->header_h - 7); - */ - - gdk_window_move (private_data->arrow_win[ARROW_MONTH_LEFT], - (widget->allocation.width - private_data->max_month_width) / 2 - arrow_vlength - HILDON_ARROW_SEP, 0); - } - if (private_data->arrow_win[ARROW_MONTH_RIGHT]) - { - /* if (year_left) - gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_RIGHT], - (allocation->width - 2 * xthickness - - 3 - private_data->arrow_width), - 3, - private_data->arrow_width, - private_data->header_h - 7); - else - gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_RIGHT], - (private_data->arrow_width - + private_data->max_month_width), - 3, - private_data->arrow_width, - private_data->header_h - 7);*/ - gdk_window_move (private_data->arrow_win[ARROW_MONTH_RIGHT], - (widget->allocation.width + private_data->max_month_width) / 2 + HILDON_ARROW_SEP, 0); - } - - - if (private_data->day_name_win) - gdk_window_move_resize (private_data->day_name_win, - private_data->week_width, /*xthickness + INNER_BORDER*/ - private_data->header_h /*+ (widget->style->ythickness + INNER_BORDER)*/, - widget->allocation.width - private_data->week_width /*- (xthickness + INNER_BORDER) * 2*/, - private_data->day_name_h); - if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) - { - if (private_data->week_win) - gdk_window_move_resize (private_data->week_win, - 0 /*(xthickness + INNER_BORDER)*/, - private_data->header_h /*+ (widget->style->ythickness + INNER_BORDER)*/, - HILDON_DAY_WIDTH, - private_data->main_h + private_data->day_name_h); - gdk_window_move_resize (private_data->main_win, - private_data->week_width /* + (xthickness + INNER_BORDER)*/, - private_data->header_h + private_data->day_name_h - /*+ (widget->style->ythickness + INNER_BORDER)*/, - widget->allocation.width - private_data->week_width - /*- (xthickness + INNER_BORDER) * 2*/, - private_data->main_h); - } - else - { - gdk_window_move_resize (private_data->main_win, - 0 /*(xthickness + INNER_BORDER)*/, - private_data->header_h + private_data->day_name_h - /*+ (widget->style->ythickness + INNER_BORDER)*/, - widget->allocation.width - - private_data->week_width - /*- (xthickness + INNER_BORDER) * 2*/, - private_data->main_h); - if (private_data->week_win) - gdk_window_move_resize (private_data->week_win, - widget->allocation.width - - private_data->week_width - /*- (xthickness + INNER_BORDER)*/, - private_data->header_h + private_data->day_name_h - /*+ (widget->style->ythickness + INNER_BORDER)*/, - private_data->week_width, - private_data->main_h); - } - } -} - -static gboolean -hildon_calendar_expose (GtkWidget *widget, - GdkEventExpose *event) -{ - HildonCalendarPrivate *private_data; - - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - - if (GTK_WIDGET_DRAWABLE (widget)) - { - if (event->window == private_data->main_win) - hildon_calendar_paint_main (widget); - - if (event->window == private_data->header_win) - hildon_calendar_paint_header (widget); - if (event->window == private_data->footer_win) - hildon_calendar_paint_footer(widget); - - if (event->window == private_data->day_name_win) - hildon_calendar_paint_day_names (widget); - - if (event->window == private_data->week_win) - hildon_calendar_paint_week_numbers (widget); - } - - /* FIXME This appeared after 2.6 -> 2.10 migration. Without this the - * arrows disappear when spinning through the calendar. Apparently, something - * overdraws them somehow or the expose events go into blackhole. This is - * a dirty fix... but kinda works */ - - hildon_calendar_paint_header (widget); - hildon_calendar_paint_footer (widget); - - return FALSE; -} - -static void -hildon_calendar_paint_header (GtkWidget *widget) -{ - HildonCalendar *calendar; - GdkGC *gc; - char buffer[255]; - int x, y; - gint header_width, cal_height; - HildonCalendarPrivate *private_data; - PangoLayout *layout; - PangoRectangle logical_rect; - gint arrow_hlength; - - calendar = HILDON_CALENDAR (widget); - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - - if (private_data->freeze_count) - { - private_data->dirty_header = 1; - return; - } - - private_data->dirty_header = 0; - gc = calendar->gc; - - /* Clear window */ - gdk_window_clear (private_data->header_win); - - header_width = widget->allocation.width /*- 2 * widget->style->xthickness*/; - cal_height = widget->allocation.height; - - g_snprintf (buffer, sizeof (buffer), "%d", calendar->year); - layout = gtk_widget_create_pango_layout (widget, buffer); - pango_layout_get_pixel_extents (layout, NULL, &logical_rect); - - gtk_widget_style_get (widget, "scroll-arrow-hlength", &arrow_hlength, NULL); - - y = (arrow_hlength - logical_rect.height) / 2; - x = (widget->allocation.width - logical_rect.width) / 2; - - /* Draw year and its arrows */ - gdk_gc_set_foreground (gc, HEADER_FG_COLOR (GTK_WIDGET (calendar))); - gdk_draw_layout (private_data->header_win, gc, x, y, layout); - - hildon_calendar_paint_arrow (widget, ARROW_YEAR_LEFT); - hildon_calendar_paint_arrow (widget, ARROW_YEAR_RIGHT); - - g_object_unref (layout); -} - -static void -hildon_calendar_paint_footer (GtkWidget *widget) -{ - HildonCalendar *calendar; - GdkGC *gc; - char buffer[255]; - int x, y; - gint header_width, cal_height; - HildonCalendarPrivate *private_data; - PangoLayout *layout; - PangoRectangle logical_rect; - gint arrow_hlength; - - calendar = HILDON_CALENDAR (widget); - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - - if (private_data->freeze_count) - { - private_data->dirty_header = 1; - return; - } - - private_data->dirty_header = 0; - gc = calendar->gc; - - /* Clear window */ - gdk_window_clear (private_data->footer_win); - - header_width = widget->allocation.width - 2 * widget->style->xthickness; - cal_height = widget->allocation.height; - - /* Draw month and its arrows */ - g_snprintf (buffer, sizeof (buffer), "%s", private_data->monthname[calendar->month]); - layout = gtk_widget_create_pango_layout (widget, buffer); - pango_layout_get_pixel_extents (layout, NULL, &logical_rect); - - gtk_widget_style_get (widget, "scroll-arrow-hlength", &arrow_hlength, NULL); - - x = (widget->allocation.width - logical_rect.width) / 2; - y = (arrow_hlength - logical_rect.height) / 2; - - gdk_gc_set_foreground (gc, HEADER_FG_COLOR(GTK_WIDGET (calendar))); - gdk_draw_layout (private_data->footer_win, gc, x, y, layout); - - hildon_calendar_paint_arrow (widget, ARROW_MONTH_LEFT); - hildon_calendar_paint_arrow (widget, ARROW_MONTH_RIGHT); - - g_object_unref(layout); -} - -static void -hildon_calendar_paint_day_names (GtkWidget *widget) -{ - HildonCalendar *calendar; - GdkGC *gc; - char buffer[255]; - int day,i; - int day_width, cal_width; - gint cal_height; - int day_wid_sep; - PangoLayout *layout; - PangoRectangle logical_rect; - HildonCalendarPrivate *private_data; - gint focus_padding; - gint focus_width; - - g_return_if_fail (HILDON_IS_CALENDAR (widget)); - calendar = HILDON_CALENDAR (widget); - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - gc = calendar->gc; - - gtk_widget_style_get (GTK_WIDGET (widget), - "focus-line-width", &focus_width, - "focus-padding", &focus_padding, - NULL); - /* - * Handle freeze/thaw functionality - */ - - if (private_data->freeze_count) - { - private_data->dirty_day_names = 1; - return; - } - private_data->dirty_day_names = 0; - - /* - * Clear the window - */ - - gdk_window_clear (private_data->day_name_win); - - day_width = private_data->day_width; - cal_width = widget->allocation.width; - cal_height = widget->allocation.height; - day_wid_sep = day_width + DAY_XSEP; - - /* - * Draw rectangles as inverted background for the labels. - */ - - /* - * Write the labels - */ - - layout = gtk_widget_create_pango_layout (widget, NULL); - - gdk_gc_set_foreground (gc, SELECTED_FG_COLOR (widget)); - for (i = 0; i < 7; i++) - { - guint x = left_x_for_column (calendar, i); - - if (gtk_widget_get_direction (GTK_WIDGET (calendar)) == GTK_TEXT_DIR_RTL) - day = 6 - i; - else - day = i; - day = (day + private_data->week_start) % 7; - g_snprintf (buffer, sizeof (buffer), "%s", private_data->abbreviated_dayname[day]); - - pango_layout_set_text (layout, buffer, -1); - pango_layout_get_pixel_extents (layout, NULL, &logical_rect); - - /* Hildon: draw passive focus for day name */ - if (calendar->focus_col == i) - gtk_paint_box(GTK_WIDGET (calendar)->style, - private_data->day_name_win, - GTK_STATE_NORMAL, - GTK_SHADOW_OUT, NULL, - GTK_WIDGET (calendar), "passive-focus", - x, - 0, - logical_rect.width + 4, - HILDON_DAY_HEIGHT); - - gdk_draw_layout (private_data->day_name_win, gc, - x + 2, - CALENDAR_MARGIN + focus_width + focus_padding + logical_rect.y, - layout); - } - g_object_unref (layout); -} - -static void -hildon_calendar_paint_week_numbers (GtkWidget *widget) -{ - HildonCalendar *calendar; - GdkGC *gc; - guint row, week = 0, year; - gint x_loc; - char buffer[10]; - gint y_loc; - HildonCalendarPrivate *private_data; - PangoLayout *layout; - PangoRectangle logical_rect; - gint focus_padding; - gint focus_width; - - g_return_if_fail (HILDON_IS_CALENDAR (widget)); - g_return_if_fail (widget->window != NULL); - calendar = HILDON_CALENDAR (widget); - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - gc = calendar->gc; - - /* - * Handle freeze/thaw functionality - */ - - if (private_data->freeze_count) - { - private_data->dirty_week = 1; - return; - } - private_data->dirty_week = 0; - - gtk_widget_style_get (GTK_WIDGET (widget), - "focus-line-width", &focus_width, - "focus-padding", &focus_padding, - NULL); - - /* - * Clear the window - */ - - gdk_window_clear (private_data->week_win); - - /* - * Draw a rectangle as inverted background for the labels. - */ - - gdk_gc_set_foreground (gc, SELECTED_BG_COLOR (widget)); - - /* Hildon: don't paint background for weekday window */ - - /* - * Write the labels - */ - - layout = gtk_widget_create_pango_layout (widget, NULL); - - gdk_gc_set_foreground (gc, SELECTED_FG_COLOR (widget)); - gdk_draw_line(private_data->week_win, gc, - HILDON_DAY_WIDTH + 7, - 0, - HILDON_DAY_WIDTH + 7, - private_data->main_h + private_data->day_name_h); - - for (row = 0; row < 6; row++) - { - year = calendar->year; - if (calendar->day[row][6] < 15 && row > 3 && calendar->month == 11) - year++; - - g_return_if_fail (week_of_year (&week, &year, - ((calendar->day[row][6] < 15 && row > 3 ? 1 : 0) - + calendar->month) % 12 + 1, calendar->day[row][6])); - - g_snprintf (buffer, sizeof (buffer), "%d", week); - pango_layout_set_text (layout, buffer, -1); - pango_layout_get_pixel_extents (layout, NULL, &logical_rect); - - /* Hildon: draw passive focus for week */ - if (calendar->focus_row == row) - { - guint y = top_y_for_row (calendar, calendar->focus_row + 1); - - gtk_paint_box(GTK_WIDGET (calendar)->style, - private_data->week_win, - GTK_STATE_NORMAL, - GTK_SHADOW_OUT, NULL, - GTK_WIDGET (calendar), "passive-focus", - 0, y, - private_data->week_width/* - 4*/, - HILDON_DAY_HEIGHT); - } - - y_loc = private_data->day_name_h + top_y_for_row (calendar, row) + (HILDON_DAY_HEIGHT - logical_rect.height) / 2; - x_loc = (HILDON_DAY_WIDTH - logical_rect.width) / 2; - - gdk_draw_layout (private_data->week_win, gc, x_loc, y_loc, layout); - } - - g_object_unref (layout); -} - -static void -hildon_calendar_paint_day_num (GtkWidget *widget, - gint day) -{ - HildonCalendar *calendar; - gint r, c, row, col; - HildonCalendarPrivate *private_data; - g_return_if_fail (HILDON_IS_CALENDAR (widget)); - - calendar = HILDON_CALENDAR (widget); - - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - - row = -1; - col = -1; - for (r = 0; r < 6; r++) - for (c = 0; c < 7; c++) - if (calendar->day_month[r][c] == MONTH_CURRENT && - calendar->day[r][c] == day) - { - row = r; - col = c; - } - - g_return_if_fail (row != -1); - g_return_if_fail (col != -1); - - hildon_calendar_paint_day (widget, row, col); -} - -static void -hildon_calendar_paint_day (GtkWidget *widget, - gint row, - gint col) -{ - HildonCalendar *calendar; - GdkGC *gc; - gchar buffer[255]; - gint day; - gint x_left; - gint x_loc; - gint y_top; - gint y_loc; - gint focus_width; - - HildonCalendarPrivate *private_data; - PangoLayout *layout; - PangoRectangle logical_rect; - - g_return_if_fail (HILDON_IS_CALENDAR (widget)); - g_return_if_fail (row < 6); - g_return_if_fail (col < 7); - calendar = HILDON_CALENDAR (widget); - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - - if (private_data->main_win == NULL) return; - - /* - * Handle freeze/thaw functionality - */ - - if (private_data->freeze_count) - { - private_data->dirty_main = 1; - return; - } - - gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL); - - day = calendar->day[row][col]; - x_left = left_x_for_column (calendar, col); - y_top = top_y_for_row (calendar, row); - - gdk_window_clear_area (private_data->main_win, x_left, y_top, - HILDON_DAY_WIDTH, HILDON_DAY_HEIGHT); - - gc = calendar->gc; - - if (calendar->day_month[row][col] == MONTH_PREV) - { - gdk_gc_set_foreground (gc, PREV_MONTH_COLOR (GTK_WIDGET (calendar))); - } - else if (calendar->day_month[row][col] == MONTH_NEXT) - { - gdk_gc_set_foreground (gc, NEXT_MONTH_COLOR (GTK_WIDGET (calendar))); - } - else - { - if (calendar->selected_day == day) - { - /* Hildon: use custom graphics */ - gtk_paint_box(GTK_WIDGET (calendar)->style, - private_data->main_win, - GTK_STATE_NORMAL, - GTK_SHADOW_NONE, NULL, - GTK_WIDGET (calendar), "active-day", - x_left, y_top, - HILDON_DAY_WIDTH, - HILDON_DAY_HEIGHT); - } - if (calendar->marked_date[day-1]) - gdk_gc_set_foreground (gc, MARKED_COLOR (GTK_WIDGET (calendar))); - else - gdk_gc_set_foreground (gc, NORMAL_DAY_COLOR (GTK_WIDGET (calendar))); - if (calendar->selected_day == day) - gdk_gc_set_foreground (gc, SELECTED_FG_COLOR (GTK_WIDGET (calendar))); - else - gdk_gc_set_foreground (gc, & (GTK_WIDGET (calendar)->style->fg[GTK_WIDGET_STATE (calendar)])); - } - - if (GTK_WIDGET_HAS_FOCUS (calendar) && - calendar->focus_row == row && - calendar->focus_col == col) - { - GtkStateType state; - - if (calendar->selected_day == day) - state = GTK_WIDGET_HAS_FOCUS (widget) ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE; - else - state = GTK_STATE_NORMAL; - - gtk_paint_focus (widget->style, - private_data->main_win, - (calendar->selected_day == day) - ? GTK_STATE_SELECTED : GTK_STATE_NORMAL, - NULL, widget, "calendar-day", - x_left, y_top, - HILDON_DAY_WIDTH, - HILDON_DAY_HEIGHT); - } - - /* Hildon: paint green indicator for current day */ - if ((day == private_data->current_day && calendar->selected_day != - private_data->current_day) && (calendar->day_month[row][col] == MONTH_CURRENT)) - hildon_calendar_check_current_date (calendar, x_left, y_top); - - g_snprintf (buffer, sizeof (buffer), "%d", day); - layout = gtk_widget_create_pango_layout (widget, buffer); - pango_layout_get_pixel_extents (layout, NULL, &logical_rect); - - x_loc = x_left + (HILDON_DAY_WIDTH - logical_rect.width) / 2; - y_loc = y_top + (HILDON_DAY_HEIGHT - logical_rect.height) / 2; - - gdk_draw_layout (private_data->main_win, gc, - x_loc, y_loc, layout); - if (calendar->marked_date[day-1] && - calendar->day_month[row][col] == MONTH_CURRENT) - gdk_draw_layout (private_data->main_win, gc, - x_loc-1, y_loc, layout); - - g_object_unref (layout); -} - -static void -hildon_calendar_paint_main (GtkWidget *widget) -{ - HildonCalendarPrivate *private_data; - gint row, col; - - g_return_if_fail (HILDON_IS_CALENDAR (widget)); - g_return_if_fail (widget->window != NULL); - - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - - if (private_data->freeze_count) - { - private_data->dirty_main = 1; - return; - } - private_data->dirty_main = 0; - gdk_window_clear (private_data->main_win); - - for (col = 0; col < 7; col++) - for (row = 0; row < 6; row++) - hildon_calendar_paint_day (widget, row, col); -} - -static void -hildon_calendar_compute_days (HildonCalendar *calendar) -{ - HildonCalendarPrivate *private_data; - gint month; - gint year; - gint ndays_in_month; - gint ndays_in_prev_month; - gint first_day; - gint row; - gint col; - gint day; - - g_return_if_fail (HILDON_IS_CALENDAR (calendar)); - - private_data = HILDON_CALENDAR_GET_PRIVATE (GTK_WIDGET (calendar)); - - year = calendar->year; - month = calendar->month + 1; - - ndays_in_month = month_length[leap (year)][month]; - - first_day = day_of_week (year, month, 1); - first_day = (first_day + 7 - private_data->week_start) % 7; - - /* Compute days of previous month */ - if (month > 1) - ndays_in_prev_month = month_length[leap (year)][month-1]; - else - ndays_in_prev_month = month_length[leap (year)][12]; - day = ndays_in_prev_month - first_day + 1; - - row = 0; - if (first_day > 0) - { - for (col = 0; col < first_day; col++) - { - calendar->day[row][col] = day; - calendar->day_month[row][col] = MONTH_PREV; - day++; - } - } - - /* Compute days of current month */ - col = first_day; - for (day = 1; day <= ndays_in_month; day++) - { - calendar->day[row][col] = day; - calendar->day_month[row][col] = MONTH_CURRENT; - - col++; - if (col == 7) - { - row++; - col = 0; - } - } - - /* Compute days of next month */ - day = 1; - for (; row <= 5; row++) - { - for (; col <= 6; col++) - { - calendar->day[row][col] = day; - calendar->day_month[row][col] = MONTH_NEXT; - day++; - } - col = 0; - } -} - -/** - * hildon_calendar_get_display_options: - * @calendar: a #HildonCalendar - * - * Returns the current display options of @calendar. - * - * Return value: the display options. - **/ -HildonCalendarDisplayOptions -hildon_calendar_get_display_options (HildonCalendar *calendar) -{ - g_return_val_if_fail (HILDON_IS_CALENDAR (calendar), 0); - - return calendar->display_flags; -} - -/** - * hildon_calendar_set_display_options: - * @calendar: a #HildonCalendar - * @flags: the display options to set - * - * Sets display options (whether to display the heading and the month - * headings). - * - **/ -void -hildon_calendar_set_display_options (HildonCalendar *calendar, - HildonCalendarDisplayOptions flags) -{ - HildonCalendarPrivate *private_data; - gint resize = 0; - GtkWidget *widget; - gint i; - HildonCalendarDisplayOptions old_flags; - - g_return_if_fail (HILDON_IS_CALENDAR (calendar)); - - widget = GTK_WIDGET (calendar); - private_data = HILDON_CALENDAR_GET_PRIVATE (calendar); - old_flags = calendar->display_flags; - - if (GTK_WIDGET_REALIZED (widget)) - { - if ((flags ^ calendar->display_flags) & HILDON_CALENDAR_NO_MONTH_CHANGE) - { - resize ++; - if (! (flags & HILDON_CALENDAR_NO_MONTH_CHANGE) - && (private_data->header_win)) - { - calendar->display_flags &= ~HILDON_CALENDAR_NO_MONTH_CHANGE; - hildon_calendar_realize_arrows (widget); - } - else - { - for (i = 0; i < 4; i++) - { - if (private_data->arrow_win[i]) - { - gdk_window_set_user_data (private_data->arrow_win[i], - NULL); - gdk_window_destroy (private_data->arrow_win[i]); - private_data->arrow_win[i] = NULL; - } - } - } - } - - if ((flags ^ calendar->display_flags) & HILDON_CALENDAR_SHOW_HEADING) - { - resize++; - - if (flags & HILDON_CALENDAR_SHOW_HEADING) - { - calendar->display_flags |= HILDON_CALENDAR_SHOW_HEADING; - hildon_calendar_realize_header (widget); - } - else - { - for (i = 0; i < 4; i++) - { - if (private_data->arrow_win[i]) - { - gdk_window_set_user_data (private_data->arrow_win[i], - NULL); - gdk_window_destroy (private_data->arrow_win[i]); - private_data->arrow_win[i] = NULL; - } - } - gdk_window_set_user_data (private_data->header_win, NULL); - gdk_window_destroy (private_data->header_win); - private_data->header_win = NULL; - } - } - - - if ((flags ^ calendar->display_flags) & HILDON_CALENDAR_SHOW_DAY_NAMES) - { - resize++; - - if (flags & HILDON_CALENDAR_SHOW_DAY_NAMES) - { - calendar->display_flags |= HILDON_CALENDAR_SHOW_DAY_NAMES; - hildon_calendar_realize_day_names (widget); - } - else - { - gdk_window_set_user_data (private_data->day_name_win, NULL); - gdk_window_destroy (private_data->day_name_win); - private_data->day_name_win = NULL; - } - } - - if ((flags ^ calendar->display_flags) & HILDON_CALENDAR_SHOW_WEEK_NUMBERS) - { - resize++; - - if (flags & HILDON_CALENDAR_SHOW_WEEK_NUMBERS) - { - calendar->display_flags |= HILDON_CALENDAR_SHOW_WEEK_NUMBERS; - hildon_calendar_realize_week_numbers (widget); - } - else - { - gdk_window_set_user_data (private_data->week_win, NULL); - gdk_window_destroy (private_data->week_win); - private_data->week_win = NULL; - } - } - - if ((flags ^ calendar->display_flags) & HILDON_CALENDAR_WEEK_START_MONDAY) - g_warning ("HILDON_CALENDAR_WEEK_START_MONDAY is ignored; the first day of the week is determined from the locale"); - - calendar->display_flags = flags; - if (resize) - gtk_widget_queue_resize (GTK_WIDGET (calendar)); - - } - else - calendar->display_flags = flags; - - g_object_freeze_notify (G_OBJECT (calendar)); - if ((old_flags ^ calendar->display_flags) & HILDON_CALENDAR_SHOW_HEADING) - g_object_notify (G_OBJECT (calendar), "show-heading"); - if ((old_flags ^ calendar->display_flags) & HILDON_CALENDAR_SHOW_DAY_NAMES) - g_object_notify (G_OBJECT (calendar), "show-day-names"); - if ((old_flags ^ calendar->display_flags) & HILDON_CALENDAR_NO_MONTH_CHANGE) - g_object_notify (G_OBJECT (calendar), "no-month-change"); - if ((old_flags ^ calendar->display_flags) & HILDON_CALENDAR_SHOW_WEEK_NUMBERS) - g_object_notify (G_OBJECT (calendar), "show-week-numbers"); - g_object_thaw_notify (G_OBJECT (calendar)); -} - -gboolean -hildon_calendar_select_month (HildonCalendar *calendar, - guint month, - guint year) -{ - HildonCalendarPrivate *priv; - - g_return_val_if_fail (HILDON_IS_CALENDAR (calendar), FALSE); - g_return_val_if_fail (month <= 11, FALSE); - - priv = HILDON_CALENDAR_GET_PRIVATE (calendar); - - if (priv->max_year && year > priv->max_year) - year = priv->max_year; - if (priv->min_year && year < priv->min_year) - year = priv->min_year; - - calendar->month = month; - calendar->year = year; - - hildon_calendar_compute_days (calendar); - - gtk_widget_queue_draw (GTK_WIDGET (calendar)); - - g_object_freeze_notify (G_OBJECT (calendar)); - g_object_notify (G_OBJECT (calendar), "month"); - g_object_notify (G_OBJECT (calendar), "year"); - g_object_thaw_notify (G_OBJECT (calendar)); - - g_signal_emit (calendar, - hildon_calendar_signals[MONTH_CHANGED_SIGNAL], - 0); - return TRUE; -} - -void -hildon_calendar_select_day (HildonCalendar *calendar, - guint day) -{ - gint row, col; - HildonCalendarPrivate *priv; - g_return_if_fail (HILDON_IS_CALENDAR (calendar)); - g_return_if_fail (day <= 31); - priv = HILDON_CALENDAR_GET_PRIVATE (calendar); - - for (row = 0; row < 6; row ++) - for (col = 0; col < 7; col++) - { - if (calendar->day_month[row][col] == MONTH_CURRENT - && calendar->day[row][col] == day) - { - calendar->focus_row = row; - calendar->focus_col = col; - } - } - - if (calendar->month != priv->current_month || - calendar->year != priv->current_year) - hildon_calendar_unmark_day (calendar, priv->current_day); - - /* Deselect the old day */ - if (calendar->selected_day > 0) - { - gint selected_day; - - selected_day = calendar->selected_day; - calendar->selected_day = 0; - if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar))) - { - hildon_calendar_paint_day_num (GTK_WIDGET (calendar), selected_day); - } - } - - calendar->selected_day = day; - - /*printf("Selected day = %d\n", day);*/ - - /* Select the new day */ - if (day != 0) - { - if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar))) - { - hildon_calendar_paint_day_num (GTK_WIDGET (calendar), day); - } - } - - g_object_notify (G_OBJECT (calendar), "day"); - g_signal_emit (calendar, - hildon_calendar_signals[DAY_SELECTED_SIGNAL], - 0); -} - -static void -hildon_calendar_select_and_focus_day (HildonCalendar *calendar, - guint day) -{ - gint old_focus_row = calendar->focus_row; - gint old_focus_col = calendar->focus_col; - gint row; - gint col; - - for (row = 0; row < 6; row ++) - for (col = 0; col < 7; col++) - { - if (calendar->day_month[row][col] == MONTH_CURRENT - && calendar->day[row][col] == day) - { - calendar->focus_row = row; - calendar->focus_col = col; - } - } - - if (old_focus_row != -1 && old_focus_col != -1) - hildon_calendar_paint_day (GTK_WIDGET (calendar), old_focus_row, old_focus_col); - - hildon_calendar_select_day (calendar, day); -} - -void -hildon_calendar_clear_marks (HildonCalendar *calendar) -{ - guint day; - - g_return_if_fail (HILDON_IS_CALENDAR (calendar)); - - for (day = 0; day < 31; day++) - { - calendar->marked_date[day] = FALSE; - } - - calendar->num_marked_dates = 0; - - if (GTK_WIDGET_DRAWABLE (calendar)) - { - hildon_calendar_paint_main (GTK_WIDGET (calendar)); - } -} - -gboolean -hildon_calendar_mark_day (HildonCalendar *calendar, - guint day) -{ - g_return_val_if_fail (HILDON_IS_CALENDAR (calendar), FALSE); - if (day >= 1 && day <= 31 && calendar->marked_date[day-1] == FALSE) - { - calendar->marked_date[day - 1] = TRUE; - calendar->num_marked_dates++; - - if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar))) - hildon_calendar_paint_day_num (GTK_WIDGET (calendar), day-1); - } - - return TRUE; -} - -gboolean -hildon_calendar_unmark_day (HildonCalendar *calendar, - guint day) -{ - g_return_val_if_fail (HILDON_IS_CALENDAR (calendar), FALSE); - - if (day >= 1 && day <= 31 && calendar->marked_date[day-1] == TRUE) - { - calendar->marked_date[day - 1] = FALSE; - calendar->num_marked_dates--; - - if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar))) - hildon_calendar_paint_day_num (GTK_WIDGET (calendar), day-1); - } - - return TRUE; -} - -void -hildon_calendar_get_date (HildonCalendar *calendar, - guint *year, - guint *month, - guint *day) -{ - g_return_if_fail (HILDON_IS_CALENDAR (calendar)); - - if (year) - *year = calendar->year; - - if (month) - *month = calendar->month; - - if (day) - *day = calendar->selected_day; -} - -static void -arrow_action (HildonCalendar *calendar, - guint arrow) -{ - switch (arrow) - { - case ARROW_YEAR_LEFT: - hildon_calendar_set_year_prev (calendar); - break; - case ARROW_YEAR_RIGHT: - hildon_calendar_set_year_next (calendar); - break; - case ARROW_MONTH_LEFT: - hildon_calendar_set_month_prev (calendar); - break; - case ARROW_MONTH_RIGHT: - hildon_calendar_set_month_next (calendar); - break; - default:; - /* do nothing */ - } - - hildon_calendar_select_and_focus_day(calendar, calendar->selected_day); -} - -static gboolean -calendar_timer (gpointer data) -{ - HildonCalendar *calendar = data; - HildonCalendarPrivate *private_data = HILDON_CALENDAR_GET_PRIVATE (calendar); - gboolean retval = FALSE; - GtkSettings *settings; - guint timeout; - - gdk_window_process_updates (((GtkWidget *) calendar)->window, TRUE); - - settings = gtk_settings_get_default (); - g_object_get (settings, "gtk-timeout-repeat", &timeout, NULL); - timeout *= 8; - - GDK_THREADS_ENTER (); - - if (private_data->timer) - { - arrow_action (calendar, private_data->click_child); - - if (private_data->need_timer) - { - private_data->need_timer = FALSE; - private_data->timer = g_timeout_add (/*CALENDAR_TIMER_DELAY*/timeout, - (GSourceFunc) calendar_timer, - (gpointer) calendar); - } - else - retval = TRUE; - } - - GDK_THREADS_LEAVE (); - - return retval; -} - -static void -start_spinning (GtkWidget *widget, - gint click_child) -{ - HildonCalendarPrivate *private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - GtkSettings *settings; - guint timeout; - - settings = gtk_settings_get_default (); - g_object_get (settings, "gtk-timeout-repeat", &timeout, NULL); - timeout *= 8; - - private_data->click_child = click_child; - - if (!private_data->timer) - { - private_data->need_timer = TRUE; - private_data->timer = g_timeout_add (/*CALENDAR_INITIAL_TIMER_DELAY*/timeout, - calendar_timer, - (gpointer) widget); - } -} - -static void -stop_spinning (GtkWidget *widget) -{ - HildonCalendarPrivate *private_data; - - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - - if (private_data->timer) - { - g_source_remove (private_data->timer); - private_data->timer = 0; - private_data->need_timer = FALSE; - } -} - -static void -hildon_calendar_destroy (GtkObject *object) -{ - stop_spinning (GTK_WIDGET (object)); - - GTK_OBJECT_CLASS (parent_class)->destroy (object); -} - -static void -hildon_calendar_grab_notify (GtkWidget *widget, - gboolean was_grabbed) -{ - if (!was_grabbed) - stop_spinning (widget); -} - -static gboolean -hildon_calendar_focus_out (GtkWidget *widget, - GdkEventFocus *event) -{ - HildonCalendarPrivate *private_data; - - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - - stop_spinning (widget); - - private_data->in_drag = 0; - - return FALSE; -} - -static gboolean -hildon_calendar_button_press (GtkWidget *widget, - GdkEventButton *event) -{ - HildonCalendar *calendar; - HildonCalendarPrivate *private_data; - gint arrow = -1; - - calendar = HILDON_CALENDAR (widget); - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - - - if (event->type == GDK_2BUTTON_PRESS) - { - if (event->window == private_data->main_win) - hildon_calendar_main_button (widget, event); - } - else if (event->window == private_data->main_win) - { - gint x = (gint) (event->x); - gint y = (gint) (event->y); - gint row = row_from_y (calendar, y); - gint col = column_from_x (calendar, x); - private_data->pressed_day = calendar->day[row][col]; - - if ((calendar->year == private_data->min_year && - calendar->month == 0 - && calendar->day_month[row][col] == MONTH_PREV) || - (calendar->year == private_data->max_year && - calendar->month == 11 && - calendar->day_month[row][col] == MONTH_NEXT)) - {} - else if (calendar->day_month[row][col] == MONTH_CURRENT) - hildon_calendar_select_and_focus_day (calendar, private_data->pressed_day); - - /* Remember month where button was pressed */ - private_data->pressed_month = calendar->month; - private_data->slide_stylus = TRUE; - } - - if (!GTK_WIDGET_HAS_FOCUS (widget)) - gtk_widget_grab_focus (widget); - - for (arrow = ARROW_YEAR_LEFT; arrow <= ARROW_MONTH_RIGHT; arrow++) - { - if (event->window == private_data->arrow_win[arrow]) - { - - /* only call the action on single click, not double */ - if (event->type == GDK_BUTTON_PRESS) - { - if (event->button == 1) - start_spinning (widget, arrow); - - arrow_action (calendar, arrow); - } - - return TRUE; - } - } - - return TRUE; -} - -static gboolean -hildon_calendar_button_release (GtkWidget *widget, - GdkEventButton *event) -{ - HildonCalendar *calendar; - HildonCalendarPrivate *private_data; - - calendar = HILDON_CALENDAR (widget); - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - - if (event->window == private_data->main_win) - { - hildon_calendar_main_button (widget, event); - gint x = (gint) (event->x); - gint y = (gint) (event->y); - gint row = row_from_y (calendar, y); - gint col = column_from_x (calendar, x); - private_data->prev_col = -1; - private_data->prev_row = -1; - - if ((private_data->pressed_day == calendar->day[row][col]) && - (private_data->pressed_month == calendar->month)) - { - if (!private_data->is_bad_day) - { - g_signal_emit (calendar, hildon_calendar_signals[SELECTED_DATE_SIGNAL], 0); - } - else - { - private_data->is_bad_day = FALSE; - } - } - } - - if (event->button == 1) - { - stop_spinning (widget); - - if (private_data->in_drag) - private_data->in_drag = 0; - } - - private_data->slide_stylus = FALSE; - return TRUE; -} - -static gboolean -hildon_calendar_motion_notify (GtkWidget *widget, - GdkEventMotion *event) -{ - HildonCalendar *calendar; - HildonCalendarPrivate *private_data; - gint event_x, event_y; - gint row, col; - gint old_row, old_col; - - calendar = HILDON_CALENDAR (widget); - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - event_x = (gint) (event->x); - event_y = (gint) (event->y); - - if (event->window == private_data->main_win) - { - /* Hildon: make active day to move, when stylus is slided */ - if (private_data->slide_stylus) - { - gint c_row = row_from_y (calendar, event_y); - gint c_col = column_from_x (calendar, event_x); - - if (calendar->day_month[c_row][c_col] == MONTH_PREV || - calendar->day_month[c_row][c_col] == MONTH_NEXT) - { } - else if ((private_data->prev_row != c_row || private_data->prev_col != c_col) && - (calendar->highlight_row != -1 && calendar->highlight_col != -1)) - { - hildon_calendar_select_and_focus_day (calendar, - calendar->day[c_row][c_col]); - /* Update passive focus indicators work weekday number and name */ - hildon_calendar_paint_week_numbers (GTK_WIDGET (calendar)); - hildon_calendar_paint_day_names (GTK_WIDGET (calendar)); - } - private_data->prev_col = c_col; - private_data->prev_row = c_row; - } - if (private_data->in_drag) - { - if (gtk_drag_check_threshold (widget, - private_data->drag_start_x, private_data->drag_start_y, - event->x, event->y)) - { - GdkDragContext *context; - GtkTargetList *target_list = gtk_target_list_new (NULL, 0); - gtk_target_list_add_text_targets (target_list, 0); - context = gtk_drag_begin (widget, target_list, GDK_ACTION_COPY, - 1, (GdkEvent *)event); - - - private_data->in_drag = 0; - - gtk_target_list_unref (target_list); - gtk_drag_set_icon_default (context); - } - } - else - { - row = row_from_y (calendar, event_y); - col = column_from_x (calendar, event_x); - - if (row != calendar->highlight_row || calendar->highlight_col != col) - { - old_row = calendar->highlight_row; - old_col = calendar->highlight_col; - if (old_row > -1 && old_col > -1) - { - calendar->highlight_row = -1; - calendar->highlight_col = -1; - hildon_calendar_paint_day (widget, old_row, old_col); - } - - calendar->highlight_row = row; - calendar->highlight_col = col; - - if (row > -1 && col > -1) - hildon_calendar_paint_day (widget, row, col); - } - } - } - - return TRUE; -} - -static gboolean -hildon_calendar_enter_notify (GtkWidget *widget, - GdkEventCrossing *event) -{ - HildonCalendarPrivate *private_data; - - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - - if (event->window == private_data->arrow_win[ARROW_MONTH_LEFT]) - { - private_data->arrow_state[ARROW_MONTH_LEFT] = GTK_STATE_PRELIGHT; - hildon_calendar_paint_arrow (widget, ARROW_MONTH_LEFT); - } - - if (event->window == private_data->arrow_win[ARROW_MONTH_RIGHT]) - { - private_data->arrow_state[ARROW_MONTH_RIGHT] = GTK_STATE_PRELIGHT; - hildon_calendar_paint_arrow (widget, ARROW_MONTH_RIGHT); - } - - if (event->window == private_data->arrow_win[ARROW_YEAR_LEFT]) - { - private_data->arrow_state[ARROW_YEAR_LEFT] = GTK_STATE_PRELIGHT; - hildon_calendar_paint_arrow (widget, ARROW_YEAR_LEFT); - } - - if (event->window == private_data->arrow_win[ARROW_YEAR_RIGHT]) - { - private_data->arrow_state[ARROW_YEAR_RIGHT] = GTK_STATE_PRELIGHT; - hildon_calendar_paint_arrow (widget, ARROW_YEAR_RIGHT); - } - - return TRUE; -} - -static gboolean -hildon_calendar_leave_notify (GtkWidget *widget, - GdkEventCrossing *event) -{ - HildonCalendar *calendar; - HildonCalendarPrivate *private_data; - gint row; - gint col; - - calendar = HILDON_CALENDAR (widget); - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - - if (event->window == private_data->main_win) - { - row = calendar->highlight_row; - col = calendar->highlight_col; - calendar->highlight_row = -1; - calendar->highlight_col = -1; - if (row > -1 && col > -1) - hildon_calendar_paint_day (widget, row, col); - } - - if (event->window == private_data->arrow_win[ARROW_MONTH_LEFT]) - { - private_data->arrow_state[ARROW_MONTH_LEFT] = GTK_STATE_NORMAL; - hildon_calendar_paint_arrow (widget, ARROW_MONTH_LEFT); - } - - if (event->window == private_data->arrow_win[ARROW_MONTH_RIGHT]) - { - private_data->arrow_state[ARROW_MONTH_RIGHT] = GTK_STATE_NORMAL; - hildon_calendar_paint_arrow (widget, ARROW_MONTH_RIGHT); - } - - if (event->window == private_data->arrow_win[ARROW_YEAR_LEFT]) - { - private_data->arrow_state[ARROW_YEAR_LEFT] = GTK_STATE_NORMAL; - hildon_calendar_paint_arrow (widget, ARROW_YEAR_LEFT); - } - - if (event->window == private_data->arrow_win[ARROW_YEAR_RIGHT]) - { - private_data->arrow_state[ARROW_YEAR_RIGHT] = GTK_STATE_NORMAL; - hildon_calendar_paint_arrow (widget, ARROW_YEAR_RIGHT); - } - - return TRUE; -} - -static void -hildon_calendar_paint_arrow (GtkWidget *widget, - guint arrow) -{ - HildonCalendarPrivate *private_data; - GdkWindow *window; - GdkGC *gc; - HildonCalendar *calendar; - gint state; - guint arrow_hlength, arrow_vlength; - /* gint width, height;*/ - - calendar = HILDON_CALENDAR (widget); - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - gtk_widget_style_get (widget, - "scroll-arrow-hlength", &arrow_hlength, - "scroll-arrow-vlength", &arrow_vlength, - NULL); - - if (private_data->freeze_count) - { - private_data->dirty_header = 1; - return; - } - window = private_data->arrow_win[arrow]; - if (window) - { - state = private_data->arrow_state[arrow]; - gc = calendar->gc; - - /* gdk_window_clear (window);*/ - gdk_window_set_background (window, &(widget)->style->bg[state]); - /* gdk_drawable_get_size (window, &width, &height);*/ - /* gdk_window_clear_area (window, - 0,0, - width,height);*/ - - gdk_window_clear(window); - - /* Hildon: added support for dimmed arrows */ - if (((private_data->min_year && calendar->year <= private_data->min_year) || - (private_data->max_year && calendar->year >= private_data->max_year))) - { - if (private_data->min_year && - calendar->year <= private_data->min_year) - { - if (arrow == ARROW_YEAR_LEFT) - gtk_paint_arrow (widget->style, window, GTK_STATE_INSENSITIVE, - GTK_SHADOW_OUT, NULL, widget, "calendar", - GTK_ARROW_LEFT, TRUE, - 0, 0, arrow_vlength, arrow_hlength); - else if (arrow == ARROW_YEAR_RIGHT || arrow == ARROW_MONTH_RIGHT) - gtk_paint_arrow (widget->style, window, state, - GTK_SHADOW_OUT, NULL, widget, "calendar", - GTK_ARROW_RIGHT, TRUE, - 0, 0, arrow_vlength, arrow_hlength); - else if (arrow == ARROW_MONTH_LEFT && calendar->month != 0) - gtk_paint_arrow (widget->style, window, state, - GTK_SHADOW_OUT, NULL, widget, "calendar", - GTK_ARROW_LEFT, TRUE, - 0, 0, arrow_vlength, arrow_hlength); - else if (arrow == ARROW_MONTH_LEFT && !calendar->month) - gtk_paint_arrow (widget->style, window, GTK_STATE_INSENSITIVE, - GTK_SHADOW_OUT, NULL, widget, "calendar", - GTK_ARROW_LEFT, TRUE, - 0, 0, arrow_vlength, arrow_hlength); - } - else if (private_data->max_year && - calendar->year >= private_data->max_year) - { - if (arrow == ARROW_YEAR_RIGHT) - gtk_paint_arrow (widget->style, window, GTK_STATE_INSENSITIVE, - GTK_SHADOW_OUT, NULL, widget, "calendar", - GTK_ARROW_RIGHT, TRUE, - 0, 0, arrow_vlength, arrow_hlength); - else if (arrow == ARROW_YEAR_LEFT || arrow == ARROW_MONTH_LEFT) - gtk_paint_arrow (widget->style, window, state, - GTK_SHADOW_OUT, NULL, widget, "calendar", - GTK_ARROW_LEFT, TRUE, - 0, 0, arrow_vlength, arrow_hlength); - else if (arrow == ARROW_MONTH_RIGHT && calendar->month != 11) - gtk_paint_arrow (widget->style, window, state, - GTK_SHADOW_OUT, NULL, widget, "calendar", - GTK_ARROW_RIGHT, TRUE, - 0, 0, arrow_vlength, arrow_hlength); - else if (arrow == ARROW_MONTH_RIGHT && calendar->month == 11) - gtk_paint_arrow (widget->style, window, GTK_STATE_INSENSITIVE, - GTK_SHADOW_OUT, NULL, widget, "calendar", - GTK_ARROW_RIGHT, TRUE, - 0, 0, arrow_vlength, arrow_hlength); - } - } - else - { - if (arrow == ARROW_MONTH_LEFT || arrow == ARROW_YEAR_LEFT) - gtk_paint_arrow (widget->style, window, state, - GTK_SHADOW_OUT, NULL, widget, "calendar", - GTK_ARROW_LEFT, TRUE, - /* width/2 - 3, height/2 - 4, 8, 8);*/ - 0, 0, arrow_vlength, arrow_hlength); - else - gtk_paint_arrow (widget->style, window, state, - GTK_SHADOW_OUT, NULL, widget, "calendar", - GTK_ARROW_RIGHT, TRUE, - /* width/2 - 2, height/2 - 4, 8, 8);*/ - 0, 0, arrow_vlength, arrow_hlength); - } - } -} - -void -hildon_calendar_freeze (HildonCalendar *calendar) -{ - g_return_if_fail (HILDON_IS_CALENDAR (calendar)); - - HILDON_CALENDAR_GET_PRIVATE (calendar)->freeze_count++; -} - -void -hildon_calendar_thaw (HildonCalendar *calendar) -{ - HildonCalendarPrivate *private_data; - - g_return_if_fail (HILDON_IS_CALENDAR (calendar)); - - private_data = HILDON_CALENDAR_GET_PRIVATE (calendar); - - if (private_data->freeze_count) - if (!(--private_data->freeze_count)) - { - if (private_data->dirty_header) - if (GTK_WIDGET_DRAWABLE (calendar)) - hildon_calendar_paint_header (GTK_WIDGET (calendar)); - - if (private_data->dirty_day_names) - if (GTK_WIDGET_DRAWABLE (calendar)) - hildon_calendar_paint_day_names (GTK_WIDGET (calendar)); - - if (private_data->dirty_week) - if (GTK_WIDGET_DRAWABLE (calendar)) - hildon_calendar_paint_week_numbers (GTK_WIDGET (calendar)); - - if (private_data->dirty_main) - if (GTK_WIDGET_DRAWABLE (calendar)) - hildon_calendar_paint_main (GTK_WIDGET (calendar)); - } -} - -static void -hildon_calendar_set_background (GtkWidget *widget) -{ - HildonCalendarPrivate *private_data; - gint i; - - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - - if (GTK_WIDGET_REALIZED (widget)) - { - for (i = 0; i < 4; i++) - { - if (private_data->arrow_win[i]) - gdk_window_set_background (private_data->arrow_win[i], - HEADER_BG_COLOR (widget)); - } - if (private_data->header_win) - gdk_window_set_background (private_data->header_win, - HEADER_BG_COLOR (widget)); - if (private_data->day_name_win) - gdk_window_set_background (private_data->day_name_win, - BACKGROUND_COLOR (widget)); - if (private_data->week_win) - gdk_window_set_background (private_data->week_win, - BACKGROUND_COLOR (widget)); - if (private_data->main_win) - gdk_window_set_background (private_data->main_win, - BACKGROUND_COLOR (widget)); - if (widget->window) - gdk_window_set_background (widget->window, - BACKGROUND_COLOR (widget)); - } -} - -static void -hildon_calendar_style_set (GtkWidget *widget, - GtkStyle *previous_style) -{ - if (previous_style && GTK_WIDGET_REALIZED (widget)) - hildon_calendar_set_background(widget); -} - -static void -hildon_calendar_state_changed (GtkWidget *widget, - GtkStateType previous_state) -{ - HildonCalendarPrivate *private_data; - int i; - - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - - if (!GTK_WIDGET_IS_SENSITIVE (widget)) - { - private_data->in_drag = 0; - stop_spinning (widget); - } - - for (i = 0; i < 4; i++) - if (GTK_WIDGET_IS_SENSITIVE (widget)) - private_data->arrow_state[i] = GTK_STATE_NORMAL; - else - private_data->arrow_state[i] = GTK_STATE_INSENSITIVE; - - hildon_calendar_set_background (widget); -} - -static void -hildon_calendar_finalize (GObject *object) -{ - HildonCalendarPrivate *private_data; - int i; - - private_data = HILDON_CALENDAR_GET_PRIVATE (object); - - for (i = 0; i < 7; i++) - g_free (private_data->abbreviated_dayname[i]); - for (i = 0; i < 12; i++) - g_free (private_data->monthname[i]); - g_free (private_data); - - (* G_OBJECT_CLASS (parent_class)->finalize) (object); -} - -static gboolean -hildon_calendar_scroll (GtkWidget *widget, - GdkEventScroll *event) -{ - HildonCalendar *calendar = HILDON_CALENDAR (widget); - - if (event->direction == GDK_SCROLL_UP) - { - if (!GTK_WIDGET_HAS_FOCUS (widget)) - gtk_widget_grab_focus (widget); - hildon_calendar_set_month_prev (calendar); - } - else if (event->direction == GDK_SCROLL_DOWN) - { - if (!GTK_WIDGET_HAS_FOCUS (widget)) - gtk_widget_grab_focus (widget); - hildon_calendar_set_month_next (calendar); - } - else - return FALSE; - - return TRUE; -} - -static void -move_focus (HildonCalendar *calendar, - gint direction) -{ - GtkTextDirection text_dir = gtk_widget_get_direction (GTK_WIDGET (calendar)); - - if ((text_dir == GTK_TEXT_DIR_LTR && direction == -1) || - (text_dir == GTK_TEXT_DIR_RTL && direction == 1)) - { - if (calendar->focus_col > 0) - calendar->focus_col--; - else if (calendar->focus_row > 0) - { - calendar->focus_col = 6; - calendar->focus_row--; - } - } - else - { - if (calendar->focus_col < 6) - calendar->focus_col++; - else if (calendar->focus_row < 5) - { - calendar->focus_col = 0; - calendar->focus_row++; - } - } -} - -static gboolean -hildon_calendar_key_press (GtkWidget *widget, - GdkEventKey *event) -{ - HildonCalendar *calendar; - HildonCalendarPrivate *priv; - GtkSettings *settings; - gint return_val; - gint old_focus_row; - gint old_focus_col; - gint row, col, day; - gboolean knav; - - calendar = HILDON_CALENDAR (widget); - priv = HILDON_CALENDAR_GET_PRIVATE (calendar); - return_val = FALSE; - - old_focus_row = calendar->focus_row; - old_focus_col = calendar->focus_col; - - settings = gtk_settings_get_default (); - g_object_get (settings, "hildon-keyboard-navigation", &knav, NULL); - - switch (event->keyval) - { - case GDK_KP_Left: - case GDK_Left: - return_val = TRUE; - if (event->state & GDK_CONTROL_MASK) - hildon_calendar_set_month_prev (calendar); - else - { - /* if we are at the first allowed day of the minimum year/month then do nothing */ - if (calendar->year == priv->min_year && calendar->month == 0 && - calendar->day_month[old_focus_row][old_focus_col-1] == MONTH_PREV) - { - g_signal_emit (calendar, hildon_calendar_signals[ERRONEOUS_DATE_SIGNAL], 0); - return TRUE; - } - else /* else normal */ - { - move_focus (calendar, -1); - if (!knav) - { - hildon_calendar_paint_day (widget, old_focus_row, old_focus_col); - hildon_calendar_paint_day (widget, calendar->focus_row, - calendar->focus_col); - } - else if (knav) - { - gint day_month = calendar->day_month[calendar->focus_row][calendar->focus_col]; - if (day_month == MONTH_CURRENT && calendar->selected_day != 1) - { - hildon_calendar_select_day(calendar, calendar->selected_day - 1); - } - else - { - if (calendar->month != 0) { - calendar->selected_day = month_length[leap (calendar->year)][calendar->month]; - } else { - calendar->selected_day = month_length[leap (calendar->year -1)][12]; - } - hildon_calendar_set_month_prev (calendar); - } - hildon_calendar_paint_week_numbers (GTK_WIDGET (calendar)); - hildon_calendar_paint_day_names (GTK_WIDGET (calendar)); - } - } - } - break; - case GDK_KP_Right: - case GDK_Right: - return_val = TRUE; - if (event->state & GDK_CONTROL_MASK) - hildon_calendar_set_month_next (calendar); - else - { - if (calendar->year == priv->max_year && calendar->month == 11 && - calendar->day_month[old_focus_row][old_focus_col+1] == MONTH_NEXT) - { - g_signal_emit (calendar, hildon_calendar_signals[ERRONEOUS_DATE_SIGNAL], 0); - return TRUE; - } - else - { - move_focus (calendar, 1); - if (!knav) - { - hildon_calendar_paint_day (widget, old_focus_row, old_focus_col); - hildon_calendar_paint_day (widget, calendar->focus_row, - calendar->focus_col); - } - else if (knav) - { - gint day_month = calendar->day_month[calendar->focus_row][calendar->focus_col]; - if (day_month == MONTH_CURRENT) - { - hildon_calendar_select_day (calendar, calendar->selected_day + 1); - } - else - { - calendar->selected_day = 1; - hildon_calendar_set_month_next (calendar); - } - hildon_calendar_paint_week_numbers (GTK_WIDGET (calendar)); - hildon_calendar_paint_day_names (GTK_WIDGET (calendar)); - } - } - } - break; - case GDK_KP_Up: - case GDK_Up: - return_val = TRUE; - if (event->state & GDK_CONTROL_MASK) - hildon_calendar_set_year_prev (calendar); - else - { - if (calendar->year == priv->min_year && calendar->month == 0 && - calendar->day_month[old_focus_row-1][old_focus_col] == MONTH_PREV) - { - g_signal_emit (calendar, hildon_calendar_signals[ERRONEOUS_DATE_SIGNAL], 0); - return TRUE; - } - else - { - if (calendar->focus_row > 0) - calendar->focus_row--; - if (!knav) - { - hildon_calendar_paint_day (widget, old_focus_row, old_focus_col); - hildon_calendar_paint_day (widget, calendar->focus_row, - calendar->focus_col); - } - else if (knav) - { - gint day_month = calendar->day_month[calendar->focus_row][calendar->focus_col]; - if (day_month == MONTH_CURRENT) - { - if ((calendar->selected_day - 7) <= 0) - { - if (calendar->month != 0) - calendar->selected_day = month_length[leap (calendar->year)][calendar->month]; - else - calendar->selected_day = month_length[leap (calendar->year - 1)][12]; - hildon_calendar_set_month_prev (calendar); - } - else - { - hildon_calendar_select_day (calendar, calendar->selected_day - 7); - } - } - else - { - calendar->selected_day = calendar->day[calendar->focus_row][calendar->focus_col]; - hildon_calendar_set_month_prev (calendar); - } - hildon_calendar_paint_week_numbers (GTK_WIDGET (calendar)); - hildon_calendar_paint_day_names (GTK_WIDGET (calendar)); - } - } - } - break; - case GDK_KP_Down: - case GDK_Down: - return_val = TRUE; - if (event->state & GDK_CONTROL_MASK) - hildon_calendar_set_year_next (calendar); - else - { - if (calendar->year == priv->max_year && calendar->month == 11 && - calendar->day_month[old_focus_row+1][old_focus_col] == MONTH_NEXT) - { - g_signal_emit (calendar, hildon_calendar_signals[ERRONEOUS_DATE_SIGNAL], 0); - return TRUE; - } - else - { - - if (calendar->focus_row < 5) - calendar->focus_row++; - if (!knav) - { - hildon_calendar_paint_day (widget, old_focus_row, old_focus_col); - hildon_calendar_paint_day (widget, calendar->focus_row, - calendar->focus_col); - } - else if (knav) - { - gint day_month = calendar->day_month[calendar->focus_row][calendar->focus_col]; - if (day_month == MONTH_CURRENT) - { - if ((calendar->selected_day + 7) > - month_length[leap (calendar->year)][calendar->month + 1]) - { - calendar->selected_day = 1; - hildon_calendar_set_month_next (calendar); - } - else - { - hildon_calendar_select_day (calendar, calendar->selected_day + 7); - } - } - else - { - calendar->selected_day = calendar->day[calendar->focus_row][calendar->focus_col]; - hildon_calendar_set_month_next (calendar); - } - hildon_calendar_paint_week_numbers (GTK_WIDGET (calendar)); - hildon_calendar_paint_day_names (GTK_WIDGET (calendar)); - } - } - } - - break; - case GDK_KP_Space: - case GDK_space: - row = calendar->focus_row; - col = calendar->focus_col; - day = calendar->day[row][col]; - - if (row > -1 && col > -1) - { - return_val = TRUE; - hildon_calendar_freeze (calendar); - - if (calendar->day_month[row][col] == MONTH_PREV) - hildon_calendar_set_month_prev (calendar); - else if (calendar->day_month[row][col] == MONTH_NEXT) - hildon_calendar_set_month_next (calendar); - - hildon_calendar_select_and_focus_day (calendar, day); - - hildon_calendar_thaw (calendar); - } - } - - return return_val; -} - -static void -hildon_calendar_set_display_option (HildonCalendar *calendar, - HildonCalendarDisplayOptions flag, - gboolean setting) -{ - HildonCalendarDisplayOptions flags; - - if (setting) - flags = calendar->display_flags | flag; - else - flags = calendar->display_flags & ~flag; - - hildon_calendar_set_display_options (calendar, flags); -} - -static gboolean -hildon_calendar_get_display_option (HildonCalendar *calendar, - HildonCalendarDisplayOptions flag) -{ - return (calendar->display_flags & flag) != 0; -} - - -static void -hildon_calendar_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - HildonCalendar *calendar; - HildonCalendarPrivate *private_data; - gint val; - - calendar = HILDON_CALENDAR (object); - private_data = HILDON_CALENDAR_GET_PRIVATE (calendar); - - switch (prop_id) - { - case PROP_YEAR: - hildon_calendar_select_month (calendar, - calendar->month, - g_value_get_int (value)); - break; - case PROP_MONTH: - hildon_calendar_select_month (calendar, - g_value_get_int (value), - calendar->year); - break; - case PROP_DAY: - hildon_calendar_select_day (calendar, - g_value_get_int (value)); - break; - case PROP_SHOW_HEADING: - hildon_calendar_set_display_option (calendar, - HILDON_CALENDAR_SHOW_HEADING, - g_value_get_boolean (value)); - break; - case PROP_SHOW_DAY_NAMES: - hildon_calendar_set_display_option (calendar, - HILDON_CALENDAR_SHOW_DAY_NAMES, - g_value_get_boolean (value)); - break; - case PROP_NO_MONTH_CHANGE: - hildon_calendar_set_display_option (calendar, - HILDON_CALENDAR_NO_MONTH_CHANGE, - g_value_get_boolean (value)); - break; - case PROP_SHOW_WEEK_NUMBERS: - hildon_calendar_set_display_option (calendar, - HILDON_CALENDAR_SHOW_WEEK_NUMBERS, - g_value_get_boolean (value)); - break; - case PROP_WEEK_START: - private_data->week_start = g_value_get_int (value); - break; - case PROP_MIN_YEAR: - val = g_value_get_int (value); - if (val <= private_data->max_year || - val == 0 || private_data->max_year == 0) - { - private_data->min_year = val; - if (val && (calendar->year < val)) - hildon_calendar_select_month (calendar, - calendar->month, - private_data->min_year); - } - else - g_warning("min-year cannot be greater than max-year"); - break; - case PROP_MAX_YEAR: - val = g_value_get_int (value); - if (val >= private_data->min_year || - val == 0 || private_data->min_year == 0) - { - private_data->max_year = val; - if (val && (calendar->year > val)) - hildon_calendar_select_month (calendar, - calendar->month, - private_data->max_year); - } - else - g_warning("max-year cannot be less than min-year"); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -hildon_calendar_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - HildonCalendar *calendar; - HildonCalendarPrivate *private_data; - - calendar = HILDON_CALENDAR (object); - private_data = HILDON_CALENDAR_GET_PRIVATE (calendar); - - switch (prop_id) - { - case PROP_YEAR: - g_value_set_int (value, calendar->year); - break; - case PROP_MONTH: - g_value_set_int (value, calendar->month); - break; - case PROP_DAY: - g_value_set_int (value, calendar->selected_day); - break; - case PROP_SHOW_HEADING: - g_value_set_boolean (value, hildon_calendar_get_display_option (calendar, - HILDON_CALENDAR_SHOW_HEADING)); - break; - case PROP_SHOW_DAY_NAMES: - g_value_set_boolean (value, hildon_calendar_get_display_option (calendar, - HILDON_CALENDAR_SHOW_DAY_NAMES)); - break; - case PROP_NO_MONTH_CHANGE: - g_value_set_boolean (value, hildon_calendar_get_display_option (calendar, - HILDON_CALENDAR_NO_MONTH_CHANGE)); - break; - case PROP_SHOW_WEEK_NUMBERS: - g_value_set_boolean (value, hildon_calendar_get_display_option (calendar, - HILDON_CALENDAR_SHOW_WEEK_NUMBERS)); - break; - case PROP_WEEK_START: - g_value_set_int (value, private_data->week_start); - break; - case PROP_MIN_YEAR: - g_value_set_int (value, private_data->min_year); - break; - case PROP_MAX_YEAR: - g_value_set_int (value, private_data->max_year); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } - -} - -static void -hildon_calendar_drag_data_get (GtkWidget *widget, - GdkDragContext *context, - GtkSelectionData *selection_data, - guint info, - guint time) -{ - HildonCalendar *calendar = HILDON_CALENDAR (widget); - GDate *date; - gchar str[128]; - gsize len; - - date = g_date_new_dmy (calendar->selected_day, calendar->month + 1, calendar->year); - len = g_date_strftime (str, 127, "%x", date); - gtk_selection_data_set_text (selection_data, str, len); - - g_free (date); -} - -/* Get/set whether drag_motion requested the drag data and - * drag_data_received should thus not actually insert the data, - * since the data doesn't result from a drop. - */ -static void -set_status_pending (GdkDragContext *context, - GdkDragAction suggested_action) -{ - g_object_set_data (G_OBJECT (context), - "gtk-calendar-status-pending", - GINT_TO_POINTER (suggested_action)); -} - -static GdkDragAction -get_status_pending (GdkDragContext *context) -{ - return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (context), - "gtk-calendar-status-pending")); -} - -static void -hildon_calendar_drag_leave (GtkWidget *widget, - GdkDragContext *context, - guint time) -{ - HildonCalendarPrivate *private_data; - - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - private_data->drag_highlight = 0; - gtk_drag_unhighlight (widget); - -} - -static gboolean -hildon_calendar_drag_motion (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - guint time) -{ - HildonCalendarPrivate *private_data; - GdkAtom target; - - private_data = HILDON_CALENDAR_GET_PRIVATE (widget); - - if (!private_data->drag_highlight) - { - private_data->drag_highlight = 1; - gtk_drag_highlight (widget); - } - - target = gtk_drag_dest_find_target (widget, context, NULL); - if (target == GDK_NONE) - gdk_drag_status (context, 0, time); - else { - set_status_pending (context, context->suggested_action); - gtk_drag_get_data (widget, context, target, time); - } - - return TRUE; -} - -static gboolean -hildon_calendar_drag_drop (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - guint time) -{ - GdkAtom target; - - target = gtk_drag_dest_find_target (widget, context, NULL); - if (target != GDK_NONE) - { - gtk_drag_get_data (widget, context, - target, - time); - return TRUE; - } - - return FALSE; -} - -static void -hildon_calendar_drag_data_received (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - GtkSelectionData *selection_data, - guint info, - guint time) -{ - HildonCalendar *calendar = HILDON_CALENDAR (widget); - guint day, month, year; - gchar *str; - GDate *date; - GdkDragAction suggested_action; - - suggested_action = get_status_pending (context); - - if (suggested_action) - { - set_status_pending (context, 0); - - /* We are getting this data due to a request in drag_motion, - * rather than due to a request in drag_drop, so we are just - * supposed to call drag_status, not actually paste in the - * data. - */ - str = (gchar *) gtk_selection_data_get_text (selection_data); - if (str) - { - date = g_date_new (); - g_date_set_parse (date, str); - if (!g_date_valid (date)) - suggested_action = 0; - g_date_free (date); - g_free (str); - } - else - suggested_action = 0; - - gdk_drag_status (context, suggested_action, time); - - return; - } - - date = g_date_new (); - str = (gchar *) gtk_selection_data_get_text (selection_data); - if (str) - { - g_date_set_parse (date, str); - g_free (str); - } - - if (!g_date_valid (date)) - { - g_warning ("Received invalid date data\n"); - g_date_free (date); - gtk_drag_finish (context, FALSE, FALSE, time); - return; - } - - day = g_date_get_day (date); - month = g_date_get_month (date); - year = g_date_get_year (date); - g_date_free (date); - - gtk_drag_finish (context, TRUE, FALSE, time); - - - g_object_freeze_notify (G_OBJECT (calendar)); - if (!(calendar->display_flags & HILDON_CALENDAR_NO_MONTH_CHANGE) - && (calendar->display_flags & HILDON_CALENDAR_SHOW_HEADING)) - hildon_calendar_select_month (calendar, month - 1, year); - hildon_calendar_select_day (calendar, day); - g_object_thaw_notify (G_OBJECT (calendar)); -} - -/* This function return TRUE if we should mark date and FALSE - * otherwise - */ -static void -hildon_calendar_check_current_date (HildonCalendar *calendar, - gint x, - gint y) -{ - HildonCalendarPrivate *private_data; - - private_data = HILDON_CALENDAR_GET_PRIVATE (calendar); - - if (calendar->month == private_data->current_month && - calendar->year == private_data->current_year) - { - gtk_paint_box( GTK_WIDGET (calendar)->style, - private_data->main_win, - GTK_STATE_NORMAL, - GTK_SHADOW_NONE, NULL, - GTK_WIDGET (calendar), "current-day", - x, y, - HILDON_DAY_WIDTH, - HILDON_DAY_HEIGHT); - } -} - -#define __HILDON_CALENDAR_C__ diff --git a/src/hildon-calendar.h b/src/hildon-calendar.h deleted file mode 100644 index 8bf0d5a..0000000 --- a/src/hildon-calendar.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald - * - * GTK Calendar Widget - * Copyright (C) 1998 Cesar Miquel and Shawn T. Amundson - - * HldonCalendar modifications - * Copyright (C) 2005, 2006 Nokia Corporation. - * - * Contact: Rodrigo Novo - * - * 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; either - * version 2 of the License, or (at your option) any later version. or (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS - * file for a list of people on the GTK+ Team. See the ChangeLog - * files for a list of changes. These files are distributed with - * GTK+ at ftp://ftp.gtk.org/pub/gtk/. - */ - -#ifndef HILDON_DISABLE_DEPRECATED - -#ifndef __HILDON_CALENDAR_H__ -#define __HILDON_CALENDAR_H__ - -#include - -G_BEGIN_DECLS - -#define HILDON_TYPE_CALENDAR \ - (hildon_calendar_get_type ()) - -#define HILDON_CALENDAR(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - HILDON_TYPE_CALENDAR, HildonCalendar)) - -#define HILDON_CALENDAR_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - HILDON_TYPE_CALENDAR, HildonCalendarClass)) - -#define HILDON_IS_CALENDAR(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_CALENDAR)) - -#define HILDON_IS_CALENDAR_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_CALENDAR)) - -#define HILDON_CALENDAR_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), HILDON_TYPE_CALENDAR, HildonCalendarClass)) - -typedef struct _HildonCalendar HildonCalendar; - -typedef struct _HildonCalendarClass HildonCalendarClass; - -typedef enum -{ - HILDON_CALENDAR_SHOW_HEADING = 1 << 0, - HILDON_CALENDAR_SHOW_DAY_NAMES = 1 << 1, - HILDON_CALENDAR_NO_MONTH_CHANGE = 1 << 2, - HILDON_CALENDAR_SHOW_WEEK_NUMBERS = 1 << 3, - HILDON_CALENDAR_WEEK_START_MONDAY = 1 << 4 -} HildonCalendarDisplayOptions; - -struct _HildonCalendar -{ - GtkWidget widget; - - GtkStyle *header_style; - GtkStyle *label_style; - - gint month; - gint year; - gint selected_day; - - gint day_month[6][7]; - gint day[6][7]; - - gint num_marked_dates; - gint marked_date[31]; - HildonCalendarDisplayOptions display_flags; - GdkColor marked_date_color[31]; - - GdkGC *gc; - GdkGC *xor_gc; - - gint focus_row; - gint focus_col; - - gint highlight_row; - gint highlight_col; - - gpointer private_data; - gchar grow_space [32]; - - /* Padding for future expansion */ - void (*_gtk_reserved1) (void); - void (*_gtk_reserved2) (void); - void (*_gtk_reserved3) (void); - void (*_gtk_reserved4) (void); -}; - -struct _HildonCalendarClass -{ - GtkWidgetClass parent_class; - - /* Signal handlers */ - void (* month_changed) (HildonCalendar *calendar); - void (* day_selected) (HildonCalendar *calendar); - void (* day_selected_double_click) (HildonCalendar *calendar); - void (* prev_month) (HildonCalendar *calendar); - void (* next_month) (HildonCalendar *calendar); - void (* prev_year) (HildonCalendar *calendar); - void (* next_year) (HildonCalendar *calendar); -}; - - -GType G_GNUC_CONST -hildon_calendar_get_type (void); - -GtkWidget* -hildon_calendar_new (void); - -gboolean -hildon_calendar_select_month (HildonCalendar *calendar, - guint month, - guint year); - -void -hildon_calendar_select_day (HildonCalendar *calendar, - guint day); - -gboolean -hildon_calendar_mark_day (HildonCalendar *calendar, - guint day); - -gboolean -hildon_calendar_unmark_day (HildonCalendar *calendar, - guint day); - -void -hildon_calendar_clear_marks (HildonCalendar *calendar); - -void -hildon_calendar_set_display_options (HildonCalendar *calendar, - HildonCalendarDisplayOptions flags); - -HildonCalendarDisplayOptions -hildon_calendar_get_display_options (HildonCalendar *calendar); - -void -hildon_calendar_get_date (HildonCalendar *calendar, - guint *year, - guint *month, - guint *day); - -void -hildon_calendar_freeze (HildonCalendar *calendar); - -void -hildon_calendar_thaw (HildonCalendar *calendar); - -G_END_DECLS - -#endif /* __HILDON_CALENDAR_H__ */ - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-caption-private.h b/src/hildon-caption-private.h deleted file mode 100644 index 3501d3c..0000000 --- a/src/hildon-caption-private.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_PRIVATE_H__ -#define __HILDON_CAPTION_PRIVATE_H__ - -G_BEGIN_DECLS - -typedef struct _HildonCaptionPrivate HildonCaptionPrivate; - -#define HILDON_CAPTION_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_CAPTION, HildonCaptionPrivate)); - -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; -}; - -G_END_DECLS - -#endif /* __HILDON_CAPTION_PRIVATE_H__ */ diff --git a/src/hildon-caption.c b/src/hildon-caption.c deleted file mode 100644 index 09ab04a..0000000 --- a/src/hildon-caption.c +++ /dev/null @@ -1,1236 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include "hildon-defines.h" -#include "hildon-caption.h" -#include "hildon-caption-private.h" - -#define _(String)\ - dgettext("hildon-libs", String) - -#define HILDON_CAPTION_SPACING 6 - -static GtkEventBox* parent_class = NULL; - -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_grab_focus (GtkWidget *widget); - -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 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, - gboolean markup); - -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); - -enum -{ - PROP_0, - PROP_LABEL, - PROP_MARKUP, - PROP_ICON, - PROP_STATUS, - PROP_SEPARATOR, - PROP_SIZE_GROUP, - PROP_ICON_POSITION, -}; - -enum -{ - CHILD_PROP_NONE, - CHILD_PROP_EXPAND -}; - -/** - * hildon_caption_get_type: - * - * Initializes and returns the type of a hildon caption. - * - * Returns: GType of #HildonCaption - */ -GType G_GNUC_CONST -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 = (gpointer) 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->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; - widget_class->grab_focus = hildon_caption_grab_focus; - - /* 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, - g_cclosure_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:markup: - * - * Caption markup. Mutually exclusive with label. - */ - g_object_class_install_property (gobject_class, PROP_MARKUP, - g_param_spec_string ("markup", - "Current markup", "Caption markup", - NULL, 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. - */ - 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 && priv->caption_area) - { - gtk_widget_unparent (priv->caption_area); - priv->caption_area = NULL; - } - - /* Free user provided strings */ - if (priv && priv->text) - { - g_free (priv->text); - priv->text = NULL; - } - - if (priv && 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); -} - -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, FALSE); - break; - - case PROP_MARKUP: - /* 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, TRUE); - 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, FALSE); - 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) -{ - gtk_widget_grab_focus (GTK_BIN (widget)->child); - - /* we'll update our focused state in set-focus when/if the child receives - * focus */ - - 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; - - 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 child_alloc; - GtkAllocation caption_alloc; - GtkRequisition req, child_req = {0}; - GtkWidget *child = NULL; - HildonCaptionPrivate *priv = NULL; - gboolean rtl; - - g_assert (HILDON_IS_CAPTION (widget)); - priv = HILDON_CAPTION_GET_PRIVATE (widget); - - /* Get the rtl status */ - rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL); - - /* 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; - if (child) - gtk_widget_get_child_requisition (child, &child_req); - - widget->allocation = *allocation; - gtk_widget_get_child_requisition (priv->caption_area, &req); - - child_alloc.height = caption_alloc.height = allocation->height; - child_alloc.width = caption_alloc.width = allocation->width; - child_alloc.x = caption_alloc.x = caption_alloc.y = child_alloc.y = 0; - - /* Center the captioned widget */ - if (rtl) - { - if (caption_alloc.width > child_req.width + HILDON_CAPTION_SPACING) - { - caption_alloc.x = caption_alloc.width - req.width; - child_alloc.width = child_req.width; - } - caption_alloc.width -= child_req.width + HILDON_CAPTION_SPACING * 2; - } - else - { - if (child_alloc.width > req.width + HILDON_CAPTION_SPACING) - { - child_alloc.x += req.width + HILDON_CAPTION_SPACING * 2; - caption_alloc.width = req.width; - } - /* Leave at least the space of the HILDON_CAPTION_SPACING in the left */ - caption_alloc.x = HILDON_CAPTION_SPACING; - - /* Leave room for the other drawable parts of the caption control */ - child_alloc.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)) - { - child_alloc.width = MIN (child_alloc.width, child_req.width); - child_alloc.height = MIN (child_alloc.height, child_req.height); - /* Center the child */ - child_alloc.y = (allocation->height - child_alloc.height - - 2 * GTK_CONTAINER (widget)->border_width)/2; - } - - /* Ensure there are no negative dimensions */ - if (child_alloc.width < 0) - { - caption_alloc.width = req.width + child_alloc.width; - child_alloc.width = 0; - caption_alloc.width = MAX (caption_alloc.width, 0); - } - - if (rtl) - child_alloc.x = caption_alloc.x - child_req.width - HILDON_CAPTION_SPACING * 2; - - child_alloc.height = MAX (child_alloc.height, 0); - caption_alloc.height = MAX (caption_alloc.height, 0); - - if (child && GTK_WIDGET_VISIBLE(child) ) - gtk_widget_size_allocate (child, &child_alloc ); - - gtk_widget_size_allocate (priv->caption_area, &caption_alloc); -} - -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_size_group: - * @caption : a #HildonCaption - * @new_group : a #GtkSizeGroup - * - * Sets a #GtkSizeGroup of a given captioned control. - * - */ -void -hildon_caption_set_size_group (const HildonCaption *self, - GtkSizeGroup *group) -{ - g_object_set (G_OBJECT(self), "size_group", group, NULL); -} - -/** - * hildon_caption_get_size_group: - * @caption : a #HildonCaption - * - * Query given captioned control for the #GtkSizeGroup assigned to it. - * - * Returns: a #GtkSizeGroup - * - */ -GtkSizeGroup* -hildon_caption_get_size_group (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", child, - "size_group", group, - "icon", icon, - "status", flag, - NULL); - - /* Do not expand GtkCheckButton by default, we want to reduce its activation area */ - if (GTK_IS_CHECK_BUTTON (child)) - hildon_caption_set_child_expand (HILDON_CAPTION (widget), FALSE); - - 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. - * - */ -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. - * - */ - -HildonCaptionIconPosition -hildon_caption_get_icon_position (const HildonCaption *caption) -{ - g_return_val_if_fail (HILDON_IS_CAPTION (caption), 0); - - 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 image widget 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 widget that is being used as the icon by the - * hildon_caption, or NULL if no icon image 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_set_label_markup: - * @caption : a #HildonCaption - * @markup : the markup text to use - * - * Sets the label markup text that appears before the control. It acts like - * #hildon_caption_set_label but is using the markup text that allows to specify - * text properties such as bold or italic. - */ -void -hildon_caption_set_label_markup (HildonCaption *caption, - const gchar *markup) -{ - g_return_if_fail (HILDON_IS_CAPTION (caption)); - - g_object_set (G_OBJECT(caption), "markup", markup, 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 (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; -} - -/* 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) -{ - GtkWidget *child = GTK_BIN (widget)->child; - gtk_widget_grab_focus (child); -} - -static void -hildon_caption_grab_focus (GtkWidget *widget) -{ - gtk_widget_grab_focus (GTK_BIN (widget)->child); -} - -/** - * hildon_caption_set_child_expand: - * @caption : a #HildonCaption - * @expand : gboolean to determine if the child is 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; -} - -static void -hildon_caption_set_label_text (HildonCaptionPrivate *priv, - gboolean markup) -{ - 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)) - { - if (markup) - gtk_label_set_markup (GTK_LABEL (priv->label), priv->text); - else - gtk_label_set_text (GTK_LABEL (priv->label), priv->text); - } - else - { - /* Append separator and set text */ - tmp = g_strconcat( priv->text, priv->separator, NULL ); - - if (markup) - gtk_label_set_markup (GTK_LABEL (priv->label), tmp); - else - gtk_label_set_text (GTK_LABEL (priv->label), tmp); - - g_free (tmp); - } - } - else - { - if (markup) - gtk_label_set_markup (GTK_LABEL (priv->label), priv->text); - else - gtk_label_set_text (GTK_LABEL (priv->label), priv->text); - } - } - else - { - /* Clear the label */ - if (markup) - gtk_label_set_markup (GTK_LABEL (priv->label), ""); - else - 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. - * - */ -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 - * - */ -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 deleted file mode 100644 index e1851b9..0000000 --- a/src/hildon-caption.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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 "hildon-enum-types.h" - -G_BEGIN_DECLS - -typedef struct _HildonCaption HildonCaption; - -typedef struct _HildonCaptionClass HildonCaptionClass; - -#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 -{ - 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. - * - */ -typedef enum -{ - HILDON_CAPTION_POSITION_LEFT = 0, - HILDON_CAPTION_POSITION_RIGHT -} HildonCaptionIconPosition; - - -struct _HildonCaption -{ - GtkEventBox parent; -}; - - -struct _HildonCaptionClass -{ - GtkEventBoxClass parent_class; - void (*activate) (HildonCaption *widget); -}; - -GType G_GNUC_CONST -hildon_caption_get_type (void); - -GtkWidget* -hildon_caption_new (GtkSizeGroup *group, - const gchar *value, - GtkWidget *control, - GtkWidget *icon, - HildonCaptionStatus flag); - -GtkSizeGroup* -hildon_caption_get_size_group (const HildonCaption *caption); - -void -hildon_caption_set_size_group (const HildonCaption *caption, - GtkSizeGroup *new_group ); - -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); - -void -hildon_caption_set_child_expand (HildonCaption *caption, - gboolean expand); - -gboolean -hildon_caption_get_child_expand (const HildonCaption *caption); - -void -hildon_caption_set_label_markup (HildonCaption *caption, - const gchar *markup); - -G_END_DECLS - -#endif /* __HILDON_CAPTION_H__ */ diff --git a/src/hildon-check-button.c b/src/hildon-check-button.c deleted file mode 100644 index 1bc26ca..0000000 --- a/src/hildon-check-button.c +++ /dev/null @@ -1,263 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser Public License as published by - * the Free Software Foundation; version 2 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser Public License for more details. - * - */ - -/** - * SECTION:hildon-check-button - * @short_description: Button with a check box inside - * - * #HildonCheckButton is a button containing a label and a check box - * which will remain 'pressed-in' when clicked. Clicking again will - * make the check box toggle its state. - * - * The state of a #HildonCheckButton can be set using - * hildon_check_button_set_active(), and retrieved using - * hildon_check_button_get_active(). The label can be set using - * gtk_button_set_label() and retrieved using gtk_button_get_label(). - * - * - * - * #HildonCheckButton does NOT support an image, so don't use - * gtk_button_set_image(). - * - * - * - * - * Using a Hildon check button - * - * void - * button_toggled (HildonCheckButton *button, gpointer user_data) - * { - * gboolean active; - * - * active = hildon_check_button_get_active (button); - * if (active) - * g_debug ("Button is active"); - * else - * g_debug ("Button is not active"); - * } - * - * GtkWidget * - * create_button (void) - * { - * GtkWidget *button; - * - * button = hildon_check_button_new (HILDON_SIZE_AUTO); - * gtk_button_set_label (GTK_BUTTON (button), "Click me"); - * - * g_signal_connect (button, "toggled", G_CALLBACK (button_toggled), NULL); - * - * return button; - * } - * - * - */ - -#include "hildon-check-button.h" - -enum { - TOGGLED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -G_DEFINE_TYPE (HildonCheckButton, hildon_check_button, GTK_TYPE_BUTTON); - -#define HILDON_CHECK_BUTTON_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_CHECK_BUTTON, HildonCheckButtonPrivate)); - -struct _HildonCheckButtonPrivate -{ - GtkCellRendererToggle *toggle_renderer; -}; - -/** - * hildon_check_button_toggled: - * @button: A #HildonCheckButton - * - * Emits the #HildonCheckButton::toggled signal on the #HildonCheckButton. - * There is no good reason for an application ever to call this function. - * - * Since: 2.2 - */ -void -hildon_check_button_toggled (HildonCheckButton *button) -{ - g_return_if_fail (HILDON_IS_CHECK_BUTTON (button)); - - g_signal_emit (button, signals[TOGGLED], 0); -} - -/** - * hildon_check_button_set_active: - * @button: A #HildonCheckButton - * @is_active: new state for the button - * - * Sets the status of a #HildonCheckButton. Set to %TRUE if you want - * @button to be 'pressed-in', and %FALSE to raise it. This action - * causes the #HildonCheckButton::toggled signal to be emitted. - * - * Since: 2.2 - **/ -void -hildon_check_button_set_active (HildonCheckButton *button, - gboolean is_active) -{ - gboolean prev_is_active; - - g_return_if_fail (HILDON_IS_CHECK_BUTTON (button)); - - prev_is_active = hildon_check_button_get_active (button); - - if (prev_is_active != is_active) { - gtk_button_clicked (GTK_BUTTON (button)); - gtk_widget_queue_draw (GTK_WIDGET (button)); - } -} - -/** - * hildon_check_button_get_active: - * @button: A #HildonCheckButton - * - * Gets the current state of @button. - * - * Return value: %TRUE if @button is active, %FALSE otherwise. - * - * Since: 2.2 - **/ -gboolean -hildon_check_button_get_active (HildonCheckButton *button) -{ - g_return_val_if_fail (HILDON_IS_CHECK_BUTTON (button), FALSE); - - return gtk_cell_renderer_toggle_get_active (button->priv->toggle_renderer); -} - -/** - * hildon_check_button_new: - * @size: Flags indicating the size of the new button - * - * Creates a new #HildonCheckButton. - * - * Return value: A newly created #HildonCheckButton - * - * Since: 2.2 - **/ -GtkWidget * -hildon_check_button_new (HildonSizeType size) -{ - GtkWidget *button = g_object_new (HILDON_TYPE_CHECK_BUTTON, "xalign", 0.0, NULL); - hildon_gtk_widget_set_theme_size (button, size); - return button; -} - -static void -hildon_check_button_clicked (GtkButton *button) -{ - HildonCheckButton *checkbutton = HILDON_CHECK_BUTTON (button); - gboolean current = hildon_check_button_get_active (checkbutton); - - gtk_cell_renderer_toggle_set_active (checkbutton->priv->toggle_renderer, !current); - - hildon_check_button_toggled (checkbutton); -} - -static void -hildon_check_button_apply_style (GtkWidget *widget) -{ - guint checkbox_size; - HildonCheckButtonPrivate *priv = HILDON_CHECK_BUTTON (widget)->priv; - - gtk_widget_style_get (widget, "checkbox-size", &checkbox_size, NULL); - - g_object_set (priv->toggle_renderer, "indicator-size", checkbox_size, NULL); -} - -static void -hildon_check_button_style_set (GtkWidget *widget, - GtkStyle *previous_style) -{ - if (GTK_WIDGET_CLASS (hildon_check_button_parent_class)->style_set) - GTK_WIDGET_CLASS (hildon_check_button_parent_class)->style_set (widget, previous_style); - - hildon_check_button_apply_style (widget); -} - -static void -hildon_check_button_class_init (HildonCheckButtonClass *klass) -{ - GObjectClass *gobject_class = (GObjectClass*) klass; - GtkWidgetClass *widget_class = (GtkWidgetClass*) klass; - GtkButtonClass *button_class = (GtkButtonClass*) klass; - - widget_class->style_set = hildon_check_button_style_set; - button_class->clicked = hildon_check_button_clicked; - - klass->toggled = NULL; - - /** - * HildonCheckButton::toggled - * - * Emitted when the #HildonCheckButton's state is changed. - * - * Since: 2.2 - */ - signals[TOGGLED] = - g_signal_new ("toggled", - G_OBJECT_CLASS_TYPE (gobject_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (HildonCheckButtonClass, toggled), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - gtk_widget_class_install_style_property ( - widget_class, - g_param_spec_uint ( - "checkbox-size", - "Size of the check box", - "Size of the check box", - 0, G_MAXUINT, 26, - G_PARAM_READABLE)); - - g_type_class_add_private (klass, sizeof (HildonCheckButtonPrivate)); -} - -static void -hildon_check_button_init (HildonCheckButton *button) -{ - HildonCheckButtonPrivate *priv = HILDON_CHECK_BUTTON_GET_PRIVATE (button); - GtkWidget *cell_view = gtk_cell_view_new (); - - /* Store private part */ - button->priv = priv; - - /* Make sure that the check box is always shown, no matter the value of gtk-button-images */ - g_signal_connect (cell_view, "notify::visible", G_CALLBACK (gtk_widget_show), NULL); - - /* Create toggle renderer and pack it into the cell view */ - priv->toggle_renderer = GTK_CELL_RENDERER_TOGGLE (gtk_cell_renderer_toggle_new ()); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cell_view), - GTK_CELL_RENDERER (priv->toggle_renderer), FALSE); - - /* Add cell view to the image */ - gtk_button_set_image (GTK_BUTTON (button), cell_view); - - gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE); - - hildon_check_button_apply_style (GTK_WIDGET (button)); -} diff --git a/src/hildon-check-button.h b/src/hildon-check-button.h deleted file mode 100644 index 6430f13..0000000 --- a/src/hildon-check-button.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser Public License as published by - * the Free Software Foundation; version 2 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser Public License for more details. - * - */ - -#ifndef __HILDON_CHECK_BUTTON_H__ -#define __HILDON_CHECK_BUTTON_H__ - -#include "hildon-gtk.h" - -G_BEGIN_DECLS - -#define HILDON_TYPE_CHECK_BUTTON \ - (hildon_check_button_get_type()) - -#define HILDON_CHECK_BUTTON(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - HILDON_TYPE_CHECK_BUTTON, HildonCheckButton)) - -#define HILDON_CHECK_BUTTON_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - HILDON_TYPE_CHECK_BUTTON, HildonCheckButtonClass)) - -#define HILDON_IS_CHECK_BUTTON(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_CHECK_BUTTON)) - -#define HILDON_IS_CHECK_BUTTON_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_CHECK_BUTTON)) - -#define HILDON_CHECK_BUTTON_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - HILDON_TYPE_CHECK_BUTTON, HildonCheckButtonClass)) - -typedef struct _HildonCheckButton HildonCheckButton; - -typedef struct _HildonCheckButtonClass HildonCheckButtonClass; - -typedef struct _HildonCheckButtonPrivate HildonCheckButtonPrivate; - -struct _HildonCheckButtonClass -{ - GtkButtonClass parent_class; - - /* Signal handlers */ - void (* toggled) (HildonCheckButton *button); -}; - -struct _HildonCheckButton -{ - GtkButton parent; - - /* private */ - HildonCheckButtonPrivate *priv; -}; - -GType -hildon_check_button_get_type (void) G_GNUC_CONST; - -GtkWidget * -hildon_check_button_new (HildonSizeType size); - -void -hildon_check_button_set_active (HildonCheckButton *button, - gboolean is_active); - -gboolean -hildon_check_button_get_active (HildonCheckButton *button); - -void -hildon_check_button_toggled (HildonCheckButton *button); - -G_END_DECLS - -#endif /* __HILDON_CHECK_BUTTON_H__ */ diff --git a/src/hildon-code-dialog-private.h b/src/hildon-code-dialog-private.h deleted file mode 100644 index fa94638..0000000 --- a/src/hildon-code-dialog-private.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_PRIVATE_H__ -#define __HILDON_CODE_DIALOG_PRIVATE_H__ - -G_BEGIN_DECLS - -#define HILDON_CODE_DIALOG_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_CODE_DIALOG, HildonCodeDialogPrivate)); - -typedef struct _HildonCodeDialogPrivate HildonCodeDialogPrivate; - -struct _HildonCodeDialogPrivate -{ - GtkWidget *entry; - GtkWidget *buttons[5][3]; - GtkWidget *help_text; - GtkIMContext *im_context; -}; - -G_END_DECLS - -#endif /* __HILDON_CODE_DIALOG_PRIVATE_H__ */ diff --git a/src/hildon-code-dialog.c b/src/hildon-code-dialog.c deleted file mode 100644 index 0c8d8ae..0000000 --- a/src/hildon-code-dialog.c +++ /dev/null @@ -1,685 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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-code-dialog - * @short_description: A keypad-like widget used to enter pincodes. - * - * #HildonCodeDialog displays a keypad that can be used to enter - * numerical pin codes or lock codes. It emits a 'input' signal each time - * an input action is performed on the dialog. - * - */ - -/* FIXME We need property access in this widget */ - -#undef HILDON_DISABLE_DEPRECATED - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include "hildon-code-dialog.h" -#include "hildon-defines.h" -#include "hildon-banner.h" -#include "hildon-code-dialog-private.h" - -#define HEIGHT (48-HILDON_MARGIN_DEFAULT) - -#define WIDTH (100-HILDON_MARGIN_DEFAULT) - -#define BACKSPACE_ICON "general_backspace" - -#define _(String) \ - dgettext("hildon-libs", String) - -#define c_(String) \ - dgettext("hildon-common-strings", String) - -#define DEVICELOCK_OK _("wdgt_bd_done") - -#define DEVICELOCK_TITLE dgettext("osso-system-lock", "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_realize (GtkWidget *widget); - -static void -hildon_code_dialog_unrealize (GtkWidget *widget); - -static void -hildon_code_dialog_finalize (GObject *object); - -static void -hildon_code_dialog_button_clicked (GtkButton *buttonm, - gpointer user_data); - -static void -hildon_code_dialog_backspace (HildonCodeDialog *dialog); - -static void -hildon_code_dialog_im_commit (GtkIMContext *im_context, - gchar *utf8, - 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); - -static void -hildon_code_dialog_real_input (HildonCodeDialog *dialog); - -static void -hildon_code_dialog_input (HildonCodeDialog *dialog); - -static GtkDialogClass* parent_class = NULL; - -static guint input_signal; - -/** - * hildon_code_dialog_get_type: - * - * Initializes and returns the type of a hildon code dialog. - * - * Returns: GType of #HildonCodeDialog - */ -GType G_GNUC_CONST -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) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (cd_class); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (cd_class); - - parent_class = GTK_DIALOG_CLASS (g_type_class_peek_parent (cd_class)); - g_type_class_add_private (cd_class, sizeof (HildonCodeDialogPrivate)); - - gobject_class->finalize = hildon_code_dialog_finalize; - - widget_class->realize = hildon_code_dialog_realize; - widget_class->unrealize = hildon_code_dialog_unrealize; - - cd_class->input = hildon_code_dialog_real_input; - - /* FIXME Document this signal! */ - input_signal = g_signal_new("input", - HILDON_TYPE_CODE_DIALOG, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (HildonCodeDialogClass, input), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, - 0); -} - -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; - - priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); - g_assert (priv); - - 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); - gtk_dialog_set_has_separator ((GtkDialog *) dialog, FALSE); - - 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), -#if GTK_CHECK_VERSION(2,11,0) || defined(MAEMO_GTK) - GTK_BUTTONBOX_CENTER); -#else - GTK_BUTTONBOX_DEFAULT_STYLE); -#endif - - okButton = gtk_dialog_add_button (GTK_DIALOG (dialog) ,DEVICELOCK_OK, - GTK_RESPONSE_OK); - - gtk_widget_set_sensitive (okButton, FALSE); - - priv->buttons[4][0] = priv->buttons[4][1] = okButton; - - priv->im_context = gtk_im_multicontext_new(); -#ifdef MAEMO_GTK - g_object_set (G_OBJECT (priv->im_context), "hildon-input-mode", - HILDON_GTK_INPUT_MODE_NUMERIC, NULL); -#endif - - /* - Connect signals. - */ - g_signal_connect (G_OBJECT (priv->im_context), "commit", - G_CALLBACK (hildon_code_dialog_im_commit), dialog); - - 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); - - gtk_widget_show_all (GTK_WIDGET (GTK_DIALOG (dialog)->vbox)); -} - -static void -hildon_code_dialog_realize (GtkWidget *widget) -{ - HildonCodeDialog *dialog = HILDON_CODE_DIALOG (widget); - HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); - - if (GTK_WIDGET_CLASS (parent_class)->realize) - (* GTK_WIDGET_CLASS (parent_class)->realize) (widget); - - gtk_im_context_set_client_window (GTK_IM_CONTEXT (priv->im_context), - GTK_WIDGET (dialog)->window); - gtk_im_context_focus_in (priv->im_context); -} - -static void -hildon_code_dialog_unrealize (GtkWidget *widget) -{ - HildonCodeDialog *dialog = HILDON_CODE_DIALOG (widget); - HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); - - gtk_im_context_set_client_window (GTK_IM_CONTEXT (priv->im_context), NULL); - - if (GTK_WIDGET_CLASS (parent_class)->unrealize) - (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); -} - -static void -hildon_code_dialog_finalize (GObject *object) -{ - HildonCodeDialog *dialog = HILDON_CODE_DIALOG (object); - HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); - - g_object_unref (priv->im_context); - - G_OBJECT_CLASS(parent_class)->finalize(object); -} - -static void -hildon_code_dialog_backspace (HildonCodeDialog *dialog) -{ - HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); - gchar *text, *pos; - - g_assert (priv); - - text = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->entry))); - - 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); - } - - gtk_editable_set_position (GTK_EDITABLE (priv->entry), -1); - - g_free (text); -} - -static void -hildon_code_dialog_button_clicked (GtkButton *button, - gpointer user_data) -{ - HildonCodeDialog *dialog = HILDON_CODE_DIALOG (user_data); - HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); - g_assert (priv); - - const char *number = gtk_button_get_label (button); - - if (number && *number ) - { - gtk_editable_set_editable (GTK_EDITABLE (priv->entry), TRUE); - - g_signal_emit_by_name (GTK_ENTRY (priv->entry)->im_context, "commit", - number); - - gtk_editable_set_editable (GTK_EDITABLE (priv->entry), FALSE); - - gtk_editable_set_position (GTK_EDITABLE (priv->entry), -1); - } - else - { - hildon_code_dialog_backspace (dialog); - } -} - -static void -hildon_code_dialog_im_commit (GtkIMContext *im_context, - gchar *utf8, - gpointer user_data) -{ - HildonCodeDialog *dialog = HILDON_CODE_DIALOG (user_data); - HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); - gint digit; - - g_assert (priv); - - digit = g_ascii_strtod(utf8, NULL); - - if (g_ascii_isdigit(*utf8)) - { - gtk_editable_set_editable (GTK_EDITABLE (priv->entry), TRUE); - - g_signal_emit_by_name (GTK_ENTRY (priv->entry)->im_context, "commit", - utf8); - - gtk_editable_set_editable (GTK_EDITABLE (priv->entry), FALSE); - - gtk_editable_set_position (GTK_EDITABLE (priv->entry), -1); - } -} - -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 = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); - gchar *text = g_strdup(gtk_entry_get_text (GTK_ENTRY (priv->entry))); - glong length = g_utf8_strlen (text, -1); - g_free (text); - g_assert (priv); - - if (length == MAX_PINCODE_LEN) - { - hildon_banner_show_information (GTK_WIDGET (dialog), - NULL, - DEVICELOCK_MAX_CHAR_REACHED); - } - - else if (! length) - { - /* make the Ok button sensitive */ - gtk_widget_set_sensitive (priv->buttons[4][0], TRUE); - } - - hildon_code_dialog_input (dialog); -} - -static gboolean -hildon_code_dialog_key_press_event (GtkWidget *widget, - GdkEventKey *event, - gpointer user_data) -{ - HildonCodeDialog *dialog = HILDON_CODE_DIALOG (user_data); - HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); - GtkWidget *new_widget = widget; - gint x, y; - - g_assert (priv); - - if (gtk_im_context_filter_keypress (priv->im_context, event)) - return TRUE; - - if (event->keyval == GDK_BackSpace) - { - hildon_code_dialog_backspace (dialog); - return TRUE; - } - - 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; -} - -/** - * hildon_code_dialog_new: - * - * Use this function to create a new HildonCodeDialog. - * - * Return value: A @HildonCodeDialog. - **/ -GtkWidget* -hildon_code_dialog_new (void) -{ - 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); - - HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); - g_assert (priv); - - return gtk_entry_get_text (GTK_ENTRY (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)); - - HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); - g_assert (priv); - - gtk_entry_set_text (GTK_ENTRY (priv->entry), ""); - gtk_widget_set_sensitive (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)); - - HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); - g_assert (priv); - - gtk_label_set_text (GTK_LABEL (priv->help_text), text); -} - -static void -hildon_code_dialog_real_input (HildonCodeDialog *dialog) -{ -} - -static void -hildon_code_dialog_input (HildonCodeDialog *dialog) -{ - /* Emit the signal */ - g_signal_emit (dialog, input_signal, 0); -} - -/** - * hildon_code_dialog_set_input_sensitive - * @dialog: The #HildonCodeDialog whose state is to be changed - * @sensitive: The new state - * - * This function will block or enable the input on the code dialog by - * making the input button sensitive (or not). - **/ -void -hildon_code_dialog_set_input_sensitive (HildonCodeDialog *dialog, - gboolean sensitive) -{ - int i; - int k; - - g_return_if_fail (HILDON_IS_CODE_DIALOG (dialog)); - - HildonCodeDialogPrivate *priv = HILDON_CODE_DIALOG_GET_PRIVATE (dialog); - g_assert (priv); - - for (i = 0; i < 5; i++) - for (k = 0; k < 3; k++) - if (i != 4 && (k != 0 || k != 2)) - gtk_widget_set_sensitive (priv->buttons [i][k], sensitive); - - gtk_widget_set_sensitive (priv->help_text, sensitive); - gtk_widget_set_sensitive (priv->entry, sensitive); -} diff --git a/src/hildon-code-dialog.h b/src/hildon-code-dialog.h deleted file mode 100644 index 577fd85..0000000 --- a/src/hildon-code-dialog.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#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)) - -#define HILDON_CODE_DIALOG_GET_CLASS(obj) \ - ((HildonCodeDialogClass *) G_OBJECT_GET_CLASS(obj)) - -typedef struct _HildonCodeDialog HildonCodeDialog; - -typedef struct _HildonCodeDialogClass HildonCodeDialogClass; - -struct _HildonCodeDialog -{ - GtkDialog parent; -}; - -struct _HildonCodeDialogClass -{ - GtkDialogClass parent_class; - void (*input) (HildonCodeDialog *dialog); -}; - -GType G_GNUC_CONST -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); - -void -hildon_code_dialog_set_input_sensitive (HildonCodeDialog *dialog, - gboolean sensitive); - -G_END_DECLS - -#endif /* __HILDON_CODE_DIALOG_H__ */ - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-color-button-private.h b/src/hildon-color-button-private.h deleted file mode 100644 index 10e7741..0000000 --- a/src/hildon-color-button-private.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_PRIVATE_H__ -#define __HILDON_COLOR_BUTTON_PRIVATE_H__ - -typedef struct _HildonColorButtonPrivate HildonColorButtonPrivate; - -#define HILDON_COLOR_BUTTON_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ - HILDON_TYPE_COLOR_BUTTON, HildonColorButtonPrivate)); - -struct _HildonColorButtonPrivate -{ - GtkWidget *dialog; - gboolean popped; - - GdkColor color; - GdkGC *gc; -}; - -#endif /* __HILDON_COLOR_BUTTON_PRIVATE_H__ */ diff --git a/src/hildon-color-button.c b/src/hildon-color-button.c deleted file mode 100644 index 49c0dfe..0000000 --- a/src/hildon-color-button.c +++ /dev/null @@ -1,648 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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. - * - * - * HildonColorButton example - * - * HildonColorButton *cbutton; - * GtkColor *color; - * - * cbutton = hildon_color_button_new(); - * gtk_object_get( GTK_OBJECT(cbutton), "color", color ); - * - * - * - */ - -#undef HILDON_DISABLE_DEPRECATED - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "hildon-color-button.h" -#include "hildon-defines.h" -#include "hildon-color-chooser-dialog.h" -#include "hildon-color-button-private.h" - -#define COLOR_FILLED_HEIGHT 22 - -#define COLOR_FILLED_WIDTH 22 - -#define COLOR_BUTTON_WIDTH 52 - -#define COLOR_BUTTON_HEIGHT 48 - -#define OUTER_BORDER_RED 0 - -#define OUTER_BORDER_BLUE 0 - -#define OUTER_BORDER_GREEN 0 - -#define OUTER_BORDER_THICKNESS 1 - -#define INNER_BORDER_RED 65535 - -#define INNER_BORDER_BLUE 65535 - -#define INNER_BORDER_GREEN 65535 - -#define INNER_BORDER_THICKNESS 2 - -enum -{ - SETUP_DIALOG, - LAST_SIGNAL -}; - -enum -{ - PROP_0, - PROP_COLOR, - PROP_POPUP_SHOWN -}; - -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; -static guint signals [LAST_SIGNAL] = { 0, }; - -/** - * hildon_color_button_get_type: - * - * Initializes and returns the type of a hildon color button. - * - * Returns: GType of #HildonColorButton. - */ -GType G_GNUC_CONST -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; - - signals[SETUP_DIALOG] = - g_signal_new ("setup-dialog", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - HILDON_TYPE_COLOR_CHOOSER_DIALOG); - - /** - * HildonColorButton:color: - * - * The currently 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)); - - /** - * HildonColorButton:popup-shown: - * - * If the color selection dialog is currently popped-up (visible) - */ - g_object_class_install_property (gobject_class, PROP_POPUP_SHOWN, - g_param_spec_boolean ("popup-shown", - "IsPopped", - "If the color selection dialog is popped up", - FALSE, - G_PARAM_READABLE)); - - g_type_class_add_private (gobject_class, sizeof (HildonColorButtonPrivate)); -} - -/* FIXME 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) -{ - HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (cb); - GdkColor outer_border, inner_border; - - g_assert (priv); - - /* 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 (priv->gc, &outer_border); - /* draw the outer border as a filled rectangle */ - gdk_draw_rectangle (widget->window, - (GTK_WIDGET_IS_SENSITIVE (widget)) ? 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 (priv->gc, &inner_border); - - /* draw the inner border as a filled rectangle */ - gdk_draw_rectangle (widget->window, - 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(priv->gc, &priv->color); - - /* draw the actual rectangle */ - gdk_draw_rectangle(widget->window, - 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; - HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (cb); - - priv->dialog = NULL; - priv->gc = NULL; - priv->popped = FALSE; - - 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) -{ - HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (object); - g_assert (priv); - - if (priv->dialog) - { - gtk_widget_destroy (priv->dialog); - 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) -{ - HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (widget); - g_assert (priv); - - GTK_WIDGET_CLASS (parent_class)->realize (widget); - - priv->gc = gdk_gc_new (widget->window); -} - -static void -hildon_color_button_unrealize (GtkWidget *widget) -{ - HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (widget); - g_assert (priv); - - if (priv->gc != NULL) { - g_object_unref (priv->gc); - 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); - HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (button); - HildonColorChooserDialog *cs_dialog; - - g_assert (priv); - - cs_dialog = (HildonColorChooserDialog *) 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)); - priv->dialog = hildon_color_chooser_dialog_new (); - cs_dialog = HILDON_COLOR_CHOOSER_DIALOG (priv->dialog); - if (parent) - gtk_window_set_transient_for (GTK_WINDOW (cs_dialog), GTK_WINDOW (parent)); - - g_signal_emit (button, signals[SETUP_DIALOG], 0, priv->dialog); - } - - /* Set the initial color for the color selector dialog */ - hildon_color_chooser_dialog_set_color (cs_dialog, &priv->color); - - /* Update the color for color button if selection was made */ - priv->popped = TRUE; - if (gtk_dialog_run (GTK_DIALOG (cs_dialog)) == GTK_RESPONSE_OK) - { - hildon_color_chooser_dialog_get_color (cs_dialog, &priv->color); - hildon_color_button_set_color (HILDON_COLOR_BUTTON (button), &priv->color); - // FIXME A queue-draw should be enough here (not set needed) - } - - gtk_widget_hide (GTK_WIDGET(cs_dialog)); - priv->popped = FALSE; -} - -/* Popup a color selector dialog on hardkey Select press. - * FIXME This is a bit hacky, should work without thi. Check. */ -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; -} - -static void -hildon_color_button_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec) -{ - HildonColorButton *cb = HILDON_COLOR_BUTTON (object); - HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (cb); - g_assert (priv); - - switch (param_id) - { - - case PROP_COLOR: - 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; - } -} - -static void -hildon_color_button_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - HildonColorButton *cb = HILDON_COLOR_BUTTON (object); - HildonColorButtonPrivate *priv = HILDON_COLOR_BUTTON_GET_PRIVATE (cb); - g_assert (priv); - - switch (param_id) - { - - case PROP_COLOR: - g_value_set_boxed (value, &priv->color); - break; - - case PROP_POPUP_SHOWN: - g_value_set_boolean (value, priv->popped); - 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_return_if_fail (HILDON_IS_COLOR_BUTTON (button)); - - g_object_set (G_OBJECT (button), "color", color, NULL); -} - -/** - * hildon_color_button_get_popup_shown - * @button: a #HildonColorButton - * - * This function checks if the color button has the color - * selection dialog currently popped-up. - * - * Returns: TRUE if the dialog is popped-up (visible to user). - * - */ -gboolean -hildon_color_button_get_popup_shown (HildonColorButton *button) -{ - HildonColorButtonPrivate *priv = NULL; - g_return_val_if_fail (HILDON_IS_COLOR_BUTTON (button), FALSE); - - priv = HILDON_COLOR_BUTTON_GET_PRIVATE (button); - g_assert (priv); - - return priv->popped; -} - -/** - * hildon_color_button_popdown - * @button: a #HildonColorButton - * - * If the color selection dialog is currently popped-up (visible) - * it will be popped-down (hidden). - * - */ -void -hildon_color_button_popdown (HildonColorButton *button) -{ - HildonColorButtonPrivate *priv = NULL; - g_return_if_fail (HILDON_IS_COLOR_BUTTON (button)); - - priv = HILDON_COLOR_BUTTON_GET_PRIVATE (button); - g_assert (priv); - - if (priv->popped && priv->dialog) { - gtk_dialog_response (GTK_DIALOG (priv->dialog), GTK_RESPONSE_CANCEL); - } -} - -/** - * hildon_color_button_get_color: - * @button: a #HildonColorButton - * @color: a color #GdkColor to be fillled with the current color - * - */ -void -hildon_color_button_get_color (HildonColorButton *button, - GdkColor *color) -{ - HildonColorButtonPrivate *priv = NULL; - g_return_if_fail (HILDON_IS_COLOR_BUTTON (button)); - g_return_if_fail (color != NULL); - - priv = HILDON_COLOR_BUTTON_GET_PRIVATE (button); - g_assert (priv); - - color->red = priv->color.red; - color->green = priv->color.green; - color->blue = priv->color.blue; - color->pixel = priv->color.pixel; -} - diff --git a/src/hildon-color-button.h b/src/hildon-color-button.h deleted file mode 100644 index cd131ea..0000000 --- a/src/hildon-color-button.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#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; - -struct _HildonColorButton -{ - GtkButton parent; -}; - -struct _HildonColorButtonClass -{ - GtkButtonClass parent_class; -}; - -GType G_GNUC_CONST -hildon_color_button_get_type (void); - -GtkWidget* -hildon_color_button_new (void); - -GtkWidget* -hildon_color_button_new_with_color (const GdkColor *color); - -void -hildon_color_button_get_color (HildonColorButton *button, - GdkColor *color); - -void -hildon_color_button_set_color (HildonColorButton *button, - GdkColor *color); - -gboolean -hildon_color_button_get_popup_shown (HildonColorButton *button); - -void -hildon_color_button_popdown (HildonColorButton *button); - -G_END_DECLS - -#endif /* __HILDON_COLOR_BUTTON_H__ */ - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-color-chooser-dialog-private.h b/src/hildon-color-chooser-dialog-private.h deleted file mode 100644 index 4ebf42f..0000000 --- a/src/hildon-color-chooser-dialog-private.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Author: Kuisma Salonen - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_PRIVATE_H__ -#define __HILDON_COLOR_CHOOSER_DIALOG_PRIVATE_H__ - -#include - -typedef struct _HildonColorChooserDialogPrivate HildonColorChooserDialogPrivate; - -#define HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ - HILDON_TYPE_COLOR_CHOOSER_DIALOG, HildonColorChooserDialogPrivate)); - -typedef struct -{ - GtkBorder radio_sizes; - GtkBorder cont_sizes; - GtkBorder num_buttons; - GtkBorder last_num_buttons; - - GdkColor default_color; -} HildonColorChooserStyleInfo; - -struct _HildonColorChooserDialogPrivate -{ - GtkWidget *hbox; - GtkWidget *vbox; - - GtkWidget *align_custom, *align_defined; - GtkWidget *area_custom, *area_defined; - GtkWidget *separator; - - GtkWidget *chooser; - - GdkColor *colors_custom, *colors_defined; - GdkColor color; - GdkGC **gc_array; - - gint selected; - - HildonColorChooserStyleInfo style_info; - - gint has_style; - - GdkColor pending_color; - - GConfClient *gconf_client; -}; - -#endif /* __HILDON_COLOR_CHOOSER_DIALOG_PRIVATE_H__ */ diff --git a/src/hildon-color-chooser-dialog.c b/src/hildon-color-chooser-dialog.c deleted file mode 100644 index 10676e4..0000000 --- a/src/hildon-color-chooser-dialog.c +++ /dev/null @@ -1,1148 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Author: Kuisma Salonen - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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 used to select a color from HSV colorspace. - * @see_also: #HildonColorButton - * - * HildonColorChooserDialog enables the user to - * select an arbitrary color from a HSV colorspace. - * The color is stored in one of the predefined color - * slots and can be reselected later on. - * - * Additionally the user can choose one of the standard "factory" - * colors. - * - */ - -#undef HILDON_DISABLE_DEPRECATED - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include "hildon-color-chooser-dialog.h" -#include "hildon-color-chooser.h" -#include "hildon-defines.h" -#include "hildon-banner.h" -#include "hildon-color-chooser-dialog-private.h" - -#define _(String) dgettext("hildon-libs", String) - -static HildonColorChooserDialogClass* parent_class = 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}}; - -static void -hildon_color_chooser_dialog_init (HildonColorChooserDialog *object); - -static void -hildon_color_chooser_dialog_class_init (HildonColorChooserDialogClass *klass); - -static void -hildon_color_chooser_dialog_size_request (GtkWidget *widget, - GtkRequisition *req); - -static void -hildon_color_chooser_dialog_size_allocate (GtkWidget *widget, - GtkAllocation *alloc); - -static void -hildon_color_chooser_dialog_realize (GtkWidget *widget); - -static void -hildon_color_chooser_dialog_unrealize (GtkWidget *widget); - -static void -hildon_color_chooser_dialog_style_set (GtkWidget *widget, - GtkStyle *previous_style); - -static void -hildon_color_chooser_dialog_show (GtkWidget *widget); - -static void -hildon_color_chooser_dialog_show_all (GtkWidget *widget); - -static gboolean -hildon_color_chooser_dialog_key_press_event (GtkWidget *widget, - GdkEventKey *event); - -static gboolean -hildon_color_chooser_dialog_key_release_event (GtkWidget *widget, - GdkEventKey *event); - -static void -hildon_color_chooser_dialog_destroy (GtkObject *object); - -static gboolean -hildon_color_chooser_dialog_area_expose (GtkWidget *widget, - GdkEventExpose *event, - gpointer data); - -static gboolean -hildon_color_chooser_dialog_area_button_press (GtkWidget *widget, - GdkEventButton *event, - gpointer data); - -static void -hildon_color_chooser_dialog_color_changed (HildonColorChooser *chooser, - gpointer data); - -static void -hildon_color_chooser_dialog_insensitive_press (GtkWidget *widget, - gpointer data); - -static void -hildon_color_chooser_dialog_refresh_style_info (HildonColorChooserDialog *dialog); - -static void -hildon_color_chooser_dialog_set_color_num (HildonColorChooserDialog *dialog, - gint num); - -static void -hildon_color_chooser_dialog_ascii_hex_to_color (gchar *s, - GdkColor *color); - -static void -hildon_color_chooser_dialog_color_to_ascii_hex (gchar *s, - GdkColor *color); - -GType G_GNUC_CONST -hildon_color_chooser_dialog_get_type (void) -{ - static GType dialog_type = 0; - - if (!dialog_type) { - static const GTypeInfo dialog_info = - { - sizeof (HildonColorChooserDialogClass), - NULL, - NULL, - (GClassInitFunc) hildon_color_chooser_dialog_class_init, - NULL, - NULL, - sizeof (HildonColorChooserDialog), - 0, - (GInstanceInitFunc) hildon_color_chooser_dialog_init, - NULL - }; - - dialog_type = g_type_register_static (GTK_TYPE_DIALOG, - "HildonColorChooserDialog", &dialog_info, 0); - } - - return dialog_type; -} - -static void -hildon_color_chooser_dialog_init (HildonColorChooserDialog *object) -{ - HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (object); - - gtk_dialog_set_has_separator (GTK_DIALOG (object), FALSE); - gtk_window_set_title (GTK_WINDOW (object), _("ecdg_ti_colour_selector")); - - g_assert (priv); - - priv->hbox = gtk_hbox_new (FALSE, 0); - priv->vbox = gtk_vbox_new (FALSE, 0); - priv->chooser = hildon_color_chooser_new (); - - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->chooser, TRUE, TRUE, 0); - gtk_box_pack_end (GTK_BOX (priv->hbox), priv->vbox, FALSE, FALSE, 0); - - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (object)->vbox), priv->hbox, TRUE, TRUE, 0); - - - priv->align_custom = gtk_alignment_new (0.5, 1.0, 0.0, 0.0); - priv->align_defined = gtk_alignment_new (0.5, 1.0, 0.0, 0.0); - - priv->area_custom = gtk_drawing_area_new (); - priv->area_defined = gtk_drawing_area_new (); - - gtk_container_add (GTK_CONTAINER (priv->align_custom), priv->area_custom); - gtk_container_add (GTK_CONTAINER (priv->align_defined), priv->area_defined); - - priv->separator = gtk_hseparator_new (); - - gtk_box_pack_start (GTK_BOX (priv->vbox), priv->align_defined, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (priv->vbox), priv->separator, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (priv->vbox), priv->align_custom, FALSE, FALSE, 0); - - gtk_dialog_add_button (GTK_DIALOG (object), _("wdgt_bd_done"), GTK_RESPONSE_OK); - gtk_dialog_set_default_response (GTK_DIALOG (object), GTK_RESPONSE_OK); - - g_signal_connect (G_OBJECT (priv->chooser), - "query-tooltip", G_CALLBACK (hildon_color_chooser_dialog_insensitive_press), object); - - g_signal_connect (G_OBJECT (priv->area_custom), - "expose-event", G_CALLBACK (hildon_color_chooser_dialog_area_expose), object); - - g_signal_connect (G_OBJECT (priv->area_defined), - "expose-event", G_CALLBACK (hildon_color_chooser_dialog_area_expose), object); - - g_signal_connect (G_OBJECT (priv->area_custom), - "button-press-event", G_CALLBACK (hildon_color_chooser_dialog_area_button_press), object); - - g_signal_connect (G_OBJECT (priv->area_defined), - "button-press-event", G_CALLBACK (hildon_color_chooser_dialog_area_button_press), object); - - g_signal_connect (G_OBJECT (priv->chooser), - "color-changed", G_CALLBACK (hildon_color_chooser_dialog_color_changed), object); - - gtk_widget_add_events (priv->area_custom, GDK_BUTTON_PRESS_MASK); - gtk_widget_add_events (priv->area_defined, GDK_BUTTON_PRESS_MASK); - - priv->selected = 0; - priv->gconf_client = gconf_client_get_default (); - - memset (&priv->style_info, 0, sizeof (HildonColorChooserStyleInfo)); - - priv->colors_custom = NULL; - priv->colors_defined = NULL; - priv->gc_array = NULL; - - priv->has_style = 0; -} - -static void -hildon_color_chooser_dialog_class_init (HildonColorChooserDialogClass *klass) -{ - GtkWidgetClass *widget_klass = GTK_WIDGET_CLASS (klass); - GtkObjectClass *object_klass = GTK_OBJECT_CLASS (klass); - gchar tmp[32]; - gint i; - - widget_klass->size_request = hildon_color_chooser_dialog_size_request; - widget_klass->size_allocate = hildon_color_chooser_dialog_size_allocate; - widget_klass->realize = hildon_color_chooser_dialog_realize; - widget_klass->unrealize = hildon_color_chooser_dialog_unrealize; - widget_klass->style_set = hildon_color_chooser_dialog_style_set; - widget_klass->show = hildon_color_chooser_dialog_show; - widget_klass->show_all = hildon_color_chooser_dialog_show_all; - widget_klass->key_press_event = hildon_color_chooser_dialog_key_press_event; - widget_klass->key_release_event = hildon_color_chooser_dialog_key_release_event; - - - object_klass->destroy = hildon_color_chooser_dialog_destroy; - - parent_class = 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)); - } - - g_type_class_add_private (object_klass, sizeof (HildonColorChooserDialogPrivate)); -} - -static void -hildon_color_chooser_dialog_size_request (GtkWidget *widget, - GtkRequisition *req) -{ - HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget); - - g_assert (priv); - - gtk_container_set_border_width (GTK_CONTAINER (priv->hbox), priv->style_info.cont_sizes.left); - - gtk_box_set_spacing (GTK_BOX (priv->hbox), priv->style_info.cont_sizes.right); - gtk_box_set_spacing (GTK_BOX (priv->vbox), priv->style_info.cont_sizes.top); - gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (widget)->vbox), priv->style_info.cont_sizes.bottom); - - gtk_widget_set_size_request (priv->area_custom, - (priv->style_info.radio_sizes.left + - 2 * priv->style_info.radio_sizes.bottom) * - (priv->style_info.num_buttons.top) + - (priv->style_info.num_buttons.top-1) * - priv->style_info.radio_sizes.top, - (priv->style_info.radio_sizes.right + - 2 * priv->style_info.radio_sizes.bottom) * - (priv->style_info.num_buttons.bottom) + - (priv->style_info.num_buttons.bottom-1) * - priv->style_info.radio_sizes.top); - - gtk_widget_set_size_request (priv->area_defined, - (priv->style_info.radio_sizes.left + - 2 * priv->style_info.radio_sizes.bottom) * - (priv->style_info.num_buttons.left) + - (priv->style_info.num_buttons.left-1) * - priv->style_info.radio_sizes.top, - (priv->style_info.radio_sizes.right + - 2 * priv->style_info.radio_sizes.bottom) * - (priv->style_info.num_buttons.right) + - (priv->style_info.num_buttons.right-1) * - priv->style_info.radio_sizes.top); - - GTK_WIDGET_CLASS (parent_class)->size_request (widget, req); -} - -static void -hildon_color_chooser_dialog_size_allocate (GtkWidget *widget, - GtkAllocation *alloc) -{ - HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget); - - GdkRectangle rect; - int i, tmp, tmp2; - - g_assert (priv); - - GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, alloc); - - if (GTK_WIDGET_REALIZED (widget)) { - tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right); - tmp2 = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); - - for (i = 0; i < tmp; i++) { - rect.x = ((i % priv->style_info.num_buttons.left) * - (priv->style_info.radio_sizes.left + - priv->style_info.radio_sizes.top + - 2 * priv->style_info.radio_sizes.bottom)) + - priv->style_info.radio_sizes.bottom; - - rect.y = ((i / priv->style_info.num_buttons.left) * - (priv->style_info.radio_sizes.right + - priv->style_info.radio_sizes.top + - 2 * priv->style_info.radio_sizes.bottom)) + - priv->style_info.radio_sizes.bottom; - - rect.width = priv->style_info.radio_sizes.left; - rect.height = priv->style_info.radio_sizes.right; - - gdk_gc_set_clip_rectangle (priv->gc_array[i], &rect); - } - - for (i = 0; i < tmp2; i++) { - rect.x = ((i % priv->style_info.num_buttons.top) * - (priv->style_info.radio_sizes.left + - priv->style_info.radio_sizes.top + - 2 * priv->style_info.radio_sizes.bottom)) + - priv->style_info.radio_sizes.bottom; - - rect.y = ((i / priv->style_info.num_buttons.top) * - (priv->style_info.radio_sizes.right + - priv->style_info.radio_sizes.top + - 2 * priv->style_info.radio_sizes.bottom)) + priv->style_info.radio_sizes.bottom; - - rect.width = priv->style_info.radio_sizes.left; - rect.height = priv->style_info.radio_sizes.right; - - gdk_gc_set_clip_rectangle (priv->gc_array[i + tmp], &rect); - } - } -} - -static void -hildon_color_chooser_dialog_realize (GtkWidget *widget) -{ - HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget); - - GdkRectangle rect; - int i, tmp, tmp2; - - g_assert (priv); - - GTK_WIDGET_CLASS(parent_class)->realize (widget); - - tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right) + - (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); - - for (i = 0; i < tmp; i++) { - priv->gc_array[i] = gdk_gc_new (widget->window); - } - - tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right); - tmp2 = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); - - for (i = 0; i < tmp; i++) { - gdk_gc_set_rgb_fg_color (priv->gc_array[i], &priv->colors_defined[i]); - - rect.x = ((i % priv->style_info.num_buttons.left) * - (priv->style_info.radio_sizes.left + - priv->style_info.radio_sizes.top + - 2 * priv->style_info.radio_sizes.bottom)) + - priv->style_info.radio_sizes.bottom; - - rect.y = ((i / priv->style_info.num_buttons.left) * - (priv->style_info.radio_sizes.right + - priv->style_info.radio_sizes.top + - 2 * priv->style_info.radio_sizes.bottom)) + - priv->style_info.radio_sizes.bottom; - - rect.width = priv->style_info.radio_sizes.left; - rect.height = priv->style_info.radio_sizes.right; - - gdk_gc_set_clip_rectangle (priv->gc_array[i], &rect); - } - - for (i = 0; i < tmp2; i++) { - gdk_gc_set_rgb_fg_color (priv->gc_array[i + tmp], &priv->colors_custom[i]); - - rect.x = ((i % priv->style_info.num_buttons.top) * - (priv->style_info.radio_sizes.left + - priv->style_info.radio_sizes.top + - 2 * priv->style_info.radio_sizes.bottom)) + - priv->style_info.radio_sizes.bottom; - - rect.y = ((i / priv->style_info.num_buttons.top) * - (priv->style_info.radio_sizes.right + - priv->style_info.radio_sizes.top + - 2 * priv->style_info.radio_sizes.bottom)) + - priv->style_info.radio_sizes.bottom; - - rect.width = priv->style_info.radio_sizes.left; - rect.height = priv->style_info.radio_sizes.right; - - gdk_gc_set_clip_rectangle (priv->gc_array[i + tmp], &rect); - } -} - -static void -hildon_color_chooser_dialog_unrealize (GtkWidget *widget) -{ - HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget); - - int i, tmp; - - tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right) + - (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); - - for (i = 0; i < tmp; i++) { - g_object_unref (priv->gc_array[i]); - priv->gc_array[i] = NULL; - } - - GTK_WIDGET_CLASS (parent_class)->unrealize (widget); -} - -static void -hildon_color_chooser_dialog_style_set (GtkWidget *widget, - GtkStyle *previous_style) -{ - HildonColorChooserDialog *dialog = HILDON_COLOR_CHOOSER_DIALOG (widget); - HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget); - - GdkColor *tmpcolor; - gchar tmp[32], key[128], *val; - int i, tmpn, setcolor = 0; - - g_assert (priv); - - if (! priv->has_style) - setcolor = 1; - - priv->has_style = 1; - - gtk_widget_style_get (widget, "default_color", &tmpcolor, NULL); - - if (tmpcolor) { - priv->style_info.default_color = *tmpcolor; - gdk_color_free (tmpcolor); - } else { - priv->style_info.default_color.red = 0x0000; - priv->style_info.default_color.green = 0x0000; - priv->style_info.default_color.blue = 0x0000; - priv->style_info.default_color.pixel = 0x00000000; - } - - hildon_color_chooser_dialog_refresh_style_info (dialog); - - if (memcmp (&priv->style_info.num_buttons, &priv->style_info.last_num_buttons, sizeof (GtkBorder))) { - if (priv->colors_custom) { - g_free (priv->colors_custom); - } if (priv->colors_defined) { - g_free (priv->colors_defined); - } if (priv->gc_array) { - if (GTK_WIDGET_REALIZED (widget)) { - tmpn = (priv->style_info.last_num_buttons.left * priv->style_info.last_num_buttons.right) + - (priv->style_info.last_num_buttons.top * priv->style_info.last_num_buttons.bottom); - - for (i = 0; i < tmpn; i++) { - g_object_unref (priv->gc_array[i]); - priv->gc_array[i] = NULL; - } - } - - g_free (priv->gc_array); - } - - priv->colors_custom = (GdkColor *) - g_malloc0 (sizeof (GdkColor) * (priv->style_info.num_buttons.top * - priv->style_info.num_buttons.bottom)); - - priv->colors_defined = (GdkColor *) - g_malloc0 (sizeof(GdkColor) * (priv->style_info.num_buttons.left * - priv->style_info.num_buttons.right)); - - tmpn = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right) + - (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); - - priv->gc_array = (GdkGC **) g_malloc0 (sizeof (GdkGC *) * tmpn); - if (GTK_WIDGET_REALIZED (widget)) { - for (i = 0; i < tmpn; i++) { - priv->gc_array[i] = gdk_gc_new (widget->window); - } - } - - if (priv->gconf_client) { - - for (i = 0; i < (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); i++) { - memset (key, 0, 128); - /* FIXME Extremally bad hardcoding */ - g_snprintf (key, 128, "/system/osso/af/color_chooser/custom_color%d", i); - val = gconf_client_get_string (priv->gconf_client, key, NULL); - - if (val) { - hildon_color_chooser_dialog_ascii_hex_to_color (val, &priv->colors_custom[i]); - g_free (val); - } else { - priv->colors_custom[i] = priv->style_info.default_color; - } - } - } else { - for (i = 0; i < (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); i++) { - priv->colors_custom[i] = priv->style_info.default_color; - } - } - } - - tmpn = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right); - - hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (priv->chooser), - (priv->selected < tmpn) ? - &priv->colors_defined[priv->selected] : - &priv->colors_custom[priv->selected - tmpn]); - - for (i = 0; i < (priv->style_info.num_buttons.left * priv->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) { - priv->colors_defined[i] = *tmpcolor; - gdk_color_free (tmpcolor); - } else { - if(i < 16) { - priv->colors_defined[i] = hardcoded_colors[i]; - } else { /* fallback to prevent segfault */ - priv->colors_defined[i].red = 0x0000; - priv->colors_defined[i].green = 0x0000; - priv->colors_defined[i].blue = 0x0000; - priv->colors_defined[i].pixel = 0x00000000; - } - } - } - - if (GTK_WIDGET_REALIZED (widget)) { - for (i = 0; i < (priv->style_info.num_buttons.left * - priv->style_info.num_buttons.right); i++) { - gdk_gc_set_rgb_fg_color (priv->gc_array[i], &priv->colors_defined[i]); - } - } - - if (setcolor) - hildon_color_chooser_dialog_set_color (HILDON_COLOR_CHOOSER_DIALOG (dialog), - &priv->pending_color); - - gtk_widget_queue_resize (widget); - - GTK_WIDGET_CLASS (parent_class)->style_set (widget, previous_style); -} - -static void -hildon_color_chooser_dialog_show (GtkWidget *widget) -{ - HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget); - - g_assert (priv); - - gtk_widget_show (priv->hbox); - gtk_widget_show (priv->vbox); - - gtk_widget_show (priv->chooser); - - gtk_widget_show (priv->align_custom); - gtk_widget_show (priv->align_defined); - - gtk_widget_show (priv->separator); - - gtk_widget_show (priv->area_custom); - gtk_widget_show (priv->area_defined); - - GTK_WIDGET_CLASS (parent_class)->show (widget); -} - -/* FIXME WTF this function is even needed here? */ -static void -hildon_color_chooser_dialog_show_all (GtkWidget *widget) -{ - hildon_color_chooser_dialog_show (widget); -} - -static gboolean -hildon_color_chooser_dialog_key_press_event (GtkWidget *widget, - GdkEventKey *event) -{ - HildonColorChooserDialog *dialog = HILDON_COLOR_CHOOSER_DIALOG (widget); - HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (widget); - int tmp, tot, sel; - - g_assert (priv); - - if (event->keyval == HILDON_HARDKEY_UP || event->keyval == HILDON_HARDKEY_DOWN || - event->keyval == HILDON_HARDKEY_LEFT || event->keyval == HILDON_HARDKEY_RIGHT) { - tmp = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); - tot = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right) + tmp; - - switch (event->keyval) { - - case HILDON_HARDKEY_UP: - if(priv->selected >= priv->style_info.num_buttons.top) { - if(priv->selected - priv->style_info.num_buttons.left >= tmp) { - sel = priv->selected - priv->style_info.num_buttons.left; - } else { - sel = priv->selected - priv->style_info.num_buttons.top; - } - - hildon_color_chooser_dialog_set_color_num (dialog, sel); - } - break; - - case HILDON_HARDKEY_DOWN: - if(priv->selected < tot - priv->style_info.num_buttons.left) { - if(priv->selected < tmp) { - sel = priv->selected + priv->style_info.num_buttons.top; - } else { - sel = priv->selected + priv->style_info.num_buttons.left; - } - - hildon_color_chooser_dialog_set_color_num (dialog, sel); - } - break; - - case HILDON_HARDKEY_LEFT: - if ((priv->selected < tmp ? - (priv->selected % priv->style_info.num_buttons.top) : - ((priv->selected - tmp) % priv->style_info.num_buttons.left)) > 0) { - sel = priv->selected - 1; - - hildon_color_chooser_dialog_set_color_num (dialog, sel); - } - break; - - case HILDON_HARDKEY_RIGHT: - if ((priv->selected < tmp) ? - (priv->selected % priv->style_info.num_buttons.top < priv->style_info.num_buttons.top - 1) : - ((priv->selected - tmp) % priv->style_info.num_buttons.left < priv->style_info.num_buttons.left - 1)) { - sel = priv->selected + 1; - - hildon_color_chooser_dialog_set_color_num (dialog, sel); - } - break; - - default: - break; - } - - return FALSE; - } - - return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event); -} - -static gboolean -hildon_color_chooser_dialog_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_class)->key_press_event (widget, event); -} - -static void -hildon_color_chooser_dialog_destroy (GtkObject *object) -{ - HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (object); - - gchar key[128], color[13]; - int i, tmp; - - g_assert (priv); - - if (priv->gconf_client) { - memset (color, 0, 13); - - tmp = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); - - for (i = 0; i < tmp; i++) { - memset (key, 0, 128); - /* FIXME Extremally bad hardcoding */ - g_snprintf (key, 128, "/system/osso/af/color_chooser/custom_color%d", i); - hildon_color_chooser_dialog_color_to_ascii_hex (color, &priv->colors_custom[i]); - gconf_client_set_string (priv->gconf_client, key, color, NULL); - } - - g_object_unref (priv->gconf_client); - priv->gconf_client = NULL; - } - - if (priv->gc_array) { - g_free (priv->gc_array); - priv->gc_array = NULL; - } if (priv->colors_defined) { - g_free (priv->colors_defined); - priv->colors_defined = NULL; - } if (priv->colors_custom) { - g_free (priv->colors_custom); - priv->colors_custom = NULL; - } - - GTK_OBJECT_CLASS (parent_class)->destroy (object); -} - -/** - * hildon_color_chooser_dialog_set_color: - * @dialog: a #HildonColorChooserDialog - * @color: a color to set on the #HildonColorChooserDialog - * - * Sets the dialog to point at the given color. It'll first try to - * search the palette of the existing colors to match the passed color. - * If the color is not found in the pallette, the color in the currently - * selected box will be modified. - * - */ -void -hildon_color_chooser_dialog_set_color (HildonColorChooserDialog *dialog, - GdkColor *color) -{ - HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (dialog); - - int i, found = -1, tmp, tmp2; - - g_assert (priv); - - if (! priv->has_style) { - priv->pending_color = *color; - return; - } - - tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right); - tmp2 = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); - - for (i = 0; i < tmp; i++) { - if (priv->colors_defined[i].red == color->red && - priv->colors_defined[i].green == color->green && - priv->colors_defined[i].blue == color->blue) { - found = i; - break; - } - } - - if (found == -1) { - for (i = 0; i < tmp2; i++) { - if (priv->colors_custom[i].red == color->red && - priv->colors_custom[i].green == color->green && - priv->colors_custom[i].blue == color->blue) { - found = i + tmp; - break; - } - } - } - - if (found == -1) { - priv->colors_custom[tmp2-1] = *color; - if (GTK_WIDGET_REALIZED (GTK_WIDGET (dialog))) { - gdk_gc_set_rgb_fg_color (priv->gc_array[tmp2-1], color); - } - hildon_color_chooser_dialog_set_color_num (dialog, tmp2 - 1); - } else { - hildon_color_chooser_dialog_set_color_num (dialog, found); - } -} - -static gboolean -hildon_color_chooser_dialog_area_expose (GtkWidget *widget, - GdkEventExpose *event, - gpointer data) -{ - HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (data); - - int i, num_selected, tot_w, tot_h, spacing, brd, x, y; - GdkGC **start_gc; - int tmp, w, h; - - g_assert (priv); - - tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right); - - if (widget == priv->area_custom) { - num_selected = priv->selected - tmp; - start_gc = priv->gc_array + tmp; - tmp = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); - w = priv->style_info.num_buttons.top; - h = priv->style_info.num_buttons.bottom; - } else { /* widget == dialog->area_defined */ - num_selected = priv->selected; - start_gc = priv->gc_array; - w = priv->style_info.num_buttons.left; - h = priv->style_info.num_buttons.right; - } - - spacing = priv->style_info.radio_sizes.top; - brd = priv->style_info.radio_sizes.bottom; - tot_w = priv->style_info.radio_sizes.left + 2 * brd; - tot_h = priv->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, - (i == num_selected) ? widget->style->bg_gc[GTK_STATE_SELECTED] : widget->style->bg_gc[GTK_STATE_NORMAL], - 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, - (i == num_selected) ? widget->style->bg_gc[GTK_STATE_NORMAL] : 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); - } - - return FALSE; -} - -static gboolean -hildon_color_chooser_dialog_area_button_press (GtkWidget *widget, - GdkEventButton *event, - gpointer data) -{ - HildonColorChooserDialog *dialog = HILDON_COLOR_CHOOSER_DIALOG (data); - HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (data); - - int i, hskip, vskip, brd, selection = -1; - int x, y, tmp, tmp2, w; - - g_assert (priv); - - x = event->x; - y = event->y; - - brd = priv->style_info.radio_sizes.bottom; - hskip = priv->style_info.radio_sizes.left + - priv->style_info.radio_sizes.top + 2 * brd; - vskip = priv->style_info.radio_sizes.right + - priv->style_info.radio_sizes.top + 2 * brd; - - tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right); - tmp2 = (priv->style_info.num_buttons.top * priv->style_info.num_buttons.bottom); - - if (widget == priv->area_defined) { - w = priv->style_info.num_buttons.left; - - for (i = 0; i < tmp; i++) { - if (x >= hskip * (i % w) + brd && x < hskip * (i % w) + brd + priv->style_info.radio_sizes.left && - y >= vskip * (i / w) + brd && y < hskip * (i / w) + brd + priv->style_info.radio_sizes.right) { - selection = i; - break; - } - } - } else { - w = priv->style_info.num_buttons.top; - for (i = 0; i < tmp2; i++) { - if (x >= hskip * (i % w) + brd && x < hskip * (i % w) + brd + priv->style_info.radio_sizes.left && - y >= vskip * (i / w) + brd && y < hskip * (i / w) + brd + priv->style_info.radio_sizes.right) { - selection = i + tmp; - break; - } - } - } - - if (selection != -1) { - hildon_color_chooser_dialog_set_color_num (dialog, selection); - } - - return FALSE; -} - -static void -hildon_color_chooser_dialog_color_changed (HildonColorChooser *chooser, - gpointer data) -{ - HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (data); - char key[128], color_str[13]; - int tmp; - GdkColor color; - - g_assert (priv); - - hildon_color_chooser_get_color (chooser, &color); - - tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right); - - if (priv->selected >= tmp) { - priv->colors_custom[priv->selected - tmp] = color; - - gdk_gc_set_rgb_fg_color (priv->gc_array[priv->selected], &priv->colors_custom[priv->selected - tmp]); - gtk_widget_queue_draw (priv->area_custom); - - if (priv->gconf_client) { - memset (key, 0, 128); - memset (color_str, 0, 13); - /* FIXME Ugly hardcoded stuff! */ - g_snprintf (key, 128, "/system/osso/af/color_chooser/custom_color%d", priv->selected - tmp); - hildon_color_chooser_dialog_color_to_ascii_hex (color_str, &priv->colors_custom[priv->selected - tmp]); - gconf_client_set_string (priv->gconf_client, key, color_str, NULL); - } - } -} - -static void -hildon_color_chooser_dialog_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_refresh_style_info (HildonColorChooserDialog *dialog) -{ - GtkBorder *tmp1, *tmp2, *tmp3; - HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (dialog); - - g_assert (priv); - - gtk_widget_style_get (GTK_WIDGET (dialog), "container_sizes", &tmp1, - "radio_sizes", &tmp2, "num_buttons", &tmp3, NULL); - - priv->style_info.last_num_buttons = priv->style_info.num_buttons; - - if (tmp1) { - priv->style_info.cont_sizes = *tmp1; - gtk_border_free (tmp1); - } else { - priv->style_info.cont_sizes.left = 0; - priv->style_info.cont_sizes.right = 8; - priv->style_info.cont_sizes.top = 4; - priv->style_info.cont_sizes.bottom = 0; - } - - if (tmp2) { - priv->style_info.radio_sizes = *tmp2; - gtk_border_free (tmp2); - } else { - priv->style_info.radio_sizes.left = 16; - priv->style_info.radio_sizes.right = 16; - priv->style_info.radio_sizes.top = 4; - priv->style_info.radio_sizes.bottom = 2; - } - - if (tmp3) { - priv->style_info.num_buttons = *tmp3; - gtk_border_free (tmp3); - } else { - priv->style_info.num_buttons.left = 8; - priv->style_info.num_buttons.right = 2; - priv->style_info.num_buttons.top = 8; - priv->style_info.num_buttons.bottom = 2; - } -} - -static void -hildon_color_chooser_dialog_set_color_num (HildonColorChooserDialog *dialog, - gint num) -{ - HildonColorChooserDialogPrivate *priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (dialog); - - int tmp; - - g_assert (priv); - - tmp = (priv->style_info.num_buttons.left * priv->style_info.num_buttons.right); - - if (num < tmp) { - gtk_widget_set_sensitive (priv->chooser, FALSE); - } else { - gtk_widget_set_sensitive (priv->chooser, TRUE); - } - - priv->selected = num; - - gtk_widget_queue_draw (priv->area_custom); - gtk_widget_queue_draw (priv->area_defined); - - priv->color = (num < tmp) ? priv->colors_defined[num] : priv->colors_custom[num - tmp]; - - hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (priv->chooser), - (num < tmp) ? &priv->colors_defined[num] : &priv->colors_custom[num - tmp]); -} - -static void -hildon_color_chooser_dialog_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_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); -} - -/** - * hildon_color_chooser_dialog_new: - * - * Creates a new color chooser dialog. - * - * Returns: a new color chooser dialog. - */ -GtkWidget* -hildon_color_chooser_dialog_new (void) -{ - return g_object_new (HILDON_TYPE_COLOR_CHOOSER_DIALOG, NULL); -} - -/** - * hildon_color_chooser_dialog_get_color: - * @dialog: a #HildonColorChooserDialog - * @color: a color structure to fill with the currently selected color - * - * Retrives the currently selected color in the color chooser dialog. - * - */ -void -hildon_color_chooser_dialog_get_color (HildonColorChooserDialog *dialog, - GdkColor *color) -{ - /* FIXME Should return pending color? */ - HildonColorChooserDialogPrivate *priv; - - g_return_if_fail (HILDON_IS_COLOR_CHOOSER_DIALOG (dialog)); - priv = HILDON_COLOR_CHOOSER_DIALOG_GET_PRIVATE (dialog); - g_assert (priv); - - hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER (priv->chooser), color); -} - diff --git a/src/hildon-color-chooser-dialog.h b/src/hildon-color-chooser-dialog.h deleted file mode 100644 index cb51d00..0000000 --- a/src/hildon-color-chooser-dialog.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Author: Kuisma Salonen - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#ifndef __HILDON_COLOR_CHOOSER_DIALOG_H__ -#define __HILDON_COLOR_CHOOSER_DIALOG_H__ - -#include - -G_BEGIN_DECLS - -#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; -}; - -struct _HildonColorChooserDialogClass -{ - GtkDialogClass parent_class; -}; - -GType G_GNUC_CONST -hildon_color_chooser_dialog_get_type (void); - -GtkWidget* -hildon_color_chooser_dialog_new (void); - -void -hildon_color_chooser_dialog_set_color (HildonColorChooserDialog *dialog, - GdkColor *color); - -void -hildon_color_chooser_dialog_get_color (HildonColorChooserDialog *dialog, - GdkColor *color); - -G_END_DECLS - -#endif /* __HILDON_COLOR_CHOOSER_DIALOG_H__ */ - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-color-chooser-private.h b/src/hildon-color-chooser-private.h deleted file mode 100644 index 80f04fb..0000000 --- a/src/hildon-color-chooser-private.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Author: Kuisma Salonen - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_PRIVATE_H__ -#define __HILDON_COLOR_CHOOSER_PRIVATE_H__ - -typedef struct _HildonColorChooserPrivate HildonColorChooserPrivate; - -#define HILDON_COLOR_CHOOSER_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ - HILDON_TYPE_COLOR_CHOOSER, HildonColorChooserPrivate)); - -struct _HildonColorChooserPrivate -{ - 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; -}; - -#endif /* __HILDON_COLOR_CHOOSER_H__ */ diff --git a/src/hildon-color-chooser.c b/src/hildon-color-chooser.c deleted file mode 100644 index 81f8704..0000000 --- a/src/hildon-color-chooser.c +++ /dev/null @@ -1,1365 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Author: Kuisma Salonen - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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 used to select a color from an HSV colorspace. - * @see_also: #HildonColorChooserDialog - * - * HildonColorChooser is a widget that displays an HSV colorspace. - * The user can manipulate the colorspace and easily select and shade of any color - * he wants. - * - * Normally you should not need to use this widget directly. Using #HildonColorButton or - * #HildonColorChooserDialog is much more handy. - * - */ - -#undef HILDON_DISABLE_DEPRECATED - -#include "hildon-color-chooser.h" -#include "hildon-color-chooser-private.h" - -static GtkWidgetClass* 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_init (HildonColorChooser *self); - -static void -hildon_color_chooser_class_init (HildonColorChooserClass *klass); - -static void -hildon_color_chooser_dispose (HildonColorChooser *self); - -static void -hildon_color_chooser_size_request (GtkWidget *widget, - GtkRequisition *req); - -static void -hildon_color_chooser_size_allocate (GtkWidget *widget, - GtkAllocation *alloc); - -static void -hildon_color_chooser_realize (GtkWidget *widget); - -static void -hildon_color_chooser_unrealize (GtkWidget *widget); - -static void -hildon_color_chooser_map (GtkWidget *widget); - -static void -hildon_color_chooser_unmap (GtkWidget *widget); - -static gboolean -hildon_color_chooser_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 -get_border (GtkWidget *w, - char *name, - GtkBorder *b); - -static void -init_borders (GtkWidget *w, - GtkBorder *inner, - GtkBorder *outer); - -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 (HildonColorChooser *self); - -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 (HildonColorChooser *self, - int x, - int y, - int w, - int h); - -inline void -inline_draw_sv_plane_dimmed (HildonColorChooser *self, - 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_expose_timer (gpointer data); - -static void -hildon_color_chooser_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec); - -static void -hildon_color_chooser_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec); - -#define EXPOSE_INTERVAL 50000 - -#define FULL_COLOR8 0xff - -#define FULL_COLOR 0x00ffffff - -enum -{ - COLOR_CHANGED, - LAST_SIGNAL -}; - -enum -{ - PROP_0, - PROP_COLOR -}; - -static guint color_chooser_signals [LAST_SIGNAL] = { 0 }; - -GType G_GNUC_CONST -hildon_color_chooser_get_type (void) -{ - static GType chooser_type = 0; - - if (!chooser_type) { - static const GTypeInfo chooser_info = - { - sizeof (HildonColorChooserClass), - NULL, - NULL, - (GClassInitFunc) hildon_color_chooser_class_init, - NULL, - NULL, - sizeof (HildonColorChooser), - 0, - (GInstanceInitFunc) hildon_color_chooser_init, - NULL - }; - - chooser_type = g_type_register_static (GTK_TYPE_WIDGET, - "HildonColorChooser", - &chooser_info, 0); - } - - return chooser_type; -} - -static void -hildon_color_chooser_init (HildonColorChooser *sel) -{ - - GTK_WIDGET_SET_FLAGS (sel, GTK_NO_WINDOW); - HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (sel); - g_assert (priv); - - priv->currhue = 0; - priv->currsat = 0; - priv->currval = 0; - - priv->mousestate = 0; - priv->mousein = FALSE; - - g_get_current_time (&priv->expose_info.last_expose_time); - - priv->expose_info.last_expose_hue = priv->currhue; - priv->expose_info.expose_queued = 0; - - priv->dimmed_plane = NULL; - priv->dimmed_bar = NULL; -} - -static void -hildon_color_chooser_class_init (HildonColorChooserClass *klass) -{ - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); - - object_class->dispose = (gpointer) hildon_color_chooser_dispose; - object_class->get_property = hildon_color_chooser_get_property; - object_class->set_property = hildon_color_chooser_set_property; - - widget_class->size_request = hildon_color_chooser_size_request; - widget_class->size_allocate = hildon_color_chooser_size_allocate; - widget_class->realize = hildon_color_chooser_realize; - widget_class->unrealize = hildon_color_chooser_unrealize; - widget_class->map = hildon_color_chooser_map; - widget_class->unmap = hildon_color_chooser_unmap; - widget_class->expose_event = hildon_color_chooser_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; - - 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 ("outer_border", - "Outer border", - "The outer border for the chooser", - 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)); - - /** - * HildonColorChooser:color: - * - * The currently selected color. - */ - g_object_class_install_property (object_class, PROP_COLOR, - g_param_spec_boxed ("color", - "Current Color", - "The selected color", - GDK_TYPE_COLOR, - G_PARAM_READWRITE)); - - 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__VOID, - G_TYPE_NONE, - 0); - - g_type_class_add_private (klass, sizeof (HildonColorChooserPrivate)); -} - -static void -hildon_color_chooser_dispose (HildonColorChooser *sel) -{ - HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (sel); - g_assert (priv); - - if (priv->dimmed_bar != NULL) { - g_object_unref (priv->dimmed_bar); - priv->dimmed_bar = NULL; - } - - if (priv->dimmed_plane != NULL) { - g_object_unref (priv->dimmed_plane); - priv->dimmed_plane = NULL; - } - - G_OBJECT_CLASS (parent_class)->dispose (G_OBJECT (sel)); -} - -static void -hildon_color_chooser_size_request (GtkWidget *widget, - GtkRequisition *req) -{ - GtkBorder inner, outer; - - 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_size_allocate (GtkWidget *widget, - GtkAllocation *alloc) -{ - HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget); - GtkBorder outer, inner; - - g_assert (priv); - - widget->allocation = *alloc; - - init_borders(widget, &inner, &outer); - - priv->hba.height = alloc->height - outer.top - outer.bottom; - priv->hba.y = alloc->y + outer.top; - priv->hba.width = inner.top; - priv->hba.x = alloc->x + alloc->width - outer.right - inner.top; - - priv->spa.x = alloc->x + outer.left; - priv->spa.y = alloc->y + outer.top; - priv->spa.height = alloc->height - outer.top - outer.bottom; - priv->spa.width = alloc->width - outer.left - outer.right - inner.top - inner.bottom; - - if (GTK_WIDGET_REALIZED (widget)) { - gdk_window_move_resize (priv->event_window, - widget->allocation.x, - widget->allocation.y, - widget->allocation.width, - widget->allocation.height); - } -} - -static void -hildon_color_chooser_realize (GtkWidget *widget) -{ - HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget); - - g_assert (priv); - 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; - priv->event_window = gdk_window_new (widget->parent->window, &attributes, attributes_mask); - - - gdk_window_set_user_data (priv->event_window, widget); - - GTK_WIDGET_CLASS (parent_class)->realize (widget); -} - -static void -hildon_color_chooser_unrealize (GtkWidget *widget) -{ - HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget); - - g_assert (priv); - - 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_color_chooser_map (GtkWidget *widget) -{ - HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget); - - g_assert (priv); - GTK_WIDGET_CLASS(parent_class)->map(widget); - - if (priv->event_window) { - gdk_window_show (priv->event_window); - } -} - -static void -hildon_color_chooser_unmap (GtkWidget *widget) -{ - HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget); - - g_assert (priv); - - if (priv->event_window) { - gdk_window_hide (priv->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_expose (GtkWidget *widget, - GdkEventExpose *event) -{ - HildonColorChooser *sel = HILDON_COLOR_CHOOSER (widget); - HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget); - - g_assert (priv); - - GtkBorder graphical_border; - - struct { - int x, y, w, h; - } area; - - - if(! GTK_WIDGET_REALIZED (widget)) { - return FALSE; - } - - get_border (widget, "graphic_border", &graphical_border); - - if (event->area.width || event->area.height) { - - gdk_draw_rectangle (widget->window, - widget->style->black_gc, - FALSE, - priv->hba.x - 2, - priv->hba.y - 2, - priv->hba.width + 3, - priv->hba.height + 3); - - gdk_draw_rectangle (widget->window, - widget->style->black_gc, - FALSE, - priv->spa.x - 2, - priv->spa.y - 2, - priv->spa.width + 3, - priv->spa.height + 3); - } - - if (priv->expose_info.expose_queued) { - if (GTK_WIDGET_SENSITIVE (widget)) { - inline_draw_hue_bar (widget, priv->hba.x, priv->hba.y, priv->hba.width, priv->hba.height, priv->hba.y, priv->hba.height); - - inline_draw_sv_plane (sel, priv->spa.x, priv->spa.y, priv->spa.width, priv->spa.height); - } else { - inline_draw_hue_bar_dimmed (widget, priv->hba.x, priv->hba.y, priv->hba.width, priv->hba.height, priv->hba.y, priv->hba.height); - - inline_draw_sv_plane_dimmed (sel, priv->spa.x, priv->spa.y, priv->spa.width, priv->spa.height); - } - - priv->expose_info.expose_queued = 0; - - g_get_current_time (&priv->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, &priv->hba); - - if(GTK_WIDGET_SENSITIVE (widget)) { - inline_draw_hue_bar (widget, area.x, area.y, area.w, area.h, priv->hba.y, priv->hba.height); - } else { - inline_draw_hue_bar_dimmed (widget, area.x, area.y, area.w, area.h, priv->hba.y, priv->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, &priv->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; - } -} - -inline void -inline_limited_expose (HildonColorChooser *sel) -{ - GTimeVal curr_time, result; - GdkEventExpose event; - HildonColorChooserPrivate *priv; - - if (! GTK_WIDGET_REALIZED (GTK_WIDGET (sel))) { - return; - } - - priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (sel); - g_assert (priv); - - if(priv->currhue == priv->expose_info.last_expose_hue) { - return; /* no need to redraw */ - } - - priv->expose_info.last_expose_hue = priv->currhue; - - g_get_current_time (&curr_time); - - inline_sub_times (&result, &curr_time, &priv->expose_info.last_expose_time); - - if(result.tv_sec != 0 || result.tv_usec >= EXPOSE_INTERVAL) { - - priv->expose_info.expose_queued = 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 if(! priv->expose_info.expose_queued) { - priv->expose_info.expose_queued = 1; - g_timeout_add ((EXPOSE_INTERVAL - result.tv_usec) / 1000, hildon_color_chooser_expose_timer, sel); - } -} - -static gboolean -hildon_color_chooser_button_press (GtkWidget *widget, - GdkEventButton *event) -{ - HildonColorChooser *sel = HILDON_COLOR_CHOOSER (widget); - HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget); - - g_assert (priv); - int x, y, tmp; - - x = (int) event->x + widget->allocation.x; - y = (int) event->y + widget->allocation.y; - - if (x >= priv->spa.x && x <= priv->spa.x + priv->spa.width && - y >= priv->spa.y && y <= priv->spa.y + priv->spa.height) { - - tmp = y - priv->spa.y; - priv->currsat = tmp * 0xffff / priv->spa.height; - tmp = x - priv->spa.x; - priv->currval = tmp * 0xffff / priv->spa.width; - - g_signal_emit (sel, color_chooser_signals[COLOR_CHANGED], 0); - gtk_widget_queue_draw (widget); - - priv->mousestate = 1; - priv->mousein = TRUE; - - gtk_grab_add(widget); - - } else if (x >= priv->hba.x && x <= priv->hba.x + priv->hba.width && - y >= priv->hba.y && y <= priv->hba.y + priv->hba.height) { - - tmp = y - priv->hba.y; - priv->currhue = tmp * 0xffff / priv->hba.height; - - g_signal_emit (sel, color_chooser_signals[COLOR_CHANGED], 0); - inline_limited_expose (sel); - - priv->mousestate = 2; - priv->mousein = TRUE; - - gtk_grab_add (widget); - } - - return FALSE; -} - -static gboolean -hildon_color_chooser_button_release (GtkWidget *widget, - GdkEventButton *event) -{ - HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget); - - g_assert (priv); - - if (priv->mousestate) { - gtk_grab_remove (widget); - } - - priv->mousestate = 0; - priv->mousein = FALSE; - - return FALSE; -} - -static gboolean -hildon_color_chooser_pointer_motion (GtkWidget *widget, - GdkEventMotion *event) -{ - HildonColorChooser *sel = HILDON_COLOR_CHOOSER (widget); - HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget); - - gint x, y, tmp; - - g_assert (priv); - - x = (gint) event->x; - y = (gint) event->y; - - if (priv->mousestate == 1) { - if (x >= priv->spa.x && x <= priv->spa.x + priv->spa.width && - y >= priv->spa.y && y <= priv->spa.y + priv->spa.height) { - - priv->currsat = (((long)(y - priv->spa.y)) * 0xffff) / priv->spa.height; - priv->currval = (((long)(x - priv->spa.x)) * 0xffff) / priv->spa.width; - - g_signal_emit (sel, color_chooser_signals[COLOR_CHANGED], 0); - gtk_widget_queue_draw(widget); - - } else if (priv->mousein == TRUE) { - } - - } else if (priv->mousestate == 2) { - if (x >= priv->hba.x && x <= priv->hba.x + priv->hba.width && - y >= priv->hba.y && y <= priv->hba.y + priv->hba.height) { - tmp = y - priv->hba.y; - tmp *= 0xffff; - tmp /= priv->hba.height; - - if(tmp != priv->currhue) { - priv->currhue = tmp; - - g_signal_emit (sel, color_chooser_signals[COLOR_CHANGED], 0); - inline_limited_expose (sel); - } - - } else if (priv->mousein == TRUE) { - } - } - - gdk_event_request_motions (event); - - return FALSE; -} - -static void -get_border (GtkWidget *w, - char *name, - GtkBorder *b) -{ - GtkBorder *tb = NULL; - - gtk_widget_style_get (w, name, &tb, NULL); - - if (tb) { - *b = *tb; - gtk_border_free (tb); - } else { - b->left = 0; - b->right = 0; - b->top = 0; - b->bottom = 0; - } -} - -static void -init_borders (GtkWidget *w, - GtkBorder *inner, - GtkBorder *outer) -{ - GtkBorder *tb; - - get_border (w, "outer_border", outer); - - gtk_widget_style_get (w, "inner_size", &tb, NULL); - - if (tb) { - *inner = *tb; - gtk_border_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; -} - -/** - * hildon_color_chooser_set_color: - * @chooser: a #HildonColorChooser - * @color: a color to be set - * - * Sets the color selected in the widget. - * Will move the crosshair pointer to indicate the passed color. - */ -void -hildon_color_chooser_set_color (HildonColorChooser *chooser, - GdkColor *color) -{ - unsigned short hue, sat, val; - unsigned long min, max; - signed long tmp, diff; - HildonColorChooserPrivate *priv; - - g_return_if_fail (HILDON_IS_COLOR_CHOOSER (chooser)); - g_return_if_fail (color != NULL); - - priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (chooser); - g_assert (priv); - - /* 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; - } - - priv->currhue = hue; - priv->currsat = sat; - priv->currval = val; - - inline_limited_expose (chooser); - g_signal_emit (chooser, color_chooser_signals[COLOR_CHANGED], 0); -} - -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; - } -} - -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) -{ - HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (widget); - - unsigned short hvec, hcurr; - unsigned char *buf, *ptr, tmp[3]; - int i, j, tmpy; - g_assert (priv); - - 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 = priv->hba.y + (priv->currhue * priv->hba.height / 0xffff); - gdk_draw_line (widget->parent->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], priv->hba.x, tmpy, priv->hba.x + priv->hba.width - 1, tmpy); - - if ((((priv->currhue * priv->hba.height) & 0xffff) > 0x8000) && (tmpy < (priv->hba.y + priv->hba.height))) { - gdk_draw_line (widget->parent->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], - priv->hba.x, tmpy+1, priv->hba.x + priv->hba.width - 1, tmpy+1); - } else if (tmpy > priv->hba.y) { - gdk_draw_line(widget->parent->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], priv->hba.x, - tmpy-1, priv->hba.x + priv->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) -{ - HildonColorChooser *sel = HILDON_COLOR_CHOOSER (widget); - HildonColorChooserPrivate *priv; - - if (w <= 0 || h <= 0) { - return; - } - - priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (sel); - g_assert (priv); - - /* We need to create (and cache) the pixbuf if we don't - * have it yet */ - if (priv->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; - } - - priv->dimmed_bar = gdk_pixbuf_new_from_data (buf, GDK_COLORSPACE_RGB, FALSE, 8, w, h, w * 3, (gpointer) g_free, buf); - } - - gdk_draw_pixbuf (widget->parent->window, widget->style->fg_gc [0], priv->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 (HildonColorChooser *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]; - HildonColorChooserPrivate *priv; - int i, j; - int tmp; - - if (w <= 0 || h <= 0) { - return; - } - - priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (sel); - g_assert (priv); - tmp = priv->spa.width * priv->spa.height; - - buf = (unsigned char *) g_malloc (w * h * 3); - ptr = buf; - - inline_h2rgb (priv->currhue, rgbtmp); - - rgby[0] = rgbtmp[0] - rgbx[0]; - rgby[1] = rgbtmp[1] - rgbx[1]; - rgby[2] = rgbtmp[2] - rgbx[2]; - - rgbx[0] /= priv->spa.width; - rgbx[1] /= priv->spa.width; - rgbx[2] /= priv->spa.width; - - rgby[0] /= tmp; - rgby[1] /= tmp; - rgby[2] /= tmp; - - rgbx[0] += (y - priv->spa.y) * rgby[0]; - rgbx[1] += (y - priv->spa.y) * rgby[1]; - rgbx[2] += (y - priv->spa.y) * rgby[2]; - - for(i = 0; i < h; i++) { - rgbtmp[0] = rgbx[0] * (x - priv->spa.x); - rgbtmp[1] = rgbx[1] * (x - priv->spa.x); - rgbtmp[2] = rgbx[2] * (x - priv->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, - (priv->spa.width * priv->currval / 0xffff) - x + priv->spa.x - 4, - (priv->spa.height * priv->currsat / 0xffff) - y + priv->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 (HildonColorChooser *sel, - int x, - int y, - int w, - int h) -{ - GtkWidget *widget = GTK_WIDGET (sel); - HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (sel); - - g_assert (priv); - - if (w <= 0 || h <= 0) { - return; - } - - /* We need to create (and cache) the pixbuf if we don't - * have it yet */ - if (priv->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 = priv->spa.width * priv->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] /= priv->spa.width; - rgbx[1] /= priv->spa.width; - rgbx[2] /= priv->spa.width; - - rgby[0] /= tmp; - rgby[1] /= tmp; - rgby[2] /= tmp; - - rgbx[0] += (y - priv->spa.y) * rgby[0]; - rgbx[1] += (y - priv->spa.y) * rgby[1]; - rgbx[2] += (y - priv->spa.y) * rgby[2]; - - for(i = 0; i < h; i++) { - rgbtmp[0] = rgbx[0] * (x - priv->spa.x); - rgbtmp[1] = rgbx[1] * (x - priv->spa.x); - rgbtmp[2] = rgbx[2] * (x - priv->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]; - } - - priv->dimmed_plane = gdk_pixbuf_new_from_data (buf, GDK_COLORSPACE_RGB, FALSE, 8, w, h, w * 3, (gpointer) g_free, buf); - } - - gdk_draw_pixbuf (widget->parent->window, widget->style->fg_gc [0], priv->dimmed_plane, 0, 0, x, y, w, h, GDK_RGB_DITHER_NONE, 0, 0); -} - - -static gboolean -hildon_color_chooser_expose_timer (gpointer data) -{ - HildonColorChooser *sel = HILDON_COLOR_CHOOSER (data); - HildonColorChooserPrivate *priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (sel); - - g_assert (priv); - - if (priv->expose_info.expose_queued) { - gtk_widget_queue_draw (GTK_WIDGET (data)); - } - - return FALSE; -} - -/** - * hildon_color_chooser_get_color: - * @chooser: a #HildonColorChooser - * @color: a color structure to fill with the currently selected color - * - * Retrives the currently selected color in the chooser. - * - */ -void -hildon_color_chooser_get_color (HildonColorChooser *chooser, - GdkColor *color) -{ - HildonColorChooserPrivate *priv; - GdkVisual *system_visual = gdk_visual_get_system (); - unsigned long rgb[3], rgb2[3]; - - g_return_if_fail (HILDON_IS_COLOR_CHOOSER (chooser)); - g_return_if_fail (color != NULL); - - priv = HILDON_COLOR_CHOOSER_GET_PRIVATE (chooser); - g_assert (priv); - - inline_h2rgb (priv->currhue, rgb); - - rgb2[0] = 0xffffff - rgb[0]; - rgb2[1] = 0xffffff - rgb[1]; - rgb2[2] = 0xffffff - rgb[2]; - - color->red = ((rgb[0] >> 8) + ((rgb2[0] >> 8) * (0xffff - priv->currsat) / 0xffff)) * priv->currval / 0xffff; - color->green = ((rgb[1] >> 8) + ((rgb2[1] >> 8) * (0xffff - priv->currsat) / 0xffff)) * priv->currval / 0xffff; - color->blue = ((rgb[2] >> 8) + ((rgb2[2] >> 8) * (0xffff - priv->currsat) / 0xffff)) * priv->currval / 0xffff; - - color->pixel = ((color->red >> (16 - system_visual->red_prec)) << system_visual->red_shift) | - ((color->green >> (16 - system_visual->green_prec)) << system_visual->green_shift) | - ((color->blue >> (16 - system_visual->blue_prec)) << system_visual->blue_shift); -} - -GtkWidget* -hildon_color_chooser_new (void) -{ - return (GtkWidget *) g_object_new (HILDON_TYPE_COLOR_CHOOSER, NULL); -} - -static void -hildon_color_chooser_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec) -{ - g_return_if_fail (HILDON_IS_COLOR_CHOOSER (object)); - - switch (param_id) - { - - case PROP_COLOR: { - GdkColor *color = g_value_get_boxed (value); - hildon_color_chooser_set_color ((HildonColorChooser *) object, color); - } break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - -static void -hildon_color_chooser_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - g_return_if_fail (HILDON_IS_COLOR_CHOOSER (object)); - - switch (param_id) - { - - case PROP_COLOR: { - GdkColor color; - hildon_color_chooser_get_color ((HildonColorChooser *) object, &color); - g_value_set_boxed (value, &color); - } break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - - diff --git a/src/hildon-color-chooser.h b/src/hildon-color-chooser.h deleted file mode 100644 index bcc8e4d..0000000 --- a/src/hildon-color-chooser.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Author: Kuisma Salonen - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#ifndef __HILDON_COLOR_CHOOSER_H__ -#define __HILDON_COLOR_CHOOSER_H__ - -#include - -G_BEGIN_DECLS - -#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; -}; - -struct _HildonColorChooserClass -{ - GtkWidgetClass parent; - - void (*color_changed) (HildonColorChooser *selection, GdkColor *color); - void (*set_color) (HildonColorChooser *, GdkColor *); -}; - -GType G_GNUC_CONST -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); - -G_END_DECLS - -#endif /* __HILDON_COLOR_CHOOSER_H__ */ - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-controlbar-private.h b/src/hildon-controlbar-private.h deleted file mode 100644 index 49983af..0000000 --- a/src/hildon-controlbar-private.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_PRIVATE_H__ -#define __HILDON_CONTROLBAR_PRIVATE_H__ - -G_BEGIN_DECLS - -typedef struct _HildonControlbarPrivate HildonControlbarPrivate; - -#define HILDON_CONTROLBAR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ - HILDON_TYPE_CONTROLBAR, HildonControlbarPrivate)); - -struct _HildonControlbarPrivate -{ - gboolean button_press; - gint old_value; -}; - -G_END_DECLS - -#endif /* __HILDON_CONTROLBAR_PRIVATE_H__ */ diff --git a/src/hildon-controlbar.c b/src/hildon-controlbar.c deleted file mode 100644 index e9b4d8e..0000000 --- a/src/hildon-controlbar.c +++ /dev/null @@ -1,893 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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. - * - * - * - * #HildonControlbar has been deprecated since Hildon 2.2 - * See Migrating Control Bars - * section to know how to migrate this deprecated widget. - * - * - * - * - * HildonControlbar example - * - * GtkWidget *cbar = hildon_controlbar_new(); - * hildon_controlbar_set_max (HILDON_CONTROLBAR (cbar), 12); - * hildon_controlbar_set_value (HILDON_CONTROLBAR (cbar), 6); - * - * - * - */ - -#undef HILDON_DISABLE_DEPRECATED - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include "hildon-controlbar.h" -#include "hildon-controlbar-private.h" - -#define _(string)\ - dgettext("hildon-libs", string) - -#define DEFAULT_WIDTH 234 - -#define DEFAULT_HEIGHT 60 - -#define DEFAULT_BORDER_WIDTH 0 - -#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; - -enum -{ - PROP_0, - 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); - -static gboolean -hildon_controlbar_change_value (GtkRange *range, - GtkScrollType scroll, - gdouble new_value, - gpointer data); - -/** - * hildon_controlbar_get_type: - * - * Initializes and returns the type of a hildon control bar. - * - * Returns: GType of #HildonControlbar - */ -GType G_GNUC_CONST -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; -} - -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; - gobject_class->constructor = hildon_controlbar_constructor; - 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; - 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 current 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); - g_assert (priv); - - priv->button_press = FALSE; - priv->old_value = 0; - range = GTK_RANGE (controlbar); - - 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); - g_assert (priv); - - /* 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 - * - * Set 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 highlights - * 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); - g_assert (priv); - - 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; - gdouble vv = adj->upper - adj->lower; - gint calc = ((new_value - adj->lower) / vv) * (vv + 1.0) + adj->lower; - - priv = HILDON_CONTROLBAR_GET_PRIVATE(range); - g_assert (priv); - - /* 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; - } - - GTK_RANGE_CLASS (parent_class)->change_value (range, scroll, calc); - - return TRUE; -} - -/* - * 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); - g_assert (priv); - - 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 (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); - g_assert (priv); - - 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); - - block_area = (w - 2 * stepper_size - 2 * stepper_spacing - 2 * inner_border_width); - - if (block_area <= 0) - return; - - block_min = 1; - 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; - - if (block_count == 0) - block_count = 1; - /* 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 deleted file mode 100644 index f3aaf34..0000000 --- a/src/hildon-controlbar.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#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)) - -#define HILDON_CONTROLBAR_GET_CLASS(obj) \ - ((HildonControlBarClass *) G_OBJECT_GET_CLASS(obj)) - -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 G_GNUC_CONST -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__ */ - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-date-button.c b/src/hildon-date-button.c deleted file mode 100644 index a27b996..0000000 --- a/src/hildon-date-button.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser Public License as published by - * the Free Software Foundation; version 2 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser Public License for more details. - * - */ - -#include - -#include "hildon-date-button.h" -#include "hildon-date-selector.h" -#include "hildon-touch-selector.h" -#include "hildon-picker-button-private.h" - -#define _(String) \ - dgettext("hildon-libs", String) - -#define c_(String) \ - dgettext("hildon-common-strings", String) - -/** - * SECTION:hildon-date-button - * @Short_Description: Button displaying and allowing selection of a date. - * @See_Also: #HildonPickerButton, #HildonTimeButton - * - * #HildonDateButton is a widget that shows a text label and a date, and allows - * the user to select a different date. Visually, it's a button that, once clicked, - * presents a #HildonPickerDialog containing a #HildonDateSelector. Once the user selects - * a different date from the selector, this will be shown in the button. - */ - -G_DEFINE_TYPE (HildonDateButton, hildon_date_button, HILDON_TYPE_PICKER_BUTTON) - -#if 0 -#define GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), HILDON_TYPE_DATE_BUTTON, HildonDateButtonPrivate)) - -typedef struct _HildonDateButtonPrivate HildonDateButtonPrivate; - -struct _HildonDateButtonPrivate -{ -}; -#endif - -#if 0 -static void -hildon_date_button_get_property (GObject * object, guint property_id, - GValue * value, GParamSpec * pspec) -{ - switch (property_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - -static void -hildon_date_button_set_property (GObject * object, guint property_id, - const GValue * value, GParamSpec * pspec) -{ - switch (property_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} -#endif - -static void -hildon_date_button_class_init (HildonDateButtonClass * klass) -{ -#if 0 - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (HildonDateButtonPrivate)); - - object_class->get_property = hildon_date_button_get_property; - object_class->set_property = hildon_date_button_set_property; -#endif -} - -static void -hildon_date_button_init (HildonDateButton * self) -{ - GtkWidget *date_selector; - - date_selector = hildon_date_selector_new (); - - hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (self), - HILDON_TOUCH_SELECTOR (date_selector)); -} - -static GtkWidget * -hildon_date_button_new_full (HildonSizeType size, - HildonButtonArrangement arrangement, - GtkWidget *selector) -{ - return g_object_new (HILDON_TYPE_DATE_BUTTON, - "title", _("wdgt_ti_date"), - "arrangement", arrangement, - "size", size, - "touch-selector", selector, - NULL); -} - -/** - * hildon_date_button_new: - * @size: One of #HildonSizeType - * @arrangement: one of #HildonButtonArrangement - * - * Creates a new #HildonDateButton. See hildon_button_new() for details on the - * parameters. - * - * Returns: a new #HildonDateButton - * - * Since: 2.2 - **/ -GtkWidget * -hildon_date_button_new (HildonSizeType size, - HildonButtonArrangement arrangement) -{ - GtkWidget *selector = hildon_date_selector_new (); - return hildon_date_button_new_full (size, arrangement, selector); -} - -/** - * hildon_date_button_new_with_year_range: - * @size: One of #HildonSizeType - * @arrangement: one of #HildonButtonArrangement - * @min_year: the minimum available year or -1 to ignore - * @max_year: the maximum available year or -1 to ignore - * - * Creates a new #HildonDateButton with a specific valid range of years. - * See hildon_date_selector_new_with_year_range() for details on the range. - * - * Returns: a new #HildonDateButton - * - * Since: 2.2 - **/ -GtkWidget * -hildon_date_button_new_with_year_range (HildonSizeType size, - HildonButtonArrangement arrangement, - gint min_year, - gint max_year) -{ - GtkWidget *selector; - selector = hildon_date_selector_new_with_year_range (min_year, max_year); - return hildon_date_button_new_full (size, arrangement, selector); -} - -/** - * hildon_date_button_get_date: - * @button: a #HildonDateButton - * @year: return location for the selected year - * @month: return location for the selected month - * @day: return location for the selected day - * - * Retrieves currently selected date from @button. - * - * Since: 2.2 - **/ -void -hildon_date_button_get_date (HildonDateButton * button, - guint * year, guint * month, guint * day) -{ - HildonTouchSelector *selector; - - g_return_if_fail (HILDON_IS_DATE_BUTTON (button)); - - selector = hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (button)); - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); - - hildon_date_selector_get_date (HILDON_DATE_SELECTOR (selector), year, month, day); -} - -/** - * hildon_date_button_set_date: - * @button: a #HildonDateButton - * @year: the year to set. - * @month: the month number to set. - * @day: the day of the month to set. - * - * Sets the date in @button. The date set will be displayed - * and will be the default selected option on the shown #HildonDateSelector. - * - * Since: 2.2 - **/ -void -hildon_date_button_set_date (HildonDateButton * button, - guint year, guint month, guint day) -{ - HildonTouchSelector *selector; - gchar *date; - - g_return_if_fail (HILDON_IS_DATE_BUTTON (button)); - - selector = hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (button)); - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); - - hildon_picker_button_disable_value_changed (HILDON_PICKER_BUTTON (button), TRUE); - hildon_date_selector_select_current_date (HILDON_DATE_SELECTOR (selector), - year, month, day); - hildon_picker_button_disable_value_changed (HILDON_PICKER_BUTTON (button), FALSE); - - date = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector)); - - hildon_button_set_value (HILDON_BUTTON (button), date); - - g_free (date); - - hildon_picker_button_value_changed (HILDON_PICKER_BUTTON (button)); -} diff --git a/src/hildon-date-button.h b/src/hildon-date-button.h deleted file mode 100644 index 5c8e1ca..0000000 --- a/src/hildon-date-button.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser Public License as published by - * the Free Software Foundation; version 2 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser Public License for more details. - * - */ - -#ifndef __HILDON_DATE_BUTTON__ -#define __HILDON_DATE_BUTTON__ - -#include - -#include "hildon-picker-button.h" - -G_BEGIN_DECLS - -#define HILDON_TYPE_DATE_BUTTON \ - hildon_date_button_get_type() - -#define HILDON_DATE_BUTTON(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj),\ - HILDON_TYPE_DATE_BUTTON, HildonDateButton)) - -#define HILDON_DATE_BUTTON_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - HILDON_TYPE_DATE_BUTTON, HildonDateButtonClass)) - -#define HILDON_IS_DATE_BUTTON(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_DATE_BUTTON)) - -#define HILDON_IS_DATE_BUTTON_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_DATE_BUTTON)) - -#define HILDON_DATE_BUTTON_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - HILDON_TYPE_DATE_BUTTON, HildonDateButtonClass)) - - -typedef struct _HildonDateButton HildonDateButton; -typedef struct _HildonDateButtonClass HildonDateButtonClass; - -struct _HildonDateButton -{ - HildonPickerButton parent; -}; - -struct _HildonDateButtonClass -{ - HildonPickerButtonClass parent_class; -}; - -GType -hildon_date_button_get_type (void); - -GtkWidget* -hildon_date_button_new (HildonSizeType size, - HildonButtonArrangement arrangement); - -GtkWidget * -hildon_date_button_new_with_year_range (HildonSizeType size, - HildonButtonArrangement arrangement, - gint min_year, - gint max_year); - -void -hildon_date_button_get_date (HildonDateButton *button, - guint *year, - guint *month, - guint *day); -void -hildon_date_button_set_date (HildonDateButton * button, - guint year, - guint month, - guint day); - -G_END_DECLS - -#endif /* __HILDON_DATE_BUTTON__ */ diff --git a/src/hildon-date-editor-private.h b/src/hildon-date-editor-private.h deleted file mode 100644 index 3206172..0000000 --- a/src/hildon-date-editor-private.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_PRIVATE_H__ -#define __HILDON_DATE_EDITOR_PRIVATE_H__ - -G_BEGIN_DECLS - -#define HILDON_DATE_EDITOR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE((obj),\ - HILDON_TYPE_DATE_EDITOR, HildonDateEditorPrivate)); - -typedef struct _HildonDateEditorPrivate HildonDateEditorPrivate; - -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 */ -}; - -G_END_DECLS - -#endif /* __HILDON_DATE_EDITOR_PRIVATE_H__ */ diff --git a/src/hildon-date-editor.c b/src/hildon-date-editor.c deleted file mode 100644 index eb8dee4..0000000 --- a/src/hildon-date-editor.c +++ /dev/null @@ -1,1570 +0,0 @@ -/* vim:set sw=4 expandtab cino=(0: - * - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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. - * - * - * - * - * #HildonDateEditor has been deprecated since Hildon 2.2 and should - * not be used in newly written code. Use #HildonDateSelector instead. See - * Migrating Date Widgets - * section to know how to migrate this deprecated widget. - * - * - * - * - * - * guint y, m, d; - * GtkDialog *dialog; - * GtkWidget *date_editor; - * - * dialog = GTK_DIALOG (gtk_dialog_new ()); - * date_editor = hildon_date_editor_new (); - * - * gtk_box_pack_start (GTK_BOX (dialog->vbox), gtk_label_new ("Choose a date"), FALSE, FALSE, 10); - * gtk_box_pack_start (GTK_BOX (dialog->vbox), date_editor, FALSE, FALSE, 10); - * gtk_dialog_add_button (dialog, "Close", GTK_RESPONSE_CANCEL); - * - * gtk_widget_show_all (GTK_WIDGET (dialog)); - * gtk_dialog_run (dialog); - * - * hildon_date_editor_get_date (HILDON_DATE_EDITOR (date_editor), &y, &m, &d); - * g_debug ("Date: %u-%u-%u", y, m, d); - * - * - * - * - */ - -#undef HILDON_DISABLE_DEPRECATED - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include - -#include "hildon-date-editor.h" -#include "hildon-calendar-popup.h" -#include "hildon-defines.h" -#include "hildon-marshalers.h" -#include "hildon-enum-types.h" -#include "hildon-time-editor.h" -#include "hildon-banner.h" -#include "hildon-date-editor-private.h" -#include "hildon-private.h" - -#define _(string) dgettext("hildon-libs", string) - -#define c_(string) dgettext("hildon-common-strings", 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 - -static GtkContainerClass* parent_class; - -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, - HildonDateTimeError type); - -static gboolean -hildon_date_editor_entry_focus_in (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_focus (GtkWidget *widget, - GtkDirectionType direction); -static gboolean -hildon_date_editor_entry_select_all (GtkWidget *widget); - -/* Property indices */ -enum -{ - PROP_0, - PROP_DAY, - PROP_MONTH, - PROP_YEAR, - PROP_MIN_YEAR, - PROP_MAX_YEAR -}; - -enum -{ - DATE_ERROR, - LAST_SIGNAL -}; - -static guint date_editor_signals[LAST_SIGNAL] = { 0 }; - -/** - * hildon_date_editor_get_type: - * - * Initializes and returns the type of a hildon date editor. - * - * Returns: GType of #HildonDateEditor - */ -GType G_GNUC_CONST -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_date_editor_focus; - - container_class->forall = hildon_child_forall; - GTK_OBJECT_CLASS(editor_class)->destroy = hildon_date_editor_destroy; - - editor_class->date_error = (gpointer) 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_TIME_ERROR); - - /** - * HildonDateEditor:year: - * - * Current year. - */ - g_object_class_install_property (gobject_class, PROP_YEAR, - g_param_spec_uint ("year", - "Current year", - "Current year", - 1, 10000, - 2007, - 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, 10000, - 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, 10000, - 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) -{ - g_assert (priv); - - gtk_image_set_from_icon_name (GTK_IMAGE (priv->calendar_icon), - "widgets_date_editor", HILDON_ICON_SIZE_SMALL); - - 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); - g_assert (priv); - - 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); - g_assert (priv); - - 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 (); - -#ifdef MAEMO_GTK - g_object_set (G_OBJECT(priv->d_entry), "hildon-input-mode", - HILDON_GTK_INPUT_MODE_NUMERIC, NULL); - g_object_set (G_OBJECT(priv->m_entry), "hildon-input-mode", - HILDON_GTK_INPUT_MODE_NUMERIC, NULL); - g_object_set (G_OBJECT(priv->y_entry), "hildon-input-mode", - HILDON_GTK_INPUT_MODE_NUMERIC, NULL); -#endif - - /* 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_focus_in), editor); - - g_signal_connect (GTK_OBJECT (priv->m_entry), "focus-in-event", - G_CALLBACK (hildon_date_editor_entry_focus_in), editor); - - g_signal_connect (GTK_OBJECT (priv->y_entry), "focus-in-event", - G_CALLBACK (hildon_date_editor_entry_focus_in), 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; - - g_assert (priv); - - 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); - 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); - break; - - case PROP_MAX_YEAR: - val = g_value_get_uint (value); - 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); - 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); - g_assert (priv); - - 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); - g_assert (priv); - - 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 (GtkWidget *) 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. */ - - priv = HILDON_DATE_EDITOR_GET_PRIVATE (editor); - g_assert (priv); - - 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 - * - * Gets the date represented by the date editor. - * You can pass NULL to any of the pointers if - * you're not interested in obtaining it. - * - */ -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)); - - 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. */ - - if (year != NULL) - *year = /*priv->year;*/ - (guint) atoi (gtk_entry_get_text (GTK_ENTRY (priv->y_entry))); - if (month != NULL) - *month = /*priv->month;*/ - (guint) atoi (gtk_entry_get_text (GTK_ENTRY (priv->m_entry))); - if (day != NULL) - *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_focus_in (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 = HILDON_DATE_TIME_ERROR_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); - g_assert (priv); - - 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, HILDON_DATE_TIME_ERROR_EMPTY_DAY, &r); - else if(widget == priv->m_entry) - g_signal_emit (ed, date_editor_signals[DATE_ERROR], 0, HILDON_DATE_TIME_ERROR_EMPTY_MONTH, &r); - else - g_signal_emit (ed, date_editor_signals[DATE_ERROR], 0, HILDON_DATE_TIME_ERROR_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 = HILDON_DATE_TIME_ERROR_MIN_MONTH; - m = 1; - } - else if (m > 12) { - error_code = HILDON_DATE_TIME_ERROR_MAX_MONTH; - m = 12; - } - } - - /* Validate year */ - if(widget == priv->y_entry) { - if (y < priv->min_year) { - error_code = HILDON_DATE_TIME_ERROR_MIN_YEAR; - y = priv->min_year; - } - else if (y > priv->max_year) { - error_code = HILDON_DATE_TIME_ERROR_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 = HILDON_DATE_TIME_ERROR_MIN_DAY; - d = 1; - } - else if (d > max_days) { - if (d > 31) { - error_code = HILDON_DATE_TIME_ERROR_MAX_DAY; - d = max_days; - } - else { /* the date does not exist (is invalid) */ - error_code = HILDON_DATE_TIME_ERROR_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 != HILDON_DATE_TIME_ERROR_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; -} - -/* 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; -} - -/* 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; - priv = HILDON_DATE_EDITOR_GET_PRIVATE (HILDON_DATE_EDITOR (data)); - - g_assert (GTK_IS_ENTRY (ed)); - g_assert (HILDON_IS_DATE_EDITOR (data)); - g_assert (priv); - - 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 == HILDON_DATE_TIME_ERROR_NO_ERROR) - { - priv->skip_validation = TRUE; - gtk_widget_child_focus (GTK_WIDGET (data), GTK_DIR_RIGHT); - } - } else { - priv->skip_validation = FALSE; - } -} - -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; - - g_assert (HILDON_IS_DATE_EDITOR (data)); - g_assert (GTK_IS_ENTRY (widget)); - - ed = HILDON_DATE_EDITOR (data); - - switch (event->keyval) { - 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. */ - hildon_date_editor_set_calendar_icon_state (ed, TRUE); - return TRUE; - case GDK_Escape: - priv = HILDON_DATE_EDITOR_GET_PRIVATE (ed); - 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); - g_assert (priv); - - hildon_date_editor_entry_validate (widget, data); - priv->skip_validation = FALSE; - - return FALSE; -} - -static gboolean -hildon_date_editor_date_error (HildonDateEditor *editor, - HildonDateTimeError type) -{ - HildonDateEditorPrivate *priv = HILDON_DATE_EDITOR_GET_PRIVATE (editor); - g_assert (priv); - - switch (type) - { - case HILDON_DATE_TIME_ERROR_MAX_DAY: - hildon_banner_show_informationf (GTK_WIDGET (editor), NULL, _("ckct_ib_maximum_value"), 31); - break; - - case HILDON_DATE_TIME_ERROR_MAX_MONTH: - hildon_banner_show_informationf (GTK_WIDGET (editor), NULL, _("ckct_ib_maximum_value"), 12); - break; - - case HILDON_DATE_TIME_ERROR_MAX_YEAR: - hildon_banner_show_informationf (GTK_WIDGET (editor), NULL, _("ckct_ib_maximum_value"), priv->max_year); - break; - - case HILDON_DATE_TIME_ERROR_MIN_DAY: - case HILDON_DATE_TIME_ERROR_MIN_MONTH: - hildon_banner_show_informationf (GTK_WIDGET (editor), NULL, _("ckct_ib_minimum_value"), 1); - break; - - case HILDON_DATE_TIME_ERROR_MIN_YEAR: - hildon_banner_show_informationf (GTK_WIDGET (editor), NULL, _("ckct_ib_minimum_value"), priv->min_year); - break; - - case HILDON_DATE_TIME_ERROR_EMPTY_DAY: - hildon_banner_show_informationf (GTK_WIDGET (editor), NULL, _("ckct_ib_set_a_value_within_range"), 1, 31); - break; - - case HILDON_DATE_TIME_ERROR_EMPTY_MONTH: - hildon_banner_show_informationf (GTK_WIDGET (editor), NULL, _("ckct_ib_set_a_value_within_range"), 1, 12); - break; - - case HILDON_DATE_TIME_ERROR_EMPTY_YEAR: - hildon_banner_show_informationf (GTK_WIDGET (editor), NULL, _("ckct_ib_set_a_value_within_range"), - priv->min_year, priv->max_year); - break; - - case HILDON_DATE_TIME_ERROR_INVALID_CHAR: - hildon_banner_show_information (GTK_WIDGET (editor), NULL, c_("ckct_ib_illegal_character")); - break; - - case HILDON_DATE_TIME_ERROR_INVALID_DATE: - hildon_banner_show_information (GTK_WIDGET (editor), 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); - g_assert (priv); - - /* 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; - gboolean rtl; - - g_assert (GTK_IS_WIDGET (widget)); - g_assert (allocation != NULL); - - ed = HILDON_DATE_EDITOR (widget); - priv = HILDON_DATE_EDITOR_GET_PRIVATE (ed); - - rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL); - 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; - - /* calculate allocations */ - if (GTK_WIDGET_VISIBLE (widget)) { - /* allocate frame */ - gtk_widget_get_child_requisition (priv->frame, &req); - - f_alloc.width = req.width; - f_alloc.height = max_req.height; - - /* allocate icon */ - 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; - - if (rtl) - { - img_alloc.x = f_alloc.x; - f_alloc.x += img_alloc.width + HILDON_MARGIN_DEFAULT; - } - - if (GTK_WIDGET_VISIBLE (priv->d_button_image)) { - gtk_widget_size_allocate (priv->d_button_image, &img_alloc); - } - - if (GTK_WIDGET_VISIBLE (priv->frame)) { - gtk_widget_size_allocate (priv->frame, &f_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); - } -} - -static gboolean -hildon_date_editor_focus (GtkWidget *widget, - GtkDirectionType direction) -{ - gboolean retval; - GtkDirectionType effective_direction; - - g_assert (HILDON_IS_DATE_EDITOR (widget)); - - retval = hildon_private_composite_focus (widget, direction, &effective_direction); - - if (retval == TRUE) - return GTK_WIDGET_CLASS (parent_class)->focus (widget, effective_direction); - else - return FALSE; -} - -/** - * 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 and has been set. - */ -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); - g_assert (priv); - - 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 and has been set. - */ -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); - g_assert (priv); - - 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 and has been set. - */ -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); - g_assert (priv); - - 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); - g_assert (priv); - - 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); - g_assert (priv); - - 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); - g_assert (priv); - - return (guint) atoi (gtk_entry_get_text (GTK_ENTRY (priv->d_entry))); -} - diff --git a/src/hildon-date-editor.h b/src/hildon-date-editor.h deleted file mode 100644 index 02c91db..0000000 --- a/src/hildon-date-editor.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#ifndef __HILDON_DATE_EDITOR_H__ -#define __HILDON_DATE_EDITOR_H__ - -#include - -#include "hildon-time-editor.h" - -G_BEGIN_DECLS - -#define HILDON_TYPE_DATE_EDITOR \ - (hildon_date_editor_get_type()) - -#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)) - -typedef struct _HildonDateEditor HildonDateEditor; - -typedef struct _HildonDateEditorClass HildonDateEditorClass; - - -struct _HildonDateEditor -{ - GtkContainer parent; -}; - -struct _HildonDateEditorClass -{ - GtkContainerClass parent_class; - - gboolean (*date_error) (HildonDateEditor *editor, HildonDateTimeError type); -}; - -GType G_GNUC_CONST -hildon_date_editor_get_type (void); - -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__ */ - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-date-selector.c b/src/hildon-date-selector.c deleted file mode 100644 index c2e0f96..0000000 --- a/src/hildon-date-selector.c +++ /dev/null @@ -1,904 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2008 Nokia Corporation. - * - * 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; either - * version 2 of the License, or (at your option) any later version. or (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/** - * SECTION:hildon-date-selector - * @short_description: A widget to select the current date. - * - * #HildonDateSelector is a date widget with multiple columns. Users - * can choose a date by selecting values in the day, month and year - * columns. - * - * The currently selected month and year can be altered with - * hildon_date_selector_select_month(). The day can be selected from - * the active month using hildon_date_selector_select_day(). - */ - -#define _GNU_SOURCE /* needed for GNU nl_langinfo_l */ -#define __USE_GNU /* needed for locale */ - -#include - -#ifdef HAVE_SYS_TIME_H -#include -#endif - -#include -#include - -#include -#include -#include - -#include "hildon-date-selector.h" - -#define HILDON_DATE_SELECTOR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_DATE_SELECTOR, HildonDateSelectorPrivate)) - -G_DEFINE_TYPE (HildonDateSelector, hildon_date_selector, HILDON_TYPE_TOUCH_SELECTOR) - -#define INIT_YEAR 100 -#define LAST_YEAR 50 /* since current year */ - -#define _(String) dgettext("hildon-libs", String) - -/* #define _(String) "%A %e. %B %Y" debug purposes */ - -enum -{ - COLUMN_STRING, - COLUMN_INT, - N_COLUMNS -}; - -enum -{ - DAY, - MONTH, - YEAR -}; - -struct _HildonDateSelectorPrivate -{ - GtkTreeModel *year_model; - GtkTreeModel *month_model; - GtkTreeModel *day_model; - - GSList *column_order; - gint day_column; - gint month_column; - gint year_column; /* it depends on the locale */ - - gchar *format; /* day/month/year format, depends on locale */ - - gint creation_day; - gint creation_month; - gint creation_year; /* date at creation time */ - - gint current_num_days; - - gint min_year; - gint max_year; -}; - -enum { - PROP_MIN_YEAR = 1, - PROP_MAX_YEAR, -}; - -static GObject * hildon_date_selector_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_properties); -static void hildon_date_selector_finalize (GObject * object); - -/* private functions */ -static GtkTreeModel *_create_day_model (HildonDateSelector * selector); -static GtkTreeModel *_create_year_model (HildonDateSelector * selector); -static GtkTreeModel *_create_month_model (HildonDateSelector * selector); - -static void _get_real_date (gint * year, gint * month, gint * day); -static void _locales_init (HildonDateSelectorPrivate * priv); - -static void _manage_selector_change_cb (HildonTouchSelector * selector, - gint num_column, gpointer data); - -static GtkTreeModel *_update_day_model (HildonDateSelector * selector); - -static gint _month_days (gint month, gint year); -static void _init_column_order (HildonDateSelector * selector); - -static gchar *_custom_print_func (HildonTouchSelector * selector, - gpointer user_data); - -/***************************************************************************/ -/* The following date routines are taken from the lib_date package. Keep - * them separate in case we want to update them if a newer lib_date comes - * out with fixes. */ - -typedef unsigned int N_int; - -typedef unsigned long N_long; - -typedef signed long Z_long; - -typedef enum -{ false = FALSE, true = TRUE } boolean; - -#define and && /* logical (boolean) operators: lower case */ - -#define or || - -static const N_int month_length[2][13] = { - {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, - {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} -}; - -static const N_int days_in_months[2][14] = { - {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}, - {0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366} -}; - -static Z_long _calc_days (N_int year, N_int mm, N_int dd); - -static N_int _day_of_week (N_int year, N_int mm, N_int dd); - -static boolean _leap (N_int year); - - -static boolean -_leap (N_int year) -{ - return ((((year % 4) == 0) and ((year % 100) != 0)) or ((year % 400) == 0)); -} - -static N_int -_day_of_week (N_int year, N_int mm, N_int dd) -{ - Z_long days; - - days = _calc_days (year, mm, dd); - if (days > 0L) { - days--; - days %= 7L; - days++; - } - return ((N_int) days); -} - -static Z_long -_year_to_days (N_int year) -{ - return (year * 365L + (year / 4) - (year / 100) + (year / 400)); -} - -static Z_long -_calc_days (N_int year, N_int mm, N_int dd) -{ - boolean lp; - - if (year < 1) - return (0L); - if ((mm < 1) or (mm > 12)) - return (0L); - if ((dd < 1) or (dd > month_length[(lp = _leap (year))][mm])) - return (0L); - return (_year_to_days (--year) + days_in_months[lp][mm] + dd); -} - -static void -hildon_date_selector_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - HildonDateSelectorPrivate *priv = HILDON_DATE_SELECTOR (object)->priv; - - switch (prop_id) - { - case PROP_MIN_YEAR: - priv->min_year = g_value_get_int (value); - break; - case PROP_MAX_YEAR: - priv->max_year = g_value_get_int (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -hildon_date_selector_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - HildonDateSelectorPrivate *priv = HILDON_DATE_SELECTOR (object)->priv; - - switch (prop_id) - { - case PROP_MIN_YEAR: - g_value_set_int (value, priv->min_year); - break; - case PROP_MAX_YEAR: - g_value_set_int (value, priv->max_year); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -hildon_date_selector_class_init (HildonDateSelectorClass * class) -{ - GObjectClass *gobject_class; - GtkObjectClass *object_class; - GtkWidgetClass *widget_class; - GtkContainerClass *container_class; - - gobject_class = (GObjectClass *) class; - object_class = (GtkObjectClass *) class; - widget_class = (GtkWidgetClass *) class; - container_class = (GtkContainerClass *) class; - - /* GObject */ - gobject_class->finalize = hildon_date_selector_finalize; - gobject_class->get_property = hildon_date_selector_get_property; - gobject_class->set_property = hildon_date_selector_set_property; - gobject_class->constructor = hildon_date_selector_constructor; - - /* GtkWidget */ - - /* GtkContainer */ - - /* properties */ - - g_object_class_install_property ( - gobject_class, - PROP_MIN_YEAR, - g_param_spec_int ( - "min-year", - "Minimum year", - "The minimum available year in the selector", - 1900, - 2100, - 1970, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); - - g_object_class_install_property ( - gobject_class, - PROP_MAX_YEAR, - g_param_spec_int ( - "max-year", - "Maximum year", - "The maximum available year in the selector", - 1900, - 2100, - 2037, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); - - /* signals */ - - g_type_class_add_private (object_class, sizeof (HildonDateSelectorPrivate)); -} - -static void -hildon_date_selector_construct_ui (HildonDateSelector *selector) -{ - GSList *iter = NULL; - gint current_item = 0; - HildonTouchSelectorColumn *column = NULL; - - selector->priv->year_model = _create_year_model (selector); - selector->priv->month_model = _create_month_model (selector); - selector->priv->day_model = _create_day_model (selector); - - /* We add the columns, checking the locale order */ - iter = selector->priv->column_order; - for (iter = selector->priv->column_order; iter; iter = g_slist_next (iter)) { - current_item = GPOINTER_TO_INT (iter->data); - - switch (current_item) { - case DAY: - column = hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), - selector->priv->day_model, TRUE); - g_object_set (G_OBJECT (column), "text-column", 0, NULL); - break; - case MONTH: - column = hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), - selector->priv->month_model, TRUE); - g_object_set (G_OBJECT (column), "text-column", 0, NULL); - break; - case YEAR: - column = hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), - selector->priv->year_model, TRUE); - g_object_set (G_OBJECT (column), "text-column", 0, NULL); - break; - default: - g_error ("Current column order incorrect"); - break; - } - } -} - -static GObject * -hildon_date_selector_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_properties) -{ - GObject *object; - HildonDateSelector *selector; - - object = G_OBJECT_CLASS (hildon_date_selector_parent_class)->constructor - (type, n_construct_properties, construct_properties); - - selector = HILDON_DATE_SELECTOR (object); - - hildon_date_selector_construct_ui (selector); - - g_signal_connect (object, "changed", G_CALLBACK (_manage_selector_change_cb), NULL); - - /* By default we should select the current day */ - hildon_date_selector_select_current_date (selector, selector->priv->creation_year, - selector->priv->creation_month, - selector->priv->creation_day); - - return object; -} - -static void -hildon_date_selector_init (HildonDateSelector * selector) -{ - selector->priv = HILDON_DATE_SELECTOR_GET_PRIVATE (selector); - - GTK_WIDGET_SET_FLAGS (GTK_WIDGET (selector), GTK_NO_WINDOW); - gtk_widget_set_redraw_on_allocate (GTK_WIDGET (selector), FALSE); - - hildon_touch_selector_set_print_func (HILDON_TOUCH_SELECTOR (selector), - _custom_print_func); - - _locales_init (selector->priv); - - _init_column_order (selector); - - _get_real_date (&selector->priv->creation_year, - &selector->priv->creation_month, &selector->priv->creation_day); - selector->priv->current_num_days = 31; -} - -static void -hildon_date_selector_finalize (GObject * object) -{ - HildonDateSelector *selector = NULL; - - selector = HILDON_DATE_SELECTOR (object); - - g_slist_free (selector->priv->column_order); - g_free (selector->priv->format); - - (*G_OBJECT_CLASS (hildon_date_selector_parent_class)->finalize) (object); -} - -/* ------------------------------ PRIVATE METHODS ---------------------------- */ -static gchar * -_custom_print_func (HildonTouchSelector * touch_selector, gpointer user_data) -{ - HildonDateSelector *selector = NULL; - gchar *result = NULL; - guint year, month, day; - gint day_of_week = 0; - static gchar string[255]; - struct tm tm = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - selector = HILDON_DATE_SELECTOR (touch_selector); - - hildon_date_selector_get_date (selector, &year, &month, &day); - day_of_week = _day_of_week (year, month + 1, day) % 7; - - tm.tm_mday = day; - tm.tm_mon = month; - tm.tm_year = year - 1900; - tm.tm_wday = day_of_week; - - strftime (string, 255, _("wdgt_va_date_long"), &tm); - - result = g_strdup (string); - - return result; -} - -/* This was copied from hildon-calendar */ -static void -_locales_init (HildonDateSelectorPrivate * priv) -{ - /* Hildon: This is not exactly portable, see - * http://bugzilla.gnome.org/show_bug.cgi?id=343415 - * The labels need to be instance variables as the startup wizard changes - * locale on runtime. - */ - locale_t l; - - l = newlocale (LC_TIME_MASK, setlocale (LC_MESSAGES, NULL), NULL); - - priv->format = g_locale_to_utf8 (nl_langinfo_l (D_FMT, l), - -1, NULL, NULL, NULL); - - freelocale (l); -} - -static void -_init_column_order (HildonDateSelector * selector) -{ - gchar *current_order[3] = { NULL, NULL, NULL }; - gchar *day_pos = NULL; - gchar *month_pos = NULL; - gchar *year_pos = NULL; - gint i, c; - gchar *aux = NULL; - - g_debug ("Current format: %s", selector->priv->format); - - /* search each token on the format */ - day_pos = g_strrstr (selector->priv->format, "%d"); - - month_pos = g_strrstr (selector->priv->format, "%m"); - year_pos = g_strrstr (selector->priv->format, "%y"); - if (year_pos == NULL) { - year_pos = g_strrstr (selector->priv->format, "%Y"); - } - - - if ((day_pos == NULL) || (month_pos == NULL) || (year_pos == NULL)) { - g_error ("Wrong date format"); /* so default values */ - - selector->priv->day_column = 0; - selector->priv->month_column = 1; - selector->priv->year_column = 2; - selector->priv->column_order = g_slist_append (NULL, GINT_TO_POINTER (DAY)); - selector->priv->column_order = - g_slist_append (selector->priv->column_order, GINT_TO_POINTER (MONTH)); - selector->priv->column_order = - g_slist_append (selector->priv->column_order, GINT_TO_POINTER (YEAR)); - } - - /* sort current_order with this values (bubble sort) */ - current_order[0] = day_pos; - current_order[1] = month_pos; - current_order[2] = year_pos; - - for (c = 1; c <= 2; c++) { - for (i = 0; i < 3 - c; i++) { - if (current_order[i] > current_order[i + 1]) { - aux = current_order[i]; - current_order[i] = current_order[i + 1]; - current_order[i + 1] = aux; - } - } - } - - /* fill the column positions */ - selector->priv->column_order = NULL; - c = 0; - for (i = 0; i < 3; i++) { - if (current_order[i] == day_pos) { - selector->priv->column_order = - g_slist_append (selector->priv->column_order, GINT_TO_POINTER (DAY)); - selector->priv->day_column = c++; - } - if (current_order[i] == month_pos) { - selector->priv->column_order = - g_slist_append (selector->priv->column_order, GINT_TO_POINTER (MONTH)); - selector->priv->month_column = c++; - } - if (current_order[i] == year_pos) { - selector->priv->column_order = - g_slist_append (selector->priv->column_order, GINT_TO_POINTER (YEAR)); - selector->priv->year_column = c++; - } - } -} - - -static GtkTreeModel * -_create_day_model (HildonDateSelector * selector) -{ - GtkListStore *store_days = NULL; - gint i = 0; - gchar label[255]; - struct tm tm = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - GtkTreeIter iter; - - store_days = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT); - for (i = 1; i < 32; i++) { - tm.tm_mday = i; - strftime (label, 255, _("wdgt_va_day_numeric"), &tm); - - gtk_list_store_append (store_days, &iter); - gtk_list_store_set (store_days, &iter, - COLUMN_STRING, label, COLUMN_INT, i, -1); - } - - return GTK_TREE_MODEL (store_days); -} - -static GtkTreeModel * -_create_year_model (HildonDateSelector * selector) -{ - GtkListStore *store_years = NULL; - gint real_year = 0; - gint i = 0; - static gchar label[255]; - struct tm tm = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - GtkTreeIter iter; - - real_year = selector->priv->creation_year; - - store_years = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT); - for (i = selector->priv->min_year; i < selector->priv->max_year + 1; i++) { - tm.tm_year = i - 1900; - strftime (label, 255, _("wdgt_va_year"), &tm); - - gtk_list_store_append (store_years, &iter); - gtk_list_store_set (store_years, &iter, - COLUMN_STRING, label, COLUMN_INT, i, -1); - } - - return GTK_TREE_MODEL (store_years); -} - -static GtkTreeModel * -_create_month_model (HildonDateSelector * selector) -{ - GtkTreeIter iter; - gint i = 0; - GtkListStore *store_months = NULL; - static gchar label[255]; - struct tm tm = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - store_months = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT); - for (i = 0; i < 12; i++) { - tm.tm_mon = i; - strftime (label, 255, _("wdgt_va_month"), &tm); - - gtk_list_store_append (store_months, &iter); - gtk_list_store_set (store_months, &iter, COLUMN_STRING, label, - COLUMN_INT, i, - -1); - } - - return GTK_TREE_MODEL (store_months); -} - -static GtkTreeModel * -_update_day_model (HildonDateSelector * selector) -{ - GtkListStore *store_days = NULL; - GtkTreePath *path = NULL; - gint i = 0; - GtkTreeIter iter; - static gchar label[255]; - struct tm tm = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - guint current_day = 0; - guint current_year = 0; - guint current_month = 0; - gint num_days = 31; - - hildon_date_selector_get_date (selector, ¤t_year, ¤t_month, - ¤t_day); - - num_days = _month_days (current_month, current_year); - store_days = GTK_LIST_STORE (selector->priv->day_model); - - if (num_days == selector->priv->current_num_days) { - return GTK_TREE_MODEL (store_days); - } - - if (num_days > selector->priv->current_num_days) { - for (i = selector->priv->current_num_days + 1; i <= num_days; i++) { - tm.tm_mday = i; - strftime (label, 255, _("wdgt_va_day_numeric"), &tm); - - gtk_list_store_append (store_days, &iter); - gtk_list_store_set (store_days, &iter, - COLUMN_STRING, label, COLUMN_INT, i, -1); - } - } else { - path = gtk_tree_path_new_from_indices (num_days, - -1); - gtk_tree_model_get_iter (GTK_TREE_MODEL (store_days), &iter, path); - do { - }while (gtk_list_store_remove (store_days, &iter)); - - gtk_tree_path_free (path); - } - - - selector->priv->current_num_days = num_days; - - /* now we select a day */ - if (current_day >= num_days) { - current_day = num_days; - } - - hildon_date_selector_select_day (selector, current_day); - - return GTK_TREE_MODEL (store_days); -} - - -static void -_get_real_date (gint * year, gint * month, gint * day) -{ - time_t secs; - struct tm *tm = NULL; - - secs = time (NULL); - tm = localtime (&secs); - - if (year != NULL) { - *year = 1900 + tm->tm_year; - } - - if (month != NULL) { - *month = tm->tm_mon; - } - - if (day != NULL) { - *day = tm->tm_mday; - } -} - - -static void -_manage_selector_change_cb (HildonTouchSelector * touch_selector, - gint num_column, gpointer data) -{ - HildonDateSelector *selector = NULL; - - g_return_if_fail (HILDON_IS_DATE_SELECTOR (touch_selector)); - selector = HILDON_DATE_SELECTOR (touch_selector); - - if ((num_column == selector->priv->month_column) || - (num_column == selector->priv->year_column)) /* it is required to check that with - * the years too,remember: leap years - * update_day_model will check if - * the number of days is different - */ - { - _update_day_model (selector); - } -} - -static gint -_month_days (gint month, gint year) -{ - gint month_days[2][12] = { - {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, - {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} - }; - - g_return_val_if_fail (month >= 0 && month < 12, -1); - - return month_days[_leap (year)][month]; -} - - -/* ------------------------------ PUBLIC METHODS ---------------------------- */ - -/** - * hildon_date_selector_new: - * - * Creates a new #HildonDateSelector - * - * Returns: a new #HildonDateSelector - * - * Since: 2.2 - **/ -GtkWidget * -hildon_date_selector_new () -{ - return g_object_new (HILDON_TYPE_DATE_SELECTOR, NULL); -} - -/** - * hildon_date_selector_new_with_year_range: - * @min_year: the minimum available year or -1 to ignore - * @max_year: the maximum available year or -1 to ignore - * - * Creates a new #HildonDateSelector with a specific year range. - * If @min_year or @max_year are set to -1, then the default - * upper or lower bound will be used, respectively. - * - * Returns: a new #HildonDateSelector - * - * Since: 2.2 - **/ -GtkWidget * -hildon_date_selector_new_with_year_range (gint min_year, - gint max_year) -{ - GtkWidget *selector; - - g_return_val_if_fail (min_year <= max_year, NULL); - - if (min_year == -1 && min_year == -1) { - selector = g_object_new (HILDON_TYPE_DATE_SELECTOR, - NULL); - } else if (min_year == -1) { - selector = g_object_new (HILDON_TYPE_DATE_SELECTOR, - "max-year", max_year, - NULL); - } else if (max_year == -1) { - selector = g_object_new (HILDON_TYPE_DATE_SELECTOR, - "min-year", min_year, - NULL); - } else { - selector = g_object_new (HILDON_TYPE_DATE_SELECTOR, - "min-year", min_year, - "max-year", max_year, - NULL); - } - - return selector; -} -/** - * hildon_date_selector_select_current_date: - * @selector: the #HildonDateSelector - * @year: the current year - * @month: the current month (0-11) - * @day: the current day (1-31, 1-30, 1-29, 1-28) depends on the month - * - * Sets the current active date on the #HildonDateSelector widget - * - * Since: 2.2 - * - * Returns: %TRUE on success, %FALSE otherwise - **/ -gboolean -hildon_date_selector_select_current_date (HildonDateSelector * selector, - guint year, guint month, guint day) -{ - GtkTreeIter iter; - gint min_year = 0; - gint max_year = 0; - gint num_days = 0; - - min_year = selector->priv->min_year; - max_year = selector->priv->max_year; - - g_return_val_if_fail (min_year <= year && year <= max_year, FALSE); - g_return_val_if_fail (month < 12, FALSE); - - num_days = _month_days (month, year); - g_return_val_if_fail (day > 0 && day <= num_days, FALSE); - - - gtk_tree_model_iter_nth_child (selector->priv->year_model, &iter, NULL, - year - min_year); - hildon_touch_selector_select_iter (HILDON_TOUCH_SELECTOR (selector), - selector->priv->year_column, &iter, - FALSE); - - gtk_tree_model_iter_nth_child (selector->priv->month_model, &iter, NULL, - month); - hildon_touch_selector_select_iter (HILDON_TOUCH_SELECTOR (selector), - selector->priv->month_column, &iter, - FALSE); - - gtk_tree_model_iter_nth_child (selector->priv->day_model, &iter, NULL, - day - 1); - hildon_touch_selector_select_iter (HILDON_TOUCH_SELECTOR (selector), - selector->priv->day_column, &iter, - FALSE); - - return TRUE; -} - - -/** - * hildon_date_selector_get_date: - * @selector: the #HildonDateSelector - * @year: to set the current year - * @month: to set the current month (0-11) - * @day: to the current day (1-31, 1-30, 1-29, 1-28) depends on the month - * - * Gets the current active date on the #HildonDateSelector widget - * - * Since: 2.2 - **/ -void -hildon_date_selector_get_date (HildonDateSelector * selector, - guint * year, guint * month, guint * day) -{ - GtkTreeIter iter; - - if (year != NULL) { - if (hildon_touch_selector_get_selected (HILDON_TOUCH_SELECTOR (selector), - selector->priv->year_column, &iter)) - gtk_tree_model_get (selector->priv->year_model, - &iter, COLUMN_INT, year, -1); - } - - if (month != NULL) { - if (hildon_touch_selector_get_selected (HILDON_TOUCH_SELECTOR (selector), - selector->priv->month_column, &iter)) - gtk_tree_model_get (selector->priv->month_model, - &iter, COLUMN_INT, month, -1); - } - - if (day != NULL) { - if (hildon_touch_selector_get_selected (HILDON_TOUCH_SELECTOR (selector), - selector->priv->day_column, &iter)) - { - gtk_tree_model_get (selector->priv->day_model, - &iter, COLUMN_INT, day, -1); - } -/* *day = *day - 1; */ - } - -} - - -/** - * hildon_date_selector_select_month: - * @selector: the #HildonDateSelector - * @month: the current month (0-11) - * @year: the current year - * - * Modify the current month and year on the current active date - * - * Utility function to keep this API similar to the previously - * existing #HildonCalendar widget. - * - * Since: 2.2 - * - * Returns: %TRUE on success, %FALSE otherwise - **/ -gboolean hildon_date_selector_select_month (HildonDateSelector *selector, - guint month, guint year) -{ - guint day = 0; - - hildon_date_selector_get_date (selector, NULL, NULL, &day); - - return hildon_date_selector_select_current_date (selector, year, month, day); -} - -/** - * hildon_date_selector_select_day: - * @selector: the #HildonDateSelector - * @day: the current day (1-31, 1-30, 1-29, 1-28) depends on the month - * - * Modify the current day on the current active date - * - * Utility function to keep this API similar to the previously - * existing #HildonCalendar widget. - * - * Since: 2.2 - **/ -void -hildon_date_selector_select_day (HildonDateSelector *selector, guint day) -{ - guint month = 0; - guint year = 0; - - hildon_date_selector_get_date (selector, &year, &month, NULL); - - hildon_date_selector_select_current_date (selector, year, month, day); -} diff --git a/src/hildon-date-selector.h b/src/hildon-date-selector.h deleted file mode 100644 index 0a775e8..0000000 --- a/src/hildon-date-selector.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2008 Nokia Corporation. - * - * 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; either - * version 2 of the License, or (at your option) any later version. or (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __HILDON_DATE_SELECTOR_H__ -#define __HILDON_DATE_SELECTOR_H__ - -#include "hildon-touch-selector.h" - -G_BEGIN_DECLS -#define HILDON_TYPE_DATE_SELECTOR \ - (hildon_date_selector_get_type ()) - -#define HILDON_DATE_SELECTOR(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - HILDON_TYPE_DATE_SELECTOR, HildonDateSelector)) - -#define HILDON_DATE_SELECTOR_CLASS(vtable) \ - (G_TYPE_CHECK_CLASS_CAST ((vtable), \ - HILDON_TYPE_DATE_SELECTOR, HildonDateSelectorClass)) - -#define HILDON_IS_DATE_SELECTOR(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_DATE_SELECTOR)) - -#define HILDON_IS_DATE_SELECTOR_CLASS(vtable) \ - (G_TYPE_CHECK_CLASS_TYPE ((vtable), HILDON_TYPE_DATE_SELECTOR)) - -#define HILDON_DATE_SELECTOR_GET_CLASS(inst) \ - (G_TYPE_INSTANCE_GET_CLASS ((inst), \ - HILDON_TYPE_DATE_SELECTOR, HildonDateSelectorClass)) - -typedef struct _HildonDateSelector HildonDateSelector; -typedef struct _HildonDateSelectorClass HildonDateSelectorClass; -typedef struct _HildonDateSelectorPrivate HildonDateSelectorPrivate; - -struct _HildonDateSelector -{ - HildonTouchSelector parent_instance; - - /*< private > */ - HildonDateSelectorPrivate *priv; -}; - -struct _HildonDateSelectorClass -{ - HildonTouchSelectorClass parent_class; - - /* signals */ -}; - - -/* construction */ -GType -hildon_date_selector_get_type (void) G_GNUC_CONST; - -GtkWidget* -hildon_date_selector_new (void); - -GtkWidget * -hildon_date_selector_new_with_year_range (gint min_year, - gint max_year); - -/* date management */ -gboolean -hildon_date_selector_select_month (HildonDateSelector *selector, - guint month, - guint year); - -void -hildon_date_selector_select_day (HildonDateSelector *selector, - guint day); - -gboolean -hildon_date_selector_select_current_date (HildonDateSelector *selector, - guint year, - guint month, - guint day); - -void -hildon_date_selector_get_date (HildonDateSelector *selector, - guint *year, - guint *month, - guint *day); - -G_END_DECLS - -#endif /* __HILDON_DATE_SELECTOR_H__ */ diff --git a/src/hildon-defines.c b/src/hildon-defines.c deleted file mode 100644 index 1321185..0000000 --- a/src/hildon-defines.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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: A collection of useful defines. - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "hildon-defines.h" - -/** - * hildon_get_icon_pixel_size: - * @size: the icon size to get pixel size for - * - * Returns the icon size (height) for the given, named icon. - * In most cases it's much more convienient to call one of the - * predefined macros instead of this function directly. - * - * Returns: the height/width of icon to use. O if icon could not be found. - */ -gint -hildon_get_icon_pixel_size (GtkIconSize size) -{ - gint w, h; - - if (gtk_icon_size_lookup (size, &w, &h)) - return h; - else - return 0; -} - - diff --git a/src/hildon-defines.h b/src/hildon-defines.h deleted file mode 100644 index bcfec6b..0000000 --- a/src/hildon-defines.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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 - * - */ - -/* FIXME: Add documentation for the macros here */ - -#ifndef __HILDON_DEFINES_H__ -#define __HILDON_DEFINES_H__ - -#include -#include - -G_BEGIN_DECLS - -/* New hildon icon sizes. */ - -#define HILDON_ICON_SIZE_XSMALL gtk_icon_size_from_name ("hildon-xsmall") - -#define HILDON_ICON_SIZE_SMALL gtk_icon_size_from_name ("hildon-small") - -#define HILDON_ICON_SIZE_STYLUS gtk_icon_size_from_name ("hildon-stylus") - -#define HILDON_ICON_SIZE_FINGER gtk_icon_size_from_name ("hildon-finger") - -#define HILDON_ICON_SIZE_THUMB gtk_icon_size_from_name ("hildon-thumb") - -#define HILDON_ICON_SIZE_LARGE gtk_icon_size_from_name ("hildon-large") - -#define HILDON_ICON_SIZE_XLARGE gtk_icon_size_from_name ("hildon-xlarge") - -/* legacy hildon icon sizes, updated for new hildon */ - -#define HILDON_ICON_SIZE_TOOLBAR \ - gtk_icon_size_from_name ("hildon-finger") -/* Actual icon sizes */ - -/* New sizes */ -#define HILDON_ICON_PIXEL_SIZE_XSMALL \ - hildon_get_icon_pixel_size (HILDON_ICON_SIZE_XSMALL) - -#define HILDON_ICON_PIXEL_SIZE_SMALL \ - hildon_get_icon_pixel_size (HILDON_ICON_SIZE_SMALL) - -#define HILDON_ICON_PIXEL_SIZE_STYLUS \ - hildon_get_icon_pixel_size (HILDON_ICON_SIZE_STYLUS) - -#define HILDON_ICON_PIXEL_SIZE_FINGER \ - hildon_get_icon_pixel_size (HILDON_ICON_SIZE_FINGER) - -#define HILDON_ICON_PIXEL_SIZE_THUMB \ - hildon_get_icon_pixel_size (HILDON_ICON_SIZE_THUMB) - -#define HILDON_ICON_PIXEL_SIZE_LARGE \ - hildon_get_icon_pixel_size (HILDON_ICON_SIZE_LARGE) - -#define HILDON_ICON_PIXEL_SIZE_XLARGE \ - hildon_get_icon_pixel_size (HILDON_ICON_SIZE_XLARGE) - -/* legacy sizes */ -#define HILDON_ICON_PIXEL_SIZE_TOOLBAR \ - hildon_get_icon_pixel_size (HILDON_ICON_SIZE_TOOLBAR) - -/* Margins */ - -#define HILDON_MARGIN_HALF 4 - -#define HILDON_MARGIN_DEFAULT 8 - -#define HILDON_MARGIN_DOUBLE 16 - -#define HILDON_MARGIN_TRIPLE 24 - -#define HILDON_WINDOW_TITLEBAR_HEIGHT 56 - -/* Hard keys */ - -#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 - -gint -hildon_get_icon_pixel_size (GtkIconSize size); - -G_END_DECLS - -#endif /* HILDON_DEFINES_H */ diff --git a/src/hildon-dialog.c b/src/hildon-dialog.c deleted file mode 100644 index 5b5653e..0000000 --- a/src/hildon-dialog.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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-dialog - * @short_description: Widget representing a popup window in the Hildon framework. - * @see_also: #HildonCodeDialog, #HildonColorChooserDialog, #HildonFontSelectionDialog, #HildonGetPasswordDialog, #HildonLoginDialog, #HildonSetPasswordDialog, #HildonSortDialog, #HildonWizardDialog - * - * #HildonDialog is a GTK widget which represent a popup window in the - * Hildon framework. It is derived from #GtkDialog and provides additional - * commodities specific to the Hildon framework. - * - * As of hildon 2.2, #HildonDialog has been deprecated in favor of #GtkDialog. - * - * - * - * #HildonDialog has been deprecated since Hildon 2.2 and should not - * be used in newly written code. See - * Migrating Hildon Dialogs - * section to know how to migrate this deprecated widget. - * - * - * - * - * Simple <structname>HildonDialog</structname> usage - * - * void quick_message (gchar *message) - * { - * - * GtkWidget *dialog, *label; - * - * dialog = hildon_dialog_new (); - * label = gtk_label_new (message); - * - * g_signal_connect_swapped (dialog, - * "response", - * G_CALLBACK (gtk_widget_destroy), - * dialog); - * - * gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), - * label); - * gtk_widget_show_all (dialog); - * - * } - * - * - */ - -#undef HILDON_DISABLE_DEPRECATED - -#include "hildon-dialog.h" -#include "hildon-gtk.h" - -G_DEFINE_TYPE (HildonDialog, hildon_dialog, GTK_TYPE_DIALOG); - -static void -hildon_dialog_class_init (HildonDialogClass *dialog_class) -{ -} - -static void -hildon_dialog_init (HildonDialog *self) -{ -} - -/** - * hildon_dialog_new: - * - * Creates a new #HildonDialog widget - * - * Returns: the newly created #HildonDialog - * - * Since: 2.2 - */ -GtkWidget* -hildon_dialog_new (void) -{ - GtkWidget *self = g_object_new (HILDON_TYPE_DIALOG, NULL); - - return self; -} - -/** - * hildon_dialog_new_with_buttons: - * @title: Title of the dialog, or %NULL - * @parent: Transient parent of the dialog, or %NULL - * @flags: from #GtkDialogFlags - * @first_button_text: stock ID or text to go in first button, or %NULL - * @Varargs: response ID for first button, then additional buttons, ending with %NULL - * - * Creates a new #HildonDialog. See gtk_dialog_new_with_buttons() for - * more information. - * - * Return value: a new #HildonDialog - * - * Since: 2.2 - */ -GtkWidget* -hildon_dialog_new_with_buttons (const gchar *title, - GtkWindow *parent, - GtkDialogFlags flags, - const gchar *first_button_text, - ...) -{ - GtkWidget *dialog; - - dialog = g_object_new (HILDON_TYPE_DIALOG, NULL); - - /* This code is copied from gtk_dialog_new_empty(), as it's a - * private function that we cannot use here */ - if (title) - gtk_window_set_title (GTK_WINDOW (dialog), title); - - if (parent) - gtk_window_set_transient_for (GTK_WINDOW (dialog), parent); - - if (flags & GTK_DIALOG_MODAL) - gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); - - if (flags & GTK_DIALOG_DESTROY_WITH_PARENT) - gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE); - - if (flags & GTK_DIALOG_NO_SEPARATOR) - gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE); - - /* This is almost copied from gtk_dialog_add_buttons_valist() */ - if (first_button_text != NULL) { - va_list args; - const gchar *text; - gint response_id; - - va_start (args, first_button_text); - text = first_button_text; - response_id = va_arg (args, gint); - - while (text != NULL) { - hildon_dialog_add_button (HILDON_DIALOG (dialog), text, response_id); - - text = va_arg (args, gchar*); - if (text == NULL) - break; - response_id = va_arg (args, int); - } - va_end (args); - } - - return dialog; -} - -/** - * hildon_dialog_add_button: - * @dialog: a #HildonDialog - * @button_text: text of the button, or stock ID - * @response_id: response ID for the button. - * - * Adds a button to the dialog. Works exactly like - * gtk_dialog_add_button(), the only difference being that the button - * has finger size. - * - * Returns: the button widget that was added - * - * Since: 2.2 - */ -GtkWidget * -hildon_dialog_add_button (HildonDialog *dialog, - const gchar *button_text, - gint response_id) -{ - GtkWidget *button; - button = gtk_dialog_add_button (GTK_DIALOG (dialog), button_text, response_id); - return button; -} - -/** - * hildon_dialog_add_buttons: - * @dialog: a #HildonDialog - * @first_button_text: text of the button, or stock ID - * @Varargs: response ID for first button, then more text-response_id pairs - * - * Adds several buttons to the dialog. Works exactly like - * gtk_dialog_add_buttons(), the only difference being that the - * buttons have finger size. - * - * Since: 2.2 - */ -void -hildon_dialog_add_buttons (HildonDialog *dialog, - const gchar *first_button_text, - ...) -{ - va_list args; - const gchar *text; - gint response_id; - - va_start (args, first_button_text); - text = first_button_text; - response_id = va_arg (args, gint); - - while (text != NULL) { - hildon_dialog_add_button (HILDON_DIALOG (dialog), text, response_id); - - text = va_arg (args, gchar*); - if (text == NULL) - break; - response_id = va_arg (args, int); - } - - va_end (args); -} - diff --git a/src/hildon-dialog.h b/src/hildon-dialog.h deleted file mode 100644 index 37ebd07..0000000 --- a/src/hildon-dialog.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#ifndef __HILDON_DIALOG_H__ -#define __HILDON_DIALOG_H__ - -#include - -#include "hildon-defines.h" - -G_BEGIN_DECLS - -#define HILDON_TYPE_DIALOG \ - (hildon_dialog_get_type ()) - -#define HILDON_DIALOG(obj) \ - (GTK_CHECK_CAST (obj, HILDON_TYPE_DIALOG, HildonDialog)) - -#define HILDON_DIALOG_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass),\ - HILDON_TYPE_DIALOG, HildonDialogClass)) - -#define HILDON_IS_DIALOG(obj) \ - (GTK_CHECK_TYPE (obj, HILDON_TYPE_DIALOG)) - -#define HILDON_IS_DIALOG_CLASS(klass) \ - (GTK_CHECH_CLASS_TYPE ((klass), HILDON_TYPE_DIALOG)) - -#define HILDON_DIALOG_GET_CLASS(obj) \ - ((HildonDialogClass *) G_OBJECT_GET_CLASS (obj)) - -typedef struct _HildonDialog HildonDialog; - -typedef struct _HildonDialogClass HildonDialogClass; - -struct _HildonDialog -{ - GtkDialog parent; -}; - -struct _HildonDialogClass -{ - GtkDialogClass parent_class; - - /* Padding for future extension */ - void (*_hildon_reserved1)(void); - void (*_hildon_reserved2)(void); - void (*_hildon_reserved3)(void); -}; - -GType G_GNUC_CONST -hildon_dialog_get_type (void); - -GtkWidget* -hildon_dialog_new (void); - -GtkWidget* -hildon_dialog_new_with_buttons (const gchar *title, - GtkWindow *parent, - GtkDialogFlags flags, - const gchar *first_button_text, - ...); - -GtkWidget * -hildon_dialog_add_button (HildonDialog *dialog, - const gchar *button_text, - gint response_id); - -void -hildon_dialog_add_buttons (HildonDialog *dialog, - const gchar *first_button_text, - ...); - -G_END_DECLS - -#endif /* __HILDON_DIALOG_H__ */ - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-edit-toolbar.c b/src/hildon-edit-toolbar.c deleted file mode 100644 index daf38b3..0000000 --- a/src/hildon-edit-toolbar.c +++ /dev/null @@ -1,324 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser Public License as published by - * the Free Software Foundation; version 2 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser Public License for more details. - * - */ - -/** - * SECTION:hildon-edit-toolbar - * @short_description: Widget representing a toolbar for editing. - * - * The #HildonEditToolbar is a toolbar which contains a label and two - * buttons, one of them being an arrow pointing backwards. - * - * The label is a description of the action that the user is supposed - * to do. The button is to be pressed when the user completes the - * action. The arrow is used to go back to the previous view - * discarding any changes. - * - * Note that those widgets don't do anything themselves by default. To - * actually peform actions the developer must provide callbacks for - * them. - * - * To add a #HildonEditToolbar to a window use - * hildon_window_set_edit_toolbar(). - * - * - * HildonEditToolbar example - * - * GtkWidget *window; - * GtkWidget *toolbar; - * // Declare more widgets here ... - * - * window = hildon_stackable_window_new (); - * toolbar = hildon_edit_toolbar_new_with_text ("Choose items to delete", "Delete"); - * // Create more widgets here ... - * - * // Add toolbar to window - * hildon_window_set_edit_toolbar (HILDON_WINDOW (window), HILDON_EDIT_TOOLBAR (toolbar)); - * - * // Add other widgets ... - * - * g_signal_connect (toolbar, "button-clicked", G_CALLBACK (delete_button_clicked), someparameter); - * g_signal_connect_swapped (toolbar, "arrow-clicked", G_CALLBACK (gtk_widget_destroy), window); - * - * gtk_widget_show_all (window); - * gtk_window_fullscreen (GTK_WINDOW (window)); - * - * - */ - -#include "hildon-edit-toolbar.h" -#include "hildon-gtk.h" - -G_DEFINE_TYPE (HildonEditToolbar, hildon_edit_toolbar, GTK_TYPE_HBOX); - -#define TOOLBAR_LEFT_PADDING 24 -#define TOOLBAR_RIGHT_PADDING 8 - -#define HILDON_EDIT_TOOLBAR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_EDIT_TOOLBAR, HildonEditToolbarPrivate)); - -typedef struct _HildonEditToolbarPrivate HildonEditToolbarPrivate; - -struct _HildonEditToolbarPrivate -{ - GtkLabel *label; - GtkButton *button; - GtkButton *arrow; -}; - -enum { - BUTTON_CLICKED, - ARROW_CLICKED, - N_SIGNALS -}; - -static guint toolbar_signals [N_SIGNALS] = { 0 }; - -static void -hildon_edit_toolbar_style_set (GtkWidget *widget, - GtkStyle *previous_style) -{ - guint width, height; - HildonEditToolbarPrivate *priv = HILDON_EDIT_TOOLBAR_GET_PRIVATE (widget); - - if (GTK_WIDGET_CLASS (hildon_edit_toolbar_parent_class)->style_set) - GTK_WIDGET_CLASS (hildon_edit_toolbar_parent_class)->style_set (widget, previous_style); - - gtk_widget_style_get (widget, - "arrow-width", &width, - "arrow-height", &height, - NULL); - - gtk_widget_set_size_request (GTK_WIDGET (priv->arrow), width, height); -} - -static gboolean -hildon_edit_toolbar_expose (GtkWidget *widget, - GdkEventExpose *event) -{ - if (GTK_WIDGET_DRAWABLE (widget)) { - gtk_paint_flat_box (widget->style, - widget->window, - GTK_STATE_NORMAL, - GTK_SHADOW_NONE, - &event->area, widget, "edit-toolbar", - widget->allocation.x, widget->allocation.y, - widget->allocation.width, widget->allocation.height); - } - - if (GTK_WIDGET_CLASS (hildon_edit_toolbar_parent_class)->expose_event) - return GTK_WIDGET_CLASS (hildon_edit_toolbar_parent_class)->expose_event (widget, event); - - return FALSE; -} - -static void -hildon_edit_toolbar_class_init (HildonEditToolbarClass *klass) -{ - GObjectClass *gobject_class = (GObjectClass *) klass; - GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; - - widget_class->style_set = hildon_edit_toolbar_style_set; - widget_class->expose_event = hildon_edit_toolbar_expose; - - g_type_class_add_private (klass, sizeof (HildonEditToolbarPrivate)); - - gtk_widget_class_install_style_property ( - widget_class, - g_param_spec_uint ( - "arrow-width", - "Width of the arrow button", - "Width of the arrow button", - 0, G_MAXUINT, 112, - G_PARAM_READABLE)); - - gtk_widget_class_install_style_property ( - widget_class, - g_param_spec_uint ( - "arrow-height", - "Height of the arrow button", - "Height of the arrow button", - 0, G_MAXUINT, 56, - G_PARAM_READABLE)); - - /** - * HildonEditToolbar::button-clicked: - * @widget: the object which received the signal. - * - * Emitted when the toolbar button has been activated (pressed and released). - * - * Since: 2.2 - */ - toolbar_signals[BUTTON_CLICKED] = - g_signal_new ("button_clicked", - G_OBJECT_CLASS_TYPE (gobject_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - /** - * HildonEditToolbar::arrow-clicked: - * @widget: the object which received the signal. - * - * Emitted when the toolbar back button (arrow) has been activated - * (pressed and released). - * - * Since: 2.2 - */ - toolbar_signals[ARROW_CLICKED] = - g_signal_new ("arrow_clicked", - G_OBJECT_CLASS_TYPE (gobject_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); -} - -static void -button_clicked_cb (GtkButton *self, - HildonEditToolbar *toolbar) -{ - g_signal_emit (toolbar, toolbar_signals[BUTTON_CLICKED], 0); -} - -static void -arrow_clicked_cb (GtkButton *self, - HildonEditToolbar *toolbar) -{ - g_signal_emit (toolbar, toolbar_signals[ARROW_CLICKED], 0); -} - -static void -hildon_edit_toolbar_init (HildonEditToolbar *self) -{ - HildonEditToolbarPrivate *priv = HILDON_EDIT_TOOLBAR_GET_PRIVATE (self); - GtkWidget *separator; - GtkAlignment *align; - GtkBox *hbox = GTK_BOX (self); - GtkBox *hbox2; - - hbox2 = GTK_BOX (gtk_hbox_new (FALSE, 0)); - align = GTK_ALIGNMENT (gtk_alignment_new (0, 0.5, 1, 1)); - priv->label = GTK_LABEL (gtk_label_new (NULL)); - priv->button = GTK_BUTTON (hildon_gtk_button_new (HILDON_SIZE_AUTO)); - separator = gtk_vseparator_new (); - priv->arrow = GTK_BUTTON (gtk_button_new ()); - - gtk_button_set_focus_on_click (priv->arrow, FALSE); - - g_signal_connect (priv->button, "clicked", G_CALLBACK (button_clicked_cb), self); - g_signal_connect (priv->arrow, "clicked", G_CALLBACK (arrow_clicked_cb), self); - - gtk_box_set_spacing (hbox, 0); - gtk_alignment_set_padding (align, 0, 0, TOOLBAR_LEFT_PADDING, TOOLBAR_RIGHT_PADDING); - - gtk_widget_set_name (GTK_WIDGET (self), "toolbar-edit-mode"); - gtk_widget_set_name (GTK_WIDGET (priv->arrow), "hildon-edit-toolbar-arrow"); - - gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET (hbox2)); - gtk_box_pack_start (hbox2, GTK_WIDGET (priv->label), TRUE, TRUE, 0); - gtk_box_pack_start (hbox2, GTK_WIDGET (priv->button), FALSE, FALSE, 0); - - gtk_box_pack_start (hbox, GTK_WIDGET (align), TRUE, TRUE, 0); - gtk_box_pack_start (hbox, separator, FALSE, FALSE, 0); - gtk_box_pack_start (hbox, GTK_WIDGET (priv->arrow), FALSE, FALSE, 0); - - gtk_misc_set_alignment (GTK_MISC (priv->label), 0, 0.5); - - gtk_widget_show_all (GTK_WIDGET (align)); - gtk_widget_show_all (separator); - gtk_widget_show_all (GTK_WIDGET (priv->arrow)); -} - -/** - * hildon_edit_toolbar_set_label: - * @toolbar: a #HildonEditToolbar - * @label: a new text for the toolbar label - * - * Sets the label of @toolbar to @label. This will clear any - * previously set value. - * - * Since: 2.2 - */ -void -hildon_edit_toolbar_set_label (HildonEditToolbar *toolbar, - const gchar *label) -{ - HildonEditToolbarPrivate *priv; - g_return_if_fail (HILDON_IS_EDIT_TOOLBAR (toolbar)); - priv = HILDON_EDIT_TOOLBAR_GET_PRIVATE (toolbar); - gtk_label_set_text (priv->label, label); -} - -/** - * hildon_edit_toolbar_set_button_label: - * @toolbar: a #HildonEditToolbar - * @label: a new text for the label of the toolbar button - * - * Sets the label of the toolbar button to @label. This will clear any - * previously set value. - * - * Since: 2.2 - */ -void -hildon_edit_toolbar_set_button_label (HildonEditToolbar *toolbar, - const gchar *label) -{ - HildonEditToolbarPrivate *priv; - g_return_if_fail (HILDON_IS_EDIT_TOOLBAR (toolbar)); - priv = HILDON_EDIT_TOOLBAR_GET_PRIVATE (toolbar); - gtk_button_set_label (priv->button, label); -} - -/** - * hildon_edit_toolbar_new: - * - * Creates a new #HildonEditToolbar. - * - * Returns: a new #HildonEditToolbar - * - * Since: 2.2 - */ -GtkWidget * -hildon_edit_toolbar_new (void) -{ - return g_object_new (HILDON_TYPE_EDIT_TOOLBAR, NULL); -} - -/** - * hildon_edit_toolbar_new_with_text: - * @label: Text for the toolbar label. - * @button: Text for the toolbar button. - * - * Creates a new #HildonEditToolbar, with the toolbar label set to - * @label and the button label set to @button. - * - * Returns: a new #HildonEditToolbar - * - * Since: 2.2 - */ -GtkWidget * -hildon_edit_toolbar_new_with_text (const gchar *label, - const gchar *button) -{ - GtkWidget *toolbar = g_object_new (HILDON_TYPE_EDIT_TOOLBAR, NULL); - - hildon_edit_toolbar_set_label (HILDON_EDIT_TOOLBAR (toolbar), label); - hildon_edit_toolbar_set_button_label (HILDON_EDIT_TOOLBAR (toolbar), button); - - return toolbar; -} diff --git a/src/hildon-edit-toolbar.h b/src/hildon-edit-toolbar.h deleted file mode 100644 index a93e7e1..0000000 --- a/src/hildon-edit-toolbar.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser Public License as published by - * the Free Software Foundation; version 2 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser Public License for more details. - * - */ - -#ifndef __HILDON_EDIT_TOOLBAR_H__ -#define __HILDON_EDIT_TOOLBAR_H__ - -#include - -G_BEGIN_DECLS - -#define HILDON_TYPE_EDIT_TOOLBAR \ - (hildon_edit_toolbar_get_type()) - -#define HILDON_EDIT_TOOLBAR(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - HILDON_TYPE_EDIT_TOOLBAR, HildonEditToolbar)) - -#define HILDON_EDIT_TOOLBAR_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - HILDON_TYPE_EDIT_TOOLBAR, HildonEditToolbarClass)) - -#define HILDON_IS_EDIT_TOOLBAR(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_EDIT_TOOLBAR)) - -#define HILDON_IS_EDIT_TOOLBAR_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_EDIT_TOOLBAR)) - -#define HILDON_EDIT_TOOLBAR_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - HILDON_TYPE_EDIT_TOOLBAR, HildonEditToolbarClass)) - -typedef struct _HildonEditToolbar HildonEditToolbar; - -typedef struct _HildonEditToolbarClass HildonEditToolbarClass; - -struct _HildonEditToolbarClass -{ - GtkHBoxClass parent_class; -}; - -struct _HildonEditToolbar -{ - GtkHBox parent; -}; - -GType -hildon_edit_toolbar_get_type (void) G_GNUC_CONST; - -GtkWidget * -hildon_edit_toolbar_new (void); - -GtkWidget * -hildon_edit_toolbar_new_with_text (const gchar *label, - const gchar *button); - -void -hildon_edit_toolbar_set_label (HildonEditToolbar *toolbar, - const gchar *label); - -void -hildon_edit_toolbar_set_button_label (HildonEditToolbar *toolbar, - const gchar *label); - -G_END_DECLS - -#endif /* __HILDON_EDIT_TOOLBAR_H__ */ diff --git a/src/hildon-entry.c b/src/hildon-entry.c deleted file mode 100644 index fad2382..0000000 --- a/src/hildon-entry.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser Public License as published by - * the Free Software Foundation; version 2 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser Public License for more details. - * - */ - -/** - * SECTION:hildon-entry - * @short_description: Widget representing a text entry in the Hildon framework. - * - * The #HildonEntry is a GTK widget which represents a text entry. It - * is derived from the #GtkEntry widget and provides additional - * commodities specific to the Hildon framework. - * - * Besides all the features inherited from #GtkEntry, a #HildonEntry - * can also have a placeholder text. This text will be shown if the - * entry is empty and doesn't have the input focus, but it's otherwise - * ignored. Thus, calls to hildon_entry_get_text() will never return - * the placeholder text, not even when it's being displayed. - * - * Although #HildonEntry is derived from #GtkEntry, - * gtk_entry_get_text() and gtk_entry_set_text() must never be used to - * get/set the text in this widget. hildon_entry_get_text() and - * hildon_entry_set_text() must be used instead. - * - * - * Creating a HildonEntry with a placeholder - * - * GtkWidget * - * create_entry (void) - * { - * GtkWidget *entry; - * - * entry = hildon_entry_new (HILDON_SIZE_AUTO); - * hildon_entry_set_placeholder (HILDON_ENTRY (entry), "First name"); - * - * return entry; - * } - * - * - */ - -#include "hildon-entry.h" -#include "hildon-helper.h" - -G_DEFINE_TYPE (HildonEntry, hildon_entry, GTK_TYPE_ENTRY); - -#define HILDON_ENTRY_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_ENTRY, HildonEntryPrivate)); - -struct _HildonEntryPrivate -{ - gchar *placeholder; - gboolean showing_placeholder; -}; - -static void -hildon_entry_show_placeholder (HildonEntry *entry) -{ - HildonEntryPrivate *priv = HILDON_ENTRY (entry)->priv; - - priv->showing_placeholder = TRUE; - gtk_entry_set_text (GTK_ENTRY (entry), priv->placeholder); - hildon_helper_set_logical_color (GTK_WIDGET (entry), - GTK_RC_TEXT, GTK_STATE_NORMAL, "ReversedSecondaryTextColor"); -} - -static void -hildon_entry_hide_placeholder (HildonEntry *entry, const gchar *text) -{ - HildonEntryPrivate *priv = HILDON_ENTRY (entry)->priv; - - priv->showing_placeholder = FALSE; - gtk_entry_set_text (GTK_ENTRY (entry), text); - hildon_helper_set_logical_color (GTK_WIDGET (entry), - GTK_RC_TEXT, GTK_STATE_NORMAL, "ReversedTextColor"); -} - -/** - * hildon_entry_set_text: - * @entry: a #HildonEntry - * @text: the new text - * - * Sets the text in @entry to @text, replacing its current contents. - * - * Note that you must never use gtk_entry_set_text() to set the text - * of a #HildonEntry. - * - * Since: 2.2 - */ -void -hildon_entry_set_text (HildonEntry *entry, - const gchar *text) -{ - g_return_if_fail (HILDON_IS_ENTRY (entry) && text != NULL); - - if (text[0] == '\0' && !GTK_WIDGET_HAS_FOCUS (entry)) { - hildon_entry_show_placeholder (entry); - } else { - hildon_entry_hide_placeholder (entry, text); - } -} - -/** - * hildon_entry_get_text: - * @entry: a #HildonEntry - * - * Gets the current text in @entry. - * - * Note that you must never use gtk_entry_get_text() to get the text - * from a #HildonEntry. - * - * Also note that placeholder text (set using - * hildon_entry_set_placeholder()) is never returned. Only text set by - * hildon_entry_set_text() or typed by the user is considered. - * - * Returns: the text in @entry. This text must not be modified or - * freed. - * - * Since: 2.2 - */ -const gchar * -hildon_entry_get_text (HildonEntry *entry) -{ - g_return_val_if_fail (HILDON_IS_ENTRY (entry), NULL); - - if (entry->priv->showing_placeholder) { - return ""; - } - - return gtk_entry_get_text (GTK_ENTRY (entry)); -} - -/** - * hildon_entry_set_placeholder: - * @entry: a #HildonEntry - * @text: the new text - * - * Sets the placeholder text in @entry to @text. - * - * Since: 2.2 - */ -void -hildon_entry_set_placeholder (HildonEntry *entry, - const gchar *text) -{ - g_return_if_fail (HILDON_IS_ENTRY (entry) && text != NULL); - - g_free (entry->priv->placeholder); - entry->priv->placeholder = g_strdup (text); - - /* Show the placeholder if it needs to be updated or if should be shown now. */ - if (entry->priv->showing_placeholder || - (!GTK_WIDGET_HAS_FOCUS (entry) && gtk_entry_get_text (GTK_ENTRY (entry)) [0] == '\0')) { - hildon_entry_show_placeholder (entry); - } -} - -/** - * hildon_entry_new: - * @size: The size of the entry - * - * Creates a new entry. - * - * Returns: a new #HildonEntry - * - * Since: 2.2 - */ -GtkWidget * -hildon_entry_new (HildonSizeType size) -{ - GtkWidget *entry = g_object_new (HILDON_TYPE_ENTRY, NULL); - - hildon_gtk_widget_set_theme_size (entry, size); - - return entry; -} - -static gboolean -hildon_entry_focus_in_event (GtkWidget *widget, - GdkEventFocus *event) -{ - if (HILDON_ENTRY (widget)->priv->showing_placeholder) { - hildon_entry_hide_placeholder (HILDON_ENTRY (widget), ""); - } - - if (GTK_WIDGET_CLASS (hildon_entry_parent_class)->focus_in_event) { - return GTK_WIDGET_CLASS (hildon_entry_parent_class)->focus_in_event (widget, event); - } else { - return FALSE; - } -} - -static gboolean -hildon_entry_focus_out_event (GtkWidget *widget, - GdkEventFocus *event) -{ - if (gtk_entry_get_text (GTK_ENTRY (widget)) [0] == '\0') { - hildon_entry_show_placeholder (HILDON_ENTRY (widget)); - } - - if (GTK_WIDGET_CLASS (hildon_entry_parent_class)->focus_out_event) { - return GTK_WIDGET_CLASS (hildon_entry_parent_class)->focus_out_event (widget, event); - } else { - return FALSE; - } -} - -static void -hildon_entry_finalize (GObject *object) -{ - HildonEntryPrivate *priv = HILDON_ENTRY (object)->priv; - - g_free (priv->placeholder); - - if (G_OBJECT_CLASS (hildon_entry_parent_class)->finalize) - G_OBJECT_CLASS (hildon_entry_parent_class)->finalize (object); -} - -static void -hildon_entry_class_init (HildonEntryClass *klass) -{ - GObjectClass *gobject_class = (GObjectClass *)klass; - GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; - - gobject_class->finalize = hildon_entry_finalize; - widget_class->focus_in_event = hildon_entry_focus_in_event; - widget_class->focus_out_event = hildon_entry_focus_out_event; - - g_type_class_add_private (klass, sizeof (HildonEntryPrivate)); -} - -static void -hildon_entry_init (HildonEntry *self) -{ - self->priv = HILDON_ENTRY_GET_PRIVATE (self); - self->priv->placeholder = g_strdup (""); - self->priv->showing_placeholder = FALSE; -} diff --git a/src/hildon-entry.h b/src/hildon-entry.h deleted file mode 100644 index eb2ab71..0000000 --- a/src/hildon-entry.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser Public License as published by - * the Free Software Foundation; version 2 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser Public License for more details. - * - */ - -#ifndef __HILDON_ENTRY_H__ -#define __HILDON_ENTRY_H__ - -#include "hildon-gtk.h" - -G_BEGIN_DECLS - -#define HILDON_TYPE_ENTRY \ - (hildon_entry_get_type()) - -#define HILDON_ENTRY(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - HILDON_TYPE_ENTRY, HildonEntry)) - -#define HILDON_ENTRY_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - HILDON_TYPE_ENTRY, HildonEntryClass)) - -#define HILDON_IS_ENTRY(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_ENTRY)) - -#define HILDON_IS_ENTRY_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_ENTRY)) - -#define HILDON_ENTRY_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - HILDON_TYPE_ENTRY, HildonEntryClass)) - -typedef struct _HildonEntry HildonEntry; - -typedef struct _HildonEntryClass HildonEntryClass; - -typedef struct _HildonEntryPrivate HildonEntryPrivate; - -struct _HildonEntryClass -{ - GtkEntryClass parent_class; -}; - -struct _HildonEntry -{ - GtkEntry parent; - - /* private */ - HildonEntryPrivate *priv; -}; - - -GType -hildon_entry_get_type (void) G_GNUC_CONST; - -GtkWidget * -hildon_entry_new (HildonSizeType size); - -void -hildon_entry_set_text (HildonEntry *entry, - const gchar *text); - -const gchar * -hildon_entry_get_text (HildonEntry *entry); - -void -hildon_entry_set_placeholder (HildonEntry *entry, - const gchar *text); - -G_END_DECLS - -#endif /* __HILDON_ENTRY_H__ */ diff --git a/src/hildon-find-toolbar-private.h b/src/hildon-find-toolbar-private.h deleted file mode 100644 index 0a49845..0000000 --- a/src/hildon-find-toolbar-private.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_PRIVATE_H__ -#define __HILDON_FIND_TOOLBAR_PRIVATE_H__ - -G_BEGIN_DECLS - -typedef struct _HildonFindToolbarPrivate HildonFindToolbarPrivate; - -struct _HildonFindToolbarPrivate -{ - GtkWidget* label; - GtkComboBoxEntry* entry_combo_box; - GtkToolItem* separator; - GtkToolItem* close_button; - - gint history_limit; -}; - -#define HILDON_FIND_TOOLBAR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ - HILDON_TYPE_FIND_TOOLBAR, HildonFindToolbarPrivate)) - - -G_END_DECLS - -#endif /* __HILDON_FIND_TOOLBAR_PRIVATE_H_ */ diff --git a/src/hildon-find-toolbar.c b/src/hildon-find-toolbar.c deleted file mode 100644 index 01ccb63..0000000 --- a/src/hildon-find-toolbar.c +++ /dev/null @@ -1,924 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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 toolbar with a search field. - * @see_also: #HildonWindow - * - * HildonFindToolbar is a toolbar that contains a search entry and a dropdown - * list with previously searched strings. The list is represented using a - * #GtkListStore and can be accesed using a property 'list'. Entries are added - * automatically to the list when the search button is pressed. - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include "hildon-find-toolbar.h" -#include "hildon-defines.h" -#include "hildon-find-toolbar-private.h" -#include "hildon-marshalers.h" - -#define _(String) \ - dgettext("hildon-libs", 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 - -static GtkTreeModel* -hildon_find_toolbar_get_list_model (HildonFindToolbarPrivate *priv); - -static GtkEntry* -hildon_find_toolbar_get_entry (HildonFindToolbarPrivate *priv); - -static gboolean -hildon_find_toolbar_filter (GtkTreeModel *model, - GtkTreeIter *iter, - gpointer self); - -static void -hildon_find_toolbar_apply_filter (HildonFindToolbar *self, - GtkTreeModel *model); - -static void -hildon_find_toolbar_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); - -static void -hildon_find_toolbar_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); - -static gboolean -hildon_find_toolbar_find_string (HildonFindToolbar *self, - GtkTreeIter *iter, - gint column, - const gchar *string); - -static gboolean -hildon_find_toolbar_history_append (HildonFindToolbar *self, - gpointer data); - -static void -hildon_find_toolbar_emit_close (GtkButton *button, - gpointer self); - -#ifdef MAEMO_GTK -static void -hildon_find_toolbar_emit_invalid_input (GtkEntry *entry, - GtkInvalidInputType type, - gpointer self); -#endif - -static void -hildon_find_toolbar_entry_activate (GtkWidget *widget, - gpointer user_data); - -static void -hildon_find_toolbar_class_init (HildonFindToolbarClass *klass); - -static void -hildon_find_toolbar_init (HildonFindToolbar *self); - -enum -{ - SEARCH = 0, - CLOSE, - INVALID_INPUT, - HISTORY_APPEND, - - LAST_SIGNAL -}; - -enum -{ - PROP_0, - PROP_LABEL = 1, - PROP_PREFIX, - PROP_LIST, - PROP_COLUMN, - PROP_MAX, - PROP_HISTORY_LIMIT -}; - -static guint HildonFindToolbar_signal [LAST_SIGNAL] = {0}; - -/** - * hildon_find_toolbar_get_type: - * - * Initializes and returns the type of a hildon fond toolbar. - * - * Returns: GType of #HildonFindToolbar - */ -GType G_GNUC_CONST -hildon_find_toolbar_get_type (void) -{ - static GType find_toolbar_type = 0; - - if (! find_toolbar_type) { - static const GTypeInfo find_toolbar_info = { - sizeof(HildonFindToolbarClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_find_toolbar_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonFindToolbar), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_find_toolbar_init, - }; - find_toolbar_type = g_type_register_static (GTK_TYPE_TOOLBAR, - "HildonFindToolbar", - &find_toolbar_info, 0); - } - - return find_toolbar_type; -} - -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 = HILDON_FIND_TOOLBAR_GET_PRIVATE (self); - g_assert (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_GET_PRIVATE (object); - g_assert (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 = HILDON_FIND_TOOLBAR_GET_PRIVATE (object); - g_assert (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; - HildonFindToolbarPrivate *priv = HILDON_FIND_TOOLBAR_GET_PRIVATE (self); - g_assert (priv); - - model = hildon_find_toolbar_get_list_model (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_GET_PRIVATE (self); - g_assert (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 FALSE; -} - -static void -hildon_find_toolbar_emit_close (GtkButton *button, - gpointer self) -{ -#ifdef MAEMO_GTK - HildonFindToolbarPrivate *priv = HILDON_FIND_TOOLBAR_GET_PRIVATE (self); - g_assert (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); - } -#endif - - /* Clicked close button */ - g_signal_emit (self, HildonFindToolbar_signal [CLOSE], 0); -} - -#ifdef MAEMO_GTK -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 (self, HildonFindToolbar_signal [INVALID_INPUT], 0); -} -#endif - -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 (find_toolbar, HildonFindToolbar_signal [SEARCH], 0); - g_signal_emit (find_toolbar, HildonFindToolbar_signal [HISTORY_APPEND], 0, &rb); -} - -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 = (gpointer) hildon_find_toolbar_history_append; - - /** - * HildonFindToolbar:label: - * - * The label to display before the search box. - * - */ - 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)); - - /** - * HildonFindToolbar:label: - * - * The label to display before the search box. - * - */ - g_object_class_install_property (object_class, PROP_PREFIX, - g_param_spec_string ("prefix", - "Prefix", "Search string", NULL, - G_PARAM_READWRITE)); - - /** - * HildonFindToolbar:list: - * - * A #GtkListStore where the search history is kept. - * - */ - 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)); - - /** - * HildonFindToolbar:column: - * - * The column number in GtkListStore where strings of - * search history are kept. - * - */ - 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)); - - /** - * HildonFindToolbar:label: - * - * The label to display before the search box. - * - */ - 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)); - - /** - * HildonFindToolbar:history-limit: - * - * Maximum number of history items in the combobox. - * - */ - 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, g_cclosure_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, g_cclosure_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, g_cclosure_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, - _hildon_marshal_BOOLEAN__VOID, - G_TYPE_BOOLEAN, 0); -} - -static void -hildon_find_toolbar_init (HildonFindToolbar *self) -{ - GtkToolItem *label_container; - GtkToolItem *entry_combo_box_container; - GtkAlignment *alignment; - - HildonFindToolbarPrivate *priv = HILDON_FIND_TOOLBAR_GET_PRIVATE (self); - g_assert (priv); - - /* Create the label */ - priv->label = gtk_label_new (_("ecdg_ti_find_toolbar_label")); - - gtk_misc_set_padding (GTK_MISC (priv->label), FIND_LABEL_XPADDING, - FIND_LABEL_YPADDING); - - label_container = gtk_tool_item_new (); - gtk_container_add (GTK_CONTAINER (label_container), - 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 */ - priv->entry_combo_box = GTK_COMBO_BOX_ENTRY (gtk_combo_box_entry_new ()); - -#ifdef MAEMO_GTK - g_signal_connect (hildon_find_toolbar_get_entry(priv), - "invalid_input", - G_CALLBACK(hildon_find_toolbar_emit_invalid_input), self); -#endif - - entry_combo_box_container = gtk_tool_item_new (); - alignment = GTK_ALIGNMENT (gtk_alignment_new (0, 0.5, 1, 0)); - - gtk_tool_item_set_expand (entry_combo_box_container, TRUE); - gtk_container_add (GTK_CONTAINER (alignment), - GTK_WIDGET (priv->entry_combo_box)); - gtk_container_add (GTK_CONTAINER (entry_combo_box_container), - GTK_WIDGET (alignment)); - 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 (priv), - "activate", - G_CALLBACK(hildon_find_toolbar_entry_activate), self); - - /* Separator */ - priv->separator = gtk_separator_tool_item_new(); - gtk_widget_set_size_request (GTK_WIDGET (priv->separator), 72, -1); - gtk_widget_show(GTK_WIDGET(priv->separator)); - gtk_toolbar_insert (GTK_TOOLBAR(self), priv->separator, -1); - - /* Close button */ - priv->close_button = gtk_tool_button_new ( - gtk_image_new_from_icon_name ("general_close", - HILDON_ICON_SIZE_TOOLBAR), - "Close"); - g_signal_connect(priv->close_button, "clicked", - G_CALLBACK(hildon_find_toolbar_emit_close), self); - gtk_widget_show_all(GTK_WIDGET(priv->close_button)); - gtk_toolbar_insert (GTK_TOOLBAR(self), priv->close_button, -1); - if ( GTK_WIDGET_CAN_FOCUS( GTK_BIN(priv->close_button)->child) ) - GTK_WIDGET_UNSET_FLAGS( - GTK_BIN(priv->close_button)->child, GTK_CAN_FOCUS); -} - -/** - * hildon_find_toolbar_new: - * @label: label for the find_toolbar, NULL to set the label to - * default "Find" - * - * Creates 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 - * - * Creates 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. - * - * Highlights the current entry in the find toolbar. - * - */ -void -hildon_find_toolbar_highlight_entry (HildonFindToolbar *self, - gboolean get_focus) -{ - GtkEntry *entry = NULL; - HildonFindToolbarPrivate *priv; - - g_return_if_fail (HILDON_IS_FIND_TOOLBAR (self)); - priv = HILDON_FIND_TOOLBAR_GET_PRIVATE (self); - g_assert (priv); - - entry = hildon_find_toolbar_get_entry (priv); - - gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1); - - if (get_focus) - gtk_widget_grab_focus (GTK_WIDGET (entry)); -} - -/** - * hildon_find_toolbar_set_active: - * @toolbar: A find toolbar to operate on - * @index: An index in the model passed during construction, or -1 to have no active item - * - * Sets the active item on the toolbar's combo-box. Simply calls gtk_combo_box_set_active on - * the HildonFindToolbar's combo. - * - */ -void -hildon_find_toolbar_set_active (HildonFindToolbar *toolbar, - gint index) -{ - HildonFindToolbarPrivate *priv; - - g_return_if_fail (HILDON_IS_FIND_TOOLBAR (toolbar)); - priv = HILDON_FIND_TOOLBAR_GET_PRIVATE (toolbar); - - gtk_combo_box_set_active (GTK_COMBO_BOX (priv->entry_combo_box), index); -} - -/** - * hildon_find_toolbar_get_active: - * @toolbar: A find toolbar to query - * - * Gets the index of the currently active item, or -1 if there's no active item. Simply - * calls gtk_combo_box_get_active on the HildonFindToolbar's combo. - * - * Returns: An integer which is the index of the currently active item, or -1 if there's no active item. - * - */ -gint -hildon_find_toolbar_get_active (HildonFindToolbar *toolbar) -{ - HildonFindToolbarPrivate *priv; - - g_return_val_if_fail (HILDON_IS_FIND_TOOLBAR (toolbar), -1); - priv = HILDON_FIND_TOOLBAR_GET_PRIVATE (toolbar); - - return gtk_combo_box_get_active (GTK_COMBO_BOX (priv->entry_combo_box)); -} - -/** - * hildon_find_toolbar_set_active_iter: - * @toolbar: A find toolbar to operate on - * @iter: An iter to make active - * - * Sets the current active item to be the one referenced by iter. Simply calls - * gtk_combo_box_set_active_iter on the HildonFindToolbar's combo. - * - */ -void -hildon_find_toolbar_set_active_iter (HildonFindToolbar *toolbar, - GtkTreeIter *iter) -{ - HildonFindToolbarPrivate *priv; - - g_return_if_fail (HILDON_IS_FIND_TOOLBAR (toolbar)); - priv = HILDON_FIND_TOOLBAR_GET_PRIVATE (toolbar); - - gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->entry_combo_box), iter); -} - -/** - * hildon_find_toolbar_get_active_iter: - * @toolbar: A find toolbar to query - * @iter: The uninitialized GtkTreeIter - * - * Sets iter to point to the current active item, if it exists. Simply calls - * gtk_combo_box_get_active_iter on the HildonFindToolbar's combo. - * - * Returns: TRUE, if iter was set - * - */ -gboolean -hildon_find_toolbar_get_active_iter (HildonFindToolbar *toolbar, - GtkTreeIter *iter) -{ - HildonFindToolbarPrivate *priv; - - g_return_val_if_fail (HILDON_IS_FIND_TOOLBAR (toolbar), FALSE); - priv = HILDON_FIND_TOOLBAR_GET_PRIVATE (toolbar); - - return gtk_combo_box_get_active_iter (GTK_COMBO_BOX (priv->entry_combo_box), iter); -} - -/** - * hildon_find_toolbar_get_last_index - * @toolbar: A find toolbar to query - * - * Returns the index of the last (most recently added) item in the toolbar. - * Can be used to set this item active in the history-append signal. - * - * - * Returns: Index of the last entry - * - */ -gint32 -hildon_find_toolbar_get_last_index (HildonFindToolbar *toolbar) -{ - HildonFindToolbarPrivate *priv; - GtkTreeModel *filter_model; - - g_return_val_if_fail (HILDON_IS_FIND_TOOLBAR (toolbar), FALSE); - priv = HILDON_FIND_TOOLBAR_GET_PRIVATE (toolbar); - - filter_model = gtk_combo_box_get_model (GTK_COMBO_BOX (priv->entry_combo_box)); - - if (filter_model == NULL) - return 0; - - gint i = 0; - GtkTreeIter iter; - - gtk_tree_model_get_iter_first (filter_model, &iter); - - while (gtk_tree_model_iter_next (filter_model, &iter)) - i++; - - return i; -} - diff --git a/src/hildon-find-toolbar.h b/src/hildon-find-toolbar.h deleted file mode 100644 index 00ce8e8..0000000 --- a/src/hildon-find-toolbar.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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 - -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_TOOLBAR_CLASS(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; - -struct _HildonFindToolbar -{ - GtkToolbar parent; -}; - -struct _HildonFindToolbarClass -{ - GtkToolbarClass parent_class; - - void (*search) (HildonFindToolbar *toolbar); - void (*close) (HildonFindToolbar *toolbar); - void (*invalid_input) (HildonFindToolbar *toolbar); - gboolean (*history_append) (HildonFindToolbar *tooblar); -}; - -GType G_GNUC_CONST -hildon_find_toolbar_get_type (void); - -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); - -void -hildon_find_toolbar_set_active (HildonFindToolbar *toolbar, - gint index); - -gint -hildon_find_toolbar_get_active (HildonFindToolbar *toolbar); - -void -hildon_find_toolbar_set_active_iter (HildonFindToolbar *toolbar, - GtkTreeIter *iter); - -gboolean -hildon_find_toolbar_get_active_iter (HildonFindToolbar *toolbar, - GtkTreeIter *iter); - -gint32 -hildon_find_toolbar_get_last_index (HildonFindToolbar *toolbar); - -G_END_DECLS - -#endif /* __HILDON_FIND_TOOLBAR_H__ */ - diff --git a/src/hildon-font-selection-dialog-private.h b/src/hildon-font-selection-dialog-private.h deleted file mode 100644 index bb0628c..0000000 --- a/src/hildon-font-selection-dialog-private.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_PRIVATE_H__ -#define __HILDON_FONT_SELECTION_DIALOG_PRIVATE_H__ - -G_BEGIN_DECLS - -#define HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_FONT_SELECTION_DIALOG, \ - HildonFontSelectionDialogPrivate)) - -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; -}; - -G_END_DECLS - -#endif /* __HILDON_FONT_SELECTION_DIALOG_PRIVATE_H__ */ diff --git a/src/hildon-font-selection-dialog.c b/src/hildon-font-selection-dialog.c deleted file mode 100644 index 175edc2..0000000 --- a/src/hildon-font-selection-dialog.c +++ /dev/null @@ -1,1417 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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. Since hildon 2.2, the previously available preview dialog - * has been removed. - */ - -#undef HILDON_DISABLE_DEPRECATED - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include -#include - -#include "hildon-font-selection-dialog.h" -#include "hildon-caption.h" -#include "hildon-color-button.h" -#include "hildon-font-selection-dialog-private.h" - -/* 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 -}; - -enum -{ - PROP_0, - PROP_FAMILY, - 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 -}; - -/* 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; - -#if 0 -static gboolean -hildon_font_selection_dialog_preview_key_press (GtkWidget *widget, - GdkEventKey *event, - gpointer unused); -#endif - -static int -cmp_families (const void *a, - const void *b); -#if 0 -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); -#endif - -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); - -#if 0 -static void -add_preview_text_attr (PangoAttrList *list, - PangoAttribute *attr, - guint start, - guint len); -#endif - -static void -toggle_clicked (GtkButton *button, - gpointer unused); - -static GtkDialogClass* parent_class = NULL; - -#define _(String) dgettext("hildon-libs", String) - -#define SUPERSCRIPT_RISE 3333 - -#define SUBSCRIPT_LOW -3333 - -#define ON_BIT 0x01 - -#define OFF_BIT 0x02 - -/** - * hildon_font_selection_dialog_get_type: - * - * Initializes and returns the type of a hildon font selection dialog - * - * Returns: GType of #HildonFontSelectionDialog - */ -GType G_GNUC_CONST -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; - - HildonFontSelectionDialogPrivate *priv = - HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(object); - - g_assert (priv); - - 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"); - /* FIXME Bad hardcoding here */ - 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: - hildon_color_button_get_color - (HILDON_COLOR_BUTTON (priv->font_color_button), &color); - g_value_set_boxed (value, (gconstpointer) &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 *family; - gboolean b; - GdkColor *color = NULL; - GdkColor black; - - HildonFontSelectionDialogPrivate *priv = HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE (object); - g_assert (priv); - - black.red = black.green = black.blue = 0; - - switch (prop_id) - { - case PROP_FAMILY: - family = g_value_get_string (value); - g_return_if_fail (family != NULL); - for(i = 0; i < priv->n_families; i++) - { - if (strcmp (family, 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; - - 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 properties to the class */ - - /** - * HildonFontSelectionDialog:family: - * - * Font family used. - */ - 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)); - - /** - * HildonFontSelectionDialog:family-set: - * - * Is font family set or inconsistent. - */ - 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)); - - /** - * HildonFontSelectionDialog:size: - * - * Font size. - */ - 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)); - - /** - * HildonFontSelectionDialog:size-set: - * - * Is font size set or inconsistent. - */ - 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)); - - /** - * HildonFontSelectionDialog:color: - * - * GdkColor for the text. - */ - 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)); - - /** - * HildonFontSelectionDialog:color-set: - * - * Is font color set or inconsistent. - */ - 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)); - - /** - * HildonFontSelectionDialog:color-set: - * - * Is font set as bold. - */ - 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)); - - /** - * HildonFontSelectionDialog:color-set: - * - * Is font bold status set or inconsistent. - */ - 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)); - - /** - * HildonFontSelectionDialog:italic: - * - * Is font set as italic. - */ - 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)); - - /** - * HildonFontSelectionDialog:italic-set: - * - * Is font italic status set or inconsistent. - */ - 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)); - - /** - * HildonFontSelectionDialog:underline: - * - * Is the font underlined. - */ - 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)); - - /** - * HildonFontSelectionDialog:underline: - * - * Is font underline status set or inconsistent. - */ - 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)); - - /** - * HildonFontSelectionDialog:strikethrough: - * - * Is the font striken-through. - */ - 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)); - - /** - * HildonFontSelectionDialog:strikethrough-set: - * - * Is the font strikenthrough status set. - */ - 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)); - - /** - * HildonFontSelectionDialog:position: - * - * The font positioning versus baseline. - */ - 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)); - - /** - * HildonFontSelectionDialog:position-set: - * - * Is the font positioning set. - */ - 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)); - - /** - * HildonFontSelectionDialog:font-scaling: - * - * The font scaling factor applied to the preview dialog. - */ - 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)); - - /** - * HildonFontSelectionDialog:preview-text: - * - * The text used for the preview dialog. - * - * Deprecated: this property is unused since hildon 2.2 - */ - 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; */ - - g_assert (priv); - 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), - _("wdgt_bd_done"), - GTK_RESPONSE_OK); - -#if 0 - 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); -#endif - - /*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); - g_assert (priv); - - 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); - - g_object_unref (group); - - 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; - g_assert (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_assert (priv); - - if (priv->preview_text != NULL) { - g_free (priv->preview_text); - priv->preview_text = NULL; - } - - if (priv->families != NULL) { - g_free (priv->families); - priv->families = NULL; - } - - if (G_OBJECT_CLASS (parent_class)->finalize) - G_OBJECT_CLASS (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); -} - -#if 0 -/* Exits the preview dialog with GTK_RESPONSE_CANCEL if Esc key - * was pressed - * FIXME This should be handled automatically */ -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_assert (priv); - - 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, - _("wdgt_bd_done"), - 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); - - if (str) - g_free (str); - - str = NULL; - - /* 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); - - /* A smallish hack to add scrollbar when font size is really big */ - - if (size_set && size > 24) { - GtkScrolledWindow *scrolled = GTK_SCROLLED_WINDOW (gtk_scrolled_window_new (NULL, NULL)); - gtk_scrolled_window_set_policy (scrolled, GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_add_with_viewport (scrolled, GTK_WIDGET (preview_label)); - gtk_container_add (GTK_CONTAINER (GTK_DIALOG(preview_dialog)->vbox), GTK_WIDGET (scrolled)); - gtk_widget_set_size_request (GTK_WIDGET (scrolled), -1, 400); - } else - gtk_container_add (GTK_CONTAINER (GTK_DIALOG(preview_dialog)->vbox), GTK_WIDGET (preview_label)); - - /* 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"))); - } - if (str != NULL) - g_free (str); - - str = NULL; - - /* 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_set_default_response (GTK_DIALOG (preview_dialog), GTK_RESPONSE_OK); - - GtkBox *action_area = (GtkBox *) GTK_DIALOG (preview_dialog)->action_area; - GtkWidget *button = ((GtkBoxChild *) ((GSList *) action_area->children)->data)->widget; - gtk_widget_grab_focus (button); - - gtk_dialog_run (GTK_DIALOG (preview_dialog)); - gtk_widget_destroy (preview_dialog); -} -#endif - -static gboolean -is_internal_font (const gchar * name) -{ - /* FIXME Extremally BAD BAD BAD way of doing things */ - - 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); - g_assert (priv); - - 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; - - g_assert (priv); - - 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); - } -} - -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); - } -} - -/** - * 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. - * Please note that since hildon 2.2, the preview has been discontinued, - * so this setting has no effect. - * - * Returns: a string pointer - */ -gchar* -hildon_font_selection_dialog_get_preview_text (HildonFontSelectionDialog * fsd) -{ - /* FIXME Return a const pointer? */ - HildonFontSelectionDialogPrivate *priv; - - g_return_val_if_fail (HILDON_IS_FONT_SELECTION_DIALOG (fsd), NULL); - - priv = HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE (fsd); - g_assert (priv); - - 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". Please note that since - * hildon 2.2, the preview has been discontinued, so this setting has no effect. - * - */ -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_assert (priv); - - g_free (priv->preview_text); - priv->preview_text = g_strdup (text); - g_object_notify (G_OBJECT (fsd), "preview-text"); -} - diff --git a/src/hildon-font-selection-dialog.h b/src/hildon-font-selection-dialog.h deleted file mode 100644 index 558f660..0000000 --- a/src/hildon-font-selection-dialog.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#ifndef __HILDON_FONT_SELECTION_DIALOG_H__ -#define __HILDON_FONT_SELECTION_DIALOG_H__ - -#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; -}; - -GType G_GNUC_CONST -hildon_font_selection_dialog_get_type (void); - -GtkWidget* -hildon_font_selection_dialog_new (GtkWindow *parent, - const gchar *title); - -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__ */ - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-get-password-dialog-private.h b/src/hildon-get-password-dialog-private.h deleted file mode 100644 index a6bdf6e..0000000 --- a/src/hildon-get-password-dialog-private.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_PRIVATE_H__ -#define __HILDON_GET_PASSWORD_DIALOG_PRIVATE_H__ - -G_BEGIN_DECLS - -#define HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_GET_PASSWORD_DIALOG, HildonGetPasswordDialogPrivate)); - -typedef struct _HildonGetPasswordDialogPrivate HildonGetPasswordDialogPrivate; - -struct _HildonGetPasswordDialogPrivate -{ - GtkLabel *message_label; - HildonCaption *password_entry; - gboolean get_old; -}; - -G_END_DECLS - -#endif /* __HILDON_GET_PASSWORD_DIALOG_PRIVATE_H__ */ diff --git a/src/hildon-get-password-dialog.c b/src/hildon-get-password-dialog.c deleted file mode 100644 index c7d993f..0000000 --- a/src/hildon-get-password-dialog.c +++ /dev/null @@ -1,672 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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 a custom message. The maximum length of the password can be set. - * - * - * HildonGetPassword example - * - * get_dialog = HILDON_GET_PASSWORD_DIALOG (hildon_get_password_dialog_new (parent, FALSE)); - * - * gtk_widget_show (GTK_WIDGET (get_dialog)); - * - * i = gtk_dialog_run (GTK_DIALOG (get_dialog)); - * - * pass = hildon_get_password_dialog_get_password (get_dialog); - * - * if (i == GTK_RESPONSE_OK && (strcmp (pass, dialog.current_password) != 0)) - * { - * gtk_infoprint (GTK_WINDOW (parent), STR_PASSWORD_INCORRECT); - * gtk_widget_set_sensitive (GTK_WIDGET (dialog.button2), FALSE); - * gtk_widget_set_sensitive (GTK_WIDGET (dialog.button3), FALSE); - * gtk_widget_set_sensitive (GTK_WIDGET (dialog.button4), FALSE); - * } - * - * else if (i == GTK_RESPONSE_OK) - * { - * gtk_widget_set_sensitive( GTK_WIDGET( dialog.button2 ), TRUE); - * } - * - * else - * { - * gtk_widget_set_sensitive (GTK_WIDGET (dialog.button2), FALSE); - * gtk_widget_set_sensitive (GTK_WIDGET (dialog.button3), FALSE); - * gtk_widget_set_sensitive (GTK_WIDGET (dialog.button4), FALSE); - * } - * gtk_widget_destroy (GTK_WIDGET (get_dialog)); - * } - * - * - */ - -#undef HILDON_DISABLE_DEPRECATED - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include - -#include "hildon-get-password-dialog.h" -#include "hildon-caption.h" -#include "hildon-banner.h" -#include "hildon-get-password-dialog-private.h" -#include "hildon-entry.h" - -#define _(String) dgettext("hildon-libs", String) - -#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 "wdgt_bd_done" - -#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 "wdgt_bd_done" - -#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" - -static GtkDialogClass* parent_class; - -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); - -#ifdef MAEMO_GTK -static void -invalid_input (GtkWidget *widget, - GtkInvalidInputType reason, - gpointer unused); -#endif - -enum -{ - PROP_0, - PROP_MESSAGE, - 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 (object); - g_assert (priv); - - switch (prop_id) { - - case PROP_MESSAGE: - /* Set label text representing password domain */ - gtk_label_set_text (priv->message_label, g_value_get_string (value)); - break; - - case PROP_PASSWORD: - hildon_entry_set_text(HILDON_ENTRY (gtk_bin_get_child (GTK_BIN (priv->password_entry))), - g_value_get_string(value)); - break; - - case PROP_NUMBERS_ONLY: -#ifdef MAEMO_GTK - /* Set input mode for the password entry */ - g_object_set(G_OBJECT (gtk_bin_get_child GTK_BIN ((priv->password_entry))), - "hildon-input-mode", - (g_value_get_boolean (value) - ? HILDON_GTK_INPUT_MODE_NUMERIC - : HILDON_GTK_INPUT_MODE_FULL), - NULL); -#endif - 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; -#ifdef MAEMO_GTK - gint input_mode; -#endif - - priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE (dialog); - g_assert (priv); - - switch (prop_id) { - - case PROP_MESSAGE: - string = gtk_label_get_text (priv->message_label); - g_value_set_string (value, string); - break; - - case PROP_PASSWORD: - string = hildon_entry_get_text (HILDON_ENTRY (gtk_bin_get_child (GTK_BIN (priv->password_entry)))); - g_value_set_string (value, string); - break; - - case PROP_NUMBERS_ONLY: -#ifdef MAEMO_GTK - /* 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 (gtk_bin_get_child (GTK_BIN (priv->password_entry))), - "hildon-input-mode", &input_mode, NULL); - g_value_set_boolean (value, - (input_mode == HILDON_GTK_INPUT_MODE_NUMERIC)); -#else - g_value_set_boolean (value, FALSE); -#endif - break; - - case PROP_CAPTION_LABEL: - string = hildon_caption_get_label (priv->password_entry); - g_value_set_string (value, string); - break; - - case PROP_MAX_CHARS: - max_length = gtk_entry_get_max_length - (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->password_entry)))); - 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 */ - - /** - * HildonGetPasswordDialog:message: - * - * Optional message displayed to the user. - */ - g_object_class_install_property - (object_class, - PROP_MESSAGE, - g_param_spec_string ("message", - "Message", - "Set optional message", - NULL, - G_PARAM_READWRITE)); - - /** - * HildonGetPasswordDialog:password: - * - * Password field contents. - */ - g_object_class_install_property - (object_class, - PROP_PASSWORD, - g_param_spec_string ("password", - "Password", - "Password field", - "DEFAULT", - G_PARAM_READWRITE)); - - /** - * HildonGetPasswordDialog:numbers-only: - * - * If the password entry field is operating in numbers-only mode. - */ - 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)); - - /** - * HildonGetPasswordDialog:caption-label: - * - * Caption label. - */ - 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)); - - /** - * HildonGetPasswordDialog:max-characters: - * - * Maximum characters than can be entered. - */ - 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)); - - /** - * HildonGetPasswordDialog:get-old: - * - * If the dialog is used to retrieve an old password or set a new one. - */ - 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; - AtkObject *atk_aux = NULL; - - /* Cache private pointer for faster member access */ - priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE (dialog); - g_assert (priv); - - /* 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->message_label = GTK_LABEL (gtk_label_new (NULL)); - - /* Create buttons */ - gtk_dialog_add_button (GTK_DIALOG (dialog), - (priv->get_old - ? _(HILDON_GET_PASSWORD_DIALOG_OK) - : _(HILDON_GET_PASSWORD_VERIFY_DIALOG_OK)), - GTK_RESPONSE_OK); - - 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 = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH); - if ((atk_aux = gtk_widget_get_accessible(control))) - { - atk_object_set_name(atk_aux, "Passwd"); - } - - gtk_entry_set_width_chars (GTK_ENTRY (control), 20); - -#ifdef MAEMO_GTK - g_object_set (control, "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL); -#endif - - gtk_entry_set_visibility (GTK_ENTRY(control), FALSE); - priv->password_entry = 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->password_entry), ""); - - /* Do the basic layout */ - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), - GTK_WIDGET (priv->message_label), FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), - GTK_WIDGET (priv->password_entry), 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); -} - -/** - * hildon_get_password_dialog_get_type: - * - * Returns GType for HildonGetPasswordDialog as produced by - * g_type_register_static(). - * - * Returns: HildonGetPasswordDialog type - */ -GType G_GNUC_CONST -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 (GtkWidget *) 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 entered password. The string should not be freed. - * - * Returns: current password entered by the user. - */ -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); - g_assert (priv); - - /* Retrieve the password entry widget */ - entry1 = GTK_ENTRY (gtk_bin_get_child (GTK_BIN (priv->password_entry))); - text1 = GTK_ENTRY (entry1)->text; - - return text1; -} - -/** - * hildon_get_password_dialog_set_message - * @dialog: the dialog - * @message: a custom message or some other descriptive text to be set - * - * Sets the optional descriptive text displayed at the top of the dialog. - */ -void -hildon_get_password_dialog_set_message (HildonGetPasswordDialog *dialog, - const gchar *message) -{ - HildonGetPasswordDialogPrivate *priv; - - g_return_if_fail (HILDON_IS_GET_PASSWORD_DIALOG (dialog)); - - priv = HILDON_GET_PASSWORD_DIALOG_GET_PRIVATE (dialog); - g_assert (priv); - - gtk_label_set_text (priv->message_label, message); - -} - -/** - * 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); - g_assert (priv); - - hildon_caption_set_label (priv->password_entry, new_caption); -} - -/** - * hildon_get_password_dialog_set_max_characters: - * @dialog: the dialog - * @max_characters: the maximum number of characters the password dialog - * accepts - * - * 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); - g_assert (priv); - - /* Apply the given length to password entry */ - gtk_entry_set_max_length (GTK_ENTRY - (gtk_bin_get_child - GTK_BIN ((priv->password_entry))), - max_characters); - - /* FIXME There is a bug here -- the prev. signal needs to be - * disconnected before connecting the new signal. Besides, this - * should go into the constructor */ - -#ifdef MAEMO_GTK - /* Connect callback to show error banner if the limit is exceeded */ - g_signal_connect (GTK_ENTRY - (gtk_bin_get_child - GTK_BIN ((priv->password_entry))), - "invalid_input", - G_CALLBACK (invalid_input), - NULL - ); -#endif -} - -#ifdef MAEMO_GTK -/* Callback that gets called when maximum chars is reached in the entry */ -static void -invalid_input (GtkWidget *widget, - GtkInvalidInputType reason, - gpointer unused) -{ - if (reason == GTK_INVALID_INPUT_MAX_CHARS_REACHED) - { - hildon_banner_show_information (widget, NULL, _(HILDON_GET_PASSWORD_DIALOG_MAX_CHARS)); - } -} -#endif diff --git a/src/hildon-get-password-dialog.h b/src/hildon-get-password-dialog.h deleted file mode 100644 index 46999cb..0000000 --- a/src/hildon-get-password-dialog.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#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)) - -typedef struct _HildonGetPasswordDialog HildonGetPasswordDialog; - -typedef struct _HildonGetPasswordDialogClass HildonGetPasswordDialogClass; - -struct _HildonGetPasswordDialog -{ - GtkDialog parent; -}; - -struct _HildonGetPasswordDialogClass -{ - GtkDialogClass parent_class; -}; - -GType G_GNUC_CONST -hildon_get_password_dialog_get_type (void); - -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_message (HildonGetPasswordDialog *dialog, - const gchar *message); - -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); - -G_END_DECLS - -#endif /* __HILDON_GET_PASSWORD_DIALOG_H__ */ - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-gtk.c b/src/hildon-gtk.c deleted file mode 100644 index fd1f9f4..0000000 --- a/src/hildon-gtk.c +++ /dev/null @@ -1,500 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser Public License as published by - * the Free Software Foundation; version 2 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser Public License for more details. - * - */ - -/** - * SECTION:hildon-gtk - * @short_description: Additional functions for Gtk widgets - * @see_also: #HildonButton, #HildonCheckButton - * - * Hildon provides some functions to extend the functionality of - * existing Gtk widgets. This also includes convenience functions to - * easily perform frequent tasks. - */ - -#include -#include - -#include "hildon-gtk.h" - -typedef void (*HildonFlagFunc) (GtkWindow *window, gpointer userdata); - -static void -image_visible_changed_cb (GtkWidget *image, - GParamSpec *arg1, - gpointer oldparent) -{ - if (!GTK_WIDGET_VISIBLE (image)) - gtk_widget_show (image); -} - -static void -parent_changed_cb (GtkWidget *image, - GParamSpec *arg1, - gpointer oldparent) -{ - /* If the parent has really changed, remove the old signal handlers */ - if (image->parent != oldparent) { - g_signal_handlers_disconnect_by_func (image, parent_changed_cb, oldparent); - g_signal_handlers_disconnect_by_func (image, image_visible_changed_cb, NULL); - } -} - -static void -image_changed_cb (GtkButton *button, - GParamSpec *arg1, - gpointer user_data) -{ - GtkWidget *image = gtk_button_get_image (button); - - g_return_if_fail (image == NULL || GTK_IS_WIDGET (image)); - - if (image != NULL) { - /* If the button has a new image, show it */ - gtk_widget_show (image); - /* Show the image no matter the value of gtk-button-images */ - g_signal_connect (image, "notify::visible", G_CALLBACK (image_visible_changed_cb), NULL); - /* If the image is removed from the button, disconnect these handlers */ - g_signal_connect (image, "notify::parent", G_CALLBACK (parent_changed_cb), image->parent); - } -} - -static void -button_common_init (GtkWidget *button, - HildonSizeType size) -{ - /* Set requested size */ - hildon_gtk_widget_set_theme_size (button, size); - - /* Set focus-on-click to FALSE by default */ - gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE); - - /* Make sure that all images in this button are always shown */ - g_signal_connect (button, "notify::image", G_CALLBACK (image_changed_cb), NULL); -} - -/** - * hildon_gtk_menu_new: - * - * This is a convenience function to create a #GtkMenu setting its - * widget name to allow Hildon specific styling. - * - * Return value: A newly created #GtkMenu widget. - * - * Since: 2.2 - **/ -GtkWidget * -hildon_gtk_menu_new (void) -{ - GtkWidget *menu = gtk_menu_new (); - gtk_widget_set_name (menu, "hildon-context-sensitive-menu"); - return menu; -} - -/** - * hildon_gtk_button_new: - * @size: Flags indicating the size of the new button - * - * This is a convenience function to create a #GtkButton setting its - * size to one of the pre-defined Hildon sizes. - * - * Buttons created with this function also override the - * "gtk-button-images" setting. Images set using - * gtk_button_set_image() are always shown. - * - * Buttons created using this function have #GtkButton:focus-on-click - * set to %FALSE by default. - * - * Return value: A newly created #GtkButton widget. - * - * Since: 2.2 - **/ -GtkWidget * -hildon_gtk_button_new (HildonSizeType size) -{ - GtkWidget *button = gtk_button_new (); - button_common_init (button, size); - return button; -} - -/** - * hildon_gtk_toggle_button_new: - * @size: Flags indicating the size of the new button - * - * This is a convenience function to create a #GtkToggleButton setting - * its size to one of the pre-defined Hildon sizes. - * - * Buttons created with this function also override the - * "gtk-button-images" setting. Images set using - * gtk_button_set_image() are always shown. - * - * Buttons created using this function have #GtkButton:focus-on-click - * set to %FALSE by default. - * - * Return value: A newly created #GtkToggleButton widget. - * - * Since: 2.2 - **/ -GtkWidget * -hildon_gtk_toggle_button_new (HildonSizeType size) -{ - GtkWidget *button = gtk_toggle_button_new (); - button_common_init (button, size); - return button; -} - -/** - * hildon_gtk_radio_button_new: - * @size: Flags indicating the size of the new button - * @group: An existing radio button group, or %NULL if you are - * creating a new group - * - * This is a convenience function to create a #GtkRadioButton setting - * its size to one of the pre-defined Hildon sizes. - * - * Buttons created with this function also override the - * "gtk-button-images" setting. Images set using - * gtk_button_set_image() are always shown. - * - * Buttons created using this function have #GtkButton:focus-on-click - * set to %FALSE by default. - * - * Return value: A newly created #GtkRadioButton widget. - * - * Since: 2.2 - **/ -GtkWidget * -hildon_gtk_radio_button_new (HildonSizeType size, - GSList *group) -{ - GtkWidget *button = gtk_radio_button_new (group); - button_common_init (button, size); - return button; -} - -/** - * hildon_gtk_radio_button_new_from_widget: - * @size: Flags indicating the size of the new button - * @radio_group_member: widget to get radio group from or %NULL - * - * This is a convenience function to create a #GtkRadioButton setting - * its size to one of the pre-defined Hildon sizes. - * - * Buttons created with this function also override the - * "gtk-button-images" setting. Images set using - * gtk_button_set_image() are always shown. - * - * Buttons created using this function have #GtkButton:focus-on-click - * set to %FALSE by default. - * - * Return value: A newly created #GtkRadioButton widget. - * - * Since: 2.2 - **/ -GtkWidget * -hildon_gtk_radio_button_new_from_widget (HildonSizeType size, - GtkRadioButton *radio_group_member) -{ - GtkWidget *button = gtk_radio_button_new_from_widget (radio_group_member); - button_common_init (button, size); - return button; -} - -#ifdef MAEMO_GTK -/** - * hildon_gtk_tree_view_new: - * @mode: the Hildon UI mode - * - * Creates a new #GtkTreeView widget with the Hildon UI mode set to - * @mode - * - * Return value: A newly created #GtkTreeView widget. - * - * Since: 2.2 - **/ -GtkWidget * -hildon_gtk_tree_view_new (HildonUIMode mode) -{ - return g_object_new (GTK_TYPE_TREE_VIEW, "hildon-ui-mode", mode, - "enable-search", FALSE, NULL); -} - -/** - * hildon_gtk_tree_view_new_with_model: - * @mode: the Hildon UI mode - * @model: the model. - * - * Creates a new #GtkTreeView widget with the Hildon UI mode set to - * @mode and the model initialized to @model. - * - * Return value: A newly created #GtkTreeView widget. - * - * Since: 2.2 - **/ -GtkWidget * -hildon_gtk_tree_view_new_with_model (HildonUIMode mode, - GtkTreeModel *model) -{ - return g_object_new (GTK_TYPE_TREE_VIEW, "hildon-ui-mode", mode, "model", model, NULL); -} - -/** - * hildon_gtk_tree_view_set_ui_mode: - * @treeview: A #GtkTreeView - * @mode: The new #HildonUIMode - * - * Sets the UI mode of @treeview to @mode. - * - * Since: 2.2 - **/ -void -hildon_gtk_tree_view_set_ui_mode (GtkTreeView *treeview, - HildonUIMode mode) -{ - g_return_if_fail (GTK_IS_TREE_VIEW (treeview)); - g_object_set (treeview, "hildon-ui-mode", mode, NULL); -} - -/** - * hildon_gtk_icon_view_new: - * @mode: the Hildon UI mode - * - * Creates a new #GtkIconView widget with the Hildon UI mode set to - * @mode - * - * Return value: A newly created #GtkIconView widget - * - * Since: 2.2 - **/ -GtkWidget * -hildon_gtk_icon_view_new (HildonUIMode mode) -{ - return g_object_new (GTK_TYPE_ICON_VIEW, "hildon-ui-mode", mode, NULL); -} - -/** - * hildon_gtk_icon_view_new_with_model: - * @mode: the Hildon UI mode - * @model: The model. - * - * Creates a new #GtkIconView widget with the Hildon UI mode set to - * @mode and the model intitialized to @model. - * - * Return value: A newly created #GtkIconView widget. - * - * Since: 2.2 - **/ -GtkWidget * -hildon_gtk_icon_view_new_with_model (HildonUIMode mode, - GtkTreeModel *model) -{ - return g_object_new (GTK_TYPE_ICON_VIEW, "hildon-ui-mode", mode, "model", model, NULL); -} - -/** - * hildon_gtk_icon_view_set_ui_mode: - * @iconview: A #GtkIconView - * @mode: The new #HildonUIMode - * - * Sets the UI mode of @iconview to @mode. - * - * Since: 2.2 - **/ -void -hildon_gtk_icon_view_set_ui_mode (GtkIconView *iconview, - HildonUIMode mode) -{ - g_return_if_fail (GTK_IS_ICON_VIEW (iconview)); - g_object_set (iconview, "hildon-ui-mode", mode, NULL); -} -#endif /* MAEMO_GTK */ - -static void -set_clear_window_flag (GtkWindow *window, - const gchar *atomname, - Atom xatom, - gboolean flag) -{ - GdkWindow *gdkwin = GTK_WIDGET (window)->window; - GdkAtom atom = gdk_atom_intern (atomname, FALSE); - - if (flag) { - guint32 set = 1; - gdk_property_change (gdkwin, atom, gdk_x11_xatom_to_atom (xatom), - 32, GDK_PROP_MODE_REPLACE, (const guchar *) &set, 1); - } else { - gdk_property_delete (gdkwin, atom); - } -} - -static void -do_set_progress_indicator (GtkWindow *window, - gpointer stateptr) -{ - guint state = GPOINTER_TO_UINT (stateptr); - set_clear_window_flag (window, "_HILDON_WM_WINDOW_PROGRESS_INDICATOR", XA_INTEGER, state); - g_signal_handlers_disconnect_matched (window, G_SIGNAL_MATCH_FUNC, - 0, 0, NULL, do_set_progress_indicator, NULL); -} - -static void -do_set_do_not_disturb (GtkWindow *window, - gpointer dndptr) -{ - gboolean dndflag = GPOINTER_TO_INT (dndptr); - set_clear_window_flag (window, "_HILDON_DO_NOT_DISTURB", XA_INTEGER, dndflag); - g_signal_handlers_disconnect_matched (window, G_SIGNAL_MATCH_FUNC, - 0, 0, NULL, do_set_do_not_disturb, NULL); -} - -static void -do_set_portrait_flags (GtkWindow *window, - gpointer flagsptr) -{ - HildonPortraitFlags flags = GPOINTER_TO_INT (flagsptr); - - set_clear_window_flag (window, "_HILDON_PORTRAIT_MODE_REQUEST", XA_CARDINAL, - flags & HILDON_PORTRAIT_MODE_REQUEST); - set_clear_window_flag (window, "_HILDON_PORTRAIT_MODE_SUPPORT", XA_CARDINAL, - flags & HILDON_PORTRAIT_MODE_SUPPORT); - - g_signal_handlers_disconnect_matched (window, G_SIGNAL_MATCH_FUNC, - 0, 0, NULL, do_set_portrait_flags, NULL); -} - -static void -set_flag (GtkWindow *window, - HildonFlagFunc func, - gpointer userdata) -{ - g_return_if_fail (GTK_IS_WINDOW (window)); - if (GTK_WIDGET_REALIZED (window)) { - (*func) (window, userdata); - } else { - g_signal_handlers_disconnect_matched (window, G_SIGNAL_MATCH_FUNC, - 0, 0, NULL, func, NULL); - g_signal_connect (window, "realize", G_CALLBACK (func), userdata); - } -} - -/** - * hildon_gtk_window_set_progress_indicator: - * @window: a #GtkWindow. - * @state: The state we want to set: 1 -> show progress indicator, 0 - * -> hide progress indicator. - * - * This functions tells the window manager to show/hide a progress - * indicator in the window title. It applies to #HildonDialog and - * #HildonWindow (including subclasses). - * - * Since: 2.2 - **/ -void -hildon_gtk_window_set_progress_indicator (GtkWindow *window, - guint state) -{ - set_flag (window, (HildonFlagFunc) do_set_progress_indicator, GUINT_TO_POINTER (state)); -} - -/** - * hildon_gtk_window_set_do_not_disturb: - * @window: a #GtkWindow - * @dndflag: %TRUE to set the "do-not-disturb" flag, %FALSE to clear it - * - * This function tells the window manager to set (or clear) the - * "do-not-disturb" flag on @window. - * - * Since: 2.2 - **/ -void -hildon_gtk_window_set_do_not_disturb (GtkWindow *window, - gboolean dndflag) -{ - set_flag (window, (HildonFlagFunc) do_set_do_not_disturb, GUINT_TO_POINTER (dndflag)); -} - -/** - * hildon_gtk_window_set_portrait_flags: - * @window: a #GtkWindow - * @portrait_flags: a combination of #HildonPortraitFlags - * - * Sets the portrait flags for @window. - * - * Since: 2.2 - **/ -void -hildon_gtk_window_set_portrait_flags (GtkWindow *window, - HildonPortraitFlags portrait_flags) -{ - set_flag (window, (HildonFlagFunc) do_set_portrait_flags, GUINT_TO_POINTER (portrait_flags)); -} - -/** - * hildon_gtk_hscale_new: - * - * Creates a new horizontal scale widget that lets the user select - * a value. The value is technically a double between 0.0 and 1.0. - * See gtk_adjustment_configure() for reconfiguring the adjustment. - * - * The scale is hildonized, which means that a click or tap immediately - * jumps to the desired position, see gtk_range_set_jump_to_position(). - * Further more the value is not displayed, see gtk_scale_set_draw_value(). - * - * Returns: a new hildonized #GtkHScale - * - * Since: 2.2 - **/ -GtkWidget* -hildon_gtk_hscale_new (void) -{ - GtkWidget *scale = gtk_hscale_new_with_range (0.0, 1.0, 0.1); - g_object_set (scale, - "draw-value", FALSE, -#ifdef MAEMO_GTK - "jump-to-position", TRUE, -#endif - NULL); - - return scale; -} - -/** - * hildon_gtk_vscale_new: - * - * Creates a new vertical scale widget that lets the user select - * a value. The value is technically a double between 0.0 and 1.0. - * See gtk_adjustment_configure() for reconfiguring the adjustment. - * - * The scale is hildonized, which means that a click or tap immediately - * jumps to the desired position, see gtk_range_set_jump_to_position(). - * Further more the value is not displayed, see gtk_scale_set_draw_value(). - * - * Returns: a new hildonized #GtkVScale - * - * Since: 2.2 - **/ -GtkWidget* -hildon_gtk_vscale_new (void) -{ - GtkWidget *scale = gtk_vscale_new_with_range (0.0, 1.0, 0.1); - g_object_set (scale, - "draw-value", FALSE, -#ifdef MAEMO_GTK - "jump-to-position", TRUE, -#endif - NULL); - - return scale; -} diff --git a/src/hildon-gtk.h b/src/hildon-gtk.h deleted file mode 100644 index 7d7e9eb..0000000 --- a/src/hildon-gtk.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser Public License as published by - * the Free Software Foundation; version 2 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser Public License for more details. - * - */ - -#ifndef __HILDON_GTK_H__ -#define __HILDON_GTK_H__ - -#include - -G_BEGIN_DECLS - -GtkWidget * -hildon_gtk_menu_new (void); - -GtkWidget * -hildon_gtk_button_new (HildonSizeType size); - -GtkWidget * -hildon_gtk_toggle_button_new (HildonSizeType size); - -GtkWidget * -hildon_gtk_radio_button_new (HildonSizeType size, - GSList *group); - -GtkWidget * -hildon_gtk_radio_button_new_from_widget (HildonSizeType size, - GtkRadioButton *radio_group_member); - -#ifdef MAEMO_GTK -GtkWidget * -hildon_gtk_tree_view_new (HildonUIMode mode); - -GtkWidget * -hildon_gtk_tree_view_new_with_model (HildonUIMode mode, - GtkTreeModel *model); - -void -hildon_gtk_tree_view_set_ui_mode (GtkTreeView *treeview, - HildonUIMode mode); - -GtkWidget * -hildon_gtk_icon_view_new (HildonUIMode mode); - -GtkWidget * -hildon_gtk_icon_view_new_with_model (HildonUIMode mode, - GtkTreeModel *model); - -void -hildon_gtk_icon_view_set_ui_mode (GtkIconView *iconview, - HildonUIMode mode); -#endif /* MAEMO_GTK */ - -void -hildon_gtk_window_set_progress_indicator (GtkWindow *window, - guint state); - -void -hildon_gtk_window_set_do_not_disturb (GtkWindow *window, - gboolean dndflag); - -typedef enum { - HILDON_PORTRAIT_MODE_REQUEST = 1 << 0, - HILDON_PORTRAIT_MODE_SUPPORT = 1 << 1 -} HildonPortraitFlags; - -void -hildon_gtk_window_set_portrait_flags (GtkWindow *window, - HildonPortraitFlags portrait_flags); - -GtkWidget* -hildon_gtk_hscale_new (void); - -GtkWidget* -hildon_gtk_vscale_new (void); - -G_END_DECLS - -#endif /* __HILDON_GTK_H__ */ diff --git a/src/hildon-helper.c b/src/hildon-helper.c deleted file mode 100644 index cd3026d..0000000 --- a/src/hildon-helper.c +++ /dev/null @@ -1,508 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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-helper - * @short_description: A collection of useful utilities and functions. - * - * Hildon provides some helper functions that can be used for commonly - * performed tasks and functionality blocks. This includes operations - * on widget styles and probing functions for touch events. - */ - -#undef HILDON_DISABLE_DEPRECATED - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "hildon-helper.h" -#include "hildon-banner.h" - -#define HILDON_FINGER_PRESSURE_THRESHOLD 0.4 - -#define HILDON_FINGER_BUTTON 8 - -#define HILDON_FINGER_ALT_BUTTON 1 - -#define HILDON_FINGER_ALT_MASK GDK_MOD4_MASK - -#define HILDON_FINGER_SIMULATE_BUTTON 2 - -struct _HildonLogicalElement -{ - gboolean is_color; /* If FALSE, it's a logical font def */ - GtkRcFlags rc_flags; - GtkStateType state; - gchar *logical_color_name; - gchar *logical_font_name; -} typedef HildonLogicalElement; - -static void -hildon_logical_element_list_free (GSList *list) -{ - GSList *iterator = list; - - while (iterator) { - HildonLogicalElement *element = (HildonLogicalElement *) iterator->data; - - g_free (element->logical_color_name); - g_free (element->logical_font_name); - g_slice_free (HildonLogicalElement, element); - - iterator = iterator->next; - } - - /* Free the list itself */ - g_slist_free (list); -} - -static GQuark -hildon_helper_logical_data_quark (void) -{ - static GQuark quark = 0; - - if (G_UNLIKELY (quark == 0)) - quark = g_quark_from_static_string ("hildon-logical-data"); - - return quark; -} - -static HildonLogicalElement* -attach_blank_element (GtkWidget *widget, - GSList **style_list) -{ - gboolean first = (*style_list == NULL) ? TRUE : FALSE; - - HildonLogicalElement *element = g_slice_new (HildonLogicalElement); - - element->is_color = FALSE; - element->rc_flags = 0; - element->state = 0; - element->logical_color_name = NULL; - element->logical_font_name = NULL; - - *style_list = g_slist_append (*style_list, element); - - if (first) - g_object_set_qdata_full (G_OBJECT (widget), hildon_helper_logical_data_quark (), *style_list, (GDestroyNotify) hildon_logical_element_list_free); - - return element; -} - -static GSList* -attach_new_font_element (GtkWidget *widget, - const gchar *font_name) -{ - GSList *style_list = g_object_get_qdata (G_OBJECT (widget), hildon_helper_logical_data_quark ()); - HildonLogicalElement *element = NULL; - - /* Try to find an element that already sets a font */ - GSList *iterator = style_list; - while (iterator) { - element = (HildonLogicalElement *) iterator->data; - - if (element->is_color == FALSE) { - /* Reusing ... */ - g_free (element->logical_font_name); - element->logical_font_name = g_strdup (font_name); - return style_list; - } - - iterator = iterator->next; - } - - /* It was not found so we need to create a new one and attach it */ - element = attach_blank_element (widget, &style_list); - element->is_color = FALSE; - element->logical_font_name = g_strdup (font_name); - return style_list; -} - -static GSList* -attach_new_color_element (GtkWidget *widget, - GtkRcFlags flags, - GtkStateType state, - const gchar *color_name) -{ - GSList *style_list = g_object_get_qdata (G_OBJECT (widget), hildon_helper_logical_data_quark ()); - HildonLogicalElement *element = NULL; - - /* Try to find an element that has same flags and state */ - GSList *iterator = style_list; - while (iterator) { - element = (HildonLogicalElement *) iterator->data; - - if (element->rc_flags == flags && - element->state == state && - element->is_color == TRUE) { - /* Reusing ... */ - g_free (element->logical_color_name); - element->logical_color_name = g_strdup (color_name); - return style_list; - } - - iterator = iterator->next; - } - - /* It was not found so we need to create a new one and attach it */ - element = attach_blank_element (widget, &style_list); - element->is_color = TRUE; - element->state = state; - element->rc_flags = flags; - element->logical_color_name = g_strdup (color_name); - return style_list; -} - -static void -hildon_change_style_recursive_from_list (GtkWidget *widget, - GtkStyle *prev_style, - GSList *list) -{ - g_assert (GTK_IS_WIDGET (widget)); - - /* Change the style for child widgets */ - if (GTK_IS_CONTAINER (widget)) { - GList *iterator, *children; - children = gtk_container_get_children (GTK_CONTAINER (widget)); - for (iterator = children; iterator != NULL; iterator = g_list_next (iterator)) - hildon_change_style_recursive_from_list (GTK_WIDGET (iterator->data), prev_style, list); - g_list_free (children); - } - - /* 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_list, - NULL); - - /* We iterate over all list elements and apply each style - * specification. */ - - GSList *iterator = list; - while (iterator) { - - HildonLogicalElement *element = (HildonLogicalElement *) iterator->data; - - if (element->is_color == TRUE) { - - /* Changing logical color */ - GdkColor color; - gtk_widget_ensure_style (widget); - if (gtk_style_lookup_color (widget->style, element->logical_color_name, &color) == TRUE) { - - switch (element->rc_flags) - { - case GTK_RC_FG: - gtk_widget_modify_fg (widget, element->state, &color); - break; - - case GTK_RC_BG: - gtk_widget_modify_bg (widget, element->state, &color); - break; - - case GTK_RC_TEXT: - gtk_widget_modify_text (widget, element->state, &color); - break; - - case GTK_RC_BASE: - gtk_widget_modify_base (widget, element->state, &color); - break; - } - } - } else { - - /* Changing logical font */ - GtkStyle *font_style = gtk_rc_get_style_by_paths (gtk_settings_get_default (), element->logical_font_name, NULL, G_TYPE_NONE); - if (font_style != NULL) { - PangoFontDescription *font_desc = font_style->font_desc; - - if (font_desc != NULL) - gtk_widget_modify_font (widget, font_desc); - } - } - - iterator = iterator->next; - } - - /* 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_list, - NULL); -} - -/** - * hildon_helper_event_button_is_finger: - * @event: A #GtkEventButton to check - * - * Checks if the given button event is a finger event. - * - * Return value: TRUE if the event is a finger event. - **/ -gboolean -hildon_helper_event_button_is_finger (GdkEventButton *event) -{ - gdouble pressure; - - if (gdk_event_get_axis ((GdkEvent*) event, GDK_AXIS_PRESSURE, &pressure) && - pressure > HILDON_FINGER_PRESSURE_THRESHOLD) - return TRUE; - - if (event->button == HILDON_FINGER_BUTTON) - return TRUE; - - if (event->button == HILDON_FINGER_ALT_BUTTON && - event->state & HILDON_FINGER_ALT_MASK) - return TRUE; - - if (event->button == HILDON_FINGER_SIMULATE_BUTTON) - return TRUE; - - return FALSE; -} - -/** - * hildon_helper_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. - * - * 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. - * When calling multiple times 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_helper_set_logical_font (GtkWidget *widget, - const gchar *logicalfontname) -{ - gulong signum = 0; - GSList *list; - - g_return_val_if_fail (GTK_IS_WIDGET (widget), 0); - g_return_val_if_fail (logicalfontname != NULL, 0); - - list = attach_new_font_element (widget, 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, 0, NULL, - G_CALLBACK (hildon_change_style_recursive_from_list), NULL); - - /* Change the font now */ - hildon_change_style_recursive_from_list (widget, NULL, list); - - /* 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_list), - list, NULL, 0); - - return signum; -} - -static GQuark -hildon_helper_insensitive_message_quark (void) -{ - static GQuark quark = 0; - - if (G_UNLIKELY (quark == 0)) - quark = g_quark_from_static_string ("hildon-insensitive-message"); - - return quark; -} - -static void -show_insensitive_message (GtkWidget *widget, - gpointer user_data) -{ - gchar *message = NULL; - - g_assert (GTK_IS_WIDGET (widget)); - - message = (gchar*) g_object_get_qdata (G_OBJECT (widget), - hildon_helper_insensitive_message_quark ()); - - if (message) - hildon_banner_show_information (widget, NULL, message); -} - - -/** - * hildon_helper_set_insensitive_message: - * @widget: A #GtkWidget to assign a banner to - * @message: A message to display to the user - * - * This function assigns an insensitive message to a @widget. When the @widget is - * in an insensitive state and the user activates it, the @message will be displayed - * using a standard #HildonBanner. - * - * Deprecated: As of hildon 2.2, it is strongly discouraged to use insensitive messages. - **/ -void -hildon_helper_set_insensitive_message (GtkWidget *widget, - const gchar *message) -{ - g_return_if_fail (GTK_IS_WIDGET (widget)); - - /* Clean up any previous instance of the insensitive message */ - g_signal_handlers_disconnect_matched (G_OBJECT (widget), G_SIGNAL_MATCH_FUNC, - 0, 0, NULL, - G_CALLBACK (show_insensitive_message), NULL); - - /* We need to dup the string because the pointer might not be valid when the - insensitive-press signal callback is executed */ - g_object_set_qdata_full (G_OBJECT (widget), hildon_helper_insensitive_message_quark (), - (gpointer)g_strdup (message), - g_free); - - if (message != NULL) { - g_signal_connect (G_OBJECT (widget), "insensitive-press", - G_CALLBACK (show_insensitive_message), NULL); - } -} - -/** - * hildon_helper_set_insensitive_messagef: - * @widget: A #GtkWidget to assign a banner to - * @format: a printf-like format string - * @Varargs: arguments for the format string - * - * A version of hildon_helper_set_insensitive_message with string formatting. - * - * Deprecated: As of hildon 2.2, it is strongly discouraged to use insensitive messages. - **/ -void -hildon_helper_set_insensitive_messagef (GtkWidget *widget, - const gchar *format, - ...) -{ - g_return_if_fail (GTK_IS_WIDGET (widget)); - - gchar *message; - va_list args; - - va_start (args, format); - message = g_strdup_vprintf (format, args); - va_end (args); - - hildon_helper_set_insensitive_message (widget, message); - - g_free (message); -} - -/** - * hildon_helper_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. - * When calling multiple times 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_helper_set_logical_color (GtkWidget *widget, - GtkRcFlags rcflags, - GtkStateType state, - const gchar *logicalcolorname) -{ - gulong signum = 0; - GSList *list = NULL; - - g_return_val_if_fail (GTK_IS_WIDGET (widget), 0); - g_return_val_if_fail (logicalcolorname != NULL, 0); - - list = attach_new_color_element (widget, rcflags, state, logicalcolorname); - - /* Disconnects the previously connected signals. */ - g_signal_handlers_disconnect_matched (G_OBJECT (widget), G_SIGNAL_MATCH_FUNC, - 0, 0, NULL, - G_CALLBACK (hildon_change_style_recursive_from_list), NULL); - - /* Change the colors now */ - hildon_change_style_recursive_from_list (widget, NULL, list); - - /* 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_list), - list, NULL, 0); - - return signum; -} - - -/** - * hildon_helper_set_thumb_scrollbar: - * @win: A #GtkScrolledWindow to use as target - * @thumb: TRUE to enable the thumb scrollbar, FALSE to disable - * - * This function enables a thumb scrollbar on a given scrolled window. It'll convert the - * existing normal scrollbar into a larger, finger-usable scrollbar that works without a stylus. - * As fingerable list rows are fairly high, consider using the whole available vertical space - * of your application for the content in order to have as many rows as possible - * visible on the screen at once. - * - * Finger-Sized scrollbar should always be used together with finger-sized content. - **/ -void -hildon_helper_set_thumb_scrollbar (GtkScrolledWindow *win, - gboolean thumb) -{ - g_return_if_fail (GTK_IS_SCROLLED_WINDOW (win)); - - if (win->vscrollbar) - gtk_widget_set_name (win->vscrollbar, (thumb) ? "hildon-thumb-scrollbar" : NULL); -} - - - - diff --git a/src/hildon-helper.h b/src/hildon-helper.h deleted file mode 100644 index 879d55f..0000000 --- a/src/hildon-helper.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_HELPER_H__ -#define __HILDON_HELPER_H__ - -#include -#include - -#include "hildon-defines.h" - -G_BEGIN_DECLS - -gulong -hildon_helper_set_logical_font (GtkWidget *widget, - const gchar *logicalfontname); - -gulong -hildon_helper_set_logical_color (GtkWidget *widget, - GtkRcFlags rcflags, - GtkStateType state, - const gchar *logicalcolorname); -gboolean -hildon_helper_event_button_is_finger (GdkEventButton *event); - -#ifndef HILDON_DISABLE_DEPRECATED -void -hildon_helper_set_insensitive_message (GtkWidget *widget, - const gchar *message); - -void -hildon_helper_set_insensitive_messagef (GtkWidget *widget, - const gchar *format, - ...); -#endif - -void -hildon_helper_set_thumb_scrollbar (GtkScrolledWindow *win, - gboolean thumb); - -G_END_DECLS - -#endif /* __HILDON_HELPER_H__ */ - diff --git a/src/hildon-hvolumebar.c b/src/hildon-hvolumebar.c deleted file mode 100644 index 3e1ff0e..0000000 --- a/src/hildon-hvolumebar.c +++ /dev/null @@ -1,377 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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. - * - * - * - * #HildonHVolumeBar has been deprecated since Hildon 2.2 - * See Migrating Volume Bars - * section to know how to migrate this deprecated widget. - * - * - * - * - * - * GtkWidget *volbar = hildon_hvolumebar_new (); - * g_signal_connect (G_OBJECT(volbar), "mute_toggled", G_CALLBACK(mute_toggle), NULL); - * g_signal_connect (G_OBJECT(volbar), "level_changed", G_CALLBACK(level_change), NULL); - * - * - * - */ - -#undef HILDON_DISABLE_DEPRECATED - -#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 60 - -#define DEFAULT_TBUTTON_HEIGHT 60 - -/* Volume bar */ -#define MINIMUM_BAR_WIDTH 147 - -#define DEFAULT_BAR_HEIGHT 60 - -#define DEFAULT_ENDING_SIZE 20 - -/* Gap to leave for mute button */ -#define VERTICAL_MUTE_GAP 0 - -#define HORIZONTAL_MUTE_GAP 0 - -/* 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); - -/** - * hildon_hvolumebar_get_type: - * - * Returns GType for HildonHVolumebar. - * - * Returns: HildonHVolumebar type - */ -GType G_GNUC_CONST -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_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; - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget); - g_assert (priv); - - 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; - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(HILDON_VOLUMEBAR(widget)); - g_assert (priv); - - 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 */ - /* FIXME Not sure if this is even needed here */ - (*GTK_WIDGET_CLASS(parent_class)->expose_event) (widget, event); - } - - return FALSE; -} - -static void -hildon_hvolumebar_size_request (GtkWidget * widget, - GtkRequisition * requisition) -{ - HildonVolumebarPrivate *priv; - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(HILDON_VOLUMEBAR(widget)); - g_assert (priv); - - /* 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; - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget); - g_assert (priv); - - 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 deleted file mode 100644 index cd19e67..0000000 --- a/src/hildon-hvolumebar.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#ifndef __HILDON_HVOLUMEBAR_H__ -#define __HILDON_HVOLUMEBAR_H__ - -#include "hildon-volumebar.h" - -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)) - -#define HILDON_HVOLUMEBAR_GET_CLASS(obj) \ - ((HildonHVolumebarClass *) G_OBJECT_GET_CLASS(obj)) - -typedef struct _HildonHVolumebar HildonHVolumebar; - -typedef struct _HildonHVolumebarClass HildonHVolumebarClass; - -struct _HildonHVolumebar -{ - HildonVolumebar parent; -}; - -struct _HildonHVolumebarClass -{ - HildonVolumebarClass parent_class; -}; - -GType G_GNUC_CONST -hildon_hvolumebar_get_type (void); - -GtkWidget* -hildon_hvolumebar_new (void); - -G_END_DECLS - -#endif /* __HILDON_HVOLUMEBAR_H__ */ - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-login-dialog-private.h b/src/hildon-login-dialog-private.h deleted file mode 100644 index 76e559c..0000000 --- a/src/hildon-login-dialog-private.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_PRIVATE_H__ -#define __HILDON_NAME_PASSWORD_DIALOG_PRIVATE_H__ - -G_BEGIN_DECLS - -#define HILDON_LOGIN_DIALOG_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ - HILDON_TYPE_LOGIN_DIALOG,\ - HildonLoginDialogPrivate)) - -typedef struct _HildonLoginDialogPrivate HildonLoginDialogPrivate; - -struct _HildonLoginDialogPrivate -{ - GtkLabel *message_label; - GtkWidget *username_entry; - GtkWidget *password_entry; -}; - -G_END_DECLS - -#endif /* __HILDON_NAME_PASSWORD_DIALOG_PRIVATE_H__ */ diff --git a/src/hildon-login-dialog.c b/src/hildon-login-dialog.c deleted file mode 100644 index 0a76f9d..0000000 --- a/src/hildon-login-dialog.c +++ /dev/null @@ -1,430 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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-login-dialog - * @short_description: A widget which allows a user to enter an username - * and a password. - * @see_also: #HildonGetPasswordDialog, #HildonSetPasswordDialog - * - * #HildonLoginDialog is used to enter a username and password - * when accessing a password protected area. The widget performs no - * input checking and is used only for retrieving the username and a - * password. - */ - -#undef HILDON_DISABLE_DEPRECATED - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include "hildon-login-dialog.h" -#include "hildon-caption.h" -#include "hildon-login-dialog-private.h" -#include "hildon-entry.h" - -enum -{ - PROP_0, - PROP_MESSAGE, - PROP_USERNAME, - PROP_PASSWORD -}; - -static void -hildon_login_dialog_class_init (HildonLoginDialogClass *class); - -static void -hildon_login_dialog_init (HildonLoginDialog *widget); - -static void -hildon_login_dialog_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); - -static void -hildon_login_dialog_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); - -#define HILDON_LOGIN_DIALOG_TITLE "frw_ti_get_user_name_and_pwd" - -#define HILDON_LOGIN_DIALOG_USERNAME "frw_ti_get_user_name_and_pwd_enter_user_name" - -#define HILDON_LOGIN_DIALOG_PASSWORD "frw_ti_get_user_name_and_pwd_enter_pwd" - -#define HILDON_LOGIN_DIALOG_OK "wdgt_bd_done" - -#define _(String) dgettext("hildon-libs", String) - -static GtkDialogClass* parent_class; - -/** - * hildon_login_dialog_get_type: - * - * Returns GType for HildonLoginDialog. - * - * Returns: HildonLoginDialog type - */ -GType G_GNUC_CONST -hildon_login_dialog_get_type (void) -{ - static GType dialog_type = 0; - - if (! dialog_type) { - static const GTypeInfo dialog_info = { - sizeof (HildonLoginDialogClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) hildon_login_dialog_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(HildonLoginDialog), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_login_dialog_init - }; - dialog_type = g_type_register_static (GTK_TYPE_DIALOG, - "HildonLoginDialog", - &dialog_info, 0); - } - - return dialog_type; -} - -static void -hildon_login_dialog_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - HildonLoginDialog *dialog = NULL; - HildonLoginDialogPrivate *priv = NULL; - - dialog = HILDON_LOGIN_DIALOG (object); - priv = HILDON_LOGIN_DIALOG_GET_PRIVATE(dialog); - g_assert (priv); - - switch (prop_id) { - - case PROP_MESSAGE: - /* Set the password message text */ - hildon_login_dialog_set_message (dialog, g_value_get_string (value)); - break; - - case PROP_USERNAME: - /* Set the current username displayed in the dialog */ - hildon_entry_set_text (HILDON_ENTRY (priv->username_entry), g_value_get_string (value)); - break; - - case PROP_PASSWORD: - /* Set the currently entered password */ - hildon_entry_set_text (HILDON_ENTRY (priv->password_entry), g_value_get_string (value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -hildon_login_dialog_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - HildonLoginDialog *dialog = NULL; - HildonLoginDialogPrivate *priv = NULL; - - dialog = HILDON_LOGIN_DIALOG (object); - priv = HILDON_LOGIN_DIALOG_GET_PRIVATE (dialog); - g_assert (priv); - - switch (prop_id) { - - case PROP_MESSAGE: - g_value_set_string (value, gtk_label_get_text (priv->message_label)); - break; - - case PROP_USERNAME: - g_value_set_string (value, hildon_login_dialog_get_username (dialog)); - break; - - case PROP_PASSWORD: - g_value_set_string (value, hildon_login_dialog_get_password (dialog)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -hildon_login_dialog_class_init (HildonLoginDialogClass *class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (class); - - parent_class = g_type_class_peek_parent (class); - - /* Override virtual functions */ - object_class->set_property = hildon_login_dialog_set_property; - object_class->get_property = hildon_login_dialog_get_property; - - /* Install new properties */ - - /** - * HildonLoginDialog:message: - * - * Optional message displayed to the user. - */ - g_object_class_install_property (object_class, - PROP_MESSAGE, - g_param_spec_string ("message", - "Message", - "Message displayed by the dialog", - NULL, - G_PARAM_READWRITE)); - - /** - * HildonLoginDialog:username: - * - * Contents of the username field. - */ - g_object_class_install_property (object_class, - PROP_USERNAME, - g_param_spec_string ("username", - "Username", - "Username field", - "DEFAULT", - G_PARAM_READWRITE)); - - /** - * HildonLoginDialog:password: - * - * Contents of the password field. - */ - g_object_class_install_property (object_class, - PROP_PASSWORD, - g_param_spec_string ("password", - "Password", - "Password field", - "DEFAULT", - G_PARAM_READWRITE)); - - /* Install private data structure */ - g_type_class_add_private (class, sizeof (HildonLoginDialogPrivate)); -} - -static void -hildon_login_dialog_init (HildonLoginDialog *dialog) -{ - /* Access private structure */ - HildonLoginDialogPrivate *priv = HILDON_LOGIN_DIALOG_GET_PRIVATE (dialog); - g_assert (priv); - - /* 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_LOGIN_DIALOG_TITLE)); - - /* Optional message label */ - /* FIXME Set the warpping for the message label */ - priv->message_label = GTK_LABEL (gtk_label_new (NULL)); - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), - GTK_WIDGET (priv->message_label), FALSE, FALSE, 0); - - /* Create buttons */ - gtk_dialog_add_button (GTK_DIALOG (dialog), _(HILDON_LOGIN_DIALOG_OK), GTK_RESPONSE_OK); - - /* Setup username entry */ - priv->username_entry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH); - -#ifdef MAEMO_GTK - g_object_set (priv->username_entry, "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL); -#endif - - caption = HILDON_CAPTION (hildon_caption_new - (group, - _(HILDON_LOGIN_DIALOG_USERNAME), - GTK_WIDGET (priv->username_entry), 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->password_entry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH); - -#ifdef MAEMO_GTK - g_object_set (priv->password_entry, "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL); -#endif - - gtk_entry_set_visibility (GTK_ENTRY (priv->password_entry), FALSE); - - caption = HILDON_CAPTION (hildon_caption_new (group, - _(HILDON_LOGIN_DIALOG_PASSWORD), - GTK_WIDGET (priv->password_entry), - 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); -} - -/** - * hildon_login_dialog_new: - * @parent: the parent window of the dialog - * - * Creates a new #HildonLoginDialog widget with Ok and Close - * buttons. - * - * Returns: the newly created #HildonLoginDialog - */ -GtkWidget* -hildon_login_dialog_new (GtkWindow *parent) -{ - GtkWidget *self = g_object_new (HILDON_TYPE_LOGIN_DIALOG, NULL); - - if (parent) - gtk_window_set_transient_for (GTK_WINDOW (self), parent); - - return self; -} - -/** - * hildon_login_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_login_dialog_new but with a - * default username and password. - * - * Returns: the newly created #HildonLoginDialog - */ -GtkWidget* -hildon_login_dialog_new_with_default (GtkWindow *parent, - const gchar *name, - const gchar *password) -{ - GtkWidget *self = hildon_login_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_login_dialog_get_username: - * @dialog: the dialog - * - * Gets the text that's in the username entry. - * - * Returns: a pointer to the name string. You should not modify it. - */ -const gchar* -hildon_login_dialog_get_username (HildonLoginDialog *dialog) -{ - HildonLoginDialogPrivate *priv; - - g_return_val_if_fail (HILDON_IS_LOGIN_DIALOG (dialog), NULL); - - priv = HILDON_LOGIN_DIALOG_GET_PRIVATE (dialog); - g_assert (priv); - - return hildon_entry_get_text (HILDON_ENTRY (priv->username_entry)); -} - -/** - * hildon_login_dialog_get_password: - * @dialog: the dialog - * - * Gets the text that's in the password entry. - * - * Returns: a pointer to the password string. You should not modify it. - */ -const gchar* -hildon_login_dialog_get_password (HildonLoginDialog *dialog) -{ - HildonLoginDialogPrivate *priv; - - g_return_val_if_fail (HILDON_IS_LOGIN_DIALOG (dialog), NULL); - - priv = HILDON_LOGIN_DIALOG_GET_PRIVATE (dialog); - g_assert (priv); - - return hildon_entry_get_text (HILDON_ENTRY (priv->password_entry)); -} - -/** - * hildon_login_dialog_set_message: - * @dialog: the dialog - * @msg: the message or some other descriptive text to be set - * - * Sets the optional descriptive text that is displayed on the top - * of the dialog. - */ -void -hildon_login_dialog_set_message (HildonLoginDialog *dialog, - const gchar *msg) -{ - HildonLoginDialogPrivate *priv; - - g_return_if_fail (HILDON_IS_LOGIN_DIALOG (dialog)); - - priv = HILDON_LOGIN_DIALOG_GET_PRIVATE (dialog); - g_assert (priv); - - gtk_label_set_text (priv->message_label, msg); -} - - diff --git a/src/hildon-login-dialog.h b/src/hildon-login-dialog.h deleted file mode 100644 index 93b78e6..0000000 --- a/src/hildon-login-dialog.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#ifndef __HILDON_NAME_PASSWORD_DIALOG_H__ -#define __HILDON_NAME_PASSWORD_DIALOG_H__ - -#include - -G_BEGIN_DECLS - -#define HILDON_TYPE_LOGIN_DIALOG \ - (hildon_login_dialog_get_type ()) - -#define HILDON_LOGIN_DIALOG(obj) \ - (GTK_CHECK_CAST (obj, HILDON_TYPE_LOGIN_DIALOG, \ - HildonLoginDialog)) - -#define HILDON_LOGIN_DIALOG_CLASS(klass) \ - (GTK_CHECK_CLASS_CAST ((klass), HILDON_TYPE_LOGIN_DIALOG, \ - HildonLoginDialogClass)) - -#define HILDON_IS_LOGIN_DIALOG(obj) \ - (GTK_CHECK_TYPE (obj, HILDON_TYPE_LOGIN_DIALOG)) - -#define HILDON_IS_LOGIN_DIALOG_CLASS(klass) \ - (GTK_CHECK_CLASS_TYPE ((klass), \ - HILDON_TYPE_LOGIN_DIALOG)) - -typedef struct _HildonLoginDialog HildonLoginDialog; - -typedef struct _HildonLoginDialogClass HildonLoginDialogClass; - -struct _HildonLoginDialog -{ - GtkDialog parent; -}; - -struct _HildonLoginDialogClass -{ - GtkDialogClass parent_class; -}; - -GType G_GNUC_CONST -hildon_login_dialog_get_type (void); - -GtkWidget* -hildon_login_dialog_new (GtkWindow *parent); - -GtkWidget* -hildon_login_dialog_new_with_default (GtkWindow *parent, - const gchar *name, - const gchar *password); - -const gchar* -hildon_login_dialog_get_username (HildonLoginDialog *dialog); - -const gchar* -hildon_login_dialog_get_password (HildonLoginDialog *dialog); - -void -hildon_login_dialog_set_message (HildonLoginDialog *dialog, - const gchar *msg); - -G_END_DECLS - -#endif /* __HILDON_LOGIN_DIALOG_H__ */ - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-main.c b/src/hildon-main.c deleted file mode 100644 index 4713af9..0000000 --- a/src/hildon-main.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * This file is part of the hildon library - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * 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, or (at your option) any later version. - * - * 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-main - * @Short_Description: Library initialization. - * - * Before using Hildon, you need to initialize it; initialization connects - * to the window system display, and parses some standard command line - * arguments. See also gtk_init () to know more details on this topic. - * - * Hildon should be initialized by using hildon_gtk_init (). Notice this function - * also initialize gtk by calling gtk_init (). In case you need a customized - * initialization of GTK+ library you could use hildon_init () after the - * customized GTK+ initialization. - * - * - * Typical <function>main</function> function for a Hildon application - * - * int - * main (int argc, char **argv) - * { - * /* Initialize i18n support */ - * gtk_set_locale (); - * - * /* Initialize the widget set */ - * hildon_gtk_init (&argc, &argv); - * - * /* Create the main window */ - * mainwin = hildon_stackable_window_new(); - * - * /* Set up our GUI elements */ - * ... - * - * /* Show the application window */ - * gtk_widget_show_all (mainwin); - * - * /* Enter the main event loop, and wait for user interaction */ - * gtk_main (); - * - * /* The user lost interest */ - * return 0; - *} - * - * - */ - - -#include -#include "hildon-main.h" - -/** - * hildon_init: - * - * Initializes the hildon library. Call this function after calling gtk_init() - * and before using any hildon or GTK+ functions in your program. - * - * Since: 2.2 - **/ -void -hildon_init (void) -{ - static gboolean initialized = FALSE; - - if (initialized) { - g_critical ("Tried to initialized Hildon more than once."); - return; - } else { - initialized = TRUE; - } - - /* Register icon sizes */ - gtk_icon_size_register ("hildon-xsmall", 16, 16); - gtk_icon_size_register ("hildon-small", 24, 24); - gtk_icon_size_register ("hildon-stylus", 32, 32); - gtk_icon_size_register ("hildon-finger", 48, 48); - gtk_icon_size_register ("hildon-thumb", 64, 64); - gtk_icon_size_register ("hildon-large", 96, 96); - gtk_icon_size_register ("hildon-xlarge", 128, 128); -} - -/** - * hildon_gtk_init: - * @argc: Address of the argc - * parameter of your main() function. Changed if any arguments were - * handled. - * @argv: Address of the argv - * parameter of main(). Any parameters understood by gtk_init() - * are stripped before return. - * - * Convenience function to initialize the GTK+ and hildon - * libraries. Use this function to replace a call to gtk_init() and also - * initialize the hildon library. See hildon_init() and gtk_init() for details. - * - * Since: 2.2 - **/ -void -hildon_gtk_init (int *argc, char ***argv) -{ - gtk_init (argc, argv); - hildon_init (); -} diff --git a/src/hildon-main.h b/src/hildon-main.h deleted file mode 100644 index 88b1694..0000000 --- a/src/hildon-main.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * This file is part of the hildon library - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * 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, or (at your option) any later version. - * - * 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 - * - */ - -G_BEGIN_DECLS - -void hildon_init (void); -void hildon_gtk_init (int *argc, char ***argv); - -G_END_DECLS diff --git a/src/hildon-marshalers.list b/src/hildon-marshalers.list deleted file mode 100644 index af8dfb1..0000000 --- a/src/hildon-marshalers.list +++ /dev/null @@ -1,32 +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 -BOOLEAN:POINTER -BOOLEAN:VOID -VOID:OBJECT -VOID:VOID -VOID:INT,DOUBLE,DOUBLE diff --git a/src/hildon-note-private.h b/src/hildon-note-private.h deleted file mode 100644 index f5ae60b..0000000 --- a/src/hildon-note-private.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_PRIVATE_H__ -#define __HILDON_NOTE_PRIVATE_H__ - -G_BEGIN_DECLS - -typedef struct _HildonNotePrivate HildonNotePrivate; - -#define HILDON_NOTE_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_NOTE, HildonNotePrivate)); - -struct _HildonNotePrivate -{ - GtkWidget *okButton; - GtkWidget *cancelButton; - GtkWidget *label; - GtkWidget *box; - GtkWidget *event_box; - GdkWindow *transfer_window; - - HildonNoteType note_n; - GtkWidget *progressbar; - gulong sound_signal_handler; - gint button_width; - - gchar *original_description; - - /* These strings stored for backwards compatibility */ - gchar *icon; - gchar *stock_icon; -}; - -G_END_DECLS - -#endif /* __HILDON_NOTE_PRIVATE_H__ */ diff --git a/src/hildon-note.c b/src/hildon-note.c deleted file mode 100644 index 814e456..0000000 --- a/src/hildon-note.c +++ /dev/null @@ -1,1053 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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. - * - * #HildonNote is a convenient way to prompt users for a small amount of - * input. A simple note contains an information text and, in case of - * confirmation notes, it shows buttons to confirm or cancel. It also can - * include a progress bar. - * - * This widget provides convenient functions to create either - * information notes, confirmation notes or cancel notes, which are - * useful to show the progress of a requested task allowing the user - * to cancel it. - * - * To create information notes you can use - * hildon_note_new_information(). hildon_note_new_confirmation() - * creates a note with a text and two buttons to confirm or - * cancel. Note that it is possible to create a confirmation note with - * customized buttons by using - * hildon_note_new_confirmation_add_buttons(). - * - * To create a note with a text, a progress bar and cancel button, - * hildon_note_new_cancel_with_progress_bar() can be used. - * - * - * HildonNote example - * - * - * gboolean - * show_confirmation_note (GtkWindow *parent) - * { - * gint retcode; - * GtkWidget *note; - * note = hildon_note_new_confirmation (parent, "Confirmation message..."); - * - * retcode = gtk_dialog_run (GTK_DIALOG (note)); - * gtk_widget_destroy (note); - * - * if (retcode == GTK_RESPONSE_OK) { - * g_debug ("User pressed 'OK' button'"); - * return TRUE; - * } else { - * g_debug ("User pressed 'Cancel' button"); - * return FALSE; - * } - * } - * - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include - -#undef HILDON_DISABLE_DEPRECATED - -#include "hildon-note.h" -#include "hildon-defines.h" -#include "hildon-sound.h" -#include "hildon-banner.h" -#include "hildon-enum-types.h" -#include "hildon-note-private.h" - -#define HILDON_INFORMATION_NOTE_MIN_HEIGHT 140 - -#define HILDON_INFORMATION_NOTE_MARGIN 100 - -#define CONFIRMATION_SOUND_PATH \ - "/usr/share/sounds/ui-confirmation_note.wav" - -#define INFORMATION_SOUND_PATH \ - "/usr/share/sounds/ui-information_note.wav" - -#define _(String) dgettext("hildon-libs", String) - -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_rename (HildonNote *note); - -static void -hildon_note_finalize (GObject *obj_self); - -static void -hildon_note_realize (GtkWidget *widget); - -static void -hildon_note_unrealize (GtkWidget *widget); - -static void -label_size_request (GtkWidget *label, - GtkRequisition *req, - GtkWidget *note); - -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); -static void -unpack_widget (GtkWidget *widget); - -enum -{ - PROP_0, - PROP_HILDON_NOTE_TYPE, - PROP_HILDON_NOTE_DESCRIPTION, - PROP_HILDON_NOTE_ICON, - PROP_HILDON_NOTE_PROGRESSBAR, - PROP_HILDON_NOTE_STOCK_ICON -}; - -static GtkDialogClass* parent_class; - -static gboolean -event_box_press_event (GtkEventBox *event_box, - GdkEventButton *event, - GtkDialog *note) -{ - HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (note); - - if (priv->note_n == HILDON_NOTE_TYPE_INFORMATION || - priv->note_n == HILDON_NOTE_TYPE_INFORMATION_THEME) { - gtk_dialog_response (note, GTK_RESPONSE_DELETE_EVENT); - return TRUE; - } else { - return FALSE; - } -} - -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); - g_assert (priv); - - switch (prop_id) { - - case PROP_HILDON_NOTE_TYPE: - priv->note_n = g_value_get_enum (value); - hildon_note_rename (note); - hildon_note_rebuild (note); - break; - - case PROP_HILDON_NOTE_DESCRIPTION: - if (priv->original_description) - g_free (priv->original_description); - priv->original_description = g_value_dup_string (value); - - gtk_label_set_text (GTK_LABEL (priv->label), priv->original_description); - /* FIXME Is the "original_description" used anywhere? */ - - break; - - case PROP_HILDON_NOTE_ICON: - if (priv->icon) { - g_free (priv->icon); - } - priv->icon = g_value_dup_string (value); - break; - - case PROP_HILDON_NOTE_STOCK_ICON: - if (priv->stock_icon) { - g_free (priv->stock_icon); - } - priv->stock_icon = g_value_dup_string (value); - 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_value_set_string (value, priv->icon); - break; - - case PROP_HILDON_NOTE_STOCK_ICON: - g_value_set_string (value, priv->stock_icon); - 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; - } -} - -/** - * hildon_note_get_type: - * - * Returns GType for HildonNote. - * - * Returns: HildonNote type - */ -GType G_GNUC_CONST -hildon_note_get_type (void) -{ - 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; - widget_class->unrealize = hildon_note_unrealize; - - 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_TYPE_CONFIRMATION, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - /** - * HildonNote:description: - * - * Description for the 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 the note. - * - * Deprecated: Since 2.2 - */ - 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 name for the note. - * - * Deprecated: Since 2.2 - */ - 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 the note (if any). - */ - 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); - g_assert (priv); - - priv->label = gtk_label_new (NULL); - gtk_label_set_line_wrap (GTK_LABEL (priv->label), TRUE); - gtk_label_set_justify (GTK_LABEL (priv->label), GTK_JUSTIFY_LEFT); - - priv->event_box = gtk_event_box_new (); - priv->icon = NULL; - priv->stock_icon = NULL; - - gtk_event_box_set_visible_window (GTK_EVENT_BOX (priv->event_box), FALSE); - gtk_event_box_set_above_child (GTK_EVENT_BOX (priv->event_box), TRUE); - g_signal_connect (priv->event_box, "button-press-event", - G_CALLBACK (event_box_press_event), dialog); - - /* Acquire real references to our internal children, since - they are not nessecarily packed into container in each - layout */ - g_object_ref_sink (priv->event_box); - g_object_ref_sink (priv->label); - - gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE); - gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); - - /* We use special hint to turn the note into information notification. */ - gtk_window_set_type_hint (GTK_WINDOW (dialog), GDK_WINDOW_TYPE_HINT_NOTIFICATION); -} - - -static void -hildon_note_finalize (GObject *obj_self) -{ - HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (obj_self); - g_assert (priv); - - /* FIXME Some of this stuff should be moved to dispose */ - - /* Free internal data */ - if (priv->event_box) - g_object_unref (priv->event_box); - - if (priv->label) - g_object_unref (priv->label); - - if (priv->icon) { - g_free (priv->icon); - priv->icon = NULL; - } - if (priv->stock_icon) { - g_free (priv->stock_icon); - priv->stock_icon = NULL; - } - - if (priv->progressbar) - g_object_unref (priv->progressbar); - - if (priv->original_description) - g_free (priv->original_description); - - G_OBJECT_CLASS (parent_class)->finalize (obj_self); -} - -static void -label_size_request (GtkWidget *label, - GtkRequisition *req, - GtkWidget *note) -{ - gint note_height = MAX (HILDON_INFORMATION_NOTE_MIN_HEIGHT, req->height); - g_object_set (note, "height-request", note_height, NULL); -} - -static void -resize_button (GtkWidget *button, gpointer *data) -{ - gint width = GPOINTER_TO_INT (data); - g_object_set (button, "width-request", width, NULL); -} - -static void -hildon_note_orientation_update (HildonNote *note, GdkScreen *screen) -{ - GtkDialog *dialog = GTK_DIALOG (note); - HildonNotePrivate* priv = HILDON_NOTE_GET_PRIVATE (note); - GtkWidget *parent; - gint button_width, padding; - gboolean portrait = gdk_screen_get_width (screen) < gdk_screen_get_height (screen); - - g_object_ref (dialog->action_area); - unpack_widget (dialog->action_area); - - if (portrait) { - parent = dialog->vbox; - button_width = gdk_screen_get_width (screen) - HILDON_MARGIN_DOUBLE * 2; - padding = HILDON_MARGIN_DOUBLE; - } else { - parent = gtk_widget_get_parent (dialog->vbox); - button_width = priv->button_width; - padding = 0; - } - - gtk_box_pack_end (GTK_BOX (parent), dialog->action_area, - portrait, TRUE, 0); - gtk_box_reorder_child (GTK_BOX (parent), dialog->action_area, 0); - gtk_container_foreach (GTK_CONTAINER (dialog->action_area), - (GtkCallback) resize_button, - GINT_TO_POINTER (button_width)); - g_object_unref (dialog->action_area); - gtk_container_child_set (GTK_CONTAINER (priv->box), priv->label, - "padding", padding, NULL); -} - -static void -screen_size_changed (GdkScreen *screen, - GtkWidget *note) -{ - HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (note); - gint screen_width = gdk_screen_get_width (screen); - gint text_width = screen_width - HILDON_INFORMATION_NOTE_MARGIN * 2; - - if (priv->note_n == HILDON_NOTE_TYPE_INFORMATION || - priv->note_n == HILDON_NOTE_TYPE_INFORMATION_THEME) { - g_object_set (note, "width-request", screen_width, NULL); - g_object_set (priv->label, "width-request", text_width, NULL); - - return; - } else if (priv->note_n == HILDON_NOTE_TYPE_CONFIRMATION) { - hildon_note_orientation_update (HILDON_NOTE (note), screen); - } -} - -static void -hildon_note_realize (GtkWidget *widget) -{ - GdkDisplay *display; - gboolean is_info_note = FALSE; - Atom atom; - const gchar *notification_type; - HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (widget); - g_assert (priv); - - /* 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); - - /* Set the _HILDON_NOTIFICATION_TYPE property so Matchbox places the window correctly */ - display = gdk_drawable_get_display (widget->window); - atom = gdk_x11_get_xatom_by_name_for_display (display, "_HILDON_NOTIFICATION_TYPE"); - - if (priv->note_n == HILDON_NOTE_TYPE_INFORMATION || - priv->note_n == HILDON_NOTE_TYPE_INFORMATION_THEME) { - notification_type = "_HILDON_NOTIFICATION_TYPE_INFO"; - is_info_note = TRUE; - } else { - notification_type = "_HILDON_NOTIFICATION_TYPE_CONFIRMATION"; - } - - XChangeProperty (GDK_WINDOW_XDISPLAY (widget->window), GDK_WINDOW_XID (widget->window), - atom, XA_STRING, 8, PropModeReplace, (guchar *) notification_type, - strlen (notification_type)); - - if (is_info_note) { - g_signal_connect (priv->label, "size-request", G_CALLBACK (label_size_request), widget); - } - - GdkScreen *screen = gtk_widget_get_screen (widget); - g_signal_connect (screen, "size-changed", G_CALLBACK (screen_size_changed), widget); - screen_size_changed (screen, widget); -} - -static void -hildon_note_unrealize (GtkWidget *widget) -{ - HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (widget); - GdkScreen *screen = gtk_widget_get_screen (widget); - - g_signal_handlers_disconnect_by_func (screen, G_CALLBACK (screen_size_changed), widget); - g_signal_handlers_disconnect_by_func (priv->label, G_CALLBACK (label_size_request), widget); - - GTK_WIDGET_CLASS (parent_class)->unrealize (widget); -} - - -/* 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); -} - -/* - Name the widget and text label based on the note type. This is used - by the theme to give proper backgrounds depending on the note type. -*/ -static void -hildon_note_rename (HildonNote *note) -{ - GEnumValue *value; - GEnumClass *enum_class; - gchar *name; - - HildonNotePrivate *priv = HILDON_NOTE_GET_PRIVATE (note); - - enum_class = g_type_class_ref (HILDON_TYPE_NOTE_TYPE); - value = g_enum_get_value (enum_class, priv->note_n); - - name = g_strconcat ("HildonNote-", value->value_nick, NULL); - gtk_widget_set_name (GTK_WIDGET (note), name); - g_free (name); - - name = g_strconcat ("HildonNoteLabel-", value->value_nick, NULL); - gtk_widget_set_name (priv->label, name); - g_free (name); - - g_type_class_unref (enum_class); -} - -static void -hildon_note_rebuild (HildonNote *note) -{ - GtkDialog *dialog; - HildonNotePrivate *priv; - gboolean is_info_note = FALSE; - - g_assert (HILDON_IS_NOTE (note)); - - priv = HILDON_NOTE_GET_PRIVATE (note); - g_assert (priv); - - dialog = GTK_DIALOG (note); - - /* Reuse exiting content widgets for new layout */ - unpack_widget (priv->label); - unpack_widget (priv->progressbar); - unpack_widget (priv->event_box); - - /* 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_TYPE_CONFIRMATION: - priv->okButton = gtk_dialog_add_button (dialog, - _("wdgt_bd_yes"), GTK_RESPONSE_OK); - priv->cancelButton = gtk_dialog_add_button (dialog, - _("wdgt_bd_no"), GTK_RESPONSE_CANCEL); - gtk_widget_show (priv->cancelButton); - g_object_get (priv->okButton, "width-request", - &priv->button_width, NULL); - gtk_widget_set_no_show_all (priv->cancelButton, FALSE); - break; - - case HILDON_NOTE_TYPE_PROGRESSBAR: - priv->cancelButton = gtk_dialog_add_button (dialog, - _("wdgt_bd_stop"), GTK_RESPONSE_CANCEL); - gtk_widget_show (priv->cancelButton); - gtk_widget_set_no_show_all (priv->cancelButton, FALSE); - break; - - case HILDON_NOTE_TYPE_INFORMATION_THEME: - case HILDON_NOTE_TYPE_INFORMATION: - is_info_note = TRUE; - break; - - case HILDON_NOTE_TYPE_CONFIRMATION_BUTTON: - default: - break; - } - - /* Don't display the action area if this is just an information - * note. This prevents text from being slightly aligned to the - * left - */ - if (is_info_note) { - gtk_widget_hide (dialog->action_area); - } else { - gtk_widget_show (dialog->action_area); - } - gtk_widget_set_no_show_all (dialog->action_area, is_info_note); - - /* Pack label vertically. Spacing is only necessary for the progressbar note. */ - priv->box = gtk_vbox_new (FALSE, priv->progressbar ? HILDON_MARGIN_DOUBLE : 0); - gtk_container_add (GTK_CONTAINER (priv->event_box), 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_container_add (GTK_CONTAINER (dialog->vbox), priv->event_box); - - gtk_widget_show_all (priv->event_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; - GtkWidget *button; - - g_return_val_if_fail (description != NULL, NULL); - - GtkWidget *conf_note = - g_object_new (HILDON_TYPE_NOTE, - "note-type", HILDON_NOTE_TYPE_CONFIRMATION_BUTTON, - "description", description, - 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); - - button = gtk_dialog_add_button (GTK_DIALOG (conf_note), message, value); - /* maemo-gtk is going to set the "no-show-all" property all - cancel/close-like buttons to TRUE, so that they are not shown. On - the other hand, this confirmation note with custom buttons should - not obey this rule, so we need to make sure they are shown. */ - gtk_widget_show (button); - gtk_widget_set_no_show_all (button, FALSE); - } - - 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 a text (description) - * that you specify and two buttons. - * - * Returns: a #GtkWidget pointer of the note - */ -GtkWidget* -hildon_note_new_confirmation (GtkWindow *parent, - const gchar *description) -{ - GtkWidget *dialog = NULL; - - g_return_val_if_fail (description != NULL, NULL); - - dialog = g_object_new (HILDON_TYPE_NOTE, - "note-type", - HILDON_NOTE_TYPE_CONFIRMATION, - "description", description, 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 a text (description) - * that you specify and two buttons. - * - * Deprecated: Since 2.2, icons are not shown in confirmation notes. Icons set - * with this function will be ignored. Use hildon_note_new_confirmation() instead. - * - * 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; - - dialog = hildon_note_new_confirmation (parent, description); - g_object_set (dialog, "icon", icon_name); - - 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 and an OK button. - * - * Returns: a #GtkWidget pointer of the note - */ -GtkWidget* -hildon_note_new_information (GtkWindow *parent, - const gchar *description) -{ - GtkWidget *dialog = NULL; - - g_return_val_if_fail (description != NULL, NULL); - - dialog = g_object_new (HILDON_TYPE_NOTE, - "note-type", - HILDON_NOTE_TYPE_INFORMATION_THEME, - "description", description, 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. - * - * Deprecated: Since 2.2, icons are not shown in confirmation notes. Icons set - * with this function will be ignored. Use hildon_note_new_information() instead. - * - * 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; - - dialog = hildon_note_new_information (parent, description); - g_object_set (dialog, "icon", icon_name); - - return dialog; -} - -/* FIXME This documentation string LIES! */ - -/** - * 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 (description != NULL, NULL); - - dialog = g_object_new (HILDON_TYPE_NOTE, - "note-type", - HILDON_NOTE_TYPE_PROGRESSBAR, - "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)); - g_assert (priv); - - if (priv->okButton) { - gtk_button_set_label (GTK_BUTTON (priv->okButton), text); - gtk_button_set_label (GTK_BUTTON (priv->cancelButton), - _("wdgt_bd_no")); - } else { - gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text); - } -} - -/** - * hildon_note_set_button_texts: - * @note: a #HildonNote - * @text_ok: the new text of the default OK button - * @text_cancel: 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 *text_ok, - const gchar *text_cancel) -{ - HildonNotePrivate *priv; - - g_return_if_fail (HILDON_IS_NOTE (note)); - - priv = HILDON_NOTE_GET_PRIVATE (HILDON_NOTE (note)); - g_assert (priv); - - if (priv->okButton) { - gtk_button_set_label (GTK_BUTTON (priv->okButton), text_ok); - gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text_cancel); - } else { - gtk_button_set_label (GTK_BUTTON (priv->cancelButton), text_cancel); - } -} - -/* 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_assert (priv); - - g_signal_handler_disconnect (widget, priv->sound_signal_handler); - - priv->sound_signal_handler = 0; - - switch (priv->note_n) - { - case HILDON_NOTE_TYPE_INFORMATION: - case HILDON_NOTE_TYPE_INFORMATION_THEME: - hildon_play_system_sound (INFORMATION_SOUND_PATH); - break; - - case HILDON_NOTE_TYPE_CONFIRMATION: - case HILDON_NOTE_TYPE_CONFIRMATION_BUTTON: - hildon_play_system_sound (CONFIRMATION_SOUND_PATH); - break; - - default: - break; - }; - - return FALSE; -} diff --git a/src/hildon-note.h b/src/hildon-note.h deleted file mode 100644 index 8e67cfd..0000000 --- a/src/hildon-note.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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 - -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; - -struct _HildonNote -{ - GtkDialog parent; -}; - -struct _HildonNoteClass -{ - GtkDialogClass parent_class; -}; - -GType G_GNUC_CONST -hildon_note_get_type (void); - -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_name (GtkWindow *parent, - const gchar *description, - const gchar *icon_name); -#endif - -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); -#ifndef HILDON_DISABLE_DEPRECATED -GtkWidget* -hildon_note_new_information_with_icon_name (GtkWindow *parent, - const gchar *description, - const gchar *icon_name); -#endif - -void -hildon_note_set_button_text (HildonNote *note, - const gchar *text); - -void -hildon_note_set_button_texts (HildonNote *note, - const gchar *text_ok, - const gchar *text_cancel); - -typedef enum -{ - HILDON_NOTE_TYPE_CONFIRMATION = 0, - HILDON_NOTE_TYPE_CONFIRMATION_BUTTON, - HILDON_NOTE_TYPE_INFORMATION, - HILDON_NOTE_TYPE_INFORMATION_THEME, - HILDON_NOTE_TYPE_PROGRESSBAR -} HildonNoteType; - -G_END_DECLS - -#endif /* __HILDON_NOTE_H__ */ diff --git a/src/hildon-number-editor-private.h b/src/hildon-number-editor-private.h deleted file mode 100644 index cabec13..0000000 --- a/src/hildon-number-editor-private.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_PRIVATE_H__ -#define __HILDON_NUMBER_EDITOR_PRIVATE_H__ - -G_BEGIN_DECLS - -typedef struct _HildonNumberEditorPrivate HildonNumberEditorPrivate; - -#define HILDON_NUMBER_EDITOR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_NUMBER_EDITOR, \ - HildonNumberEditorPrivate)); - -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 */ -}; - -G_END_DECLS - -#endif /* __HILDON_NUMBER_EDITOR_PRIVATE_H__ */ diff --git a/src/hildon-number-editor.c b/src/hildon-number-editor.c deleted file mode 100644 index 994918e..0000000 --- a/src/hildon-number-editor.c +++ /dev/null @@ -1,1053 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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. - * - * - * - * #HildonNumberEditor has been deprecated since Hildon 2.2 - * See Migrating Number Widgets - * section to know how to migrate this deprecated widget. - * - * - * - * - * HildonNumberEditor example - * - * number_editor = hildon_number_editor_new (-250, 500); - * hildon_number_editor_set_range (number_editor, 0, 100); - * - * - */ - -#undef HILDON_DISABLE_DEPRECATED - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#include "hildon-number-editor.h" -#include "hildon-marshalers.h" -#include "hildon-defines.h" -#include "hildon-enum-types.h" -#include "hildon-banner.h" -#include "hildon-number-editor-private.h" -#include "hildon-private.h" - -#define _(String) dgettext("hildon-libs", String) - -/*Pixel spec defines*/ -#define NUMBER_EDITOR_HEIGHT 30 - -/* Size of plus and minus buttons */ -#define BUTTON_HEIGHT 30 - -#define BUTTON_WIDTH 30 - -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_focus (GtkWidget *widget, - GtkDirectionType direction); - -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); - -enum -{ - RANGE_ERROR, - LAST_SIGNAL -}; - -enum { - PROP_0, - PROP_VALUE -}; - -static GtkContainerClass* parent_class; - -static guint HildonNumberEditor_signal[LAST_SIGNAL] = {0}; - -/** - * hildon_number_editor_get_type: - * - * Returns GType for HildonNumberEditor. - * - * Returns: HildonNumberEditor type - */ -GType G_GNUC_CONST -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_number_editor_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; - - /** - * HildonNumberEditor:value: - * - * The current value of the number editor. - */ - 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); - g_assert (priv); - - 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); - g_assert (priv); - - /* 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) -{ - g_assert (priv != NULL); - - 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); - g_assert (priv); - - /* 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); - g_assert (priv); - - 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); - -#ifdef MAEMO_GTK - g_object_set (G_OBJECT (priv->num_entry), - "hildon-input-mode", HILDON_GTK_INPUT_MODE_NUMERIC, NULL); -#endif - - 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); - g_assert (priv); - - 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; - - /* Update text in entry to new value */ - buffer = g_strdup_printf ("%d", value); - gtk_entry_set_text (GTK_ENTRY (priv->num_entry), buffer); - g_free (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); - g_assert (priv); - - settings = gtk_settings_get_default (); - g_object_get (settings, "gtk-timeout-initial", &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) - { - change_numbers (editor, priv->button_type); - 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-timeout-repeat", &timeout, NULL); - timeout *= 8; - - priv->button_event_id = g_timeout_add (timeout, - (GSourceFunc) do_mouse_timeout, - editor); - - return FALSE; -} - -static gboolean -do_mouse_timeout (HildonNumberEditor *editor) -{ - HildonNumberEditorPrivate *priv; - g_assert (HILDON_IS_NUMBER_EDITOR (editor)); - - priv = HILDON_NUMBER_EDITOR_GET_PRIVATE (editor); - g_assert (priv); - - GDK_THREADS_ENTER (); - - /* Update value based on button held */ - 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); - g_assert (priv); - - 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) -{ - g_assert (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); - g_assert (priv); - - 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 = HILDON_NUMBER_EDITOR_ERROR_MAXIMUM_VALUE_EXCEED; - fixup_value = priv->end; - } - else if (value < priv->start && (priv->start < 0 || (priv->start >= 0 && value <= 0))) - { - error_code = HILDON_NUMBER_EDITOR_ERROR_MINIMUM_VALUE_EXCEED; - fixup_value = priv->start; - } - } - else - { - if (value > priv->end) { - error_code = HILDON_NUMBER_EDITOR_ERROR_MAXIMUM_VALUE_EXCEED; - fixup_value = priv->end; - } - else if (value < priv->start) { - error_code = HILDON_NUMBER_EDITOR_ERROR_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 = HILDON_NUMBER_EDITOR_ERROR_ERRONEOUS_VALUE; - } - else if (! allow_intermediate) - error_code = HILDON_NUMBER_EDITOR_ERROR_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); - g_assert (priv); - - /* 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); - g_assert (priv); - - 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_focus (GtkWidget *widget, - GtkDirectionType direction) -{ - gboolean retval; - GtkDirectionType effective_direction; - - g_assert (HILDON_IS_NUMBER_EDITOR (widget)); - - retval = hildon_private_composite_focus (widget, direction, &effective_direction); - - if (retval == TRUE) - return GTK_WIDGET_CLASS (parent_class)->focus (widget, effective_direction); - else - return FALSE; -} - -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); - g_assert (priv); - - min = priv->start; - max = priv->end; - - /* Construct error message */ - switch (type) - { - case HILDON_NUMBER_EDITOR_ERROR_MAXIMUM_VALUE_EXCEED: - err_msg = g_strdup_printf (_("ckct_ib_maximum_value"), max, max); - break; - - case HILDON_NUMBER_EDITOR_ERROR_MINIMUM_VALUE_EXCEED: - err_msg = g_strdup_printf (_("ckct_ib_minimum_value"), min, min); - break; - - case HILDON_NUMBER_EDITOR_ERROR_ERRONEOUS_VALUE: - err_msg = - g_strdup_printf (_("ckct_ib_set_a_value_within_range"), min, max); - break; - } - - /* Infoprint error */ - if (err_msg) - { - hildon_banner_show_information (GTK_WIDGET (GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET(editor), - GTK_TYPE_WINDOW))), NULL, 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); - g_assert (priv); - - /* 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); - g_assert (priv); - - 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_assert (priv); - - 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 deleted file mode 100644 index 7f46590..0000000 --- a/src/hildon-number-editor.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#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)) - -#define HILDON_NUMBER_EDITOR_GET_CLASS(obj) \ - ((HildonNumberEditorClass *) G_OBJECT_GET_CLASS(obj)) - -typedef struct _HildonNumberEditor HildonNumberEditor; - -typedef struct _HildonNumberEditorClass HildonNumberEditorClass; - -struct _HildonNumberEditor -{ - GtkContainer parent; -}; - -typedef enum -{ - HILDON_NUMBER_EDITOR_ERROR_MAXIMUM_VALUE_EXCEED, - HILDON_NUMBER_EDITOR_ERROR_MINIMUM_VALUE_EXCEED, - HILDON_NUMBER_EDITOR_ERROR_ERRONEOUS_VALUE -} HildonNumberEditorErrorType; - -struct _HildonNumberEditorClass -{ - GtkContainerClass parent_class; - - gboolean (*range_error) (HildonNumberEditor *editor, HildonNumberEditorErrorType type); -}; - -GType G_GNUC_CONST -hildon_number_editor_get_type (void); - -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__ */ - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-pannable-area.c b/src/hildon-pannable-area.c deleted file mode 100644 index 717d5ae..0000000 --- a/src/hildon-pannable-area.c +++ /dev/null @@ -1,3278 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * This widget is based on MokoFingerScroll from libmokoui - * OpenMoko Application Framework UI Library - * Authored by Chris Lord - * Copyright (C) 2006-2007 OpenMoko Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser Public License as published by - * the Free Software Foundation; version 2 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser Public License for more details. - * - */ - -/** - * SECTION: hildon-pannable-area - * @short_description: A scrolling widget designed for touch screens - * @see_also: #GtkScrolledWindow - * - * #HildonPannableArea is a container widget that can be "panned" (scrolled) - * up and down using the touchscreen with fingers. The widget has no scrollbars, - * but it rather shows small scroll indicators to give an idea of the part of the - * content that is visible at a time. The scroll indicators appear when a dragging - * motion is started on the pannable area. - * - * The scrolling is "kinetic", meaning the motion can be "flicked" and it will - * continue from the initial motion by gradually slowing down to an eventual stop. - * The motion can also be stopped immediately by pressing the touchscreen over the - * pannable area. - */ - -#undef HILDON_DISABLE_DEPRECATED - -#include -#if USE_CAIRO_SCROLLBARS == 1 -#include -#endif -#include - -#include "hildon-pannable-area.h" -#include "hildon-marshalers.h" -#include "hildon-enum-types.h" - -#define USE_CAIRO_SCROLLBARS 0 - -#define SCROLL_BAR_MIN_SIZE 5 -#define RATIO_TOLERANCE 0.000001 -#define SCROLL_FADE_TIMEOUT 100 -#define MOTION_EVENTS_PER_SECOND 25 -#define CURSOR_STOPPED_TIMEOUT 80 -#define PANNABLE_MAX_WIDTH 788 -#define PANNABLE_MAX_HEIGHT 378 - -G_DEFINE_TYPE (HildonPannableArea, hildon_pannable_area, GTK_TYPE_BIN) - -#define PANNABLE_AREA_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), HILDON_TYPE_PANNABLE_AREA, \ - HildonPannableAreaPrivate)) - -struct _HildonPannableAreaPrivate { - HildonPannableAreaMode mode; - HildonMovementMode mov_mode; - GdkWindow *event_window; - gdouble x; /* Used to store mouse co-ordinates of the first or */ - gdouble y; /* previous events in a press-motion pair */ - gdouble ex; /* Used to store mouse co-ordinates of the last */ - gdouble ey; /* motion event in acceleration mode */ - gboolean enabled; - gboolean clicked; - guint32 last_time; /* Last event time, to stop infinite loops */ - gint last_type; - gboolean last_in; - gboolean moved; - gdouble vmin; - gdouble vmax; - gdouble vmax_overshooting; - gdouble vfast_factor; - gdouble decel; - gdouble drag_inertia; - gdouble scroll_time; - gdouble vel_factor; - guint sps; - guint panning_threshold; - guint scrollbar_fade_delay; - guint bounce_steps; - guint force; - guint direction_error_margin; - gdouble vel_x; - gdouble vel_y; - GdkWindow *child; - gint child_width; - gint child_height; - gint ix; /* Initial click mouse co-ordinates */ - gint iy; - gint cx; /* Initial click child window mouse co-ordinates */ - gint cy; - guint idle_id; - gdouble scroll_to_x; - gdouble scroll_to_y; - gdouble motion_x; - gdouble motion_y; - gint overshot_dist_x; - gint overshot_dist_y; - gint overshooting_y; - gint overshooting_x; - gdouble scroll_indicator_alpha; - gint motion_event_scroll_timeout; - gint scroll_indicator_timeout; - gint scroll_indicator_event_interrupt; - gint scroll_delay_counter; - gint vovershoot_max; - gint hovershoot_max; - gboolean initial_hint; - gboolean initial_effect; - gboolean low_friction_mode; - gboolean first_drag; - - gboolean size_request_policy; - gboolean hscroll_visible; - gboolean vscroll_visible; - GdkRectangle hscroll_rect; - GdkRectangle vscroll_rect; - guint indicator_width; - - GtkAdjustment *hadjust; - GtkAdjustment *vadjust; - - GtkPolicyType vscrollbar_policy; - GtkPolicyType hscrollbar_policy; - - GdkGC *scrollbars_gc; -}; - -/*signals*/ -enum { - HORIZONTAL_MOVEMENT, - VERTICAL_MOVEMENT, - LAST_SIGNAL -}; - -static guint pannable_area_signals [LAST_SIGNAL] = { 0 }; - -enum { - PROP_ENABLED = 1, - PROP_MODE, - PROP_MOVEMENT_MODE, - PROP_VELOCITY_MIN, - PROP_VELOCITY_MAX, - PROP_VEL_MAX_OVERSHOOTING, - PROP_VELOCITY_FAST_FACTOR, - PROP_DECELERATION, - PROP_DRAG_INERTIA, - PROP_SPS, - PROP_PANNING_THRESHOLD, - PROP_SCROLLBAR_FADE_DELAY, - PROP_BOUNCE_STEPS, - PROP_FORCE, - PROP_DIRECTION_ERROR_MARGIN, - PROP_VSCROLLBAR_POLICY, - PROP_HSCROLLBAR_POLICY, - PROP_VOVERSHOOT_MAX, - PROP_HOVERSHOOT_MAX, - PROP_SCROLL_TIME, - PROP_INITIAL_HINT, - PROP_LOW_FRICTION_MODE, - PROP_SIZE_REQUEST_POLICY, - PROP_HADJUSTMENT, - PROP_VADJUSTMENT, - PROP_LAST -}; - -static void hildon_pannable_area_class_init (HildonPannableAreaClass * klass); -static void hildon_pannable_area_init (HildonPannableArea * area); -static void hildon_pannable_area_get_property (GObject * object, - guint property_id, - GValue * value, - GParamSpec * pspec); -static void hildon_pannable_area_set_property (GObject * object, - guint property_id, - const GValue * value, - GParamSpec * pspec); -static void hildon_pannable_area_dispose (GObject * object); -static void hildon_pannable_area_realize (GtkWidget * widget); -static void hildon_pannable_area_unrealize (GtkWidget * widget); -static void hildon_pannable_area_size_request (GtkWidget * widget, - GtkRequisition * requisition); -static void hildon_pannable_area_size_allocate (GtkWidget * widget, - GtkAllocation * allocation); -static void hildon_pannable_area_child_allocate_calculate (GtkWidget * widget, - GtkAllocation * allocation, - GtkAllocation * child_allocation); -static void hildon_pannable_area_style_set (GtkWidget * widget, - GtkStyle * previous_style); -static void hildon_pannable_area_map (GtkWidget * widget); -static void hildon_pannable_area_unmap (GtkWidget * widget); -static void hildon_pannable_area_grab_notify (GtkWidget *widget, - gboolean was_grabbed, - gpointer user_data); -#if USE_CAIRO_SCROLLBARS == 1 -static void rgb_from_gdkcolor (GdkColor *color, gdouble *r, gdouble *g, gdouble *b); -#else /* USE_CAIRO_SCROLLBARS */ -static void tranparency_color (GdkColor *color, - GdkColor colora, - GdkColor colorb, - gdouble transparency); -#endif /* USE_CAIRO_SCROLLBARS */ -static void hildon_pannable_draw_vscroll (GtkWidget * widget, - GdkColor *back_color, - GdkColor *scroll_color); -static void hildon_pannable_draw_hscroll (GtkWidget * widget, - GdkColor *back_color, - GdkColor *scroll_color); -static void hildon_pannable_area_initial_effect (GtkWidget * widget); -static void hildon_pannable_area_redraw (HildonPannableArea * area); -static void hildon_pannable_area_launch_fade_timeout (HildonPannableArea * area, - gdouble alpha); -static void hildon_pannable_area_adjust_value_changed (HildonPannableArea * area, - gpointer data); -static void hildon_pannable_area_adjust_changed (HildonPannableArea * area, - gpointer data); -static gboolean hildon_pannable_area_scroll_indicator_fade(HildonPannableArea * area); -static gboolean hildon_pannable_area_expose_event (GtkWidget * widget, - GdkEventExpose * event); -static GdkWindow * hildon_pannable_area_get_topmost (GdkWindow * window, - gint x, gint y, - gint * tx, gint * ty, - GdkEventMask mask); -static void synth_crossing (GdkWindow * child, - gint x, gint y, - gint x_root, gint y_root, - guint32 time, gboolean in); -static gboolean hildon_pannable_area_button_press_cb (GtkWidget * widget, - GdkEventButton * event); -static void hildon_pannable_area_refresh (HildonPannableArea * area); -static gboolean hildon_pannable_area_check_scrollbars (HildonPannableArea * area); -static void hildon_pannable_axis_scroll (HildonPannableArea *area, - GtkAdjustment *adjust, - gdouble *vel, - gdouble inc, - gint *overshooting, - gint *overshot_dist, - gdouble *scroll_to, - gint overshoot_max, - gboolean *s); -static void hildon_pannable_area_scroll (HildonPannableArea *area, - gdouble x, gdouble y); -static gboolean hildon_pannable_area_timeout (HildonPannableArea * area); -static void hildon_pannable_area_calculate_velocity (gdouble *vel, - gdouble delta, - gdouble dist, - gdouble vmax, - gdouble drag_inertia, - gdouble force, - guint sps); -static gboolean hildon_pannable_area_motion_event_scroll_timeout (HildonPannableArea *area); -static void hildon_pannable_area_motion_event_scroll (HildonPannableArea *area, - gdouble x, gdouble y); -static gboolean hildon_pannable_area_motion_notify_cb (GtkWidget * widget, - GdkEventMotion * event); -static gboolean hildon_pannable_leave_notify_event (GtkWidget *widget, - GdkEventCrossing *event); -static gboolean hildon_pannable_area_button_release_cb (GtkWidget * widget, - GdkEventButton * event); -static gboolean hildon_pannable_area_scroll_cb (GtkWidget *widget, - GdkEventScroll *event); -static void hildon_pannable_area_child_mapped (GtkWidget *widget, - GdkEvent *event, - gpointer user_data); -static void hildon_pannable_area_add (GtkContainer *container, GtkWidget *child); -static void hildon_pannable_area_remove (GtkContainer *container, GtkWidget *child); -static void hildon_pannable_calculate_vel_factor (HildonPannableArea * self); - - -static void -hildon_pannable_area_class_init (HildonPannableAreaClass * klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass); - - - g_type_class_add_private (klass, sizeof (HildonPannableAreaPrivate)); - - object_class->get_property = hildon_pannable_area_get_property; - object_class->set_property = hildon_pannable_area_set_property; - object_class->dispose = hildon_pannable_area_dispose; - - widget_class->realize = hildon_pannable_area_realize; - widget_class->unrealize = hildon_pannable_area_unrealize; - widget_class->map = hildon_pannable_area_map; - widget_class->unmap = hildon_pannable_area_unmap; - widget_class->size_request = hildon_pannable_area_size_request; - widget_class->size_allocate = hildon_pannable_area_size_allocate; - widget_class->expose_event = hildon_pannable_area_expose_event; - widget_class->style_set = hildon_pannable_area_style_set; - widget_class->button_press_event = hildon_pannable_area_button_press_cb; - widget_class->button_release_event = hildon_pannable_area_button_release_cb; - widget_class->motion_notify_event = hildon_pannable_area_motion_notify_cb; - widget_class->leave_notify_event = hildon_pannable_leave_notify_event; - widget_class->scroll_event = hildon_pannable_area_scroll_cb; - - container_class->add = hildon_pannable_area_add; - container_class->remove = hildon_pannable_area_remove; - - klass->horizontal_movement = NULL; - klass->vertical_movement = NULL; - - g_object_class_install_property (object_class, - PROP_ENABLED, - g_param_spec_boolean ("enabled", - "Enabled", - "Enable or disable finger-scroll.", - TRUE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_VSCROLLBAR_POLICY, - g_param_spec_enum ("vscrollbar_policy", - "vscrollbar policy", - "Visual policy of the vertical scrollbar", - GTK_TYPE_POLICY_TYPE, - GTK_POLICY_AUTOMATIC, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_HSCROLLBAR_POLICY, - g_param_spec_enum ("hscrollbar_policy", - "hscrollbar policy", - "Visual policy of the horizontal scrollbar", - GTK_TYPE_POLICY_TYPE, - GTK_POLICY_AUTOMATIC, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_MODE, - g_param_spec_enum ("mode", - "Scroll mode", - "Change the finger-scrolling mode.", - HILDON_TYPE_PANNABLE_AREA_MODE, - HILDON_PANNABLE_AREA_MODE_AUTO, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_MOVEMENT_MODE, - g_param_spec_flags ("mov_mode", - "Scroll movement mode", - "Controls if the widget can scroll vertically, horizontally or both", - HILDON_TYPE_MOVEMENT_MODE, - HILDON_MOVEMENT_MODE_VERT, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_VELOCITY_MIN, - g_param_spec_double ("velocity_min", - "Minimum scroll velocity", - "Minimum distance the child widget should scroll " - "per 'frame', in pixels per frame.", - 0, G_MAXDOUBLE, 20, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_VELOCITY_MAX, - g_param_spec_double ("velocity_max", - "Maximum scroll velocity", - "Maximum distance the child widget should scroll " - "per 'frame', in pixels per frame.", - 0, G_MAXDOUBLE, 500, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_VEL_MAX_OVERSHOOTING, - g_param_spec_double ("velocity_overshooting_max", - "Maximum scroll velocity when overshooting", - "Maximum distance the child widget should scroll " - "per 'frame', in pixels per frame when it overshoots after hitting the edge.", - 0, G_MAXDOUBLE, 20, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_VELOCITY_FAST_FACTOR, - g_param_spec_double ("velocity_fast_factor", - "Fast velocity factor", - "Minimum velocity that is considered 'fast': " - "children widgets won't receive button presses. " - "Expressed as a fraction of the maximum velocity.", - 0, 1, 0.02, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_DECELERATION, - g_param_spec_double ("deceleration", - "Deceleration multiplier", - "The multiplier used when decelerating when in " - "acceleration scrolling mode.", - 0, 1.0, 0.93, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_DRAG_INERTIA, - g_param_spec_double ("drag_inertia", - "Inertia of the cursor dragging", - "Percentage of the calculated speed in each moment we are are going to use" - "to calculate the launch speed, the other part would be the speed" - "calculated previously", - 0, 1.0, 0.85, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_SPS, - g_param_spec_uint ("sps", - "Scrolls per second", - "Amount of scroll events to generate per second.", - 0, G_MAXUINT, 20, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_PANNING_THRESHOLD, - g_param_spec_uint ("panning_threshold", - "Threshold to consider a motion event an scroll", - "Amount of pixels to consider a motion event an scroll, if it is less" - "it is a click detected incorrectly by the touch screen.", - 0, G_MAXUINT, 6, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_SCROLLBAR_FADE_DELAY, - g_param_spec_uint ("scrollbar_fade_delay", - "Time before starting to fade the scrollbar", - "Time the scrollbar is going to be visible if the widget is not in" - "action in miliseconds", - 0, G_MAXUINT, 3000, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_BOUNCE_STEPS, - g_param_spec_uint ("bounce_steps", - "Bounce steps", - "Number of steps that is going to be used to bounce when hitting the" - "edge, the rubberband effect depends on it", - 0, G_MAXUINT, 3, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_FORCE, - g_param_spec_uint ("force", - "Multiplier of the calculated speed", - "Force applied to the movement, multiplies the calculated speed of the" - "user movement the cursor in the screen", - 0, G_MAXUINT, 120, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_DIRECTION_ERROR_MARGIN, - g_param_spec_uint ("direction_error_margin", - "Margin in the direction detection", - "After detecting the direction of the movement (horizontal or" - "vertical), we can add this margin of error to allow the movement in" - "the other direction even apparently it is not", - 0, G_MAXUINT, 10, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_VOVERSHOOT_MAX, - g_param_spec_int ("vovershoot_max", - "Vertical overshoot distance", - "Space we allow the widget to pass over its vertical limits when" - "hitting the edges, set 0 in order to deactivate overshooting.", - 0, G_MAXINT, 150, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_HOVERSHOOT_MAX, - g_param_spec_int ("hovershoot_max", - "Horizontal overshoot distance", - "Space we allow the widget to pass over its horizontal limits when" - "hitting the edges, set 0 in order to deactivate overshooting.", - 0, G_MAXINT, 150, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_SCROLL_TIME, - g_param_spec_double ("scroll_time", - "Time to scroll to a position", - "The time to scroll to a position when calling the hildon_pannable_scroll_to function", - 1.0, 20.0, 10.0, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_INITIAL_HINT, - g_param_spec_boolean ("initial-hint", - "Initial hint", - "Whether to hint the user about the pannability of the container.", - TRUE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_LOW_FRICTION_MODE, - g_param_spec_boolean ("low-friction-mode", - "Do not decelerate the initial velocity", - "Avoid decelerating the panning movement, like no friction, the widget" - "will stop in the edges or if the user clicks.", - FALSE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_SIZE_REQUEST_POLICY, - g_param_spec_enum ("size-request-policy", - "Size Requisition policy", - "Controls the size request policy of the widget", - HILDON_TYPE_SIZE_REQUEST_POLICY, - HILDON_SIZE_REQUEST_MINIMUM, - G_PARAM_READWRITE| - G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_HADJUSTMENT, - g_param_spec_object ("hadjustment", - "Horizontal Adjustment", - "The GtkAdjustment for the horizontal position", - GTK_TYPE_ADJUSTMENT, - G_PARAM_READABLE)); - g_object_class_install_property (object_class, - PROP_VADJUSTMENT, - g_param_spec_object ("vadjustment", - "Vertical Adjustment", - "The GtkAdjustment for the vertical position", - GTK_TYPE_ADJUSTMENT, - G_PARAM_READABLE)); - - gtk_widget_class_install_style_property (widget_class, - g_param_spec_uint - ("indicator-width", - "Width of the scroll indicators", - "Pixel width used to draw the scroll indicators.", - 0, G_MAXUINT, 8, - G_PARAM_READWRITE)); - /** - * HildonPannableArea::horizontal-movement: - * @hildonpannable: the object which received the signal - * @direction: the direction of the movement #HILDON_MOVEMENT_UP or #HILDON_MOVEMENT_DOWN - * @initial_x: the x value of the touched point in the area when the motion started - * @initial_y: the y value of the touched point in the area when the motion started - * - * The horizontal-movement signal is emitted when the pannable area - * starts a horizontal movement. - * - * Since: 2.2 - */ - pannable_area_signals[HORIZONTAL_MOVEMENT] = - g_signal_new ("horizontal_movement", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (HildonPannableAreaClass, horizontal_movement), - NULL, NULL, - _hildon_marshal_VOID__INT_DOUBLE_DOUBLE, - G_TYPE_NONE, 3, - G_TYPE_INT, - G_TYPE_DOUBLE, - G_TYPE_DOUBLE); - - /** - * HildonPannableArea::vertical-movement: - * @hildonpannable: the object which received the signal - * @direction: the direction of the movement #HILDON_MOVEMENT_LEFT or #HILDON_MOVEMENT_RIGHT - * @initial_x: the x value when the motion started - * @initial_y: the y value when the motion started - * - * The vertical-movement signal is emitted when the pannable area - * starts a vertical movement. - * - * Since: 2.2 - */ - pannable_area_signals[VERTICAL_MOVEMENT] = - g_signal_new ("vertical_movement", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (HildonPannableAreaClass, vertical_movement), - NULL, NULL, - _hildon_marshal_VOID__INT_DOUBLE_DOUBLE, - G_TYPE_NONE, 3, - G_TYPE_INT, - G_TYPE_DOUBLE, - G_TYPE_DOUBLE); - - -} - -static void -hildon_pannable_area_init (HildonPannableArea * area) -{ - HildonPannableAreaPrivate *priv = PANNABLE_AREA_PRIVATE (area); - - GTK_WIDGET_UNSET_FLAGS (area, GTK_NO_WINDOW); - - area->priv = priv; - - priv->moved = FALSE; - priv->clicked = FALSE; - priv->last_time = 0; - priv->last_type = 0; - priv->vscroll_visible = TRUE; - priv->hscroll_visible = TRUE; - priv->indicator_width = 6; - priv->overshot_dist_x = 0; - priv->overshot_dist_y = 0; - priv->overshooting_y = 0; - priv->overshooting_x = 0; - priv->idle_id = 0; - priv->vel_x = 0; - priv->vel_y = 0; - priv->scroll_indicator_alpha = 0.0; - priv->scroll_indicator_timeout = 0; - priv->motion_event_scroll_timeout = 0; - priv->scroll_indicator_event_interrupt = 0; - priv->scroll_delay_counter = priv->scrollbar_fade_delay; - priv->scroll_to_x = -1; - priv->scroll_to_y = -1; - priv->first_drag = TRUE; - priv->initial_effect = TRUE; - priv->child_width = 0; - priv->child_height = 0; - priv->last_in = TRUE; - - hildon_pannable_calculate_vel_factor (area); - - gtk_widget_add_events (GTK_WIDGET (area), GDK_POINTER_MOTION_HINT_MASK); - - priv->hadjust = - GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); - priv->vadjust = - GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); - - g_object_ref_sink (G_OBJECT (priv->hadjust)); - g_object_ref_sink (G_OBJECT (priv->vadjust)); - - g_signal_connect_swapped (priv->hadjust, "value-changed", - G_CALLBACK (hildon_pannable_area_adjust_value_changed), area); - g_signal_connect_swapped (priv->vadjust, "value-changed", - G_CALLBACK (hildon_pannable_area_adjust_value_changed), area); - g_signal_connect_swapped (priv->hadjust, "changed", - G_CALLBACK (hildon_pannable_area_adjust_changed), area); - g_signal_connect_swapped (priv->vadjust, "changed", - G_CALLBACK (hildon_pannable_area_adjust_changed), area); - g_signal_connect (area, "grab-notify", - G_CALLBACK (hildon_pannable_area_grab_notify), NULL); -} - -static void -hildon_pannable_area_get_property (GObject * object, - guint property_id, - GValue * value, - GParamSpec * pspec) -{ - HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (object)->priv; - - switch (property_id) { - case PROP_ENABLED: - g_value_set_boolean (value, priv->enabled); - break; - case PROP_MODE: - g_value_set_enum (value, priv->mode); - break; - case PROP_MOVEMENT_MODE: - g_value_set_flags (value, priv->mov_mode); - break; - case PROP_VELOCITY_MIN: - g_value_set_double (value, priv->vmin); - break; - case PROP_VELOCITY_MAX: - g_value_set_double (value, priv->vmax); - break; - case PROP_VEL_MAX_OVERSHOOTING: - g_value_set_double (value, priv->vmax_overshooting); - break; - case PROP_VELOCITY_FAST_FACTOR: - g_value_set_double (value, priv->vfast_factor); - break; - case PROP_DECELERATION: - g_value_set_double (value, priv->decel); - break; - case PROP_DRAG_INERTIA: - g_value_set_double (value, priv->drag_inertia); - break; - case PROP_SPS: - g_value_set_uint (value, priv->sps); - break; - case PROP_PANNING_THRESHOLD: - g_value_set_uint (value, priv->panning_threshold); - break; - case PROP_SCROLLBAR_FADE_DELAY: - /* convert to miliseconds */ - g_value_set_uint (value, priv->scrollbar_fade_delay * SCROLL_FADE_TIMEOUT); - break; - case PROP_BOUNCE_STEPS: - g_value_set_uint (value, priv->bounce_steps); - break; - case PROP_FORCE: - g_value_set_uint (value, priv->force); - break; - case PROP_DIRECTION_ERROR_MARGIN: - g_value_set_uint (value, priv->direction_error_margin); - break; - case PROP_VSCROLLBAR_POLICY: - g_value_set_enum (value, priv->vscrollbar_policy); - break; - case PROP_HSCROLLBAR_POLICY: - g_value_set_enum (value, priv->hscrollbar_policy); - break; - case PROP_VOVERSHOOT_MAX: - g_value_set_int (value, priv->vovershoot_max); - break; - case PROP_HOVERSHOOT_MAX: - g_value_set_int (value, priv->hovershoot_max); - break; - case PROP_SCROLL_TIME: - g_value_set_double (value, priv->scroll_time); - break; - case PROP_INITIAL_HINT: - g_value_set_boolean (value, priv->initial_hint); - break; - case PROP_LOW_FRICTION_MODE: - g_value_set_boolean (value, priv->low_friction_mode); - break; - case PROP_SIZE_REQUEST_POLICY: - g_value_set_enum (value, priv->size_request_policy); - break; - case PROP_HADJUSTMENT: - g_value_set_object (value, - hildon_pannable_area_get_hadjustment - (HILDON_PANNABLE_AREA (object))); - break; - case PROP_VADJUSTMENT: - g_value_set_object (value, - hildon_pannable_area_get_vadjustment - (HILDON_PANNABLE_AREA (object))); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - -static void -hildon_pannable_area_set_property (GObject * object, - guint property_id, - const GValue * value, - GParamSpec * pspec) -{ - HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (object)->priv; - gboolean enabled; - - switch (property_id) { - case PROP_ENABLED: - enabled = g_value_get_boolean (value); - - if ((priv->enabled != enabled) && (GTK_WIDGET_REALIZED (object))) { - if (enabled) - gdk_window_raise (priv->event_window); - else - gdk_window_lower (priv->event_window); - } - - priv->enabled = enabled; - break; - case PROP_MODE: - priv->mode = g_value_get_enum (value); - break; - case PROP_MOVEMENT_MODE: - priv->mov_mode = g_value_get_flags (value); - break; - case PROP_VELOCITY_MIN: - priv->vmin = g_value_get_double (value); - break; - case PROP_VELOCITY_MAX: - priv->vmax = g_value_get_double (value); - break; - case PROP_VEL_MAX_OVERSHOOTING: - priv->vmax_overshooting = g_value_get_double (value); - break; - case PROP_VELOCITY_FAST_FACTOR: - priv->vfast_factor = g_value_get_double (value); - break; - case PROP_DECELERATION: - hildon_pannable_calculate_vel_factor (HILDON_PANNABLE_AREA (object)); - - priv->decel = g_value_get_double (value); - break; - case PROP_DRAG_INERTIA: - priv->drag_inertia = g_value_get_double (value); - break; - case PROP_SPS: - priv->sps = g_value_get_uint (value); - break; - case PROP_PANNING_THRESHOLD: - priv->panning_threshold = g_value_get_uint (value); - break; - case PROP_SCROLLBAR_FADE_DELAY: - /* convert to miliseconds */ - priv->scrollbar_fade_delay = g_value_get_uint (value)/(SCROLL_FADE_TIMEOUT); - break; - case PROP_BOUNCE_STEPS: - priv->bounce_steps = g_value_get_uint (value); - break; - case PROP_FORCE: - priv->force = g_value_get_uint (value); - break; - case PROP_DIRECTION_ERROR_MARGIN: - priv->direction_error_margin = g_value_get_uint (value); - break; - case PROP_VSCROLLBAR_POLICY: - priv->vscrollbar_policy = g_value_get_enum (value); - - gtk_widget_queue_resize (GTK_WIDGET (object)); - break; - case PROP_HSCROLLBAR_POLICY: - priv->hscrollbar_policy = g_value_get_enum (value); - - gtk_widget_queue_resize (GTK_WIDGET (object)); - break; - case PROP_VOVERSHOOT_MAX: - priv->vovershoot_max = g_value_get_int (value); - break; - case PROP_HOVERSHOOT_MAX: - priv->hovershoot_max = g_value_get_int (value); - break; - case PROP_SCROLL_TIME: - priv->scroll_time = g_value_get_double (value); - - hildon_pannable_calculate_vel_factor (HILDON_PANNABLE_AREA (object)); - break; - case PROP_INITIAL_HINT: - priv->initial_hint = g_value_get_boolean (value); - break; - case PROP_LOW_FRICTION_MODE: - priv->low_friction_mode = g_value_get_boolean (value); - break; - case PROP_SIZE_REQUEST_POLICY: - hildon_pannable_area_set_size_request_policy (HILDON_PANNABLE_AREA (object), - g_value_get_enum (value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - -static void -hildon_pannable_area_dispose (GObject * object) -{ - HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (object)->priv; - GtkWidget *child = gtk_bin_get_child (GTK_BIN (object)); - - if (priv->idle_id) { - g_source_remove (priv->idle_id); - priv->idle_id = 0; - } - - if (priv->scroll_indicator_timeout){ - g_source_remove (priv->scroll_indicator_timeout); - priv->scroll_indicator_timeout = 0; - } - - if (priv->motion_event_scroll_timeout){ - g_source_remove (priv->motion_event_scroll_timeout); - priv->motion_event_scroll_timeout = 0; - } - - if (child) { - g_signal_handlers_disconnect_by_func (child, - hildon_pannable_area_child_mapped, - object); - } - - g_signal_handlers_disconnect_by_func (object, - hildon_pannable_area_grab_notify, - NULL); - - if (priv->hadjust) { - g_signal_handlers_disconnect_by_func (priv->hadjust, - hildon_pannable_area_adjust_value_changed, - object); - g_signal_handlers_disconnect_by_func (priv->hadjust, - hildon_pannable_area_adjust_changed, - object); - g_object_unref (priv->hadjust); - priv->hadjust = NULL; - } - - if (priv->vadjust) { - g_signal_handlers_disconnect_by_func (priv->vadjust, - hildon_pannable_area_adjust_value_changed, - object); - g_signal_handlers_disconnect_by_func (priv->vadjust, - hildon_pannable_area_adjust_changed, - object); - g_object_unref (priv->vadjust); - priv->vadjust = NULL; - } - - if (G_OBJECT_CLASS (hildon_pannable_area_parent_class)->dispose) - G_OBJECT_CLASS (hildon_pannable_area_parent_class)->dispose (object); -} - -static void -hildon_pannable_area_realize (GtkWidget * widget) -{ - GdkWindowAttr attributes; - gint attributes_mask; - gint border_width; - HildonPannableAreaPrivate *priv; - - priv = HILDON_PANNABLE_AREA (widget)->priv; - - GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); - - border_width = GTK_CONTAINER (widget)->border_width; - - attributes.x = widget->allocation.x + border_width; - attributes.y = widget->allocation.y + border_width; - attributes.width = MAX (widget->allocation.width - 2 * border_width, 0); - attributes.height = MAX (widget->allocation.height - 2 * border_width, 0); - attributes.window_type = GDK_WINDOW_CHILD; - - /* avoid using the hildon_window */ - attributes.visual = gtk_widget_get_visual (widget); - attributes.colormap = gtk_widget_get_colormap (widget); - attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK; - attributes.wclass = GDK_INPUT_OUTPUT; - - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - - widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), - &attributes, attributes_mask); - gdk_window_set_user_data (widget->window, widget); - - /* create the events window */ - attributes.x = 0; - attributes.y = 0; - attributes.event_mask = gtk_widget_get_events (widget) - | GDK_BUTTON_MOTION_MASK - | GDK_BUTTON_PRESS_MASK - | GDK_BUTTON_RELEASE_MASK - | GDK_SCROLL_MASK - | GDK_EXPOSURE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK; - attributes.wclass = GDK_INPUT_ONLY; - - 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); - - widget->style = gtk_style_attach (widget->style, widget->window); - gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); - - priv->scrollbars_gc = gdk_gc_new (GDK_DRAWABLE (widget->window)); - gdk_gc_copy (priv->scrollbars_gc, widget->style->fg_gc[GTK_STATE_INSENSITIVE]); -} - -static void -hildon_pannable_area_unrealize (GtkWidget * widget) -{ - HildonPannableAreaPrivate *priv; - - priv = HILDON_PANNABLE_AREA (widget)->priv; - - if (priv->event_window != NULL) { - gdk_window_set_user_data (priv->event_window, NULL); - gdk_window_destroy (priv->event_window); - priv->event_window = NULL; - } - - gdk_gc_unref (priv->scrollbars_gc); - - if (GTK_WIDGET_CLASS (hildon_pannable_area_parent_class)->unrealize) - (*GTK_WIDGET_CLASS (hildon_pannable_area_parent_class)->unrealize)(widget); -} - -static void -hildon_pannable_area_size_request (GtkWidget * widget, - GtkRequisition * requisition) -{ - GtkRequisition child_requisition = {0}; - HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (widget)->priv; - GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget)); - - if (child && GTK_WIDGET_VISIBLE (child)) - { - gtk_widget_size_request (child, &child_requisition); - } - - if (priv->hscrollbar_policy == GTK_POLICY_NEVER) { - requisition->width = child_requisition.width; - } else { - switch (priv->size_request_policy) { - case HILDON_SIZE_REQUEST_CHILDREN: - requisition->width = MIN (PANNABLE_MAX_WIDTH, - child_requisition.width); - break; - case HILDON_SIZE_REQUEST_MINIMUM: - default: - requisition->width = priv->indicator_width; - } - } - - if (priv->vscrollbar_policy == GTK_POLICY_NEVER) { - requisition->height = child_requisition.height; - } else { - switch (priv->size_request_policy) { - case HILDON_SIZE_REQUEST_CHILDREN: - requisition->height = MIN (PANNABLE_MAX_HEIGHT, - child_requisition.height); - break; - case HILDON_SIZE_REQUEST_MINIMUM: - default: - requisition->height = priv->indicator_width; - } - } - - requisition->width += 2 * GTK_CONTAINER (widget)->border_width; - requisition->height += 2 * GTK_CONTAINER (widget)->border_width; -} - -static void -hildon_pannable_area_child_allocate_calculate (GtkWidget * widget, - GtkAllocation * allocation, - GtkAllocation * child_allocation) -{ - gint border_width; - HildonPannableAreaPrivate *priv; - - border_width = GTK_CONTAINER (widget)->border_width; - - priv = HILDON_PANNABLE_AREA (widget)->priv; - - child_allocation->x = 0; - child_allocation->y = 0; - child_allocation->width = MAX (allocation->width - 2 * border_width - - (priv->vscroll_visible ? priv->vscroll_rect.width : 0), 0); - child_allocation->height = MAX (allocation->height - 2 * border_width - - (priv->hscroll_visible ? priv->hscroll_rect.height : 0), 0); - - if (priv->overshot_dist_y > 0) { - child_allocation->y = MIN (child_allocation->y + priv->overshot_dist_y, - child_allocation->height); - child_allocation->height = MAX (child_allocation->height - priv->overshot_dist_y, 0); - } else if (priv->overshot_dist_y < 0) { - child_allocation->height = MAX (child_allocation->height + priv->overshot_dist_y, 0); - } - - if (priv->overshot_dist_x > 0) { - child_allocation->x = MIN (child_allocation->x + priv->overshot_dist_x, - child_allocation->width); - child_allocation->width = MAX (child_allocation->width - priv->overshot_dist_x, 0); - } else if (priv->overshot_dist_x < 0) { - child_allocation->width = MAX (child_allocation->width + priv->overshot_dist_x, 0); - } -} - -static void -hildon_pannable_area_size_allocate (GtkWidget * widget, - GtkAllocation * allocation) -{ - GtkAllocation child_allocation; - HildonPannableAreaPrivate *priv; - GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget)); - gint border_width; - - border_width = GTK_CONTAINER (widget)->border_width; - - widget->allocation = *allocation; - - priv = HILDON_PANNABLE_AREA (widget)->priv; - - if (GTK_WIDGET_REALIZED (widget)) { - gdk_window_move_resize (widget->window, - allocation->x + border_width, - allocation->y + border_width, - allocation->width - border_width * 2, - allocation->height - border_width * 2); - gdk_window_move_resize (priv->event_window, - 0, - 0, - allocation->width - border_width * 2, - allocation->height - border_width * 2); - } - - if (child && GTK_WIDGET_VISIBLE (child)) { - - hildon_pannable_area_child_allocate_calculate (widget, - allocation, - &child_allocation); - - gtk_widget_size_allocate (child, &child_allocation); - - if (hildon_pannable_area_check_scrollbars (HILDON_PANNABLE_AREA (widget))) { - hildon_pannable_area_child_allocate_calculate (widget, - allocation, - &child_allocation); - - gtk_widget_size_allocate (child, &child_allocation); - } - - /* we have to do this after child size_allocate because page_size is - * changed when we allocate the size of the children */ - if (priv->overshot_dist_y < 0) { - gtk_adjustment_set_value (priv->vadjust, priv->vadjust->upper - - priv->vadjust->page_size); - } - - if (priv->overshot_dist_x < 0) { - gtk_adjustment_set_value (priv->hadjust, priv->hadjust->upper - - priv->hadjust->page_size); - } - - } else { - hildon_pannable_area_check_scrollbars (HILDON_PANNABLE_AREA (widget)); - } -} - -static void -hildon_pannable_area_style_set (GtkWidget * widget, - GtkStyle * previous_style) -{ - HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (widget)->priv; - - GTK_WIDGET_CLASS (hildon_pannable_area_parent_class)-> - style_set (widget, previous_style); - - gtk_widget_style_get (widget, "indicator-width", &priv->indicator_width, NULL); -} - -static void -hildon_pannable_area_map (GtkWidget * widget) -{ - HildonPannableAreaPrivate *priv; - - priv = HILDON_PANNABLE_AREA (widget)->priv; - - gdk_window_show (widget->window); - - if (priv->event_window != NULL && !priv->enabled) - gdk_window_show (priv->event_window); - - (*GTK_WIDGET_CLASS (hildon_pannable_area_parent_class)->map) (widget); - - if (priv->event_window != NULL && priv->enabled) - gdk_window_show (priv->event_window); -} - -static void -hildon_pannable_area_unmap (GtkWidget * widget) -{ - HildonPannableAreaPrivate *priv; - - priv = HILDON_PANNABLE_AREA (widget)->priv; - - if (priv->event_window != NULL) - gdk_window_hide (priv->event_window); - - gdk_window_hide (widget->window); - - (*GTK_WIDGET_CLASS (hildon_pannable_area_parent_class)->unmap) (widget); -} - -static void -hildon_pannable_area_grab_notify (GtkWidget *widget, - gboolean was_grabbed, - gpointer user_data) -{ - /* an internal widget has grabbed the focus and now has returned it, - we have to do some release actions */ - if (was_grabbed) { - HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (widget)->priv; - - priv->scroll_indicator_event_interrupt = 0; - - if ((!priv->scroll_indicator_timeout)&&(priv->scroll_indicator_alpha)>0.1) { - priv->scroll_delay_counter = priv->scrollbar_fade_delay; - - hildon_pannable_area_launch_fade_timeout (HILDON_PANNABLE_AREA (widget), - priv->scroll_indicator_alpha); - } - - priv->last_type = 3; - priv->moved = FALSE; - } -} - -#if USE_CAIRO_SCROLLBARS == 1 - -static void -rgb_from_gdkcolor (GdkColor *color, gdouble *r, gdouble *g, gdouble *b) -{ - *r = (color->red >> 8) / 255.0; - *g = (color->green >> 8) / 255.0; - *b = (color->blue >> 8) / 255.0; -} - -static void -hildon_pannable_draw_vscroll (GtkWidget * widget, - GdkColor *back_color, - GdkColor *scroll_color) -{ - HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (widget)->priv; - gfloat y, height; - cairo_t *cr; - cairo_pattern_t *pattern; - gdouble r, g, b; - gint radius = (priv->vscroll_rect.width/2) - 1; - - cr = gdk_cairo_create(widget->window); - - /* Draw the background */ - rgb_from_gdkcolor (back_color, &r, &g, &b); - cairo_set_source_rgb (cr, r, g, b); - cairo_rectangle(cr, priv->vscroll_rect.x, priv->vscroll_rect.y, - priv->vscroll_rect.width, - priv->vscroll_rect.height); - cairo_fill_preserve (cr); - cairo_clip (cr); - - /* Calculate the scroll bar height and position */ - y = ((priv->vadjust->value - priv->vadjust->lower) / (priv->vadjust->upper - priv->vadjust->lower)) * - (widget->allocation.height - - (priv->hscroll_visible ? priv->indicator_width : 0)); - height = ((((priv->vadjust->value - priv->vadjust->lower) + - priv->vadjust->page_size) / - (priv->vadjust->upper - priv->vadjust->lower)) * - (widget->allocation.height - - (priv->hscroll_visible ? priv->indicator_width : 0))) - y; - - /* Set a minimum height */ - height = MAX (SCROLL_BAR_MIN_SIZE, height); - - /* Check the max y position */ - y = MIN (y, widget->allocation.height - - (priv->hscroll_visible ? priv->hscroll_rect.height : 0) - - height); - - /* Draw the scrollbar */ - rgb_from_gdkcolor (scroll_color, &r, &g, &b); - - pattern = cairo_pattern_create_linear(radius+1, y, radius+1,y + height); - cairo_pattern_add_color_stop_rgb(pattern, 0, r, g, b); - cairo_pattern_add_color_stop_rgb(pattern, 1, r/2, g/2, b/2); - cairo_set_source(cr, pattern); - cairo_fill(cr); - cairo_pattern_destroy(pattern); - - cairo_arc(cr, priv->vscroll_rect.x + radius + 1, y + radius + 1, radius, G_PI, 0); - cairo_line_to(cr, priv->vscroll_rect.x + (radius * 2) + 1, y + height - radius); - cairo_arc(cr, priv->vscroll_rect.x + radius + 1, y + height - radius, radius, 0, G_PI); - cairo_line_to(cr, priv->vscroll_rect.x + 1, y + height - radius); - cairo_clip (cr); - - cairo_paint_with_alpha(cr, priv->scroll_indicator_alpha); - - cairo_destroy(cr); -} - -static void -hildon_pannable_draw_hscroll (GtkWidget * widget, - GdkColor *back_color, - GdkColor *scroll_color) -{ - HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (widget)->priv; - gfloat x, width; - cairo_t *cr; - cairo_pattern_t *pattern; - gdouble r, g, b; - gint radius = (priv->hscroll_rect.height/2) - 1; - - cr = gdk_cairo_create(widget->window); - - /* Draw the background */ - rgb_from_gdkcolor (back_color, &r, &g, &b); - cairo_set_source_rgb (cr, r, g, b); - cairo_rectangle(cr, priv->hscroll_rect.x, priv->hscroll_rect.y, - priv->hscroll_rect.width, - priv->hscroll_rect.height); - cairo_fill_preserve (cr); - cairo_clip (cr); - - /* calculate the scrollbar width and position */ - x = ((priv->hadjust->value - priv->hadjust->lower) / (priv->hadjust->upper - priv->hadjust->lower)) * - (widget->allocation.width - (priv->vscroll_visible ? priv->indicator_width : 0)); - width =((((priv->hadjust->value - priv->hadjust->lower) + - priv->hadjust->page_size) / (priv->hadjust->upper - priv->hadjust->lower)) * - (widget->allocation.width - - (priv->vscroll_visible ? priv->indicator_width : 0))) - x; - - /* Set a minimum width */ - width = MAX (SCROLL_BAR_MIN_SIZE, width); - - /* Check the max x position */ - x = MIN (x, widget->allocation.width - - (priv->vscroll_visible ? priv->vscroll_rect.width : 0) - - width); - - /* Draw the scrollbar */ - rgb_from_gdkcolor (scroll_color, &r, &g, &b); - - pattern = cairo_pattern_create_linear(x, radius+1, x+width, radius+1); - cairo_pattern_add_color_stop_rgb(pattern, 0, r, g, b); - cairo_pattern_add_color_stop_rgb(pattern, 1, r/2, g/2, b/2); - cairo_set_source(cr, pattern); - cairo_fill(cr); - cairo_pattern_destroy(pattern); - - cairo_arc_negative(cr, x + radius + 1, priv->hscroll_rect.y + radius + 1, radius, 3*G_PI_2, G_PI_2); - cairo_line_to(cr, x + width - radius, priv->hscroll_rect.y + (radius * 2) + 1); - cairo_arc_negative(cr, x + width - radius, priv->hscroll_rect.y + radius + 1, radius, G_PI_2, 3*G_PI_2); - cairo_line_to(cr, x + width - radius, priv->hscroll_rect.y + 1); - cairo_clip (cr); - - cairo_paint_with_alpha(cr, priv->scroll_indicator_alpha); - - cairo_destroy(cr); -} - -#else /* USE_CAIRO_SCROLLBARS */ - -static void -tranparency_color (GdkColor *color, - GdkColor colora, - GdkColor colorb, - gdouble transparency) -{ - gdouble diff; - - diff = colora.red - colorb.red; - color->red = colora.red-diff*transparency; - - diff = colora.green - colorb.green; - color->green = colora.green-diff*transparency; - - diff = colora.blue - colorb.blue; - color->blue = colora.blue-diff*transparency; -} - -static void -hildon_pannable_draw_vscroll (GtkWidget *widget, - GdkColor *back_color, - GdkColor *scroll_color) -{ - HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (widget)->priv; - gfloat y, height; - GdkColor transp_color; - GdkGC *gc = widget->style->fg_gc[GTK_STATE_INSENSITIVE]; - - gdk_draw_rectangle (widget->window, - widget->style->bg_gc[GTK_STATE_NORMAL], - TRUE, - priv->vscroll_rect.x, priv->vscroll_rect.y, - priv->vscroll_rect.width, - priv->vscroll_rect.height); - - y = ((priv->vadjust->value - priv->vadjust->lower) / (priv->vadjust->upper - priv->vadjust->lower)) * - (widget->allocation.height - (priv->hscroll_visible ? priv->indicator_width : 0)); - height = ((((priv->vadjust->value - priv->vadjust->lower) + priv->vadjust->page_size) / - (priv->vadjust->upper - priv->vadjust->lower)) * - (widget->allocation.height - - (priv->hscroll_visible ? priv->indicator_width : 0))) - y; - - /* Set a minimum height */ - height = MAX (SCROLL_BAR_MIN_SIZE, height); - - /* Check the max y position */ - y = MIN (y, widget->allocation.height - - (priv->hscroll_visible ? priv->hscroll_rect.height : 0) - - height); - - if (priv->scroll_indicator_alpha < 1.0) { - tranparency_color (&transp_color, *back_color, *scroll_color, - priv->scroll_indicator_alpha); - - gdk_gc_set_rgb_fg_color (priv->scrollbars_gc, &transp_color); - - gc = priv->scrollbars_gc; - } - - gdk_draw_rectangle (widget->window, gc, - TRUE, priv->vscroll_rect.x, y, - priv->vscroll_rect.width, height); -} - -static void -hildon_pannable_draw_hscroll (GtkWidget *widget, - GdkColor *back_color, - GdkColor *scroll_color) -{ - HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (widget)->priv; - gfloat x, width; - GdkColor transp_color; - GdkGC *gc = widget->style->fg_gc[GTK_STATE_INSENSITIVE]; - - gdk_draw_rectangle (widget->window, - widget->style->bg_gc[GTK_STATE_INSENSITIVE], - TRUE, - priv->hscroll_rect.x, priv->hscroll_rect.y, - priv->hscroll_rect.width, - priv->hscroll_rect.height); - - /* calculate the scrollbar width and position */ - x = ((priv->hadjust->value - priv->hadjust->lower) / (priv->hadjust->upper - priv->hadjust->lower)) * - (widget->allocation.width - (priv->vscroll_visible ? priv->indicator_width : 0)); - width =((((priv->hadjust->value - priv->hadjust->lower) + - priv->hadjust->page_size) / (priv->hadjust->upper - priv->hadjust->lower)) * - (widget->allocation.width - - (priv->vscroll_visible ? priv->indicator_width : 0))) - x; - - /* Set a minimum width */ - width = MAX (SCROLL_BAR_MIN_SIZE, width); - - /* Check the max x position */ - x = MIN (x, widget->allocation.width - - (priv->vscroll_visible ? priv->vscroll_rect.width : 0) - - width); - - if (priv->scroll_indicator_alpha < 1.0) { - tranparency_color (&transp_color, *back_color, *scroll_color, - priv->scroll_indicator_alpha); - - gdk_gc_set_rgb_fg_color (priv->scrollbars_gc, &transp_color); - - gc = priv->scrollbars_gc; - } - - gdk_draw_rectangle (widget->window, gc, - TRUE, x, priv->hscroll_rect.y, width, - priv->hscroll_rect.height); -} - -#endif /* USE_CAIRO_SCROLLBARS */ - -static void -hildon_pannable_area_initial_effect (GtkWidget * widget) -{ - HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (widget)->priv; - gboolean hscroll_visible, vscroll_visible; - - if (priv->initial_hint) { - - vscroll_visible = (priv->vadjust->upper - priv->vadjust->lower > - priv->vadjust->page_size); - hscroll_visible = (priv->hadjust->upper - priv->hadjust->lower > - priv->hadjust->page_size); - - if (priv->vscroll_visible || priv->hscroll_visible) { - - priv->scroll_indicator_event_interrupt = 0; - priv->scroll_delay_counter = priv->scrollbar_fade_delay; - - hildon_pannable_area_launch_fade_timeout (HILDON_PANNABLE_AREA (widget), 1.0); - } - } -} - -static void -hildon_pannable_area_launch_fade_timeout (HildonPannableArea * area, - gdouble alpha) -{ - HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (area)->priv; - - priv->scroll_indicator_alpha = alpha; - - if (!priv->scroll_indicator_timeout) - priv->scroll_indicator_timeout = - gdk_threads_add_timeout (SCROLL_FADE_TIMEOUT, - (GSourceFunc) hildon_pannable_area_scroll_indicator_fade, - area); -} - -static void -hildon_pannable_area_adjust_changed (HildonPannableArea * area, - gpointer data) -{ - if (GTK_WIDGET_REALIZED (area)) - hildon_pannable_area_refresh (area); -} - -static void -hildon_pannable_area_adjust_value_changed (HildonPannableArea * area, - gpointer data) -{ - if (GTK_WIDGET_REALIZED (area)) { - HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (area)->priv; - - hildon_pannable_area_redraw (area); - - if ((priv->vscroll_visible) || (priv->hscroll_visible)) { - priv->scroll_indicator_event_interrupt = 0; - priv->scroll_delay_counter = priv->scrollbar_fade_delay; - - hildon_pannable_area_launch_fade_timeout (area, 1.0); - } - } -} - -static void -hildon_pannable_area_redraw (HildonPannableArea * area) -{ - HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (area)->priv; - - /* Redraw scroll indicators */ - if (GTK_WIDGET_DRAWABLE (area)) { - if (priv->hscroll_visible) { - gdk_window_invalidate_rect (GTK_WIDGET (area)->window, - &priv->hscroll_rect, FALSE); - } - - if (priv->vscroll_visible) { - gdk_window_invalidate_rect (GTK_WIDGET (area)->window, - &priv->vscroll_rect, FALSE); - } - } -} - -static gboolean -hildon_pannable_area_scroll_indicator_fade(HildonPannableArea * area) -{ - HildonPannableAreaPrivate *priv = area->priv; - - /* if moving do not fade out */ - if (((ABS (priv->vel_y)>1.0)|| - (ABS (priv->vel_x)>1.0))&&(!priv->clicked)) { - - return TRUE; - } - - if (priv->scroll_indicator_event_interrupt) { - /* Stop a fade out, and fade back in */ - if (priv->scroll_indicator_alpha > 0.9) { - priv->scroll_indicator_alpha = 1.0; - priv->scroll_indicator_timeout = 0; - - return FALSE; - } else { - priv->scroll_indicator_alpha += 0.2; - hildon_pannable_area_redraw (area); - - return TRUE; - } - } - - if ((priv->scroll_indicator_alpha > 0.9) && - (priv->scroll_delay_counter > 0)) { - priv->scroll_delay_counter--; - - return TRUE; - } - - if (!priv->scroll_indicator_event_interrupt) { - /* Continue fade out */ - if (priv->scroll_indicator_alpha < 0.1) { - priv->scroll_indicator_timeout = 0; - priv->scroll_indicator_alpha = 0.0; - - return FALSE; - } else { - priv->scroll_indicator_alpha -= 0.2; - hildon_pannable_area_redraw (area); - - return TRUE; - } - } - - return TRUE; -} - -static gboolean -hildon_pannable_area_expose_event (GtkWidget * widget, - GdkEventExpose * event) -{ - - HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (widget)->priv; -#if USE_CAIRO_SCROLLBARS == 1 - GdkColor back_color = widget->style->bg[GTK_STATE_NORMAL]; - GdkColor scroll_color = widget->style->base[GTK_STATE_SELECTED]; -#else /* USE_CAIRO_SCROLLBARS */ - GdkColor back_color = widget->style->bg[GTK_STATE_NORMAL]; - GdkColor scroll_color = widget->style->fg[GTK_STATE_INSENSITIVE]; -#endif - - if (gtk_bin_get_child (GTK_BIN (widget))) { - - if (priv->scroll_indicator_alpha > 0.1) { - if (priv->vscroll_visible) { - hildon_pannable_draw_vscroll (widget, &back_color, &scroll_color); - } - if (priv->hscroll_visible) { - hildon_pannable_draw_hscroll (widget, &back_color, &scroll_color); - } - } - - /* draw overshooting rectangles */ - if (priv->overshot_dist_y > 0) { - gint overshot_height; - - overshot_height = MIN (priv->overshot_dist_y, widget->allocation.height - - (priv->hscroll_visible ? priv->hscroll_rect.height : 0)); - - gdk_draw_rectangle (widget->window, - widget->style->bg_gc[GTK_STATE_NORMAL], - TRUE, - 0, - 0, - widget->allocation.width - - (priv->vscroll_visible ? priv->vscroll_rect.width : 0), - overshot_height); - } else if (priv->overshot_dist_y < 0) { - gint overshot_height; - gint overshot_y; - - overshot_height = - MAX (priv->overshot_dist_y, - -(widget->allocation.height - - (priv->hscroll_visible ? priv->hscroll_rect.height : 0))); - - overshot_y = MAX (widget->allocation.height + - overshot_height - - (priv->hscroll_visible ? priv->hscroll_rect.height : 0), 0); - - gdk_draw_rectangle (widget->window, - widget->style->bg_gc[GTK_STATE_NORMAL], - TRUE, - 0, - overshot_y, - widget->allocation.width - - priv->vscroll_rect.width, - -overshot_height); - } - - if (priv->overshot_dist_x > 0) { - gint overshot_width; - - overshot_width = MIN (priv->overshot_dist_x, widget->allocation.width - - (priv->vscroll_visible ? priv->vscroll_rect.width : 0)); - - gdk_draw_rectangle (widget->window, - widget->style->bg_gc[GTK_STATE_NORMAL], - TRUE, - 0, - 0, - overshot_width, - widget->allocation.height - - (priv->hscroll_visible ? priv->hscroll_rect.height : 0)); - } else if (priv->overshot_dist_x < 0) { - gint overshot_width; - gint overshot_x; - - overshot_width = - MAX (priv->overshot_dist_x, - -(widget->allocation.width - - (priv->vscroll_visible ? priv->vscroll_rect.width : 0))); - - overshot_x = MAX (widget->allocation.width + - overshot_width - - (priv->vscroll_visible ? priv->vscroll_rect.width : 0), 0); - - gdk_draw_rectangle (widget->window, - widget->style->bg_gc[GTK_STATE_NORMAL], - TRUE, - overshot_x, - 0, - -overshot_width, - widget->allocation.height - - priv->hscroll_rect.height); - } - - } - - if (G_UNLIKELY (priv->initial_effect)) { - - hildon_pannable_area_initial_effect (widget); - - priv->initial_effect = FALSE; - } - - return GTK_WIDGET_CLASS (hildon_pannable_area_parent_class)->expose_event (widget, event); -} - -static GdkWindow * -hildon_pannable_area_get_topmost (GdkWindow * window, - gint x, gint y, - gint * tx, gint * ty, - GdkEventMask mask) -{ - /* Find the GdkWindow at the given point, by recursing from a given - * parent GdkWindow. Optionally return the co-ordinates transformed - * relative to the child window. - */ - gint width, height; - GList *c, *children; - GdkWindow *selected_window = NULL; - - gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height); - if ((x < 0) || (x >= width) || (y < 0) || (y >= height)) - return NULL; - - children = gdk_window_peek_children (window); - - if (!children) { - if (tx) - *tx = x; - if (ty) - *ty = y; - selected_window = window; - } - - for (c = children; c; c = c->next) { - GdkWindow *child = (GdkWindow *) c->data; - gint wx, wy; - - gdk_drawable_get_size (GDK_DRAWABLE (child), &width, &height); - gdk_window_get_position (child, &wx, &wy); - - if ((x >= wx) && (x < (wx + width)) && (y >= wy) && (y < (wy + height)) && - (gdk_window_is_visible (child))) { - - if (gdk_window_peek_children (child)) { - selected_window = hildon_pannable_area_get_topmost (child, x-wx, y-wy, - tx, ty, mask); - if (!selected_window) { - if (tx) - *tx = x; - if (ty) - *ty = y; - selected_window = child; - } - } else { - if ((gdk_window_get_events (child)&mask)) { - if (tx) - *tx = x-wx; - if (ty) - *ty = y-wy; - selected_window = child; - } - } - } - } - - return selected_window; -} - -static void -synth_crossing (GdkWindow * child, - gint x, gint y, - gint x_root, gint y_root, - guint32 time, gboolean in) -{ - GdkEventCrossing *crossing_event; - GdkEventType type = in ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY; - - /* Send synthetic enter event */ - crossing_event = (GdkEventCrossing *) gdk_event_new (type); - ((GdkEventAny *) crossing_event)->type = type; - ((GdkEventAny *) crossing_event)->window = g_object_ref (child); - ((GdkEventAny *) crossing_event)->send_event = FALSE; - crossing_event->subwindow = g_object_ref (child); - crossing_event->time = time; - crossing_event->x = x; - crossing_event->y = y; - crossing_event->x_root = x_root; - crossing_event->y_root = y_root; - crossing_event->mode = GDK_CROSSING_NORMAL; - crossing_event->detail = GDK_NOTIFY_UNKNOWN; - crossing_event->focus = FALSE; - crossing_event->state = 0; - gdk_event_put ((GdkEvent *) crossing_event); - gdk_event_free ((GdkEvent *) crossing_event); -} - -static gboolean -hildon_pannable_area_button_press_cb (GtkWidget * widget, - GdkEventButton * event) -{ - gint x, y; - HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (widget)->priv; - - if ((!priv->enabled) || (event->button != 1) || - ((event->time == priv->last_time) && - (priv->last_type == 1)) || (gtk_bin_get_child (GTK_BIN (widget)) == NULL)) - return TRUE; - - priv->scroll_indicator_event_interrupt = 1; - - hildon_pannable_area_launch_fade_timeout (HILDON_PANNABLE_AREA (widget), - priv->scroll_indicator_alpha); - - priv->last_time = event->time; - priv->last_type = 1; - - priv->scroll_to_x = -1; - priv->scroll_to_y = -1; - - if (priv->clicked && priv->child) { - /* Widget stole focus on last click, send crossing-out event */ - synth_crossing (priv->child, 0, 0, event->x_root, event->y_root, - event->time, FALSE); - } - - priv->x = event->x; - priv->y = event->y; - priv->ix = priv->x; - priv->iy = priv->y; - - /* Don't allow a click if we're still moving fast */ - if ((ABS (priv->vel_x) <= (priv->vmax * priv->vfast_factor)) && - (ABS (priv->vel_y) <= (priv->vmax * priv->vfast_factor))) - priv->child = - hildon_pannable_area_get_topmost (gtk_bin_get_child (GTK_BIN (widget))->window, - event->x, event->y, &x, &y, GDK_BUTTON_PRESS_MASK); - else - priv->child = NULL; - - priv->clicked = TRUE; - - /* Stop scrolling on mouse-down (so you can flick, then hold to stop) */ - priv->vel_x = 0; - priv->vel_y = 0; - - if (priv->child) { - - gdk_drawable_get_size (priv->child, &priv->child_width, - &priv->child_height); - priv->last_in = TRUE; - - g_object_add_weak_pointer ((GObject *) priv->child, - (gpointer) & priv->child); - - event = (GdkEventButton *) gdk_event_copy ((GdkEvent *) event); - event->x = x; - event->y = y; - priv->cx = x; - priv->cy = y; - - synth_crossing (priv->child, x, y, event->x_root, - event->y_root, event->time, TRUE); - - /* Send synthetic click (button press/release) event */ - ((GdkEventAny *) event)->window = g_object_ref (priv->child); - - gdk_event_put ((GdkEvent *) event); - gdk_event_free ((GdkEvent *) event); - } else - priv->child = NULL; - - return TRUE; -} - -static gboolean -hildon_pannable_area_check_scrollbars (HildonPannableArea * area) -{ - HildonPannableAreaPrivate *priv = area->priv; - gboolean prev_hscroll_visible, prev_vscroll_visible; - - prev_hscroll_visible = priv->hscroll_visible; - prev_vscroll_visible = priv->vscroll_visible; - - if (!gtk_bin_get_child (GTK_BIN (area))) { - priv->vscroll_visible = FALSE; - priv->hscroll_visible = FALSE; - } else { - switch (priv->hscrollbar_policy) { - case GTK_POLICY_ALWAYS: - priv->hscroll_visible = TRUE; - break; - case GTK_POLICY_NEVER: - priv->hscroll_visible = FALSE; - break; - default: - priv->hscroll_visible = (priv->hadjust->upper - priv->hadjust->lower > - priv->hadjust->page_size); - } - - switch (priv->vscrollbar_policy) { - case GTK_POLICY_ALWAYS: - priv->vscroll_visible = TRUE; - break; - case GTK_POLICY_NEVER: - priv->vscroll_visible = FALSE; - break; - default: - priv->vscroll_visible = (priv->vadjust->upper - priv->vadjust->lower > - priv->vadjust->page_size); - } - - /* Store the vscroll/hscroll areas for redrawing */ - if (priv->vscroll_visible) { - GtkAllocation *allocation = >K_WIDGET (area)->allocation; - priv->vscroll_rect.x = allocation->width - priv->indicator_width; - priv->vscroll_rect.y = 0; - priv->vscroll_rect.width = priv->indicator_width; - priv->vscroll_rect.height = allocation->height - - (priv->hscroll_visible ? priv->indicator_width : 0); - } - if (priv->hscroll_visible) { - GtkAllocation *allocation = >K_WIDGET (area)->allocation; - priv->hscroll_rect.y = allocation->height - priv->indicator_width; - priv->hscroll_rect.x = 0; - priv->hscroll_rect.height = priv->indicator_width; - priv->hscroll_rect.width = allocation->width - - (priv->vscroll_visible ? priv->indicator_width : 0); - } - } - - return ((priv->hscroll_visible != prev_hscroll_visible) || - (priv->vscroll_visible != prev_vscroll_visible)); -} - -static void -hildon_pannable_area_refresh (HildonPannableArea * area) -{ - if (GTK_WIDGET_DRAWABLE (area) && - hildon_pannable_area_check_scrollbars (area)) { - gtk_widget_queue_resize (GTK_WIDGET (area)); - } else { - hildon_pannable_area_redraw (area); - } -} - -/* Scroll by a particular amount (in pixels). Optionally, return if - * the scroll on a particular axis was successful. - */ -static void -hildon_pannable_axis_scroll (HildonPannableArea *area, - GtkAdjustment *adjust, - gdouble *vel, - gdouble inc, - gint *overshooting, - gint *overshot_dist, - gdouble *scroll_to, - gint overshoot_max, - gboolean *s) -{ - gdouble dist; - HildonPannableAreaPrivate *priv = area->priv; - - dist = gtk_adjustment_get_value (adjust) - inc; - - /* Overshooting - * We use overshot_dist to define the distance of the current overshoot, - * and overshooting to define the direction/whether or not we are overshot - */ - if (!(*overshooting)) { - - /* Initiation of the overshoot happens when the finger is released - * and the current position of the pannable contents are out of range - */ - if (dist < adjust->lower) { - if (s) *s = FALSE; - - dist = adjust->lower; - - if (overshoot_max!=0) { - *overshooting = 1; - *scroll_to = -1; - *overshot_dist = CLAMP (*overshot_dist + *vel, 0, overshoot_max); - *vel = MIN (priv->vmax_overshooting, *vel); - gtk_widget_queue_resize (GTK_WIDGET (area)); - } else { - *vel = 0.0; - } - } else if (dist > adjust->upper - adjust->page_size) { - if (s) *s = FALSE; - - dist = adjust->upper - adjust->page_size; - - if (overshoot_max!=0) { - *overshooting = 1; - *scroll_to = -1; - *overshot_dist = CLAMP (*overshot_dist + *vel, -overshoot_max, 0); - *vel = MAX (-priv->vmax_overshooting, *vel); - gtk_widget_queue_resize (GTK_WIDGET (area)); - } else { - *vel = 0.0; - } - } else { - if ((*scroll_to) != -1) { - if (((inc < 0)&&(*scroll_to <= dist))|| - ((inc > 0)&&(*scroll_to >= dist))) { - dist = *scroll_to; - *scroll_to = -1; - *vel = 0; - } - } - } - - gtk_adjustment_set_value (adjust, dist); - } else { - if (!priv->clicked) { - - /* When the overshoot has started we continue for - * PROP_BOUNCE_STEPS more steps into the overshoot before we - * reverse direction. The deceleration factor is calculated - * based on the percentage distance from the first item with - * each iteration, therefore always returning us to the - * top/bottom most element - */ - if (*overshot_dist > 0) { - - if ((*overshooting < priv->bounce_steps) && (*vel > 0)) { - (*overshooting)++; - *vel = (((gdouble)*overshot_dist)/overshoot_max) * (*vel); - } else if ((*overshooting >= priv->bounce_steps) && (*vel > 0)) { - *vel *= -1; - } else if ((*overshooting > 1) && (*vel < 0)) { - /* we add the MIN in order to avoid very small speeds */ - *vel = MIN ((((gdouble)*overshot_dist)*0.4) * -1, -2.0); - } - - *overshot_dist = CLAMP (*overshot_dist + *vel, 0, overshoot_max); - - gtk_widget_queue_resize (GTK_WIDGET (area)); - - } else if (*overshot_dist < 0) { - - if ((*overshooting < priv->bounce_steps) && (*vel < 0)) { - (*overshooting)++; - *vel = (((gdouble)*overshot_dist)/overshoot_max) * (*vel) * -1; - } else if ((*overshooting >= priv->bounce_steps) && (*vel < 0)) { - *vel *= -1; - } else if ((*overshooting > 1) && (*vel > 0)) { - /* we add the MAX in order to avoid very small speeds */ - *vel = MAX ((((gdouble)*overshot_dist)*0.4) * -1, 2.0); - } - - *overshot_dist = CLAMP (*overshot_dist + (*vel), -overshoot_max, 0); - - gtk_widget_queue_resize (GTK_WIDGET (area)); - - } else { - *overshooting = 0; - *vel = 0; - gtk_widget_queue_resize (GTK_WIDGET (area)); - } - } else { - - gint overshot_dist_old = *overshot_dist; - - if (*overshot_dist > 0) { - *overshot_dist = CLAMP ((*overshot_dist) + inc, 0, overshoot_max); - } else if (*overshot_dist < 0) { - *overshot_dist = CLAMP ((*overshot_dist) + inc, -1 * overshoot_max, 0); - } else { - *overshooting = 0; - gtk_adjustment_set_value (adjust, dist); - } - - if (*overshot_dist != overshot_dist_old) - gtk_widget_queue_resize (GTK_WIDGET (area)); - } - } -} - -static void -hildon_pannable_area_scroll (HildonPannableArea *area, - gdouble x, gdouble y) -{ - gboolean sx, sy; - HildonPannableAreaPrivate *priv = area->priv; - gboolean hscroll_visible, vscroll_visible; - - if (gtk_bin_get_child (GTK_BIN (area)) == NULL) - return; - - vscroll_visible = (priv->vadjust->upper - priv->vadjust->lower > - priv->vadjust->page_size); - hscroll_visible = (priv->hadjust->upper - priv->hadjust->lower > - priv->hadjust->page_size); - - sx = TRUE; - sy = TRUE; - - if (vscroll_visible) { - hildon_pannable_axis_scroll (area, priv->vadjust, &priv->vel_y, y, - &priv->overshooting_y, &priv->overshot_dist_y, - &priv->scroll_to_y, priv->vovershoot_max, &sy); - } else { - priv->vel_y = 0; - } - - if (hscroll_visible) { - hildon_pannable_axis_scroll (area, priv->hadjust, &priv->vel_x, x, - &priv->overshooting_x, &priv->overshot_dist_x, - &priv->scroll_to_x, priv->hovershoot_max, &sx); - } else { - priv->vel_x = 0; - } - - /* If the scroll on a particular axis wasn't succesful, reset the - * initial scroll position to the new mouse co-ordinate. This means - * when you get to the top of the page, dragging down works immediately. - */ - if (priv->mode == HILDON_PANNABLE_AREA_MODE_ACCEL) { - if (!sx) { - priv->x = priv->ex; - } - - if (!sy) { - priv->y = priv->ey; - } - } -} - -static gboolean -hildon_pannable_area_timeout (HildonPannableArea * area) -{ - HildonPannableAreaPrivate *priv = area->priv; - - if ((!priv->enabled) || (priv->mode == HILDON_PANNABLE_AREA_MODE_PUSH)) { - priv->idle_id = 0; - - return FALSE; - } - - if (!priv->clicked) { - /* Decelerate gradually when pointer is raised */ - if ((!priv->overshot_dist_y) && - (!priv->overshot_dist_x)) { - - /* in case we move to a specific point do not decelerate when arriving */ - if ((priv->scroll_to_x != -1)||(priv->scroll_to_y != -1)) { - - if (ABS (priv->vel_x) >= 1.5) { - priv->vel_x *= priv->decel; - } - - if (ABS (priv->vel_y) >= 1.5) { - priv->vel_y *= priv->decel; - } - - } else { - if ((!priv->low_friction_mode) || - ((priv->mov_mode&HILDON_MOVEMENT_MODE_HORIZ) && - (ABS (priv->vel_x) < 0.8*priv->vmax))) - priv->vel_x *= priv->decel; - - if ((!priv->low_friction_mode) || - ((priv->mov_mode&HILDON_MOVEMENT_MODE_VERT) && - (ABS (priv->vel_y) < 0.8*priv->vmax))) - priv->vel_y *= priv->decel; - - if ((ABS (priv->vel_x) < 1.0) && (ABS (priv->vel_y) < 1.0)) { - priv->vel_x = 0; - priv->vel_y = 0; - priv->idle_id = 0; - - return FALSE; - } - } - } - } else if (priv->mode == HILDON_PANNABLE_AREA_MODE_AUTO) { - priv->idle_id = 0; - - return FALSE; - } - - hildon_pannable_area_scroll (area, priv->vel_x, priv->vel_y); - - return TRUE; -} - -static void -hildon_pannable_area_calculate_velocity (gdouble *vel, - gdouble delta, - gdouble dist, - gdouble vmax, - gdouble drag_inertia, - gdouble force, - guint sps) -{ - gdouble rawvel; - - if (ABS (dist) >= RATIO_TOLERANCE) { - rawvel = (dist / ABS (delta)) * force; - *vel = *vel * (1 - drag_inertia) + - rawvel * drag_inertia; - *vel = *vel > 0 ? MIN (*vel, vmax) - : MAX (*vel, -1 * vmax); - } -} - -static gboolean -hildon_pannable_area_motion_event_scroll_timeout (HildonPannableArea *area) -{ - HildonPannableAreaPrivate *priv = area->priv; - - if ((priv->motion_x != 0)||(priv->motion_y != 0)) - hildon_pannable_area_scroll (area, priv->motion_x, priv->motion_y); - - priv->motion_event_scroll_timeout = 0; - - return FALSE; -} - -static void -hildon_pannable_area_motion_event_scroll (HildonPannableArea *area, - gdouble x, gdouble y) -{ - HildonPannableAreaPrivate *priv = area->priv; - - if (priv->motion_event_scroll_timeout) { - - priv->motion_x += x; - priv->motion_y += y; - - } else { - - /* we do not delay the first event but the next ones */ - hildon_pannable_area_scroll (area, x, y); - - priv->motion_x = 0; - priv->motion_y = 0; - - priv->motion_event_scroll_timeout = gdk_threads_add_timeout - ((gint) (1000.0 / (gdouble) MOTION_EVENTS_PER_SECOND), - (GSourceFunc) hildon_pannable_area_motion_event_scroll_timeout, area); - } -} - -static gboolean -hildon_pannable_area_motion_notify_cb (GtkWidget * widget, - GdkEventMotion * event) -{ - HildonPannableArea *area = HILDON_PANNABLE_AREA (widget); - HildonPannableAreaPrivate *priv = area->priv; - gdouble x, y; - gdouble delta; - - if (gtk_bin_get_child (GTK_BIN (widget)) == NULL) - return TRUE; - - if ((!priv->enabled) || (!priv->clicked) || - ((event->time == priv->last_time) && (priv->last_type == 2))) { - gdk_window_get_pointer (widget->window, NULL, NULL, 0); - return TRUE; - } - - if (priv->last_type == 1) { - priv->first_drag = TRUE; - } - - x = event->x - priv->x; - y = event->y - priv->y; - - if (priv->first_drag && (!priv->moved) && - ((ABS (x) > (priv->panning_threshold)) - || (ABS (y) > (priv->panning_threshold)))) { - priv->moved = TRUE; - x = 0; - y = 0; - - if (priv->first_drag) { - gboolean vscroll_visible; - gboolean hscroll_visible; - - if (ABS (priv->iy - event->y) >= - ABS (priv->ix - event->x)) { - - g_signal_emit (area, - pannable_area_signals[VERTICAL_MOVEMENT], - 0, (priv->iy > event->y) ? - HILDON_MOVEMENT_UP : - HILDON_MOVEMENT_DOWN, - (gdouble)priv->ix, (gdouble)priv->iy); - - vscroll_visible = (priv->vadjust->upper - priv->vadjust->lower > - priv->vadjust->page_size); - - if (!((vscroll_visible)&& - (priv->mov_mode&HILDON_MOVEMENT_MODE_VERT))) { - - hscroll_visible = (priv->hadjust->upper - priv->hadjust->lower > - priv->hadjust->page_size); - - /* even in case we do not have to move we check if this - could be a fake horizontal movement */ - if (!((hscroll_visible)&& - (priv->mov_mode&HILDON_MOVEMENT_MODE_HORIZ)) || - (ABS (priv->iy - event->y) - - ABS (priv->ix - event->x) >= priv->direction_error_margin)) - priv->moved = FALSE; - } - } else { - - g_signal_emit (area, - pannable_area_signals[HORIZONTAL_MOVEMENT], - 0, (priv->ix > event->x) ? - HILDON_MOVEMENT_LEFT : - HILDON_MOVEMENT_RIGHT, - (gdouble)priv->ix, (gdouble)priv->iy); - - hscroll_visible = (priv->hadjust->upper - priv->hadjust->lower > - priv->hadjust->page_size); - - if (!((hscroll_visible)&& - (priv->mov_mode&HILDON_MOVEMENT_MODE_HORIZ))) { - - vscroll_visible = (priv->vadjust->upper - priv->vadjust->lower > - priv->vadjust->page_size); - - /* even in case we do not have to move we check if this - could be a fake vertical movement */ - if (!((vscroll_visible) && - (priv->mov_mode&HILDON_MOVEMENT_MODE_VERT)) || - (ABS (priv->ix - event->x) - - ABS (priv->iy - event->y) >= priv->direction_error_margin)) - priv->moved = FALSE; - } - } - - if ((priv->moved)&&(priv->child)) { - gint pos_x, pos_y; - - pos_x = priv->cx + (event->x - priv->ix); - pos_y = priv->cy + (event->y - priv->iy); - - synth_crossing (priv->child, pos_x, pos_y, event->x_root, - event->y_root, event->time, FALSE); - } - } - - priv->first_drag = FALSE; - - if ((priv->mode != HILDON_PANNABLE_AREA_MODE_PUSH) && - (priv->mode != HILDON_PANNABLE_AREA_MODE_AUTO)) { - - if (!priv->idle_id) - priv->idle_id = gdk_threads_add_timeout ((gint) - (1000.0 / (gdouble) priv->sps), - (GSourceFunc) - hildon_pannable_area_timeout, area); - } - } - - if (priv->moved) { - switch (priv->mode) { - case HILDON_PANNABLE_AREA_MODE_PUSH: - /* Scroll by the amount of pixels the cursor has moved - * since the last motion event. - */ - hildon_pannable_area_motion_event_scroll (area, x, y); - priv->x = event->x; - priv->y = event->y; - break; - case HILDON_PANNABLE_AREA_MODE_ACCEL: - /* Set acceleration relative to the initial click */ - priv->ex = event->x; - priv->ey = event->y; - priv->vel_x = ((x > 0) ? 1 : -1) * - (((ABS (x) / - (gdouble) widget->allocation.width) * - (priv->vmax - priv->vmin)) + priv->vmin); - priv->vel_y = ((y > 0) ? 1 : -1) * - (((ABS (y) / - (gdouble) widget->allocation.height) * - (priv->vmax - priv->vmin)) + priv->vmin); - break; - case HILDON_PANNABLE_AREA_MODE_AUTO: - - delta = event->time - priv->last_time; - - if (priv->mov_mode&HILDON_MOVEMENT_MODE_VERT) { - gdouble dist = event->y - priv->y; - - hildon_pannable_area_calculate_velocity (&priv->vel_y, - delta, - dist, - priv->vmax, - priv->drag_inertia, - priv->force, - priv->sps); - } else { - y = 0; - priv->vel_y = 0; - } - - if (priv->mov_mode&HILDON_MOVEMENT_MODE_HORIZ) { - gdouble dist = event->x - priv->x; - - hildon_pannable_area_calculate_velocity (&priv->vel_x, - delta, - dist, - priv->vmax, - priv->drag_inertia, - priv->force, - priv->sps); - } else { - x = 0; - priv->vel_x = 0; - } - - hildon_pannable_area_motion_event_scroll (area, x, y); - - if (priv->mov_mode&HILDON_MOVEMENT_MODE_HORIZ) - priv->x = event->x; - if (priv->mov_mode&HILDON_MOVEMENT_MODE_VERT) - priv->y = event->y; - - break; - - default: - break; - } - } else if (priv->child) { - gboolean in; - gint pos_x, pos_y; - - pos_x = priv->cx + (event->x - priv->ix); - pos_y = priv->cy + (event->y - priv->iy); - - in = (((0 <= pos_x)&&(priv->child_width >= pos_x)) && - ((0 <= pos_y)&&(priv->child_height >= pos_y))); - - if (((!priv->last_in)&&in)||((priv->last_in)&&(!in))) { - - synth_crossing (priv->child, pos_x, pos_y, event->x_root, - event->y_root, event->time, in); - - priv->last_in = in; - } - } - - priv->last_time = event->time; - priv->last_type = 2; - - if (priv->child) { - /* Send motion notify to child */ - event = (GdkEventMotion *) gdk_event_copy ((GdkEvent *) event); - event->x = priv->cx + (event->x - priv->ix); - event->y = priv->cy + (event->y - priv->iy); - event->window = g_object_ref (priv->child); - gdk_event_put ((GdkEvent *) event); - gdk_event_free ((GdkEvent *) event); - } - - gdk_window_get_pointer (widget->window, NULL, NULL, 0); - - return TRUE; -} - -static gboolean -hildon_pannable_leave_notify_event (GtkWidget *widget, - GdkEventCrossing *event) -{ - HildonPannableArea *area = HILDON_PANNABLE_AREA (widget); - HildonPannableAreaPrivate *priv = area->priv; - - if ((priv->child)&&(priv->last_in)) { - priv->last_in = FALSE; - - synth_crossing (priv->child, 0, 0, event->x_root, - event->y_root, event->time, FALSE); - } - - return FALSE; -} - -static gboolean -hildon_pannable_area_button_release_cb (GtkWidget * widget, - GdkEventButton * event) -{ - HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (widget)->priv; - gint x, y; - GdkWindow *child; - - if (((event->time == priv->last_time) && (priv->last_type == 3)) - || (gtk_bin_get_child (GTK_BIN (widget)) == NULL) - || (!priv->clicked) || (!priv->enabled) || (event->button != 1)) - return TRUE; - - priv->scroll_indicator_event_interrupt = 0; - priv->scroll_delay_counter = priv->scrollbar_fade_delay; - - /* move all the way to the last position */ - if (priv->motion_event_scroll_timeout) { - g_source_remove (priv->motion_event_scroll_timeout); - hildon_pannable_area_motion_event_scroll_timeout (HILDON_PANNABLE_AREA (widget)); - priv->motion_x = 0; - priv->motion_y = 0; - } - - if (priv->last_type == 2) { - gdouble delta = event->time - priv->last_time; - - if (priv->mov_mode&HILDON_MOVEMENT_MODE_VERT) { - gdouble dist = event->y - priv->y; - - if (ABS (dist) >= 1.0) { - hildon_pannable_area_calculate_velocity (&priv->vel_y, - delta, - dist, - priv->vmax, - priv->drag_inertia, - priv->force, - priv->sps); - - priv->motion_y = dist; - hildon_pannable_area_motion_event_scroll_timeout (HILDON_PANNABLE_AREA (widget)); - } else - if (delta >= CURSOR_STOPPED_TIMEOUT) { - y = 0; - priv->vel_y = 0; - } - } - - if (priv->mov_mode&HILDON_MOVEMENT_MODE_HORIZ) { - gdouble dist = event->x - priv->x; - - if (ABS (dist) >= 1.0) { - hildon_pannable_area_calculate_velocity (&priv->vel_x, - delta, - dist, - priv->vmax, - priv->drag_inertia, - priv->force, - priv->sps); - priv->motion_x = dist; - hildon_pannable_area_motion_event_scroll_timeout (HILDON_PANNABLE_AREA (widget)); - } else - if (delta >= CURSOR_STOPPED_TIMEOUT) { - x = 0; - priv->vel_x = 0; - } - } - } - - if ((ABS (priv->vel_y) > 1.0)|| - (ABS (priv->vel_x) > 1.0)) { - priv->scroll_indicator_alpha = 1.0; - } - - hildon_pannable_area_launch_fade_timeout (HILDON_PANNABLE_AREA (widget), - priv->scroll_indicator_alpha); - - priv->clicked = FALSE; - - if (priv->mode == HILDON_PANNABLE_AREA_MODE_AUTO || - priv->mode == HILDON_PANNABLE_AREA_MODE_ACCEL) { - - /* If overshoot has been initiated with a finger down, on release set max speed */ - if (priv->overshot_dist_y != 0) { - priv->overshooting_y = priv->bounce_steps; /* Hack to stop a bounce in the finger down case */ - priv->vel_y = priv->vmax_overshooting; - } - - if (priv->overshot_dist_x != 0) { - priv->overshooting_x = priv->bounce_steps; /* Hack to stop a bounce in the finger down case */ - priv->vel_x = priv->vmax_overshooting; - } - - if ((ABS (priv->vel_y) >= priv->vmin) || - (ABS (priv->vel_x) >= priv->vmin)) { - - if (!priv->idle_id) - priv->idle_id = gdk_threads_add_timeout ((gint) (1000.0 / (gdouble) priv->sps), - (GSourceFunc) - hildon_pannable_area_timeout, widget); - } - } - - priv->last_time = event->time; - priv->last_type = 3; - - if (!priv->child) { - priv->moved = FALSE; - return TRUE; - } - - child = - hildon_pannable_area_get_topmost (gtk_bin_get_child (GTK_BIN (widget))->window, - event->x, event->y, &x, &y, GDK_BUTTON_RELEASE_MASK); - - event = (GdkEventButton *) gdk_event_copy ((GdkEvent *) event); - event->x = x; - event->y = y; - - /* Leave the widget if we've moved - This doesn't break selection, - * but stops buttons from being clicked. - */ - if ((child != priv->child) || (priv->moved)) { - /* Send synthetic leave event */ - synth_crossing (priv->child, x, y, event->x_root, - event->y_root, event->time, FALSE); - /* Send synthetic button release event */ - ((GdkEventAny *) event)->window = g_object_ref (priv->child); - gdk_event_put ((GdkEvent *) event); - } else { - /* Send synthetic button release event */ - ((GdkEventAny *) event)->window = g_object_ref (child); - gdk_event_put ((GdkEvent *) event); - /* Send synthetic leave event */ - synth_crossing (priv->child, x, y, event->x_root, - event->y_root, event->time, FALSE); - } - g_object_remove_weak_pointer ((GObject *) priv->child, - (gpointer) & priv->child); - - priv->moved = FALSE; - gdk_event_free ((GdkEvent *) event); - - return TRUE; -} - -/* utility event handler */ -static gboolean -hildon_pannable_area_scroll_cb (GtkWidget *widget, - GdkEventScroll *event) -{ - GtkAdjustment *adj = NULL; - HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (widget)->priv; - - if ((!priv->enabled) || - (gtk_bin_get_child (GTK_BIN (widget)) == NULL)) - return TRUE; - - priv->scroll_indicator_event_interrupt = 0; - priv->scroll_delay_counter = priv->scrollbar_fade_delay + 20; - - hildon_pannable_area_launch_fade_timeout (HILDON_PANNABLE_AREA (widget), 1.0); - - /* Stop inertial scrolling */ - if (priv->idle_id) { - priv->vel_x = 0.0; - priv->vel_y = 0.0; - priv->overshooting_x = 0; - priv->overshooting_y = 0; - - if ((priv->overshot_dist_x>0)||(priv->overshot_dist_y>0)) { - priv->overshot_dist_x = 0; - priv->overshot_dist_y = 0; - - gtk_widget_queue_resize (GTK_WIDGET (widget)); - } - - g_source_remove (priv->idle_id); - priv->idle_id = 0; - } - - if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_DOWN) - adj = priv->vadjust; - else - adj = priv->hadjust; - - if (adj) - { - gdouble delta, new_value; - - /* from gtkrange.c calculate delta*/ - delta = pow (adj->page_size, 2.0 / 3.0); - - if (event->direction == GDK_SCROLL_UP || - event->direction == GDK_SCROLL_LEFT) - delta = - delta; - - new_value = CLAMP (adj->value + delta, adj->lower, adj->upper - adj->page_size); - - gtk_adjustment_set_value (adj, new_value); - } - - return TRUE; -} - -static void -hildon_pannable_area_child_mapped (GtkWidget *widget, - GdkEvent *event, - gpointer user_data) -{ - HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (user_data)->priv; - - if (priv->event_window != NULL && priv->enabled) - gdk_window_raise (priv->event_window); -} - -static void -hildon_pannable_area_add (GtkContainer *container, GtkWidget *child) -{ - HildonPannableAreaPrivate *priv = HILDON_PANNABLE_AREA (container)->priv; - - g_return_if_fail (gtk_bin_get_child (GTK_BIN (container)) == NULL); - - gtk_widget_set_parent (child, GTK_WIDGET (container)); - GTK_BIN (container)->child = child; - - g_signal_connect_after (child, "map-event", - G_CALLBACK (hildon_pannable_area_child_mapped), - container); - - if (!gtk_widget_set_scroll_adjustments (child, priv->hadjust, priv->vadjust)) { - g_warning ("%s: cannot add non scrollable widget, " - "wrap it in a viewport", __FUNCTION__); - } -} - -static void -hildon_pannable_area_remove (GtkContainer *container, GtkWidget *child) -{ - g_return_if_fail (HILDON_IS_PANNABLE_AREA (container)); - g_return_if_fail (child != NULL); - g_return_if_fail (gtk_bin_get_child (GTK_BIN (container)) == child); - - gtk_widget_set_scroll_adjustments (child, NULL, NULL); - - g_signal_handlers_disconnect_by_func (child, - hildon_pannable_area_child_mapped, - container); - - /* chain parent class handler to remove child */ - GTK_CONTAINER_CLASS (hildon_pannable_area_parent_class)->remove (container, child); -} - -static void -hildon_pannable_calculate_vel_factor (HildonPannableArea * self) -{ - HildonPannableAreaPrivate *priv = self->priv; - gfloat fct = 0; - gfloat fct_i = 1; - gint i, n; - - n = ceil (priv->sps * priv->scroll_time); - - for (i = 0; i < n && fct_i >= RATIO_TOLERANCE; i++) { - fct_i *= priv->decel; - fct += fct_i; - } - - priv->vel_factor = fct; -} - -/** - * hildon_pannable_area_new: - * - * Create a new pannable area widget - * - * Returns: the newly created #HildonPannableArea - * - * Since: 2.2 - */ - -GtkWidget * -hildon_pannable_area_new (void) -{ - return g_object_new (HILDON_TYPE_PANNABLE_AREA, NULL); -} - -/** - * hildon_pannable_area_new_full: - * @mode: #HildonPannableAreaMode - * @enabled: Value for the enabled property - * @vel_min: Value for the velocity-min property - * @vel_max: Value for the velocity-max property - * @decel: Value for the deceleration property - * @sps: Value for the sps property - * - * Create a new #HildonPannableArea widget and set various properties - * - * returns: the newly create #HildonPannableArea - * - * Since: 2.2 - */ - -GtkWidget * -hildon_pannable_area_new_full (gint mode, gboolean enabled, - gdouble vel_min, gdouble vel_max, - gdouble decel, guint sps) -{ - return g_object_new (HILDON_TYPE_PANNABLE_AREA, - "mode", mode, - "enabled", enabled, - "velocity_min", vel_min, - "velocity_max", vel_max, - "deceleration", decel, "sps", sps, NULL); -} - -/** - * hildon_pannable_area_add_with_viewport: - * @area: A #HildonPannableArea - * @child: Child widget to add to the viewport - * - * Convenience function used to add a child to a #GtkViewport, and add the - * viewport to the scrolled window. - * - * Since: 2.2 - */ - -void -hildon_pannable_area_add_with_viewport (HildonPannableArea * area, - GtkWidget * child) -{ - GtkBin *bin; - GtkWidget *viewport; - - g_return_if_fail (HILDON_IS_PANNABLE_AREA (area)); - g_return_if_fail (GTK_IS_WIDGET (child)); - g_return_if_fail (child->parent == NULL); - - bin = GTK_BIN (area); - - if (bin->child != NULL) - { - g_return_if_fail (GTK_IS_VIEWPORT (bin->child)); - g_return_if_fail (GTK_BIN (bin->child)->child == NULL); - - viewport = bin->child; - } - else - { - HildonPannableAreaPrivate *priv = area->priv; - - viewport = gtk_viewport_new (priv->hadjust, - priv->vadjust); - gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport), GTK_SHADOW_NONE); - gtk_container_add (GTK_CONTAINER (area), viewport); - } - - gtk_widget_show (viewport); - gtk_container_add (GTK_CONTAINER (viewport), child); -} - -/** - * hildon_pannable_area_scroll_to: - * @area: A #HildonPannableArea. - * @x: The x coordinate of the destination point or -1 to ignore this axis. - * @y: The y coordinate of the destination point or -1 to ignore this axis. - * - * Smoothly scrolls @area to ensure that (@x, @y) is a visible point - * on the widget. To move in only one coordinate, you must set the other one - * to -1. Notice that, in %HILDON_PANNABLE_AREA_MODE_PUSH mode, this function - * works just like hildon_pannable_area_jump_to(). - * - * This function is useful if you need to present the user with a particular - * element inside a scrollable widget, like #GtkTreeView. For instance, - * the following example shows how to scroll inside a #GtkTreeView to - * make visible an item, indicated by the #GtkTreeIter @iter. - * - * - * - * GtkTreePath *path; - * GdkRectangle *rect; - * - * path = gtk_tree_model_get_path (model, &iter); - * gtk_tree_view_get_background_area (GTK_TREE_VIEW (treeview), - * path, NULL, &rect); - * gtk_tree_view_convert_bin_window_to_tree_coords (GTK_TREE_VIEW (treeview), - * 0, rect.y, NULL, &y); - * hildon_pannable_area_scroll_to (panarea, -1, y); - * gtk_tree_path_free (path); - * - * - * - * If you want to present a child widget in simpler scenarios, - * use hildon_pannable_area_scroll_to_child() instead. - * - * There is a precondition to this function: the widget must be - * already realized. Check the hildon_pannable_area_jump_to_child() for - * more tips regarding how to call this function during - * initialization. - * - * Since: 2.2 - **/ -void -hildon_pannable_area_scroll_to (HildonPannableArea *area, - const gint x, const gint y) -{ - HildonPannableAreaPrivate *priv; - gint width, height; - gint dist_x, dist_y; - gboolean hscroll_visible, vscroll_visible; - - g_return_if_fail (GTK_WIDGET_REALIZED (area)); - g_return_if_fail (HILDON_IS_PANNABLE_AREA (area)); - - priv = area->priv; - - vscroll_visible = (priv->vadjust->upper - priv->vadjust->lower > - priv->vadjust->page_size); - hscroll_visible = (priv->hadjust->upper - priv->hadjust->lower > - priv->hadjust->page_size); - - if (((!vscroll_visible)&&(!hscroll_visible)) || - (x == -1 && y == -1)) { - return; - } - - if (priv->mode == HILDON_PANNABLE_AREA_MODE_PUSH) - hildon_pannable_area_jump_to (area, x, y); - - width = priv->hadjust->upper - priv->hadjust->lower; - height = priv->vadjust->upper - priv->vadjust->lower; - - g_return_if_fail (x < width || y < height); - - if ((x > -1)&&(hscroll_visible)) { - priv->scroll_to_x = x - priv->hadjust->page_size/2; - dist_x = priv->scroll_to_x - priv->hadjust->value; - if (dist_x == 0) { - priv->scroll_to_x = -1; - } else { - priv->vel_x = - dist_x/priv->vel_factor; - } - } else { - priv->scroll_to_x = -1; - } - - if ((y > -1)&&(vscroll_visible)) { - priv->scroll_to_y = y - priv->vadjust->page_size/2; - dist_y = priv->scroll_to_y - priv->vadjust->value; - if (dist_y == 0) { - priv->scroll_to_y = -1; - } else { - priv->vel_y = - dist_y/priv->vel_factor; - } - } else { - priv->scroll_to_y = y; - } - - if ((priv->scroll_to_y == -1) && (priv->scroll_to_y == -1)) { - return; - } - - hildon_pannable_area_launch_fade_timeout (area, 1.0); - - if (!priv->idle_id) - priv->idle_id = gdk_threads_add_timeout ((gint) (1000.0 / (gdouble) priv->sps), - (GSourceFunc) - hildon_pannable_area_timeout, area); -} - -/** - * hildon_pannable_area_jump_to: - * @area: A #HildonPannableArea. - * @x: The x coordinate of the destination point or -1 to ignore this axis. - * @y: The y coordinate of the destination point or -1 to ignore this axis. - * - * Jumps the position of @area to ensure that (@x, @y) is a visible - * point in the widget. In order to move in only one coordinate, you - * must set the other one to -1. See hildon_pannable_area_scroll_to() - * function for an example of how to calculate the position of - * children in scrollable widgets like #GtkTreeview. - * - * There is a precondition to this function: the widget must be - * already realized. Check the hildon_pannable_area_jump_to_child() for - * more tips regarding how to call this function during - * initialization. - * - * Since: 2.2 - **/ -void -hildon_pannable_area_jump_to (HildonPannableArea *area, - const gint x, const gint y) -{ - HildonPannableAreaPrivate *priv; - gint width, height; - - g_return_if_fail (HILDON_IS_PANNABLE_AREA (area)); - g_return_if_fail (GTK_WIDGET_REALIZED (area)); - g_return_if_fail (x >= -1 && y >= -1); - - if (x == -1 && y == -1) { - return; - } - - priv = area->priv; - - width = priv->hadjust->upper - priv->hadjust->lower; - height = priv->vadjust->upper - priv->vadjust->lower; - - g_return_if_fail (x < width || y < height); - - if (x != -1) { - gdouble jump_to = x - priv->hadjust->page_size/2; - - if (jump_to > priv->hadjust->upper - priv->hadjust->page_size) { - jump_to = priv->hadjust->upper - priv->hadjust->page_size; - } - - gtk_adjustment_set_value (priv->hadjust, jump_to); - } - - if (y != -1) { - gdouble jump_to = y - priv->vadjust->page_size/2; - - if (jump_to > priv->vadjust->upper - priv->vadjust->page_size) { - jump_to = priv->vadjust->upper - priv->vadjust->page_size; - } - - gtk_adjustment_set_value (priv->vadjust, jump_to); - } - - priv->scroll_indicator_alpha = 1.0; - - if (priv->scroll_indicator_timeout) { - g_source_remove (priv->scroll_indicator_timeout); - priv->scroll_indicator_timeout = 0; - } - - if (priv->idle_id) { - priv->vel_x = 0.0; - priv->vel_y = 0.0; - priv->overshooting_x = 0; - priv->overshooting_y = 0; - - if ((priv->overshot_dist_x>0)||(priv->overshot_dist_y>0)) { - priv->overshot_dist_x = 0; - priv->overshot_dist_y = 0; - - gtk_widget_queue_resize (GTK_WIDGET (area)); - } - - g_source_remove (priv->idle_id); - priv->idle_id = 0; - } -} - -/** - * hildon_pannable_area_scroll_to_child: - * @area: A #HildonPannableArea. - * @child: A #GtkWidget, descendant of @area. - * - * Smoothly scrolls until @child is visible inside @area. @child must - * be a descendant of @area. If you need to scroll inside a scrollable - * widget, e.g., #GtkTreeview, see hildon_pannable_area_scroll_to(). - * - * There is a precondition to this function: the widget must be - * already realized. Check the hildon_pannable_area_jump_to_child() for - * more tips regarding how to call this function during - * initialization. - * - * Since: 2.2 - **/ -void -hildon_pannable_area_scroll_to_child (HildonPannableArea *area, GtkWidget *child) -{ - GtkWidget *bin_child; - gint x, y; - - g_return_if_fail (GTK_WIDGET_REALIZED (area)); - g_return_if_fail (HILDON_IS_PANNABLE_AREA (area)); - g_return_if_fail (GTK_IS_WIDGET (child)); - g_return_if_fail (gtk_widget_is_ancestor (child, GTK_WIDGET (area))); - - if (GTK_BIN (area)->child == NULL) - return; - - /* We need to get to check the child of the inside the area */ - bin_child = GTK_BIN (area)->child; - - /* we check if we added a viewport */ - if (GTK_IS_VIEWPORT (bin_child)) { - bin_child = GTK_BIN (bin_child)->child; - } - - if (gtk_widget_translate_coordinates (child, bin_child, 0, 0, &x, &y)) - hildon_pannable_area_scroll_to (area, x, y); -} - -/** - * hildon_pannable_area_jump_to_child: - * @area: A #HildonPannableArea. - * @child: A #GtkWidget, descendant of @area. - * - * Jumps to make sure @child is visible inside @area. @child must - * be a descendant of @area. If you want to move inside a scrollable - * widget, like, #GtkTreeview, see hildon_pannable_area_scroll_to(). - * - * There is a precondition to this function: the widget must be - * already realized. You can control if the widget is ready with the - * GTK_WIDGET_REALIZED macro. If you want to call this function during - * the initialization process of the widget do it inside a callback to - * the ::realize signal, using g_signal_connect_after() function. - * - * Since: 2.2 - **/ -void -hildon_pannable_area_jump_to_child (HildonPannableArea *area, GtkWidget *child) -{ - GtkWidget *bin_child; - gint x, y; - - g_return_if_fail (GTK_WIDGET_REALIZED (area)); - g_return_if_fail (HILDON_IS_PANNABLE_AREA (area)); - g_return_if_fail (GTK_IS_WIDGET (child)); - g_return_if_fail (gtk_widget_is_ancestor (child, GTK_WIDGET (area))); - - if (gtk_bin_get_child (GTK_BIN (area)) == NULL) - return; - - /* We need to get to check the child of the inside the area */ - bin_child = gtk_bin_get_child (GTK_BIN (area)); - - /* we check if we added a viewport */ - if (GTK_IS_VIEWPORT (bin_child)) { - bin_child = gtk_bin_get_child (GTK_BIN (bin_child)); - } - - if (gtk_widget_translate_coordinates (child, bin_child, 0, 0, &x, &y)) - hildon_pannable_area_jump_to (area, x, y); -} - -/** - * hildon_pannable_get_child_widget_at: - * @area: A #HildonPannableArea. - * @x: horizontal coordinate of the point - * @y: vertical coordinate of the point - * - * Get the widget at the point (x, y) inside the pannable area. In - * case no widget found it returns NULL. - * - * returns: the #GtkWidget if we find a widget, NULL in any other case - * - * Since: 2.2 - **/ -GtkWidget* -hildon_pannable_get_child_widget_at (HildonPannableArea *area, - gdouble x, gdouble y) -{ - GdkWindow *window = NULL; - GtkWidget *child_widget = NULL; - - window = hildon_pannable_area_get_topmost - (gtk_bin_get_child (GTK_BIN (area))->window, - x, y, NULL, NULL, GDK_ALL_EVENTS_MASK); - - gdk_window_get_user_data (window, (gpointer) &child_widget); - - return child_widget; -} - - -/** - * hildon_pannable_area_get_hadjustment: - * @area: A #HildonPannableArea. - * - * Returns the horizontal adjustment. This adjustment is the internal - * widget adjustment used to control the animations. Do not modify it - * directly to change the position of the pannable, to do that use the - * pannable API. If you modify the object directly it could cause - * artifacts in the animations. - * - * returns: The horizontal #GtkAdjustment - * - * Since: 2.2 - **/ -GtkAdjustment* -hildon_pannable_area_get_hadjustment (HildonPannableArea *area) -{ - - g_return_val_if_fail (HILDON_IS_PANNABLE_AREA (area), NULL); - - return area->priv->hadjust; -} - -/** - * hildon_pannable_area_get_vadjustment: - * @area: A #HildonPannableArea. - * - * Returns the vertical adjustment. This adjustment is the internal - * widget adjustment used to control the animations. Do not modify it - * directly to change the position of the pannable, to do that use the - * pannable API. If you modify the object directly it could cause - * artifacts in the animations. - * - * returns: The vertical #GtkAdjustment - * - * Since: 2.2 - **/ -GtkAdjustment* -hildon_pannable_area_get_vadjustment (HildonPannableArea *area) -{ - g_return_val_if_fail (HILDON_IS_PANNABLE_AREA (area), NULL); - - return area->priv->vadjust; -} - - -/** - * hildon_pannable_area_get_size_request_policy: - * @area: A #HildonPannableArea. - * - * This function returns the current size request policy of the - * widget. That policy controls the way the size_request is done in - * the pannable area. Check - * hildon_pannable_area_set_size_request_policy() for a more detailed - * explanation. - * - * returns: the policy is currently being used in the widget - * #HildonSizeRequestPolicy. - * - * Since: 2.2 - **/ -HildonSizeRequestPolicy -hildon_pannable_area_get_size_request_policy (HildonPannableArea *area) -{ - HildonPannableAreaPrivate *priv; - - g_return_val_if_fail (HILDON_IS_PANNABLE_AREA (area), FALSE); - - priv = area->priv; - - return priv->size_request_policy; -} - -/** - * hildon_pannable_area_set_size_request_policy: - * @area: A #HildonPannableArea. - * @size_request_policy: One of the allowed #HildonSizeRequestPolicy - * - * This function sets the pannable area size request policy. That - * policy controls the way the size_request is done in the pannable - * area. Pannable can use the size request of its children - * (#HILDON_SIZE_REQUEST_CHILDREN) or the minimum size required for - * the area itself (#HILDON_SIZE_REQUEST_MINIMUM), the latter is the - * default. Recall this size depends on the scrolling policy you are - * requesting to the pannable area, if you set #GTK_POLICY_NEVER this - * parameter will not have any effect with - * #HILDON_SIZE_REQUEST_MINIMUM set. - * - * Since: 2.2 - * - * Deprecated: This method and the policy request is deprecated, DO - * NOT use it in future code, the only policy properly supported in - * gtk+ nowadays is the minimum size. Use #gtk_window_set_default_size - * or #gtk_window_set_geometry_hints with the proper size in your case - * to define the height of your dialogs. - **/ -void -hildon_pannable_area_set_size_request_policy (HildonPannableArea *area, - HildonSizeRequestPolicy size_request_policy) -{ - HildonPannableAreaPrivate *priv; - - g_return_if_fail (HILDON_IS_PANNABLE_AREA (area)); - - priv = area->priv; - - if (priv->size_request_policy == size_request_policy) - return; - - priv->size_request_policy = size_request_policy; - - gtk_widget_queue_resize (GTK_WIDGET (area)); - - g_object_notify (G_OBJECT (area), "size-request-policy"); -} - diff --git a/src/hildon-pannable-area.h b/src/hildon-pannable-area.h deleted file mode 100644 index e1c59a7..0000000 --- a/src/hildon-pannable-area.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * This widget is based on MokoFingerScroll from libmokoui - * OpenMoko Application Framework UI Library - * Authored by Chris Lord - * Copyright (C) 2006-2007 OpenMoko Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser Public License as published by - * the Free Software Foundation; version 2 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser Public License for more details. - * - */ - -#ifndef _HILDON_PANNABLE_AREA -#define _HILDON_PANNABLE_AREA - -#include - -G_BEGIN_DECLS - -#define HILDON_TYPE_PANNABLE_AREA \ - hildon_pannable_area_get_type() - -#define HILDON_PANNABLE_AREA(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - HILDON_TYPE_PANNABLE_AREA, HildonPannableArea)) - -#define HILDON_PANNABLE_AREA_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - HILDON_TYPE_PANNABLE_AREA, HildonPannableAreaClass)) - -#define HILDON_IS_PANNABLE_AREA(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_PANNABLE_AREA)) - -#define HILDON_IS_PANNABLE_AREA_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_PANNABLE_AREA)) - -#define HILDON_PANNABLE_AREA_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - HILDON_TYPE_PANNABLE_AREA, HildonPannableAreaClass)) - -/** - * HildonPannableAreaMode: - * @HILDON_PANNABLE_AREA_MODE_PUSH: Areaing follows pointer - * @HILDON_PANNABLE_AREA_MODE_ACCEL: Areaing uses physics to "spin" the widget - * @HILDON_PANNABLE_AREA_MODE_AUTO: Automatically chooses between push and accel - * modes, depending on input. - * - * Used to change the behaviour of the pannable areaing - */ -typedef enum { - HILDON_PANNABLE_AREA_MODE_PUSH, - HILDON_PANNABLE_AREA_MODE_ACCEL, - HILDON_PANNABLE_AREA_MODE_AUTO -} HildonPannableAreaMode; - -/** - * HildonMovementMode: - * @HILDON_MOVEMENT_MODE_HORIZ: - * @HILDON_MOVEMENT_MODE_VERT: - * @HILDON_MOVEMENT_MODE_BOTH: - * - * Used to control the movement of the pannable, we can allow or - * disallow horizontal or vertical movement. This way the applications - * can control the movement using scroll_to and jump_to functions - */ -typedef enum { - HILDON_MOVEMENT_MODE_HORIZ = 1 << 1, - HILDON_MOVEMENT_MODE_VERT = 1 << 2, - HILDON_MOVEMENT_MODE_BOTH = 0x000006 -} HildonMovementMode; - -/** - * HildonMovementDirection: - * @HILDON_MOVEMENT_UP: - * @HILDON_MOVEMENT_DOWN: - * @HILDON_MOVEMENT_LEFT: - * @HILDON_MOVEMENT_RIGHT: - * - * Used to point out the direction of the movement - */ -typedef enum { - HILDON_MOVEMENT_UP, - HILDON_MOVEMENT_DOWN, - HILDON_MOVEMENT_LEFT, - HILDON_MOVEMENT_RIGHT -} HildonMovementDirection; - -/** - * HildonSizeRequestPolicy: - * @HILDON_SIZE_REQUEST_MINIMUM: The minimum size the widget could use - * to paint itself - * @HILDON_SIZE_REQUEST_CHILDREN: The minimum size of the children of - * the widget - * - * Used to control the size request policy of the widget - * - * Deprecated: This define and the policy request is deprecated, DO - * NOT use it in future code. Check - * #hildon_pannable_area_set_size_request_policy documentation for - * more information. - */ -#ifndef HILDON_DISABLE_DEPRECATED -typedef enum { - HILDON_SIZE_REQUEST_MINIMUM, - HILDON_SIZE_REQUEST_CHILDREN -} HildonSizeRequestPolicy; -#endif - -/** - * HildonPannableArea: - * - * HildonPannableArea has no publicly accessible fields - */ -typedef struct _HildonPannableArea HildonPannableArea; -typedef struct _HildonPannableAreaClass HildonPannableAreaClass; -typedef struct _HildonPannableAreaPrivate HildonPannableAreaPrivate; - -struct _HildonPannableArea -{ - GtkBin parent; - - /* private */ - HildonPannableAreaPrivate *priv; -}; - -struct _HildonPannableAreaClass -{ - GtkBinClass parent_class; - - void (* horizontal_movement) (HildonPannableArea *area, - HildonMovementDirection direction, - gdouble x, gdouble y); - void (* vertical_movement) (HildonPannableArea *area, - HildonMovementDirection direction, - gdouble x, gdouble y); -}; - -GType hildon_pannable_area_get_type (void); - -GtkWidget* hildon_pannable_area_new (void); -GtkWidget* hildon_pannable_area_new_full (gint mode, gboolean enabled, - gdouble vel_min, gdouble vel_max, - gdouble decel, guint sps); -void hildon_pannable_area_add_with_viewport (HildonPannableArea *area, - GtkWidget *child); -void hildon_pannable_area_scroll_to (HildonPannableArea *area, - const gint x, const gint y); -void hildon_pannable_area_jump_to (HildonPannableArea *area, - const gint x, const gint y); -void hildon_pannable_area_scroll_to_child (HildonPannableArea *area, - GtkWidget *child); -void hildon_pannable_area_jump_to_child (HildonPannableArea *area, - GtkWidget *child); -GtkWidget* hildon_pannable_get_child_widget_at (HildonPannableArea *area, - gdouble x, gdouble y); -#ifndef HILDON_DISABLE_DEPRECATED -HildonSizeRequestPolicy hildon_pannable_area_get_size_request_policy (HildonPannableArea *area); -void hildon_pannable_area_set_size_request_policy (HildonPannableArea *area, - HildonSizeRequestPolicy size_request_policy); -#endif -GtkAdjustment* hildon_pannable_area_get_hadjustment (HildonPannableArea *area); -GtkAdjustment* hildon_pannable_area_get_vadjustment (HildonPannableArea *area); - -G_END_DECLS - -#endif /* _HILDON_PANNABLE_AREA */ diff --git a/src/hildon-picker-button-private.h b/src/hildon-picker-button-private.h deleted file mode 100644 index 6760288..0000000 --- a/src/hildon-picker-button-private.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser Public License as published by - * the Free Software Foundation; version 2 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser Public License for more details. - * - */ - -#ifndef __HILDON_PICKER_BUTTON_PRIVATE__ -#define __HILDON_PICKER_BUTTON_PRIVATE__ - -#include "hildon-picker-button.h" - -G_BEGIN_DECLS - -G_GNUC_INTERNAL void -hildon_picker_button_disable_value_changed (HildonPickerButton *button, - gboolean disable); - -G_END_DECLS - -#endif /* __HILDON_PICKER_BUTTON_PRIVATE__ */ diff --git a/src/hildon-picker-button.c b/src/hildon-picker-button.c deleted file mode 100644 index dd5d300..0000000 --- a/src/hildon-picker-button.c +++ /dev/null @@ -1,614 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser Public License as published by - * the Free Software Foundation; version 2 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser Public License for more details. - * - */ - -/** - * SECTION:hildon-picker-button - * @short_description: A button that launches a #HildonPickerDialog and displays the - * selected item - * @see_also: #HildonTouchSelector, #HildonPickerDialog - * - * #HildonPickerButton is a widget that lets the user select a particular item from - * a list. Visually, it's a button with title and value labels that brings up a - * #HildonPickerDialog. The user can then use this dialog to choose an item, which - * will be displayed in the value label of the button. - * - * You should create your own #HildonTouchSelector at convenience and set it - * to the #HildonPickerButton with hildon_picker_button_set_selector(). For - * the common use cases of buttons to select date and time, you can use #HildonDateButton - * and #HildonTimeButton. - * - * - * - * GtkWidget * - * create_selector (void) - * { - * GtkWidget *selector; - * - * selector = hildon_touch_selector_new_text (); - * - * hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), "America"); - * hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), "Europe"); - * hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), "Asia"); - * hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), "Africa"); - * hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), "Australia"); - * - * hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, 2); - * - * return selector; - * } - * - * GtkWidget * - * create_button (HildonTouchSelector *selector) - * { - * GtkWidget *button; - * - * button = hildon_picker_button_new (HILDON_SIZE_AUTO, HILDON_BUTTON_ARRANGEMENT_VERTICAL); - * hildon_button_set_title (HILDON_BUTTON (button), "Continent"); - * - * hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (button), - * HILDON_TOUCH_SELECTOR (selector)); - * - * return button; - * } - * - * - */ - -#include "hildon-picker-button.h" -#include "hildon-picker-button-private.h" -#include "hildon-picker-dialog.h" - -G_DEFINE_TYPE (HildonPickerButton, hildon_picker_button, HILDON_TYPE_BUTTON) - -#define GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), HILDON_TYPE_PICKER_BUTTON, HildonPickerButtonPrivate)) - -typedef struct _HildonPickerButtonPrivate HildonPickerButtonPrivate; - -struct _HildonPickerButtonPrivate -{ - GtkWidget *selector; - GtkWidget *dialog; - gchar *done_button_text; - guint disable_value_changed : 1; -}; - -/* Signals */ -enum -{ - VALUE_CHANGED, - LAST_SIGNAL -}; - -enum -{ - PROP_SELECTOR = 1, - PROP_DONE_BUTTON_TEXT -}; - -static guint picker_button_signals[LAST_SIGNAL] = { 0 }; - -static gboolean -_current_selector_empty (HildonPickerButton *button); - -static void -hildon_picker_button_selector_selection_changed (HildonTouchSelector * selector, - gint column, - gpointer user_data); - -static void -hildon_picker_button_selector_columns_changed (HildonTouchSelector * selector, - gpointer user_data); - - -static void -hildon_picker_button_get_property (GObject * object, guint property_id, - GValue * value, GParamSpec * pspec) -{ - switch (property_id) { - case PROP_SELECTOR: - g_value_set_object (value, - hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (object))); - break; - case PROP_DONE_BUTTON_TEXT: - g_value_set_string (value, - hildon_picker_button_get_done_button_text (HILDON_PICKER_BUTTON (object))); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - -static void -hildon_picker_button_set_property (GObject * object, guint property_id, - const GValue * value, GParamSpec * pspec) -{ - switch (property_id) { - case PROP_SELECTOR: - hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (object), - g_value_get_object (value)); - break; - case PROP_DONE_BUTTON_TEXT: - hildon_picker_button_set_done_button_text (HILDON_PICKER_BUTTON (object), - g_value_get_string (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - -static void -hildon_picker_button_finalize (GObject * object) -{ - HildonPickerButtonPrivate *priv; - - priv = GET_PRIVATE (object); - - if (priv->selector) { - g_signal_handlers_disconnect_by_func (priv->selector, - hildon_picker_button_selector_selection_changed, - object); - g_signal_handlers_disconnect_by_func (priv->selector, - hildon_picker_button_selector_columns_changed, - object); - g_object_unref (priv->selector); - priv->selector = NULL; - } - if (priv->dialog) { - gtk_widget_destroy (priv->dialog); - priv->dialog = NULL; - } - - if (priv->done_button_text) { - g_free (priv->done_button_text); - priv->done_button_text = NULL; - } - - G_OBJECT_CLASS (hildon_picker_button_parent_class)->finalize (object); -} - -/** - * hildon_picker_button_value_changed: - * @button: a #HildonPickerButton - * - * Emits a "#HildonPickerButton::value-changed" signal to the given - * #HildonPickerButton - * - * Since: 2.2 - **/ -void -hildon_picker_button_value_changed (HildonPickerButton *button) -{ - HildonPickerButtonPrivate *priv; - g_return_if_fail (HILDON_IS_PICKER_BUTTON (button)); - priv = GET_PRIVATE (button); - - if (!priv->disable_value_changed) - g_signal_emit (button, picker_button_signals[VALUE_CHANGED], 0); -} - -G_GNUC_INTERNAL void -hildon_picker_button_disable_value_changed (HildonPickerButton *button, - gboolean disable) -{ - HildonPickerButtonPrivate *priv; - g_return_if_fail (HILDON_IS_PICKER_BUTTON (button)); - priv = GET_PRIVATE (button); - - priv->disable_value_changed = disable; -} - -static void -_selection_changed (HildonPickerButton *button) -{ - HildonPickerButtonPrivate *priv = GET_PRIVATE (button); - - if (!GTK_IS_WINDOW (priv->dialog) || - !GTK_WIDGET_VISIBLE (GTK_WINDOW (priv->dialog))) { - gchar *value = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (priv->selector)); - if (value) { - hildon_button_set_value (HILDON_BUTTON (button), value); - g_free (value); - hildon_picker_button_value_changed (button); - } - } -} - -static void -hildon_picker_button_on_dialog_response (GtkDialog *dialog, - gint response, - gpointer user_data) -{ - HildonPickerButton *button; - HildonPickerButtonPrivate *priv; - gchar *value; - - button = HILDON_PICKER_BUTTON (user_data); - priv = GET_PRIVATE (button); - - if (response == GTK_RESPONSE_OK) { - value = hildon_touch_selector_get_current_text - (HILDON_TOUCH_SELECTOR (priv->selector)); - hildon_button_set_value (HILDON_BUTTON (button), value); - g_free (value); - hildon_picker_button_value_changed (button); - } - - gtk_widget_hide (GTK_WIDGET (dialog)); -} - -static void -hildon_picker_button_clicked (GtkButton * button) -{ - GtkWidget *parent; - HildonPickerButtonPrivate *priv; - - priv = GET_PRIVATE (HILDON_PICKER_BUTTON (button)); - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (priv->selector)); - - /* Create the dialog if it doesn't exist already. */ - if (!priv->dialog) { - parent = gtk_widget_get_toplevel (GTK_WIDGET (button)); - if (GTK_WIDGET_TOPLEVEL (parent)) { - priv->dialog = hildon_picker_dialog_new (GTK_WINDOW (parent)); - } else { - priv->dialog = hildon_picker_dialog_new (NULL); - } - - hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (priv->dialog), - HILDON_TOUCH_SELECTOR (priv->selector)); - if (priv->done_button_text) { - hildon_picker_dialog_set_done_label (HILDON_PICKER_DIALOG (priv->dialog), - priv->done_button_text); - } - - gtk_window_set_modal (GTK_WINDOW (priv->dialog), - gtk_window_get_modal (GTK_WINDOW (parent))); - gtk_window_set_title (GTK_WINDOW (priv->dialog), - hildon_button_get_title (HILDON_BUTTON (button))); - g_signal_connect (priv->dialog, "response", - G_CALLBACK (hildon_picker_button_on_dialog_response), - button); - g_signal_connect (priv->dialog, "delete-event", - G_CALLBACK (gtk_widget_hide_on_delete), - NULL); - } - - if (_current_selector_empty (HILDON_PICKER_BUTTON (button))) { - g_warning ("There are no elements in the selector. Nothing to show."); - } { - gtk_window_present (GTK_WINDOW (priv->dialog)); - } -} - -static void -hildon_picker_button_selector_selection_changed (HildonTouchSelector * selector, - gint column, - gpointer user_data) - -{ - _selection_changed (HILDON_PICKER_BUTTON (user_data)); -} - -static void -hildon_picker_button_selector_columns_changed (HildonTouchSelector * selector, - gpointer user_data) - -{ - _selection_changed (HILDON_PICKER_BUTTON (user_data)); -} - -static void -hildon_picker_button_class_init (HildonPickerButtonClass * klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass); - - g_type_class_add_private (klass, sizeof (HildonPickerButtonPrivate)); - - object_class->get_property = hildon_picker_button_get_property; - object_class->set_property = hildon_picker_button_set_property; - object_class->finalize = hildon_picker_button_finalize; - - button_class->clicked = hildon_picker_button_clicked; - - g_object_class_install_property (object_class, - PROP_SELECTOR, - g_param_spec_object ("touch-selector", - "HildonTouchSelector widget", - "HildonTouchSelector widget to be launched on button clicked", - HILDON_TYPE_TOUCH_SELECTOR, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_DONE_BUTTON_TEXT, - g_param_spec_string ("done-button-text", - "HildonPickerDialog \"done\" button text", - "The text for the \"done\" button in the dialog launched", - NULL, - G_PARAM_READWRITE)); - - /** - * HildonPickerButton::value-changed: - * @widget: the widget that received the signal - * - * The ::value-changed signal is emitted each time the user chooses a different - * item from the #HildonTouchSelector related, and the value label gets updated. - * - * Since: 2.2 - */ - picker_button_signals[VALUE_CHANGED] = - g_signal_new ("value-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - 0, - NULL, NULL, - g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL); -} - -static void -hildon_picker_button_init (HildonPickerButton * self) -{ - HildonPickerButtonPrivate *priv; - - priv = GET_PRIVATE (self); - - priv->dialog = NULL; - priv->selector = NULL; - priv->done_button_text = NULL; - priv->disable_value_changed = FALSE; - - hildon_button_set_style (HILDON_BUTTON (self), - HILDON_BUTTON_STYLE_PICKER); -} - -static gboolean -_current_selector_empty (HildonPickerButton *button) -{ - HildonPickerButtonPrivate *priv; - HildonTouchSelector *selector = NULL; - GtkTreeModel *model = NULL; - GtkTreeIter iter; - gint i = 0; - - priv = GET_PRIVATE (button); - selector = HILDON_TOUCH_SELECTOR (priv->selector); - - g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), TRUE); - - if (hildon_touch_selector_has_multiple_selection (selector)) { - return FALSE; - } else { - for (i=0; i < hildon_touch_selector_get_num_columns (selector); i++) { - model = hildon_touch_selector_get_model (selector, i); - - if (gtk_tree_model_get_iter_first (model, &iter)) { - return FALSE; - } - } - return TRUE; - } -} - -/** - * hildon_picker_button_new: - * @size: One of #HildonSizeType, specifying the size of the new button. - * @arrangement: one of #HildonButtonArrangement, specifying the placement of the - * labels. - * - * Creates a new #HildonPickerButton. See hildon_button_new() for details on the - * parameters. - * - * Returns: a newly created #HildonPickerButton - * - * Since: 2.2 - **/ -GtkWidget * -hildon_picker_button_new (HildonSizeType size, - HildonButtonArrangement arrangement) -{ - GtkWidget *button; - - button = g_object_new (HILDON_TYPE_PICKER_BUTTON, - "arrangement", arrangement, "size", size, - NULL); - - return button; -} - -/** - * hildon_picker_button_set_selector: - * @button: a #HildonPickerButton - * @selector: a #HildonTouchSelector - * - * Sets @selector as the #HildonTouchSelector to be shown in the - * #HildonPickerDialog that @button brings up. - * - * Since: 2.2 - **/ -void -hildon_picker_button_set_selector (HildonPickerButton * button, - HildonTouchSelector * selector) -{ - HildonPickerButtonPrivate *priv; - gchar *value = NULL; - - g_return_if_fail (HILDON_IS_PICKER_BUTTON (button)); - g_return_if_fail (!selector || HILDON_IS_TOUCH_SELECTOR (selector)); - - priv = GET_PRIVATE (button); - - if (priv->selector) { - g_signal_handlers_disconnect_by_func (priv->selector, - hildon_picker_button_selector_selection_changed, - button); - g_signal_handlers_disconnect_by_func (priv->selector, - hildon_picker_button_selector_columns_changed, - button); - g_object_unref (priv->selector); - } - - priv->selector = GTK_WIDGET (selector); - - if (selector) { - g_object_ref (selector); - - g_signal_connect (G_OBJECT (selector), "changed", - G_CALLBACK (hildon_picker_button_selector_selection_changed), - button); - - g_signal_connect (G_OBJECT (selector), "columns-changed", - G_CALLBACK (hildon_picker_button_selector_columns_changed), - button); - - value = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (priv->selector)); - } - - if (!value) - value = g_strdup (""); - - hildon_button_set_value (HILDON_BUTTON (button), value); - hildon_picker_button_value_changed (button); - - g_free (value); -} - -/** - * hildon_picker_button_get_selector: - * @button: a #HildonPickerButton - * - * Retrieves the #HildonTouchSelector associated to @button. - * - * Returns: a #HildonTouchSelector - * - * Since: 2.2 - **/ -HildonTouchSelector * -hildon_picker_button_get_selector (HildonPickerButton * button) -{ - HildonPickerButtonPrivate *priv; - - g_return_val_if_fail (HILDON_IS_PICKER_BUTTON (button), NULL); - - priv = GET_PRIVATE (button); - - return HILDON_TOUCH_SELECTOR (priv->selector); -} - -/** - * hildon_picker_button_get_active: - * @button: a #HildonPickerButton - * - * Returns the index of the currently active item, or -1 if there's no - * active item. If the selector has several columns, only the first - * one is used. - * - * Returns: an integer which is the index of the currently active item, or -1 if there's no active item. - * - * Since: 2.2 - **/ -gint -hildon_picker_button_get_active (HildonPickerButton * button) -{ - HildonTouchSelector *sel; - g_return_val_if_fail (HILDON_IS_PICKER_BUTTON (button), -1); - - sel = hildon_picker_button_get_selector (button); - - return hildon_touch_selector_get_active (sel, 0); -} - -/** - * hildon_picker_button_set_active: - * @button: a #HildonPickerButton - * @index: the index of the item to select, or -1 to have no active item - * - * Sets the active item of the #HildonTouchSelector associated to - * @button to @index. If the selector has several columns, only the - * first one is used. - * - * Since: 2.2 - **/ -void -hildon_picker_button_set_active (HildonPickerButton * button, - gint index) -{ - HildonTouchSelector *sel; - gchar *text; - g_return_if_fail (HILDON_IS_PICKER_BUTTON (button)); - - sel = hildon_picker_button_get_selector (button); - hildon_touch_selector_set_active (sel, 0, index); - - text = hildon_touch_selector_get_current_text (sel); - hildon_button_set_value (HILDON_BUTTON (button), text); - g_free (text); -} - -/** - * hildon_picker_button_get_done_button_text: - * @button: a #HildonPickerButton - * - * Gets the text used in the #HildonPickerDialog that is launched by - * @button. If no custom text is set, then %NULL is returned. - * - * Returns: the custom string to be used, or %NULL if the default - * #HildonPickerDialog::done-button-text is to be used. - * - * Since: 2.2 - **/ -const gchar * -hildon_picker_button_get_done_button_text (HildonPickerButton *button) -{ - HildonPickerButtonPrivate *priv; - - g_return_val_if_fail (HILDON_IS_PICKER_BUTTON (button), NULL); - - priv = GET_PRIVATE (button); - - return priv->done_button_text; -} - -/** - * hildon_picker_button_set_done_button_text: - * @button: a #HildonPickerButton - * @done_button_text: a string - * - * Sets a custom string to be used in the "done" button in #HildonPickerDialog. - * If unset, the default HildonPickerButton::done-button-text property - * value will be used. - * - * Since: 2.2 - **/ -void -hildon_picker_button_set_done_button_text (HildonPickerButton *button, - const gchar *done_button_text) -{ - HildonPickerButtonPrivate *priv; - - g_return_if_fail (HILDON_IS_PICKER_BUTTON (button)); - g_return_if_fail (done_button_text != NULL); - - priv = GET_PRIVATE (button); - - g_free (priv->done_button_text); - priv->done_button_text = g_strdup (done_button_text); - - if (priv->dialog) { - hildon_picker_dialog_set_done_label (HILDON_PICKER_DIALOG (priv->dialog), - priv->done_button_text); - } -} diff --git a/src/hildon-picker-button.h b/src/hildon-picker-button.h deleted file mode 100644 index cecc7a5..0000000 --- a/src/hildon-picker-button.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser Public License as published by - * the Free Software Foundation; version 2 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser Public License for more details. - * - */ - -#ifndef __HILDON_PICKER_BUTTON__ -#define __HILDON_PICKER_BUTTON__ - -#include - -#include "hildon-button.h" -#include "hildon-touch-selector.h" - -G_BEGIN_DECLS - -#define HILDON_TYPE_PICKER_BUTTON \ - hildon_picker_button_get_type() - -#define HILDON_PICKER_BUTTON(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - HILDON_TYPE_PICKER_BUTTON, HildonPickerButton)) - -#define HILDON_PICKER_BUTTON_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - HILDON_TYPE_PICKER_BUTTON, HildonPickerButtonClass)) - -#define HILDON_IS_PICKER_BUTTON(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_PICKER_BUTTON)) - -#define HILDON_IS_PICKER_BUTTON_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_PICKER_BUTTON)) - -#define HILDON_PICKER_BUTTON_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - HILDON_TYPE_PICKER_BUTTON, HildonPickerButtonClass)) - -typedef struct _HildonPickerButton HildonPickerButton; -typedef struct _HildonPickerButtonClass HildonPickerButtonClass; - -struct _HildonPickerButton -{ - HildonButton parent; -}; - -struct _HildonPickerButtonClass -{ - HildonButtonClass parent_class; -}; - -GType -hildon_picker_button_get_type (void); - -GtkWidget* -hildon_picker_button_new (HildonSizeType size, - HildonButtonArrangement arrangement); - -void -hildon_picker_button_set_selector (HildonPickerButton * button, - HildonTouchSelector *selector); - -HildonTouchSelector* -hildon_picker_button_get_selector (HildonPickerButton *button); - -void -hildon_picker_button_set_active (HildonPickerButton * button, - gint index); - -gint -hildon_picker_button_get_active (HildonPickerButton * button); - -const gchar * -hildon_picker_button_get_done_button_text (HildonPickerButton * button); - -void -hildon_picker_button_set_done_button_text (HildonPickerButton *button, - const gchar *done_button_text); - -void -hildon_picker_button_value_changed (HildonPickerButton *button); - -G_END_DECLS - -#endif /* __HILDON_PICKER_BUTTON__ */ diff --git a/src/hildon-picker-dialog.c b/src/hildon-picker-dialog.c deleted file mode 100644 index 5539c99..0000000 --- a/src/hildon-picker-dialog.c +++ /dev/null @@ -1,643 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2008 Nokia Corporation. - * - * 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; either - * version 2 of the License, or (at your option) any later version. or (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/** - * SECTION:hildon-picker-dialog - * @short_description: A utility widget that shows a #HildonTouchSelector widget - * - * #HildonPickerDialog is a dialog that is used to show a - * #HildonTouchSelector widget and a 'Done' button to allow users to - * finish their selections. - * - * The #HildonPickerDialog will show a 'Done' button in case the - * #HildonTouchSelector allows multiple selection. The label of the - * button can be set using hildon_picker_dialog_set_done_label() and - * retrieved using hildon_picker_dialog_get_done_label() - * - * Note that in most cases developers don't need to deal directly with - * this widget. #HildonPickerButton is designed to pop up a - * #HildonPickerDialog and manage the interaction with it. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include - -#include "hildon-touch-selector.h" -#include "hildon-touch-selector-entry.h" -#include "hildon-picker-dialog.h" - -#define _(String) dgettext("hildon-libs", String) - -#define HILDON_PICKER_DIALOG_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_PICKER_DIALOG, HildonPickerDialogPrivate)) - -G_DEFINE_TYPE (HildonPickerDialog, hildon_picker_dialog, HILDON_TYPE_DIALOG) - -#define HILDON_TOUCH_SELECTOR_HEIGHT 320 - -struct _HildonPickerDialogPrivate -{ - GtkWidget *selector; - GtkWidget *button; - - gulong signal_changed_id; - gulong signal_columns_changed_id; - - gboolean center_on_show; - GSList *current_selection; - gchar *current_text; -}; - -/* properties */ -enum -{ - PROP_0, - PROP_DONE_BUTTON_TEXT, - PROP_CENTER_ON_SHOW, - PROP_LAST -}; - -enum -{ - RESPONSE, - LAST_SIGNAL -}; - -#define DEFAULT_DONE_BUTTON_TEXT _("wdgt_bd_done") - -static void -hildon_picker_dialog_set_property (GObject * object, - guint prop_id, - const GValue * value, - GParamSpec * pspec); - -static void -hildon_picker_dialog_get_property (GObject * object, - guint prop_id, - GValue * value, GParamSpec * pspec); - -static void -hildon_picker_dialog_finalize (GObject *object); - -/* gtkwidget */ -static void -hildon_picker_dialog_show (GtkWidget *widget); - -static void -hildon_picker_dialog_realize (GtkWidget *widget); - -/* private functions */ -static gboolean -requires_done_button (HildonPickerDialog * dialog); - -static void -prepare_action_area (HildonPickerDialog *dialog); - -static void -setup_interaction_mode (HildonPickerDialog * dialog); - -static void -_select_on_selector_changed_cb (HildonTouchSelector * dialog, - gint column, - gpointer data); - -static gboolean -_hildon_picker_dialog_set_selector (HildonPickerDialog * dialog, - HildonTouchSelector * selector); - -static void -_on_dialog_response (GtkDialog *dialog, - gint response_id, - gpointer data); - -static void -_save_current_selection (HildonPickerDialog *dialog); - -static void -_restore_current_selection (HildonPickerDialog *dialog); - -static void -_clean_current_selection (HildonPickerDialog *dialog); - -/**********************************************************************************/ - -static void -hildon_picker_dialog_class_init (HildonPickerDialogClass * class) -{ - GObjectClass *gobject_class; - GtkObjectClass *object_class; - GtkWidgetClass *widget_class; - GtkContainerClass *container_class; - - gobject_class = (GObjectClass *) class; - object_class = (GtkObjectClass *) class; - widget_class = (GtkWidgetClass *) class; - container_class = (GtkContainerClass *) class; - - /* GObject */ - gobject_class->set_property = hildon_picker_dialog_set_property; - gobject_class->get_property = hildon_picker_dialog_get_property; - gobject_class->finalize = hildon_picker_dialog_finalize; - - /* GtkWidget */ - widget_class->show = hildon_picker_dialog_show; - widget_class->realize = hildon_picker_dialog_realize; - - /* HildonPickerDialog */ - class->set_selector = _hildon_picker_dialog_set_selector; - - /* signals */ - - /* properties */ - /** - * HildonPickerDialog - * - * Button label - * - * Since: 2.2 - */ - g_object_class_install_property (gobject_class, - PROP_DONE_BUTTON_TEXT, - g_param_spec_string ("done-button-text", - "Done Button Label", - "Done Button Label", - DEFAULT_DONE_BUTTON_TEXT, - G_PARAM_READABLE | - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property (gobject_class, - PROP_CENTER_ON_SHOW, - g_param_spec_boolean ("center-on-show", - "Center on show", - "If the dialog should center" - " on the current selection" - " when it is showed", - TRUE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_type_class_add_private (object_class, sizeof (HildonPickerDialogPrivate)); -} - - -static void -hildon_picker_dialog_init (HildonPickerDialog * dialog) -{ - dialog->priv = HILDON_PICKER_DIALOG_GET_PRIVATE (dialog); - - dialog->priv->selector = NULL; - dialog->priv->button = - gtk_dialog_add_button (GTK_DIALOG (dialog), "", GTK_RESPONSE_OK); - gtk_widget_grab_default (dialog->priv->button); - - dialog->priv->signal_changed_id = 0; - dialog->priv->signal_columns_changed_id = 0; - dialog->priv->center_on_show = TRUE; - dialog->priv->current_selection = NULL; - dialog->priv->current_text = NULL; - - g_signal_connect (G_OBJECT (dialog), - "response", G_CALLBACK (_on_dialog_response), - NULL); -} - - -static void -hildon_picker_dialog_set_property (GObject * object, - guint param_id, - const GValue * value, GParamSpec * pspec) -{ - HildonPickerDialog *dialog; - - dialog = HILDON_PICKER_DIALOG (object); - - switch (param_id) { - case PROP_DONE_BUTTON_TEXT: - hildon_picker_dialog_set_done_label (HILDON_PICKER_DIALOG (object), - g_value_get_string (value)); - break; - case PROP_CENTER_ON_SHOW: - dialog->priv->center_on_show = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - -static void -hildon_picker_dialog_get_property (GObject * object, - guint param_id, - GValue * value, GParamSpec * pspec) -{ - HildonPickerDialog *dialog; - - dialog = HILDON_PICKER_DIALOG (object); - - switch (param_id) { - case PROP_DONE_BUTTON_TEXT: - g_value_set_string (value, hildon_picker_dialog_get_done_label (dialog)); - break; - case PROP_CENTER_ON_SHOW: - g_value_set_boolean (value, dialog->priv->center_on_show); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - -static void -hildon_picker_dialog_finalize (GObject *object) -{ - _clean_current_selection (HILDON_PICKER_DIALOG (object)); - - G_OBJECT_CLASS (hildon_picker_dialog_parent_class)->finalize (object); -} - -static void -hildon_picker_dialog_show (GtkWidget *widget) -{ - HildonPickerDialog *dialog = HILDON_PICKER_DIALOG (widget); - HildonTouchSelector *selector; - - GTK_WIDGET_CLASS (hildon_picker_dialog_parent_class)->show (widget); - - if (dialog->priv->center_on_show) { - selector = hildon_picker_dialog_get_selector (dialog); - hildon_touch_selector_center_on_selected (selector); - } - - _save_current_selection (dialog); - prepare_action_area (dialog); - -} - -static void -hildon_picker_dialog_realize (GtkWidget *widget) -{ - setup_interaction_mode (HILDON_PICKER_DIALOG (widget)); - - GTK_WIDGET_CLASS (hildon_picker_dialog_parent_class)->realize (widget); -} - -/* ------------------------------ PRIVATE METHODS ---------------------------- */ - -static void -_select_on_selector_changed_cb (HildonTouchSelector * selector, - gint column, gpointer data) -{ - g_return_if_fail (HILDON_IS_PICKER_DIALOG (data)); - - gtk_dialog_response (GTK_DIALOG (data), GTK_RESPONSE_OK); -} - -static gboolean -selection_completed (HildonPickerDialog *dialog) -{ - HildonPickerDialogPrivate *priv; - GList *list; - gint i, n_cols; - gboolean all_selected = TRUE; - - priv = HILDON_PICKER_DIALOG_GET_PRIVATE (dialog); - - n_cols = hildon_touch_selector_get_num_columns (HILDON_TOUCH_SELECTOR (priv->selector)); - for (i = 0; i < n_cols; i++) { - list = hildon_touch_selector_get_selected_rows (HILDON_TOUCH_SELECTOR (priv->selector), i); - if (list == NULL) { - all_selected = FALSE; - break; - } - g_list_foreach (list, (GFunc)gtk_tree_path_free, NULL); - g_list_free (list); - } - - return all_selected; -} - -static void -_on_dialog_response (GtkDialog *dialog, - gint response_id, - gpointer data) -{ - if (response_id == GTK_RESPONSE_OK) { - if (selection_completed (HILDON_PICKER_DIALOG (dialog)) == FALSE) { - g_signal_stop_emission_by_name (dialog, "response"); - } - } else if (response_id == GTK_RESPONSE_DELETE_EVENT) { - _restore_current_selection (HILDON_PICKER_DIALOG (dialog)); - } -} - -static void -on_selector_columns_changed (HildonTouchSelector * selector, gpointer userdata) -{ - HildonPickerDialog * dialog; - - dialog = HILDON_PICKER_DIALOG (userdata); - - prepare_action_area (dialog); - if (GTK_WIDGET_REALIZED (dialog)) { - setup_interaction_mode (dialog); - } -} - -/** - * hildon_picker_dialog_set_done_label: - * @dialog: a #HildonPickerDialog - * @label: a string - * - * Sets a custom string to be used as the 'Done' button label in @dialog. - * - * Since: 2.2 - **/ -void -hildon_picker_dialog_set_done_label (HildonPickerDialog * dialog, - const gchar * label) -{ - HildonPickerDialogPrivate *priv; - - g_return_if_fail (HILDON_IS_PICKER_DIALOG (dialog)); - g_return_if_fail (label != NULL); - - priv = HILDON_PICKER_DIALOG_GET_PRIVATE (dialog); - - gtk_button_set_label (GTK_BUTTON (priv->button), label); -} - -/** - * hildon_picker_dialog_get_done_label: - * @dialog: a #HildonPickerDialog - * - * Retrieves current 'Done' button label. - * - * Returns: the custom string to be used. - * - * Since: 2.2 - **/ -const gchar * -hildon_picker_dialog_get_done_label (HildonPickerDialog * dialog) -{ - HildonPickerDialogPrivate *priv; - - g_return_val_if_fail (HILDON_IS_PICKER_DIALOG (dialog), NULL); - - priv = HILDON_PICKER_DIALOG_GET_PRIVATE (dialog); - - return gtk_button_get_label (GTK_BUTTON (priv->button)); -} - -static void -free_path_list (GList *list) -{ - g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL); - g_list_free (list); -} - -static void -_clean_current_selection (HildonPickerDialog *dialog) -{ - if (dialog->priv->current_selection) { - g_slist_foreach (dialog->priv->current_selection, (GFunc) free_path_list, NULL); - g_slist_free (dialog->priv->current_selection); - dialog->priv->current_selection = NULL; - } - if (dialog->priv->current_text) { - g_free (dialog->priv->current_text); - dialog->priv->current_text = NULL; - } -} - -static void -_save_current_selection (HildonPickerDialog *dialog) -{ - HildonTouchSelector *selector; - gint i, columns; - - selector = HILDON_TOUCH_SELECTOR (dialog->priv->selector); - - _clean_current_selection (dialog); - - columns = hildon_touch_selector_get_num_columns (selector); - for (i = 0; i < columns; i++) { - dialog->priv->current_selection - = g_slist_append (dialog->priv->current_selection, - hildon_touch_selector_get_selected_rows (selector, i)); - } - if (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector)) { - HildonEntry *entry = hildon_touch_selector_entry_get_entry (HILDON_TOUCH_SELECTOR_ENTRY (selector)); - dialog->priv->current_text = g_strdup (hildon_entry_get_text (entry)); - } -} - -static void -_restore_current_selection (HildonPickerDialog *dialog) -{ - GSList *current_selection, *iter; - GList *selected, *selected_iter; - GtkTreePath *current_path; - HildonTouchSelector *selector; - GtkTreeModel *model; - GtkTreeIter tree_iter; - gint i; - - if (dialog->priv->current_selection == NULL) - return; - - current_selection = dialog->priv->current_selection; - selector = HILDON_TOUCH_SELECTOR (dialog->priv->selector); - - if (hildon_touch_selector_get_num_columns (selector) != - g_slist_length (current_selection)) { - /* We conclude that if the current selection has the same - numbers of columns that the selector, all this ok - Anyway this shouldn't happen. */ - g_critical ("Trying to restore the selection on a selector after change" - " the number of columns. Are you removing columns while the" - " dialog is open?"); - return; - } - - if (dialog->priv->signal_changed_id) - g_signal_handler_block (selector, dialog->priv->signal_changed_id); - for (iter = current_selection, i = 0; iter; iter = g_slist_next (iter), i++) { - selected = (GList *) (iter->data); - model = hildon_touch_selector_get_model (selector, i); - hildon_touch_selector_unselect_all (selector, i); - for (selected_iter = selected; selected_iter; selected_iter = g_list_next (selected_iter)) { - current_path = (GtkTreePath *) selected_iter->data; - gtk_tree_model_get_iter (model, &tree_iter, current_path); - hildon_touch_selector_select_iter (selector, i, &tree_iter, FALSE); - } - } - if (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector) && dialog->priv->current_text != NULL) { - HildonEntry *entry = hildon_touch_selector_entry_get_entry (HILDON_TOUCH_SELECTOR_ENTRY (selector)); - hildon_entry_set_text (entry, dialog->priv->current_text); - } - if (dialog->priv->signal_changed_id) - g_signal_handler_unblock (selector, dialog->priv->signal_changed_id); -} - -static gboolean -requires_done_button (HildonPickerDialog * dialog) -{ - return hildon_touch_selector_has_multiple_selection - (HILDON_TOUCH_SELECTOR (dialog->priv->selector)); -} - -static void -prepare_action_area (HildonPickerDialog *dialog) -{ - if (requires_done_button (dialog)) { - gtk_dialog_set_has_separator (GTK_DIALOG (dialog), TRUE); - gtk_widget_show (GTK_DIALOG (dialog)->action_area); - } else { - gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE); - gtk_widget_hide (GTK_DIALOG (dialog)->action_area); - } -} - -static void -setup_interaction_mode (HildonPickerDialog * dialog) -{ - if (dialog->priv->signal_changed_id) { - g_signal_handler_disconnect (dialog->priv->selector, - dialog->priv->signal_changed_id); - } - - if (requires_done_button (dialog) == FALSE) { - dialog->priv->signal_changed_id = - g_signal_connect (G_OBJECT (dialog->priv->selector), "changed", - G_CALLBACK (_select_on_selector_changed_cb), dialog); - } -} - -/*------------------------- PUBLIC METHODS ---------------------------- */ - -/** - * hildon_picker_dialog_new: - * @parent: the parent window - * - * Creates a new #HildonPickerDialog - * - * Returns: a new #HildonPickerDialog - * - * Since: 2.2 - **/ -GtkWidget * -hildon_picker_dialog_new (GtkWindow * parent) -{ - GtkDialog *dialog = NULL; - - dialog = g_object_new (HILDON_TYPE_PICKER_DIALOG, NULL); - - if (parent) { - gtk_window_set_transient_for (GTK_WINDOW (dialog), parent); - } - - return GTK_WIDGET (dialog); -} - - -static gboolean -_hildon_picker_dialog_set_selector (HildonPickerDialog * dialog, - HildonTouchSelector * selector) -{ - g_object_ref (selector); - - /* Remove the old selector, if any */ - if (dialog->priv->selector != NULL) { - gtk_container_remove (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), - dialog->priv->selector); - if (dialog->priv->signal_columns_changed_id) { - g_signal_handler_disconnect (dialog->priv->selector, - dialog->priv->signal_columns_changed_id); - } - } - - dialog->priv->selector = GTK_WIDGET (selector); - - /* Pack the new selector */ - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), - dialog->priv->selector, TRUE, TRUE, 0); - - g_object_unref (selector); - - /* Ensure that the dialog's height is correct */ - gtk_widget_set_size_request (GTK_WIDGET (dialog->priv->selector), -1, - HILDON_TOUCH_SELECTOR_HEIGHT); - - gtk_widget_show (dialog->priv->selector); - - prepare_action_area (dialog); - if (GTK_WIDGET_REALIZED (dialog)) { - setup_interaction_mode (dialog); - } - - dialog->priv->signal_columns_changed_id = g_signal_connect (G_OBJECT (dialog->priv->selector), - "columns-changed", - G_CALLBACK (on_selector_columns_changed), dialog); - return TRUE; -} - -/** - * hildon_picker_dialog_set_selector: - * @dialog: a #HildonPickerDialog - * @selector: a #HildonTouchSelector - * - * Sets @selector as the #HildonTouchSelector to be shown in @dialog - * - * Returns: %TRUE if @selector was set, %FALSE otherwise - * - * Since: 2.2 - **/ -gboolean -hildon_picker_dialog_set_selector (HildonPickerDialog * dialog, - HildonTouchSelector * selector) -{ - g_return_val_if_fail (HILDON_IS_PICKER_DIALOG (dialog), FALSE); - g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE); - - return HILDON_PICKER_DIALOG_GET_CLASS (dialog)->set_selector (dialog, selector); -} - -/** - * hildon_picker_dialog_get_selector: - * @dialog: a #HildonPickerDialog - * - * Retrieves the #HildonTouchSelector associated to @dialog. - * - * Returns: a #HildonTouchSelector - * - * Since: 2.2 - **/ -HildonTouchSelector * -hildon_picker_dialog_get_selector (HildonPickerDialog * dialog) -{ - g_return_val_if_fail (HILDON_IS_PICKER_DIALOG (dialog), NULL); - - return HILDON_TOUCH_SELECTOR (dialog->priv->selector); -} diff --git a/src/hildon-picker-dialog.h b/src/hildon-picker-dialog.h deleted file mode 100644 index 3d867f5..0000000 --- a/src/hildon-picker-dialog.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2008 Nokia Corporation. - * - * 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; either - * version 2 of the License, or (at your option) any later version. or (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __HILDON_PICKER_DIALOG_H__ -#define __HILDON_PICKER_DIALOG_H__ - -#ifdef HILDON_DISABLE_DEPRECATED - #define __SHOULD_REENABLE_DISABLE_DEPRECATED -#endif - -#undef HILDON_DISABLE_DEPRECATED -#include "hildon-dialog.h" - -#ifdef __SHOULD_REENABLE_DISABLE_DEPRECATED - #define HILDON_DISABLE_DEPRECATED -#endif - -#include "hildon-touch-selector.h" - -G_BEGIN_DECLS - -#define HILDON_TYPE_PICKER_DIALOG \ - (hildon_picker_dialog_get_type ()) - -#define HILDON_PICKER_DIALOG(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - HILDON_TYPE_PICKER_DIALOG, HildonPickerDialog)) - -#define HILDON_PICKER_DIALOG_CLASS(vtable) \ - (G_TYPE_CHECK_CLASS_CAST ((vtable), \ - HILDON_TYPE_PICKER_DIALOG, HildonPickerDialogClass)) - -#define HILDON_IS_PICKER_DIALOG(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_PICKER_DIALOG)) - -#define HILDON_IS_PICKER_DIALOG_CLASS(vtable) \ - (G_TYPE_CHECK_CLASS_TYPE ((vtable), HILDON_TYPE_PICKER_DIALOG)) - -#define HILDON_PICKER_DIALOG_GET_CLASS(inst) \ - (G_TYPE_INSTANCE_GET_CLASS ((inst), \ - HILDON_TYPE_PICKER_DIALOG, HildonPickerDialogClass)) - -typedef struct _HildonPickerDialog HildonPickerDialog; -typedef struct _HildonPickerDialogClass HildonPickerDialogClass; -typedef struct _HildonPickerDialogPrivate HildonPickerDialogPrivate; - -struct _HildonPickerDialog -{ - HildonDialog parent_instance; - - /*< private > */ - HildonPickerDialogPrivate *priv; -}; - -struct _HildonPickerDialogClass -{ - HildonDialogClass parent_class; - - gboolean (* set_selector) (HildonPickerDialog *dialog, - HildonTouchSelector *selector); -}; - -/* construction */ -GType -hildon_picker_dialog_get_type (void) G_GNUC_CONST; - -GtkWidget* -hildon_picker_dialog_new (GtkWindow * parent); - -gboolean -hildon_picker_dialog_set_selector (HildonPickerDialog *dialog, - HildonTouchSelector *selector); - -void -hildon_picker_dialog_set_done_label (HildonPickerDialog *dialog, - const gchar *label); - -const gchar* -hildon_picker_dialog_get_done_label (HildonPickerDialog *dialog); - -HildonTouchSelector* -hildon_picker_dialog_get_selector (HildonPickerDialog *dialog); - -G_END_DECLS - -#endif /* __HILDON_PICKER_SELECTOR_H__ */ diff --git a/src/hildon-private.c b/src/hildon-private.c deleted file mode 100644 index b7190c8..0000000 --- a/src/hildon-private.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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 - * - */ - -#undef HILDON_DISABLE_DEPRECATED - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "hildon-private.h" -#include "hildon-date-editor.h" -#include "hildon-time-editor.h" - -/* This function is a private function of hildon. 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 G_GNUC_INTERNAL -hildon_private_composite_focus (GtkWidget *widget, - GtkDirectionType direction, - GtkDirectionType *effective_direction) -{ - GtkWidget *toplevel = NULL; - GtkWidget *focus_widget = NULL; - gboolean coming_from_outside = FALSE; - - toplevel = gtk_widget_get_toplevel (widget); - - focus_widget = GTK_WINDOW (toplevel)->focus_widget; - - if (focus_widget == NULL || gtk_widget_is_ancestor (focus_widget, widget) == FALSE) - { - /* When coming from outside we want to give focus to the first - item in the widgets */ - *effective_direction = GTK_DIR_TAB_FORWARD; - coming_from_outside = TRUE; - } - else - *effective_direction = direction; - - switch (direction) { - case GTK_DIR_UP: - case GTK_DIR_DOWN: - case GTK_DIR_TAB_FORWARD: - case GTK_DIR_TAB_BACKWARD: - if ((HILDON_IS_DATE_EDITOR (widget) || HILDON_IS_TIME_EDITOR(widget)) && - !coming_from_outside) - return FALSE; - /* fall through */ - default: - return TRUE; - } - - g_assert_not_reached (); - return TRUE; -} - - diff --git a/src/hildon-private.h b/src/hildon-private.h deleted file mode 100644 index 67b79f4..0000000 --- a/src/hildon-private.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#ifndef __HILDON_PRIVATE_H__ -#define __HILDON_PRIVATE_H__ - -#include - -G_BEGIN_DECLS - -gboolean G_GNUC_INTERNAL -hildon_private_composite_focus (GtkWidget *widget, - GtkDirectionType direction, - GtkDirectionType *effective_direction); - -G_END_DECLS - -#endif /* __HILDON_PRIVATE_H__ */ - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-program-private.h b/src/hildon-program-private.h deleted file mode 100644 index bf2a3f7..0000000 --- a/src/hildon-program-private.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_PRIVATE_H__ -#define __HILDON_PROGRAM_PRIVATE_H__ - -#include - -#include "hildon-window.h" -#include "hildon-stackable-window.h" - -G_BEGIN_DECLS - -#define HILDON_PROGRAM_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_PROGRAM, HildonProgramPrivate)); - -typedef struct _HildonProgramPrivate HildonProgramPrivate; - -struct _HildonProgramPrivate -{ - gboolean killable; - gboolean is_topmost; - guint window_count; - GtkMenu *common_menu; - HildonAppMenu *common_app_menu; - GtkWidget *common_toolbar; - GSList *windows; - Window window_group; -}; - -G_END_DECLS - -#endif /* __HILDON_PROGRAM_PRIVATE_H__ */ diff --git a/src/hildon-program.c b/src/hildon-program.c deleted file mode 100644 index 47ead29..0000000 --- a/src/hildon-program.c +++ /dev/null @@ -1,843 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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-program - * @short_description: An object that represents an application running in the Hildon framework. - * @see_also: #HildonWindow, #HildonStackableWindow - * - * #HildonProgram is an object used to represent an application running - * in the Hildon framework. - * - * Applications can have one or more #HildonWindows. These - * can be registered in the #HildonProgram with hildon_program_add_window(), - * and can be unregistered similarly with hildon_program_remove_window(). - * - * #HildonProgram provides the programmer with commodities such - * as applying a common toolbar and menu to all registered - * #HildonWindows. This is done with hildon_program_set_common_menu(), - * hildon_program_set_common_app_menu() and hildon_program_set_common_toolbar(). - * - * #HildonProgram is also used to apply program-wide properties that - * are specific to the Hildon framework. For instance - * hildon_program_set_can_hibernate() sets whether or not an application - * can be set to hibernate by the Hildon task navigator, in situations of - * low memory. - * - * - * - * HildonProgram *program; - * HildonWindow *window1; - * HildonWindow *window2; - * GtkToolbar *common_toolbar, *window_specific_toolbar; - * HildonAppMenu *menu; - * - * program = HILDON_PROGRAM (hildon_program_get_instance ()); - * - * window1 = HILDON_WINDOW (hildon_window_new ()); - * window2 = HILDON_WINDOW (hildon_window_new ()); - * - * common_toolbar = create_common_toolbar (); - * window_specific_toolbar = create_window_specific_toolbar (); - * - * menu = create_menu (); - * - * hildon_program_add_window (program, window1); - * hildon_program_add_window (program, window2); - * - * hildon_program_set_common_app_menu (program, menu); - * - * hildon_program_set_common_toolbar (program, common_toolbar); - * hildon_window_add_toolbar (window1, window_specific_toolbar); - * - * hildon_program_set_can_hibernate (program, TRUE); - * - * - */ - -#undef HILDON_DISABLE_DEPRECATED - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "hildon-program.h" -#include "hildon-program-private.h" -#include "hildon-window-private.h" -#include "hildon-window-stack.h" -#include "hildon-app-menu-private.h" - -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 G_GNUC_CONST -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) -{ - HildonProgramPrivate *priv = HILDON_PROGRAM_GET_PRIVATE (self); - g_assert (priv); - - 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_menu = NULL; - priv->common_app_menu = NULL; - priv->common_toolbar = NULL; - priv->windows = NULL; -} - -static void -hildon_program_finalize (GObject *self) -{ - HildonProgramPrivate *priv = HILDON_PROGRAM_GET_PRIVATE (HILDON_PROGRAM (self)); - g_assert (priv); - - 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; - } -} - -static void -hildon_program_class_init (HildonProgramClass *self) -{ - GObjectClass *object_class = G_OBJECT_CLASS (self); - - g_type_class_add_private (self, sizeof (HildonProgramPrivate)); - - /* 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 */ - - /** - * HildonProgram:is-topmost: - * - * Whether one of the program's window or dialog currently - * is activated by window manager. - */ - 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)); - - /** - * HildonProgram:can-hibernate: - * - * Whether the program should be set to hibernate by the Task - * Navigator in low memory situation. - */ - 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) -{ - HildonProgramPrivate *priv = HILDON_PROGRAM_GET_PRIVATE (object); - g_assert (priv); - - 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; - } -} - -/** - * hildon_program_pop_window_stack: - * @self: A #HildonProgram - * - * Pops a window from the stack. - * - * Deprecated: Use hildon_window_stack_pop() instead - * - * Returns: A #HildonStackableWindow, or %NULL - * - * Since: 2.2 - */ -HildonStackableWindow * -hildon_program_pop_window_stack (HildonProgram *self) -{ - HildonWindowStack *stack = hildon_window_stack_get_default (); - GtkWidget *win = hildon_window_stack_pop_1 (stack); - g_warning ("%s: this function is deprecated. Use hildon_window_stack_pop() instead", __FUNCTION__); - return win ? HILDON_STACKABLE_WINDOW (win) : NULL; -} - -/** - * hildon_program_peek_window_stack: - * @self: A #HildonProgram - * - * Deprecated: Use hildon_window_stack_peek() instead - * - * Returns: A #HildonStackableWindow, or %NULL - * - * Since: 2.2 - */ -HildonStackableWindow * -hildon_program_peek_window_stack (HildonProgram *self) -{ - HildonWindowStack *stack = hildon_window_stack_get_default (); - GtkWidget *win = hildon_window_stack_peek (stack); - g_warning ("%s: this function is deprecated. Use hildon_window_stack_peek() instead", __FUNCTION__); - return win ? HILDON_STACKABLE_WINDOW (win) : NULL; -} - -/* Utilities */ -static gint -hildon_program_window_list_compare (gconstpointer window_a, - gconstpointer window_b) -{ - g_return_val_if_fail (HILDON_IS_WINDOW(window_a) && - HILDON_IS_WINDOW(window_b), 1); - - 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) -{ - gboolean is_topmost; - Window active_window; - HildonProgramPrivate *priv; - - priv = HILDON_PROGRAM_GET_PRIVATE (program); - g_assert (priv); - - active_window = hildon_window_get_active_window(); - is_topmost = FALSE; - - if (active_window) - { - gint xerror; - XWMHints *wm_hints; - - gdk_error_trap_push (); - wm_hints = XGetWMHints (GDK_DISPLAY (), active_window); - xerror = gdk_error_trap_pop (); - if (xerror) - { - if (wm_hints) - XFree (wm_hints); - return; - } - - if (wm_hints) - { - is_topmost = (wm_hints->window_group == priv->window_group); - XFree (wm_hints); - } - } - - /* Send notification if is_topmost has changed */ - if (!priv->is_topmost != !is_topmost) - { - priv->is_topmost = is_topmost; - g_object_notify (G_OBJECT (program), "is-topmost"); - } - - /* Check each window if it was is_topmost */ - g_slist_foreach (priv->windows, - (GFunc)hildon_program_window_list_is_is_topmost, &active_window); -} - -/* - * 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; -} - -/* - * 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)); -} - -/** - * hildon_program_get_instance: - * - * Returns the #HildonProgram for the current process. The object is - * created on the first call. Note that you're not supposed to unref - * the returned object since it's not reffed in the first place. - * - * Return value: the #HildonProgram. - **/ -HildonProgram* -hildon_program_get_instance (void) -{ - static HildonProgram *program = NULL; - - if (! program) - { - program = g_object_new (HILDON_TYPE_PROGRAM, NULL); - } - - return program; -} - -/** - * hildon_program_add_window: - * @self: 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(), hildon_program_set_common_app_menu() - * and hildon_program_set_common_toolbar(). - **/ -void -hildon_program_add_window (HildonProgram *self, - HildonWindow *window) -{ - HildonProgramPrivate *priv; - - g_return_if_fail (HILDON_IS_PROGRAM (self)); - g_return_if_fail (HILDON_IS_WINDOW (window)); - - priv = HILDON_PROGRAM_GET_PRIVATE (self); - g_assert (priv); - - 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(), hildon_program_set_common_app_menu() - * and hildon_program_set_common_toolbar() will not affect the window. - **/ -void -hildon_program_remove_window (HildonProgram *self, - HildonWindow *window) -{ - HildonProgramPrivate *priv; - - g_return_if_fail (HILDON_IS_PROGRAM (self)); - g_return_if_fail (HILDON_IS_WINDOW (window)); - - priv = HILDON_PROGRAM_GET_PRIVATE (self); - g_assert (priv); - - g_return_if_fail (g_slist_find (priv->windows, window)); - - 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 can_hibernate) -{ - HildonProgramPrivate *priv; - - g_return_if_fail (HILDON_IS_PROGRAM (self)); - - priv = HILDON_PROGRAM_GET_PRIVATE (self); - g_assert (priv); - - if (priv->killable != can_hibernate) - { - g_slist_foreach (priv->windows, - (GFunc) hildon_window_set_can_hibernate_property, &can_hibernate); - } - - priv->killable = can_hibernate; -} - -/** - * hildon_program_get_can_hibernate: - * @self: The #HildonProgram which can hibernate or not - * - * Returns whether the #HildonProgram is set to be support hibernation - * from the Hildon task navigator - * - * Return value: %TRUE if the program can hibernate, %FALSE otherwise. - **/ -gboolean -hildon_program_get_can_hibernate (HildonProgram *self) -{ - HildonProgramPrivate *priv; - - g_return_val_if_fail (HILDON_IS_PROGRAM (self), FALSE); - - priv = HILDON_PROGRAM_GET_PRIVATE (self); - g_assert (priv); - - 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 #HildonWindows - * registered with the #HildonProgram. Only one common #GtkMenu can be - * set, further calls will detach the previous common #GtkMenu. A - * #HildonWindow can use its own #GtkMenu with - * hildon_window_set_menu() - * - * This method does not support #HildonAppMenus. See - * hildon_program_set_common_app_menu() for that. - * - * Since: 2.2 - **/ -void -hildon_program_set_common_menu (HildonProgram *self, - GtkMenu *menu) -{ - HildonProgramPrivate *priv; - - g_return_if_fail (HILDON_IS_PROGRAM (self)); - - priv = HILDON_PROGRAM_GET_PRIVATE (self); - g_assert (priv); - - if (priv->common_menu) - { - if (GTK_WIDGET_VISIBLE (priv->common_menu)) - { - gtk_menu_popdown (priv->common_menu); - gtk_menu_shell_deactivate (GTK_MENU_SHELL (priv->common_menu)); - } - - if (gtk_menu_get_attach_widget (priv->common_menu)) - { - gtk_menu_detach (priv->common_menu); - } - else - { - g_object_unref (priv->common_menu); - } - } - - priv->common_menu = 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 - * - * Returns the #GtkMenu that was set as common menu for this - * #HildonProgram. - * - * Return value: the #GtkMenu or %NULL of no common menu was set. - **/ -GtkMenu* -hildon_program_get_common_menu (HildonProgram *self) -{ - HildonProgramPrivate *priv; - - g_return_val_if_fail (HILDON_IS_PROGRAM (self), NULL); - - priv = HILDON_PROGRAM_GET_PRIVATE (self); - g_assert (priv); - - return priv->common_menu; -} - -/** - * hildon_program_set_common_app_menu: - * @self: The #HildonProgram in which the common menu should be used - * @menu: A #HildonAppMenu to use as common menu for the program - * - * Sets a #HildonAppMenu that will appear in all - * #HildonWindows registered with the #HildonProgram. Only - * one common #HildonAppMenu can be set, further calls will detach the - * previous common #HildonAppMenu. A #HildonWindow can use its own - * #HildonAppMenu with hildon_window_set_app_menu() - * - * This method does not support #GtkMenus. See - * hildon_program_set_common_menu() for that. - * - * Since: 2.2 - **/ -void -hildon_program_set_common_app_menu (HildonProgram *self, - HildonAppMenu *menu) -{ - HildonProgramPrivate *priv; - HildonAppMenu *old_menu; - - g_return_if_fail (HILDON_IS_PROGRAM (self)); - g_return_if_fail (menu == NULL || HILDON_IS_APP_MENU (menu)); - - priv = HILDON_PROGRAM_GET_PRIVATE (self); - g_assert (priv); - - old_menu = priv->common_app_menu; - - /* Set new menu */ - priv->common_app_menu = menu; - if (menu) - g_object_ref_sink (menu); - - /* Hide and unref old menu */ - if (old_menu) { - hildon_app_menu_set_parent_window (old_menu, NULL); - g_object_unref (old_menu); - } -} - -/** - * hildon_program_get_common_app_menu: - * @self: The #HildonProgram from which to retrieve the common app menu - * - * Returns the #HildonAppMenu that was set as common menu for this - * #HildonProgram. - * - * Return value: the #HildonAppMenu or %NULL of no common app menu was - * set. - * - * Since: 2.2 - **/ -HildonAppMenu* -hildon_program_get_common_app_menu (HildonProgram *self) -{ - HildonProgramPrivate *priv; - - g_return_val_if_fail (HILDON_IS_PROGRAM (self), NULL); - - priv = HILDON_PROGRAM_GET_PRIVATE (self); - g_assert (priv); - - return priv->common_app_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_add_toolbar(). Both - * #HildonProgram and #HildonWindow specific toolbars will be shown - **/ -void -hildon_program_set_common_toolbar (HildonProgram *self, - GtkToolbar *toolbar) -{ - HildonProgramPrivate *priv; - - g_return_if_fail (HILDON_IS_PROGRAM (self)); - - priv = HILDON_PROGRAM_GET_PRIVATE (self); - g_assert (priv); - - 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 - * - * Returns the #GtkToolbar that was set as common toolbar for this - * #HildonProgram. - * - * Return value: the #GtkToolbar or %NULL of no common toolbar was - * set. - **/ -GtkToolbar* -hildon_program_get_common_toolbar (HildonProgram *self) -{ - HildonProgramPrivate *priv; - - g_return_val_if_fail (HILDON_IS_PROGRAM (self), NULL); - - priv = HILDON_PROGRAM_GET_PRIVATE (self); - g_assert (priv); - - return priv->common_toolbar ? GTK_TOOLBAR (priv->common_toolbar) : NULL; -} - -/** - * hildon_program_get_is_topmost: - * @self: A #HildonWindow - * - * Returns whether one of the program's windows or dialogs is - * currently activated by the window manager. - * - * Return value: %TRUE if a window or dialog is topmost, %FALSE - * otherwise. - **/ -gboolean -hildon_program_get_is_topmost (HildonProgram *self) -{ - HildonProgramPrivate *priv; - - g_return_val_if_fail (HILDON_IS_PROGRAM (self), FALSE); - - priv = HILDON_PROGRAM_GET_PRIVATE (self); - g_assert (priv); - - return priv->is_topmost; -} - -/** - * hildon_program_go_to_root_window: - * @self: A #HildonProgram - * - * Goes to the root window of the stack. - * - * Deprecated: See #HildonWindowStack - * - * Since: 2.2 - */ -void -hildon_program_go_to_root_window (HildonProgram *self) -{ - HildonWindowStack *stack = hildon_window_stack_get_default (); - gint n = hildon_window_stack_size (stack); - g_warning ("%s: this function is deprecated. Use hildon_window_stack_pop() instead.", __FUNCTION__); - if (n > 1) { - hildon_window_stack_pop (stack, n-1, NULL); - } -} diff --git a/src/hildon-program.h b/src/hildon-program.h deleted file mode 100644 index a4d3210..0000000 --- a/src/hildon-program.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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" -#include "hildon-stackable-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_PROGRAM_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_CAST ((obj), \ - HILDON_TYPE_PROGRAM, HildonProgramClass)) - -#define HILDON_IS_PROGRAM(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_PROGRAM)) - -#define HILDON_IS_PROGRAM_CLASS(klass) \ - (G_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_PROGRAM)) - -#define HILDON_PROGRAM_GET_CLASS(obj) \ - ((HildonProgramClass *) G_OBJECT_GET_CLASS(obj)) - -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 G_GNUC_CONST -hildon_program_get_type (void); - -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 can_hibernate); - -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_app_menu (HildonProgram *self, - HildonAppMenu *menu); - -HildonAppMenu* -hildon_program_get_common_app_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); - -#ifndef HILDON_DISABLE_DEPRECATED -HildonStackableWindow * -hildon_program_pop_window_stack (HildonProgram *self); - -HildonStackableWindow * -hildon_program_peek_window_stack (HildonProgram *self); - -void -hildon_program_go_to_root_window (HildonProgram *self); -#endif /* HILDON_DISABLE_DEPRECATED */ - -G_END_DECLS - -#endif /* __HILDON_PROGRAM_H__ */ diff --git a/src/hildon-range-editor-private.h b/src/hildon-range-editor-private.h deleted file mode 100644 index d23d60e..0000000 --- a/src/hildon-range-editor-private.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_PRIVATE_H__ -#define __HILDON_RANGE_EDITOR_PRIVATE_H__ - -G_BEGIN_DECLS - -#define HILDON_RANGE_EDITOR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_RANGE_EDITOR, HildonRangeEditorPrivate)); - -typedef struct _HildonRangeEditorPrivate HildonRangeEditorPrivate; - -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 */ -}; - -G_END_DECLS - -#endif /* __HILDON_RANGE_EDITOR_PRIVATE_H__ */ diff --git a/src/hildon-range-editor.c b/src/hildon-range-editor.c deleted file mode 100644 index beb5322..0000000 --- a/src/hildon-range-editor.c +++ /dev/null @@ -1,1079 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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. - * - * - * - * #HildonRangeEditor has been deprecated since Hildon 2.2 and should not - * be used in newly written code. See - * Migrating Number Widgets - * section to know how to migrate this deprecated widget. - * - * - * - * - * - * range_editor = hildon_range_editor_new (); - * hildon_range_editor_set_limits (editor, start, end ); - * hildon_range_editor_get_range (editor, &start, &end); - * - * - */ - -#undef HILDON_DISABLE_DEPRECATED - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#include "hildon-range-editor.h" -#include "hildon-banner.h" -#include "hildon-range-editor-private.h" - -#define _(string) \ - dgettext("hildon-libs", 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 - -static GtkContainerClass *parent_class = NULL; - -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); - -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); - -enum -{ - PROP_0, - PROP_LOWER = 1, - PROP_HIGHER, - PROP_MIN, - PROP_MAX, - PROP_SEPARATOR -}; - -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); - g_assert (priv); - - 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); - -#ifdef MAEMO_GTK - g_object_set (G_OBJECT (priv->start_entry), - "hildon-input-mode", HILDON_GTK_INPUT_MODE_NUMERIC, NULL); - - g_object_set( G_OBJECT (priv->end_entry), - "hildon-input-mode", HILDON_GTK_INPUT_MODE_NUMERIC, NULL); -#endif - - 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); - g_assert (priv); - - /* 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 (GTK_ENTRY (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); - g_assert (priv); - - 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 useful 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); - g_assert (priv); - - 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); - g_assert (priv); - - 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); - g_assert (priv); - - 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 = {0}; - GtkAllocation child2_allocation = {0}; - GtkAllocation child3_allocation = {0}; - - priv = HILDON_RANGE_EDITOR_GET_PRIVATE (widget); - g_assert (priv); - - 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); - g_assert (priv); - - 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); -} - -/** - * hildon_range_editor_get_type: - * - * Initializes, and returns the type of a hildon range editor. - * - * Returns: GType of #HildonRangeEditor - * - */ -GType G_GNUC_CONST -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) -{ - g_return_if_fail (HILDON_IS_RANGE_EDITOR (editor) && start && end); - - *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 deleted file mode 100644 index 5f10e60..0000000 --- a/src/hildon-range-editor.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#ifndef __HILDON_RANGE_EDITOR_H__ -#define __HILDON_RANGE_EDITOR_H__ - -#include - -G_BEGIN_DECLS - -#define HILDON_TYPE_RANGE_EDITOR \ - (hildon_range_editor_get_type()) - -#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)) - -#define HILDON_RANGE_EDITOR_GET_CLASS(obj) \ - ((HildonRangeEditorClass *) G_OBJECT_GET_CLASS(obj)) - -typedef struct _HildonRangeEditor HildonRangeEditor; - -typedef struct _HildonRangeEditorClass HildonRangeEditorClass; - -struct _HildonRangeEditor -{ - GtkContainer parent; -}; - -struct _HildonRangeEditorClass -{ - GtkContainerClass parent_class; -}; - -GType G_GNUC_CONST -hildon_range_editor_get_type (void); - -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__ */ - -#endif /* HILDON_DISABLE_DEPRECATED */ - diff --git a/src/hildon-remote-texture-private.h b/src/hildon-remote-texture-private.h deleted file mode 100644 index 806cc22..0000000 --- a/src/hildon-remote-texture-private.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_REMOTE_TEXTURE_PRIVATE_H__ -#define __HILDON_REMOTE_TEXTURE_PRIVATE_H__ - - -#include -#include - -G_BEGIN_DECLS - -typedef struct _HildonRemoteTexturePrivate HildonRemoteTexturePrivate; - -#define HILDON_REMOTE_TEXTURE_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_REMOTE_TEXTURE, HildonRemoteTexturePrivate)); - -struct _HildonRemoteTexturePrivate -{ - guint ready : 1; - - guint set_shm : 1; - guint set_damage : 1; - guint set_show : 1; - guint set_position : 1; - guint set_offset : 1; - guint set_scale : 1; - guint set_parent : 1; - - key_t shm_key; - guint shm_width; - guint shm_height; - guint shm_bpp; - - gint damage_x1; - gint damage_y1; - gint damage_x2; - gint damage_y2; - - guint show; - guint opacity; - - gint x; - gint y; - gint width; - gint height; - - double offset_x; - double offset_y; - - double scale_x; - double scale_y; - - GtkWindow* parent; - gulong parent_map_event_cb_id; - - gulong map_event_cb_id; -}; - -G_END_DECLS - -#endif /* __HILDON_REMOTE_TEXTURE_PRIVATE_H__ */ diff --git a/src/hildon-remote-texture.c b/src/hildon-remote-texture.c deleted file mode 100644 index f8bbbd7..0000000 --- a/src/hildon-remote-texture.c +++ /dev/null @@ -1,943 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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-remote-texture - * @short_description: Widget representing a Clutter/GLES texture created - * from a shared memory area. - * - * The #HildonRemoteTexture is a GTK+ widget which allows the rendering of - * a shared memory area within hildon-desktop. It allows the memory area to - * be positioned and scaled, without altering its' contents. - */ - -#include -#include - -#include "hildon-remote-texture.h" -#include "hildon-remote-texture-private.h" - -G_DEFINE_TYPE (HildonRemoteTexture, hildon_remote_texture, GTK_TYPE_WINDOW); - -static GdkFilterReturn -hildon_remote_texture_event_filter (GdkXEvent *xevent, - GdkEvent *event, - gpointer data); -static void -hildon_remote_texture_update_ready (HildonRemoteTexture *self); -static void -hildon_remote_texture_send_pending_messages (HildonRemoteTexture *self); -static void -hildon_remote_texture_send_all_messages (HildonRemoteTexture *self); -static gboolean -hildon_remote_texture_parent_map_event (GtkWidget *parent, - GdkEvent *event, - gpointer user_data); -static gboolean -hildon_remote_texture_map_event (GtkWidget *widget, - GdkEvent *event, - gpointer user_data); - -static guint32 shm_atom; -static guint32 damage_atom; -static guint32 show_atom; -static guint32 position_atom; -static guint32 offset_atom; -static guint32 scale_atom; -static guint32 parent_atom; -static guint32 ready_atom; - -static gboolean atoms_initialized = FALSE; - -static void -hildon_remote_texture_realize (GtkWidget *widget) -{ - GdkDisplay *display; - Atom wm_type, applet_type; - - GTK_WIDGET_CLASS (hildon_remote_texture_parent_class)->realize (widget); - - /* Set remote texture window type. */ - - display = gdk_drawable_get_display (widget->window); - - wm_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"); - applet_type = gdk_x11_get_xatom_by_name_for_display (display, "_HILDON_WM_WINDOW_TYPE_REMOTE_TEXTURE"); - - XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (widget->window), wm_type, - XA_ATOM, 32, PropModeReplace, - (unsigned char *) &applet_type, 1); - - /* This is a bit of a hack, but for the sake of speed (it is assumed that - * once HildonRemoteTexture is created, a lot of ClientMessages will - * follow), we cache all ClientMessages atoms in static variables. */ - - if (!atoms_initialized) - { - shm_atom = - gdk_x11_get_xatom_by_name_for_display - (display, "_HILDON_TEXTURE_CLIENT_MESSAGE_SHM"); - damage_atom = - gdk_x11_get_xatom_by_name_for_display - (display, "_HILDON_TEXTURE_CLIENT_MESSAGE_DAMAGE"); - show_atom = - gdk_x11_get_xatom_by_name_for_display - (display, "_HILDON_TEXTURE_CLIENT_MESSAGE_SHOW"); - position_atom = - gdk_x11_get_xatom_by_name_for_display - (display, "_HILDON_TEXTURE_CLIENT_MESSAGE_POSITION"); - offset_atom = - gdk_x11_get_xatom_by_name_for_display - (display, "_HILDON_TEXTURE_CLIENT_MESSAGE_OFFSET"); - scale_atom = - gdk_x11_get_xatom_by_name_for_display - (display, "_HILDON_TEXTURE_CLIENT_MESSAGE_SCALE"); - parent_atom = - gdk_x11_get_xatom_by_name_for_display - (display, "_HILDON_TEXTURE_CLIENT_MESSAGE_PARENT"); - ready_atom = - gdk_x11_get_xatom_by_name_for_display - (display, "_HILDON_TEXTURE_CLIENT_READY"); -#if 0 - g_debug ("shm atom = %lu\n", shm_atom); - g_debug ("damage atom = %lu\n", damage_atom); - g_debug ("show atom = %lu\n", show_atom); - g_debug ("position atom = %lu\n", position_atom); - g_debug ("offset atom = %lu\n", offset_atom); - g_debug ("scale atom = %lu\n", scale_atom); - g_debug ("parent atom = %lu\n", parent_atom); - g_debug ("ready atom = %lu\n", ready_atom); -#endif - - atoms_initialized = TRUE; - } - - /* Wait for a ready message */ - - gdk_window_add_filter (widget->window, - hildon_remote_texture_event_filter, - widget); -} - -static void -hildon_remote_texture_unrealize (GtkWidget *widget) -{ - gdk_window_remove_filter (widget->window, - hildon_remote_texture_event_filter, - widget); - - GTK_WIDGET_CLASS (hildon_remote_texture_parent_class)->unrealize (widget); -} - -static void -hildon_remote_texture_show (GtkWidget *widget) -{ - HildonRemoteTexture *self = HILDON_REMOTE_TEXTURE (widget); - - GTK_WIDGET_CLASS (hildon_remote_texture_parent_class)->show (widget); - hildon_remote_texture_set_show (self, 1); -} - -static void -hildon_remote_texture_hide (GtkWidget *widget) -{ - HildonRemoteTexture *self = HILDON_REMOTE_TEXTURE (widget); - - hildon_remote_texture_set_show (self, 0); - GTK_WIDGET_CLASS (hildon_remote_texture_parent_class)->hide (widget); -} - -static void -hildon_remote_texture_class_init (HildonRemoteTextureClass *klass) -{ - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - - widget_class->realize = hildon_remote_texture_realize; - widget_class->unrealize = hildon_remote_texture_unrealize; - widget_class->show = hildon_remote_texture_show; - widget_class->hide = hildon_remote_texture_hide; - - g_type_class_add_private (klass, sizeof (HildonRemoteTexturePrivate)); -} - -static void -hildon_remote_texture_init (HildonRemoteTexture *self) -{ - HildonRemoteTexturePrivate - *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); - - /* Default non-zero values for the private variables */ - - priv->scale_x = 1; - priv->scale_y = 1; - priv->opacity = 0xff; -} - -/** - * hildon_remote_texture_new: - * - * Creates a new #HildonRemoteTexture. - * - * Return value: A #HildonRemoteTexture - * - * Since: 2.2 - **/ -GtkWidget* -hildon_remote_texture_new (void) -{ - HildonRemoteTexture *newwindow = g_object_new (HILDON_TYPE_REMOTE_TEXTURE, NULL); - - gtk_window_set_decorated (GTK_WINDOW (newwindow), FALSE); - - return GTK_WIDGET (newwindow); -} - -/* - * An filter for GDK X11 events, waiting for PropertyNotify (window property - * changes) events, keeping track of remote texture ready atom. - * Having the ready atom set on the window by the window manager will trigger - * updates of actor parameters (position/rotation/etc...) to be sent off - * to the window manager for processing. - */ -static GdkFilterReturn -hildon_remote_texture_event_filter (GdkXEvent *xevent, - GdkEvent *event, - gpointer data) -{ - HildonRemoteTexture *self = HILDON_REMOTE_TEXTURE (data); - XAnyEvent *any = xevent; - - if (any->type == PropertyNotify) - { - XPropertyEvent *property = xevent; - - if (property->atom == ready_atom) - { - hildon_remote_texture_update_ready (self); - } - } - - return GDK_FILTER_CONTINUE; -} - -/* - * Check for the ready atom on the remote texture X11 window. - * If present, send all pending remote texture messages to the - * window manager. - */ -static void -hildon_remote_texture_update_ready (HildonRemoteTexture *self) -{ - HildonRemoteTexturePrivate - *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); - GtkWidget *widget = GTK_WIDGET (self); - Display *display = GDK_WINDOW_XDISPLAY (widget->window); - Window window = GDK_WINDOW_XID (widget->window); - - int status; - gint xerror; - - Atom actual_type; - int actual_format; - unsigned long nitems, bytes_after; - unsigned char *prop = NULL; - - /* Check for the "ready" property */ - - gdk_error_trap_push (); - status = XGetWindowProperty (display, window, - ready_atom, 0, 32, - False, XA_ATOM, - &actual_type, &actual_format, - &nitems, &bytes_after, &prop); - xerror = gdk_error_trap_pop(); - - if (prop) - { - /* We do not actually use the property value for anything, - * it is enough that the property is set. */ - - XFree (prop); - } - - if (xerror || - (status != Success) || (actual_type != XA_ATOM) || - (actual_format != 32) || (nitems != 1)) - { - priv->ready = 0; - return; - } - - if (priv->ready) - { - /* The ready flag has been set once already. This means that - * the WM has restarted. Trigger re-mapping of the widget to - * update the texture actor first. Then push all remote - * texture settings anew. */ - - priv->map_event_cb_id = - g_signal_connect (G_OBJECT (self), - "map-event", - G_CALLBACK(hildon_remote_texture_map_event), - self); - - if (GTK_WIDGET_MAPPED (GTK_WIDGET (self))) - { - gtk_widget_unmap (GTK_WIDGET (self)); - gtk_widget_map (GTK_WIDGET (self)); - } - - return; - } - - priv->ready = 1; - - /* Send all pending messages */ - - hildon_remote_texture_send_pending_messages (self); -} - -static void -hildon_remote_texture_send_pending_messages (HildonRemoteTexture *self) -{ - HildonRemoteTexturePrivate - *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); - - if (priv->set_shm) - hildon_remote_texture_set_image(self, - priv->shm_key, - priv->shm_width, priv->shm_height, - priv->shm_bpp); - - if (priv->set_damage) - hildon_remote_texture_update_area (self, - priv->damage_x1, - priv->damage_y1, - priv->damage_x2 - priv->damage_x1, - priv->damage_y2 - priv->damage_y1); - - if (priv->set_position) - hildon_remote_texture_set_position (self, - priv->x, - priv->y, - priv->width, - priv->height); - - if (priv->set_offset) - hildon_remote_texture_set_offset (self, - priv->offset_x, - priv->offset_y); - - if (priv->set_scale) - hildon_remote_texture_set_scale (self, - priv->scale_x, - priv->scale_y); - - if (priv->set_parent) - hildon_remote_texture_set_parent (self, - priv->parent); - - if (priv->set_show) - hildon_remote_texture_set_show_full (self, - priv->show, priv->opacity); -} - -static void -hildon_remote_texture_send_all_messages (HildonRemoteTexture *self) -{ - HildonRemoteTexturePrivate - *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); - - priv->set_shm = 1; - priv->set_damage = 1; - priv->set_position = 1; - priv->set_scale = 1; - priv->set_parent = 1; - priv->set_show = 1; - - hildon_remote_texture_send_pending_messages (self); -} - -/* ------------------------------------------------------------- */ - -/** - * hildon_remote_texture_send_message: - * @self: A #HildonRemoteTexture - * @message_type: Message id for the remote texture message. - * @l0: 1st remote texture message parameter. - * @l1: 2nd remote texture message parameter. - * @l2: 3rd remote texture message parameter. - * @l3: 4th remote texture message parameter. - * @l4: 5th remote texture message parameter. - * - * Sends an X11 ClientMessage event to the window manager with - * the specified parameters -- id (@message_type) and data (@l0, - * @l1, @l2, @l3, @l4). - * - * This is an internal utility function that application will - * not need to call directly. - * - * Since: 2.2 - **/ -void -hildon_remote_texture_send_message (HildonRemoteTexture *self, - guint32 message_type, - guint32 l0, - guint32 l1, - guint32 l2, - guint32 l3, - guint32 l4) -{ - GtkWidget *widget = GTK_WIDGET (self); - Display *display = GDK_WINDOW_XDISPLAY (widget->window); - Window window = GDK_WINDOW_XID (widget->window); - - XEvent event = { 0 }; - - event.xclient.type = ClientMessage; - event.xclient.window = window; - event.xclient.message_type = (Atom)message_type; - event.xclient.format = 32; - event.xclient.data.l[0] = l0; - event.xclient.data.l[1] = l1; - event.xclient.data.l[2] = l2; - event.xclient.data.l[3] = l3; - event.xclient.data.l[4] = l4; - -#if 0 - g_debug ("%lu (%lu %lu %lu %lu %lu) -> %lu\n", - message_type, - l0, l1, l2, l3, l4, - window); -#endif - - XSendEvent (display, window, True, - StructureNotifyMask, - (XEvent *)&event); -} - -/** - * hildon_remote_texture_set_image: - * @self: A #HildonRemoteTexture - * @key: The key that would be used with shmget in hildon-desktop. The key - * should probably be created with ftok, and the relevant shared memory - * area should be created before this call. - * @width: width of image in pixels - * @height: height of image in pixels - * @bpp: BYTES per pixel - usually 2,3 or 4 - * - * Since: 2.2 - */ -void -hildon_remote_texture_set_image (HildonRemoteTexture *self, - key_t key, - guint width, - guint height, - guint bpp) -{ - HildonRemoteTexturePrivate - *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); - GtkWidget *widget = GTK_WIDGET (self); - - priv->set_shm = 1; - priv->shm_key = key; - priv->shm_width = width; - priv->shm_height = height; - priv->shm_bpp = bpp; - - if (GTK_WIDGET_MAPPED (widget) && priv->ready) - { - /* Defer messages until the remote texture is parented - * and the parent window is mapped */ - if (!priv->parent || !GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent))) - return; - hildon_remote_texture_send_message (self, - shm_atom, - priv->shm_key, - priv->shm_width, - priv->shm_height, - priv->shm_bpp, - 0); - priv->set_shm = 0; - } -} - -/** - * hildon_remote_texture_update_area: - * @self: A #HildonRemoteTexture - * @x: offset of damaged area in pixels - * @y: offset of damaged area in pixels - * @width: width of damaged area in pixels - * @height: height of damaged area in pixels - * - * This signals to hildon-desktop that a specific region of the memory area - * has changed. This will trigger a redraw and will update the relevant tiles - * of the texture. - * - * Since: 2.2 - */ -void -hildon_remote_texture_update_area (HildonRemoteTexture *self, - gint x, - gint y, - gint width, - gint height) -{ - HildonRemoteTexturePrivate - *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); - GtkWidget *widget = GTK_WIDGET (self); - - if (priv->damage_x1==priv->damage_x2 || priv->damage_y1==priv->damage_y2) - { - priv->damage_x1 = x; - priv->damage_y1 = y; - priv->damage_x2 = x+width; - priv->damage_y2 = y+height; - } - else - { - if (xdamage_x1) priv->damage_x1 = x; - if (ydamage_y1) priv->damage_y1 = y; - if (x+width>priv->damage_x2) priv->damage_x2 = x+width; - if (y+height>priv->damage_y2) priv->damage_y2 = y+height; - } - priv->set_damage = 1; - - if (GTK_WIDGET_MAPPED (widget) && priv->ready) - { - /* Defer messages until the remote texture is parented - * and the parent window is mapped */ - if (!priv->parent || !GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent))) - return; - hildon_remote_texture_send_message (self, - damage_atom, - priv->damage_x1, - priv->damage_y1, - priv->damage_x2 - priv->damage_x1, - priv->damage_y2 - priv->damage_y1, - 0); - priv->set_damage = 0; - priv->damage_x1 = 0; - priv->damage_y1 = 0; - priv->damage_x2 = 0; - priv->damage_y2 = 0; - } -} - -/** - * hildon_remote_texture_set_show_full: - * @self: A #HildonRemoteTexture - * @show: A boolean flag setting the visibility of the remote texture. - * @opacity: Desired opacity setting - * - * Send a message to the window manager setting the visibility of - * the remote texture. This will only affect the visibility of - * the remote texture set by the compositing window manager in its own - * rendering pipeline, after X has drawn the window to the off-screen - * buffer. This setting, naturally, has no effect if the #HildonRemoteTexture - * widget is not visible in X11 terms (i.e. realized and mapped). - * - * Furthermore, if a widget is parented, its final visibility will be - * affected by that of the parent window. - * - * The opacity setting ranges from zero (0), being completely transparent - * to 255 (0xff) being fully opaque. - * - * If the remote texture WM-counterpart is not ready, the show message - * will be queued until the WM is ready for it. - * - * Since: 2.2 - **/ -void -hildon_remote_texture_set_show_full (HildonRemoteTexture *self, - gint show, - gint opacity) -{ - HildonRemoteTexturePrivate - *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); - GtkWidget *widget = GTK_WIDGET (self); - - if (opacity > 255) - opacity = 255; - - if (opacity < 0) - opacity = 0; - - priv->show = show; - priv->opacity = opacity; - priv->set_show = 1; - - if (GTK_WIDGET_MAPPED (widget) && priv->ready) - { - /* Defer show messages until the remote texture is parented - * and the parent window is mapped */ - if (!priv->parent || !GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent))) - return; - hildon_remote_texture_send_message (self, - show_atom, - show, opacity, - 0, 0, 0); - priv->set_show = 0; - } -} - -/** - * hildon_remote_texture_set_show: - * @self: A #HildonRemoteTexture - * @show: A boolean flag setting the visibility of the remote texture. - * - * This function is a shortcut for hildon_remote_texture_set_show_full(), - * setting the overall actor visibility without changing it's opacity - * setting. - * - * Since: 2.2 - **/ -void -hildon_remote_texture_set_show (HildonRemoteTexture *self, - gint show) -{ - HildonRemoteTexturePrivate - *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); - - hildon_remote_texture_set_show_full (self, - show, priv->opacity); -} - -/** - * hildon_remote_texture_set_opacity: - * @self: A #HildonRemoteTexture - * @opacity: Desired opacity setting - * - * This function is a shortcut for hildon_remote_texture_set_show_full(), - * setting actor opacity without changing it's overall visibility. - * - * See hildon_remote_texture_set_show_full() for description of the range - * of values @opacity argument takes. - * - * Since: 2.2 - **/ -void -hildon_remote_texture_set_opacity (HildonRemoteTexture *self, - gint opacity) -{ - HildonRemoteTexturePrivate - *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); - - hildon_remote_texture_set_show_full (self, - priv->show, opacity); -} - -/** - * hildon_remote_texture_set_position: - * @self: A #HildonRemoteTexture - * @x: Desired X coordinate - * @y: Desired Y coordinate - * @width: Desired width - * @height: Desired height - * - * Send a message to the window manager setting the offset of the remote - * texture in the window (in Remote texture's pixels). The texture - * is also subject to the animation effects rendered by the compositing - * window manager on that window (like those by task switcher). - * - * If the remote texture WM-counterpart is not ready, the show message - * will be queued until the WM is ready for it. - * - * Since: 2.2 - **/ -void -hildon_remote_texture_set_position (HildonRemoteTexture *self, - gint x, - gint y, - gint width, - gint height) -{ - HildonRemoteTexturePrivate - *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); - GtkWidget *widget = GTK_WIDGET (self); - - priv->x = x; - priv->y = y; - priv->width = width; - priv->height = height; - priv->set_position = 1; - - if (GTK_WIDGET_MAPPED (widget) && priv->ready) - { - /* Defer messages until the remote texture is parented - * and the parent window is mapped */ - - if (!priv->parent || !GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent))) - return; - hildon_remote_texture_send_message (self, - position_atom, - x, y, - width, height, 0); - priv->set_position = 0; - } -} - -/** - * hildon_remote_texture_set_offset: - * @self: A #HildonRemoteTexture - * @x: Desired X offset - * @y: Desired Y offset - * - * Send a message to the window manager setting the offset of the remote - * texture in the window (in Remote texture's pixels). The texture - * is also subject to the animation effects rendered by the compositing - * window manager on that window (like those by task switcher). - * - * If the remote texture WM-counterpart is not ready, the show message - * will be queued until the WM is ready for it. - * - * Since: 2.2 - **/ -void -hildon_remote_texture_set_offset (HildonRemoteTexture *self, - double x, - double y) -{ - HildonRemoteTexturePrivate - *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); - GtkWidget *widget = GTK_WIDGET (self); - - priv->offset_x = x; - priv->offset_y = y; - priv->set_offset = 1; - - if (GTK_WIDGET_MAPPED (widget) && priv->ready) - { - /* Defer messages until the remote texture is parented - * and the parent window is mapped */ - - if (!priv->parent || !GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent))) - return; - hildon_remote_texture_send_message (self, - offset_atom, - (gint)(x*65536), (gint)(y*65536), - 0, 0, 0); - priv->set_offset = 0; - } -} - -/** - * hildon_remote_texture_set_scalex: - * @self: A #HildonRemoteTexture - * @x_scale: The scale factor for the memory area to be rendered in the X-axis - * @y_scale: The scale factor for the memory area to be rendered in the X-axis - * - * Since: 2.2 - **/ -void -hildon_remote_texture_set_scale (HildonRemoteTexture *self, - double x_scale, - double y_scale) -{ - HildonRemoteTexturePrivate - *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); - GtkWidget *widget = GTK_WIDGET (self); - - priv->scale_x = x_scale; - priv->scale_y = y_scale; - priv->set_scale = 1; - - if (GTK_WIDGET_MAPPED (widget) && priv->ready) - { - /* Defer messages until the remote texture is parented - * and the parent window is mapped */ - if (!priv->parent || !GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent))) - return; - hildon_remote_texture_send_message (self, - scale_atom, - priv->scale_x * (1 << 16), - priv->scale_y * (1 << 16), - 0, 0, 0); - priv->set_scale = 0; - } -} - -/* - * This callback will be triggered by the parent widget of - * an remote texture when it is mapped. The compositing - * window manager is now ready to parent the remote texture - * into the target parent window. - */ -static gboolean -hildon_remote_texture_parent_map_event (GtkWidget *parent, - GdkEvent *event, - gpointer user_data) -{ - hildon_remote_texture_set_parent (HILDON_REMOTE_TEXTURE (user_data), - GTK_WINDOW (parent)); - return FALSE; -} - -/* - * This callback will be triggered by the widget re-mapping - * itself in case of WM restarting. The point is to push all - * remote texture parameters anew to the WM. - */ -static gboolean -hildon_remote_texture_map_event (GtkWidget *widget, - GdkEvent *event, - gpointer user_data) -{ - HildonRemoteTexture - *self = HILDON_REMOTE_TEXTURE (user_data); - HildonRemoteTexturePrivate - *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); - - hildon_remote_texture_send_all_messages (self); - - /* Disconnect the "map-event" handler after the "emergency resend all - * actor parameters" drill is over. */ - - if (priv->map_event_cb_id) - { - g_signal_handler_disconnect (self, - priv->map_event_cb_id); - priv->map_event_cb_id = 0; - } - - return FALSE; -} - -/** - * hildon_remote_texture_set_parent: - * @self: A #HildonRemoteTexture - * @parent: A #GtkWindow that the actor will be parented to. - * - * Send a message to the window manager setting the parent window - * for the remote texture. Parenting an actor will not affect the - * X window that the HildonRemoteTexture represents, but it's off-screen - * bitmap as it is handled by the compositing window manager. - * - * Parenting an remote texture will affect its visibility as set - * by the gtk_widget_show(), gtk_widget_hide() and - * hildon_remote_texture_set_show(). The remote texture will only be - * visible when the top-level window it is parented is visible. - * - * Passing %NULL as a @parent argument will unparent the remote texture. - * This will restore the actor's visibility if it was suppressed by - * being unparented or parented to an unmapped window. - * - * If the remote texture WM-counterpart is not ready, the show message - * will be queued until the WM is ready for it. - * - * Since: 2.2 - **/ -void -hildon_remote_texture_set_parent (HildonRemoteTexture *self, - GtkWindow *parent) -{ - HildonRemoteTexturePrivate - *priv = HILDON_REMOTE_TEXTURE_GET_PRIVATE (self); - GtkWidget *widget = GTK_WIDGET (self); - - gtk_window_set_transient_for (GTK_WINDOW (self), parent); - - if (priv->parent != parent) - { - /* Setting a new parent */ - - if (priv->parent) - { - if (priv->parent_map_event_cb_id) - g_signal_handler_disconnect (priv->parent, - priv->parent_map_event_cb_id); - - /* Might need a synchronized "parent(0)" or "parent(new parent)" - * message here before we can safely decrease the reference count. */ - - g_object_unref (priv->parent); - } - - priv->parent = parent; - priv->set_parent = 1; - - if (parent != 0) - { - /* The widget is being (re)parented, not unparented. */ - - g_object_ref (parent); - - priv->parent_map_event_cb_id = - g_signal_connect (G_OBJECT (priv->parent), - "map-event", - G_CALLBACK(hildon_remote_texture_parent_map_event), - self); - } - else - { - priv->parent_map_event_cb_id = 0; - } - } - - if (GTK_WIDGET_MAPPED (widget) && priv->ready) - { - Window win = 0; - - /* If the remote texture is being unparented or parented to an - * unmapped widget, force its visibility to "hidden". */ - - if (!priv->parent || !GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent))) - { - hildon_remote_texture_send_message (self, - show_atom, - 0, priv->opacity, - 0, 0, 0); - } - - /* If the widget is being parented (parent != 0), only proceed when - * the parent widget is realized, since we need the X window id of - * the parent. If the widget is being unparented (parent == 0), pass - * the "special" window id of 0 in the message. */ - - if (priv->parent) - { - if (!GTK_WIDGET_MAPPED (GTK_WIDGET (priv->parent))) - return; - - GdkWindow *gdk = GTK_WIDGET (parent)->window; - win = GDK_WINDOW_XID (gdk); - } - - hildon_remote_texture_send_message (self, - parent_atom, - win, - 0, 0, 0, 0); - priv->set_parent = 0; - - /* Set remote texture visibility to desired value (in case it was - * forced off when the actor was parented into an unmapped widget). */ - - hildon_remote_texture_send_message (self, - show_atom, - priv->show, priv->opacity, - 0, 0, 0); - priv->set_show = 0; - } -} - diff --git a/src/hildon-remote-texture.h b/src/hildon-remote-texture.h deleted file mode 100644 index 3bdfd1d..0000000 --- a/src/hildon-remote-texture.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_REMOTE_TEXTURE_H__ -#define __HILDON_REMOTE_TEXTURE_H__ - -#include "hildon-window.h" -#include -#include - -G_BEGIN_DECLS - -#define HILDON_TYPE_REMOTE_TEXTURE \ - (hildon_remote_texture_get_type()) - -#define HILDON_REMOTE_TEXTURE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - HILDON_TYPE_REMOTE_TEXTURE, \ - HildonRemoteTexture)) - -#define HILDON_REMOTE_TEXTURE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - HILDON_TYPE_REMOTE_TEXTURE, \ - HildonRemoteTextureClass)) - -#define HILDON_IS_REMOTE_TEXTURE(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ - HILDON_TYPE_REMOTE_TEXTURE)) - -#define HILDON_IS_REMOTE_TEXTURE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), \ - HILDON_TYPE_REMOTE_TEXTURE)) - -#define HILDON_REMOTE_TEXTURE_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - HILDON_TYPE_REMOTE_TEXTURE, \ - HildonRemoteTextureClass)) - -typedef struct _HildonRemoteTexture HildonRemoteTexture; -typedef struct _HildonRemoteTextureClass HildonRemoteTextureClass; - -struct _HildonRemoteTextureClass -{ - GtkWindowClass parent_class; - - /* Padding for future extension */ - void (*_hildon_reserved1)(void); - void (*_hildon_reserved2)(void); - void (*_hildon_reserved3)(void); - void (*_hildon_reserved4)(void); -}; - -struct _HildonRemoteTexture -{ - GtkWindow parent; -}; - -GType -hildon_remote_texture_get_type (void) G_GNUC_CONST; - -GtkWidget* -hildon_remote_texture_new (void); - -void -hildon_remote_texture_send_message (HildonRemoteTexture *self, - guint32 message_type, - guint32 l0, - guint32 l1, - guint32 l2, - guint32 l3, - guint32 l4); - -void -hildon_remote_texture_set_image (HildonRemoteTexture *self, - key_t key, - guint width, - guint height, - guint bpp); -void -hildon_remote_texture_update_area (HildonRemoteTexture *self, - gint x, - gint y, - gint width, - gint height); -void -hildon_remote_texture_set_show_full (HildonRemoteTexture *self, - gint show, - gint opacity); -void -hildon_remote_texture_set_show (HildonRemoteTexture *self, - gint show); -void -hildon_remote_texture_set_opacity (HildonRemoteTexture *self, - gint opacity); -void -hildon_remote_texture_set_position (HildonRemoteTexture *self, - gint x, - gint y, - gint width, - gint height); -void -hildon_remote_texture_set_offset (HildonRemoteTexture *self, - double x, - double y); -void -hildon_remote_texture_set_scale (HildonRemoteTexture *self, - double x_scale, - double y_scale); -void -hildon_remote_texture_set_parent (HildonRemoteTexture *self, - GtkWindow *parent); - -G_END_DECLS - -#endif /* __HILDON_REMOTE_TEXTURE_H__ */ diff --git a/src/hildon-seekbar-private.h b/src/hildon-seekbar-private.h deleted file mode 100644 index b58f881..0000000 --- a/src/hildon-seekbar-private.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_PRIVATE_H__ -#define __HILDON_SEEKBAR_PRIVATE_H__ - -G_BEGIN_DECLS - -typedef struct _HildonSeekbarPrivate HildonSeekbarPrivate; - -#define HILDON_SEEKBAR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_SEEKBAR, HildonSeekbarPrivate)); - -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.. */ -}; - -G_END_DECLS - -#endif /* __HILDON_SEEKBAR_PRIVATE_H__ */ diff --git a/src/hildon-seekbar.c b/src/hildon-seekbar.c deleted file mode 100644 index 19c8351..0000000 --- a/src/hildon-seekbar.c +++ /dev/null @@ -1,618 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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. - */ - -#undef HILDON_DISABLE_DEPRECATED - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include "hildon-seekbar.h" -#include "hildon-seekbar-private.h" - -static GtkScaleClass* parent_class = NULL; - -static void -hildon_seekbar_class_init (HildonSeekbarClass *seekbar_class); - -static void -hildon_seekbar_init (HildonSeekbar *seekbar); - -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); - -static void -hildon_seekbar_size_request (GtkWidget *widget, - GtkRequisition *event); - -static void -hildon_seekbar_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); - -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 - -#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 - -#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 - -enum -{ - PROP_0, - PROP_TOTAL_TIME, - PROP_POSITION, - PROP_FRACTION -}; - -/** - * hildon_seekbar_get_type: - * - * Initializes, and returns the type of a hildon seekbar. - * - * Returns: GType of #HildonSeekbar - * - */ -GType G_GNUC_CONST -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->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; - - /** - * HildonSeekbar:total-time: - * - * Total playing time of this media file. - */ - 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)); - - /** - * HildonSeekbar:position: - * - * Current position in this media file. - */ - 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)); - - /** - * HildonSeekbar:fraction: - * - * Current fraction related to the progress indicator. - */ - 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) -{ - GtkRange *range = GTK_RANGE(seekbar); - - /* Initialize range widget */ - range->orientation = GTK_ORIENTATION_HORIZONTAL; - range->flippable = 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); - -#if defined(MAEMO_GTK) || GTK_CHECK_VERSION(2,11,0) - return gtk_range_get_fill_level (GTK_RANGE (seekbar)); -#else - return 0; -#endif -} - -/** - * 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), "show-fill-level", TRUE, NULL); - - fraction = CLAMP (fraction, range->adjustment->lower, - range->adjustment->upper); - -#if defined(MAEMO_GTK) || GTK_CHECK_VERSION(2,11,0) - /* Update stream position of range widget */ - gtk_range_set_fill_level (range, fraction); -#endif - - 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 defined(MAEMO_GTK) || GTK_CHECK_VERSION(2,11,0) - if (value <= gtk_range_get_fill_level (range)) { -#else - if (value) { -#endif - 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 (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); -} - -/* - * 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 deleted file mode 100644 index 1937076..0000000 --- a/src/hildon-seekbar.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#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)) - -#define HILDON_SEEKBAR_GET_CLASS(obj) \ - ((HildonSeekBarClass *) G_OBJECT_GET_CLASS(obj)) - - -typedef struct _HildonSeekbar HildonSeekbar; - -typedef struct _HildonSeekbarClass HildonSeekbarClass; - -struct _HildonSeekbar -{ - GtkScale parent; -}; - -struct _HildonSeekbarClass -{ - GtkScaleClass parent_class; -}; - -GType G_GNUC_CONST -hildon_seekbar_get_type (void); - -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__ */ - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-set-password-dialog-private.h b/src/hildon-set-password-dialog-private.h deleted file mode 100644 index 1eef7f3..0000000 --- a/src/hildon-set-password-dialog-private.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_PRIVATE_H__ -#define __HILDON_SET_PASSWORD_DIALOG_PRIVATE_H__ - -G_BEGIN_DECLS - -#define HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE(obj)\ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_SET_PASSWORD_DIALOG, \ - HildonSetPasswordDialogPrivate)); - -typedef struct _HildonSetPasswordDialogPrivate HildonSetPasswordDialogPrivate; - -struct _HildonSetPasswordDialogPrivate -{ - GtkWidget *checkbox; - - GtkLabel *message_label; - - GtkWidget *pwd1st_entry; - GtkWidget *pwd1st_caption; - gchar *pwd1st_caption_string; - - GtkWidget *pwd2nd_entry; - GtkWidget *pwd2nd_caption; - gchar *pwd2nd_caption_string; - - gboolean protection; -}; - -G_END_DECLS - -#endif /* __HILDON_SET_PASSWORD_DIALOG_PRIVATE_H__ */ diff --git a/src/hildon-set-password-dialog.c b/src/hildon-set-password-dialog.c deleted file mode 100644 index baf4bcf..0000000 --- a/src/hildon-set-password-dialog.c +++ /dev/null @@ -1,743 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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. - */ - -#undef HILDON_DISABLE_DEPRECATED - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hildon-set-password-dialog.h" -#include "hildon-caption.h" -#include "hildon-note.h" -#include "hildon-defines.h" -#include "hildon-banner.h" -#include "hildon-set-password-dialog-private.h" -#include "hildon-entry.h" -#include "hildon-check-button.h" - -#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 "wdgt_bd_done" - -#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 "wdgt_bd_done" - -#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" - -#define _(String) dgettext("hildon-libs", String) - -#define c_(String) dgettext("hildon-common-strings", String) - -static GtkDialogClass* parent_class; - -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); - -enum -{ - PROP_0, - PROP_MESSAGE, - PROP_PASSWORD, - PROP_HILDON_PASSWORD_DIALOG -}; - -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); - g_assert (priv); - - switch (prop_id) { - - case PROP_MESSAGE: - /* Update domain label to display new value */ - gtk_label_set_text (priv->message_label, g_value_get_string (value)); - break; - - case PROP_PASSWORD: - /* Update password entry to display new value */ - hildon_entry_set_text (HILDON_ENTRY (priv->pwd1st_entry), 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 */ - /* FIXME It looks kinda extremally bad that this is here... - * what about situations where this prop is NOT set during - * constructing? */ - 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); - g_assert (priv); - - switch (prop_id) { - - case PROP_MESSAGE: - g_value_set_string (value, gtk_label_get_text (priv->message_label)); - break; - - case PROP_PASSWORD: - g_value_set_string (value, - hildon_entry_get_text (HILDON_ENTRY (priv->pwd1st_entry))); - 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; - AtkObject *atk_aux = NULL; - - GtkSizeGroup *group; - - priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE (dialog); - g_assert (priv); - 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->message_label = GTK_LABEL (gtk_label_new (NULL)); - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), - GTK_WIDGET(priv->message_label), FALSE, FALSE, 0); - gtk_widget_show (GTK_WIDGET (priv->message_label)); - - if (priv->protection == TRUE) { - /* Use Change Password Dialog strings */ - priv->pwd1st_caption_string = _(HILDON_SET_MODIFY_PASSWORD_DIALOG_PASSWORD); - priv->pwd2nd_caption_string = _(HILDON_SET_MODIFY_PASSWORD_DIALOG_VERIFY_PASSWORD); - - /* Setup checkbox to enable/disable password protection */ - priv->checkbox = hildon_check_button_new (HILDON_SIZE_AUTO_WIDTH | HILDON_SIZE_FINGER_HEIGHT); - gtk_button_set_label (GTK_BUTTON (priv->checkbox), _(HILDON_SET_MODIFY_PASSWORD_DIALOG_LABEL)); - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), - priv->checkbox, TRUE, TRUE, 0); - gtk_widget_show (priv->checkbox); - hildon_check_button_set_active (HILDON_CHECK_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->pwd1st_caption_string = _(HILDON_SET_PASSWORD_DIALOG_PASSWORD); - priv->pwd2nd_caption_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->pwd1st_entry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH); - if ((atk_aux = gtk_widget_get_accessible(priv->pwd1st_entry))) - { - atk_object_set_name(atk_aux, "Old Passwd"); - } - - -#ifdef MAEMO_GTK - g_object_set (priv->pwd1st_entry, "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL); -#endif - - gtk_entry_set_visibility (GTK_ENTRY(priv->pwd1st_entry), FALSE); - gtk_widget_show (priv->pwd1st_entry); - priv->pwd1st_caption = hildon_caption_new (group, - priv->pwd1st_caption_string, - priv->pwd1st_entry, - NULL, HILDON_CAPTION_OPTIONAL); - - hildon_caption_set_separator (HILDON_CAPTION(priv->pwd1st_caption), ""); - gtk_entry_set_visibility (GTK_ENTRY (priv->pwd1st_entry), FALSE); - gtk_box_pack_start (GTK_BOX(GTK_DIALOG (dialog)->vbox), - priv->pwd1st_caption, TRUE, TRUE, 0); - gtk_widget_show (priv->pwd1st_caption); - - /* Create the password verify field */ - priv->pwd2nd_entry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH); - if ((atk_aux = gtk_widget_get_accessible(priv->pwd2nd_entry))) - { - atk_object_set_name(atk_aux, "New Passwd"); - } - - -#ifdef MAEMO_GTK - g_object_set (priv->pwd2nd_entry, "hildon-input-mode", HILDON_GTK_INPUT_MODE_FULL, NULL); -#endif - - gtk_widget_show (priv->pwd2nd_entry); - priv->pwd2nd_caption = hildon_caption_new (group, - priv->pwd2nd_caption_string, - priv->pwd2nd_entry, - NULL, HILDON_CAPTION_OPTIONAL); - hildon_caption_set_separator (HILDON_CAPTION (priv->pwd2nd_caption), ""); - gtk_entry_set_visibility (GTK_ENTRY (priv->pwd2nd_entry), FALSE); - gtk_box_pack_start (GTK_BOX(GTK_DIALOG (dialog)->vbox), - priv->pwd2nd_caption, TRUE, TRUE, 0); - gtk_widget_show (priv->pwd2nd_caption); - - /* 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 */ - gtk_dialog_add_button (GTK_DIALOG (dialog), _(priv->protection - ? HILDON_SET_MODIFY_PASSWORD_DIALOG_OK - : HILDON_SET_PASSWORD_DIALOG_OK), GTK_RESPONSE_OK); - - gtk_widget_show_all (GTK_DIALOG (dialog)->vbox); - gtk_widget_show_all (GTK_DIALOG (dialog)->action_area); - - /* 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_MESSAGE, - g_param_spec_string ("message", - "Message", - "A message to display to the user", - NULL, - G_PARAM_READWRITE)); - - /** - * HildonSetPasswordDialog:modify-protection: - * - * Password type. - */ - 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)); - - /** - * HildonSetPasswordDialog:password: - * - * Content of the password field. - */ - 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 *pwd1st_entry; - GtkEntry *pwd2nd_entry; - gchar *text1; - gchar *text2; - HildonNote *note; - gint i; - HildonSetPasswordDialogPrivate *priv; - - priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE (dialog); - g_assert (priv); - - /* Password and verification */ - pwd1st_entry = GTK_ENTRY (gtk_bin_get_child - (GTK_BIN (priv->pwd1st_caption))); - pwd2nd_entry = GTK_ENTRY (gtk_bin_get_child - (GTK_BIN (priv->pwd2nd_caption))); - text1 = GTK_ENTRY (pwd1st_entry)->text; - text2 = GTK_ENTRY (pwd2nd_entry)->text; - - /* User accepted the dialog */ - if (arg1 == GTK_RESPONSE_OK) { - /* Is the checkbox marked, so password protection is still in use? */ - if (hildon_check_button_get_active (HILDON_CHECK_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"); - - hildon_banner_show_information (GTK_WIDGET (dialog), NULL, - c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH)); - - gtk_widget_grab_focus (GTK_WIDGET (pwd2nd_entry)); - - } else { - /* Error: Passwords don't match, so start over */ - g_signal_stop_emission_by_name (G_OBJECT(dialog), - "response"); - - hildon_entry_set_text (HILDON_ENTRY (pwd1st_entry), ""); - hildon_entry_set_text (HILDON_ENTRY (pwd2nd_entry), ""); - - hildon_banner_show_information (GTK_WIDGET (dialog), NULL, - c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH)); - - gtk_widget_grab_focus (GTK_WIDGET (pwd1st_entry)); - } - } 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 */ - hildon_banner_show_information (GTK_WIDGET (dialog), NULL, c_(HILDON_SET_PASSWORD_DIALOG_EMPTY)); - } else { - /* Error: Second field doesn't match - the empty first field, so start over */ - hildon_banner_show_information (GTK_WIDGET (dialog), NULL, c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH)); - hildon_entry_set_text (HILDON_ENTRY (pwd2nd_entry), ""); - } - - gtk_widget_grab_focus (GTK_WIDGET (pwd1st_entry)); - } - } 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 *pwd1st_entry; - GtkEntry *pwd2nd_entry; - gchar *text1; - gchar *text2; - - HildonSetPasswordDialogPrivate *priv; - - priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE (dialog); - g_assert (priv); - - /* Password and confirmation */ - pwd1st_entry = GTK_ENTRY (gtk_bin_get_child - (GTK_BIN (priv->pwd1st_caption))); - - pwd2nd_entry = GTK_ENTRY (gtk_bin_get_child - (GTK_BIN (priv->pwd2nd_caption))); - - text1 = GTK_ENTRY (pwd1st_entry)->text; - text2 = GTK_ENTRY (pwd2nd_entry)->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"); - hildon_banner_show_information (GTK_WIDGET (dialog), NULL, c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH)); - - gtk_widget_grab_focus (GTK_WIDGET (priv->pwd2nd_entry)); - - } else { - /* Error: Passwords don't match, so start over */ - g_signal_stop_emission_by_name (G_OBJECT(dialog), "response"); - hildon_entry_set_text (HILDON_ENTRY (pwd1st_entry), ""); - hildon_entry_set_text (HILDON_ENTRY (pwd2nd_entry), ""); - hildon_banner_show_information (GTK_WIDGET (dialog), NULL, c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH)); - - gtk_widget_grab_focus (GTK_WIDGET (priv->pwd1st_entry)); - } - } else { - /* First field is empty */ - g_signal_stop_emission_by_name (G_OBJECT (dialog), "response"); - if (text2[0] == '\0') { - /* Error: Both fields are empty */ - hildon_banner_show_information (GTK_WIDGET (dialog), NULL, c_(HILDON_SET_PASSWORD_DIALOG_EMPTY)); - } else { - /* Error: Second field doesn't match - the empty first field, so start over */ - hildon_banner_show_information (GTK_WIDGET (dialog), NULL, c_(HILDON_SET_PASSWORD_DIALOG_MISMATCH)); - hildon_entry_set_text (HILDON_ENTRY (pwd2nd_entry), ""); - } - - gtk_widget_grab_focus (GTK_WIDGET (pwd1st_entry)); - } - } 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; - - g_assert (priv); - - /* If the user enabled/disabled the password protection feature - we enable/disable password entries accordingly */ - active = hildon_check_button_get_active (HILDON_CHECK_BUTTON (widget)); - gtk_widget_set_sensitive (GTK_WIDGET (priv->pwd1st_entry), active); - gtk_widget_set_sensitive (GTK_WIDGET (priv->pwd2nd_entry), active); -} - -/** - * hildon_set_password_dialog_get_type: - * - * Returns GType for HildonPasswordDialog as produced by - * g_type_register_static(). - * - * Returns: HildonSetPasswordDialog type - */ -GType G_GNUC_CONST -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); - g_assert (priv); - - return GTK_ENTRY (priv->pwd1st_entry)->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); - g_assert (priv); - - return priv->protection; -} - -/** - * hildon_set_password_dialog_set_message: - * @dialog: the dialog - * @message: the message or some other descriptive text to be set - * - * Sets the optional descriptive text. - */ -void -hildon_set_password_dialog_set_message (HildonSetPasswordDialog *dialog, - const gchar *message) -{ - HildonSetPasswordDialogPrivate *priv = NULL; - - g_return_if_fail (HILDON_IS_SET_PASSWORD_DIALOG (dialog)); - - priv = HILDON_SET_PASSWORD_DIALOG_GET_PRIVATE (dialog); - g_assert (priv); - - gtk_label_set_text (priv->message_label, message); -} diff --git a/src/hildon-set-password-dialog.h b/src/hildon-set-password-dialog.h deleted file mode 100644 index 4c360eb..0000000 --- a/src/hildon-set-password-dialog.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#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)) - -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 G_GNUC_CONST -hildon_set_password_dialog_get_type (void); - -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_message (HildonSetPasswordDialog *dialog, - const gchar *message); - -G_END_DECLS - -#endif /* __HILDON_SET_PASSWORD_DIALOG_H__ */ - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-sort-dialog-private.h b/src/hildon-sort-dialog-private.h deleted file mode 100644 index 788660e..0000000 --- a/src/hildon-sort-dialog-private.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_PRIVATE_H__ -#define __HILDON_SORT_DIALOG_PRIVATEH__ - -G_BEGIN_DECLS - -#define HILDON_SORT_DIALOG_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), HILDON_TYPE_SORT_DIALOG, HildonSortDialogPrivate)); - -typedef struct _HildonSortDialogPrivate HildonSortDialogPrivate; - -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; -}; - -G_END_DECLS - -#endif /* __HILDON_SORT_DIALOG_PRIVATE_H__ */ diff --git a/src/hildon-sort-dialog.c b/src/hildon-sort-dialog.c deleted file mode 100644 index 3f5b49f..0000000 --- a/src/hildon-sort-dialog.c +++ /dev/null @@ -1,589 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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. - * - * - * - * #HildonSortDialog has been deprecated since Hildon 2.2 - * See Migrating Sort Dialogs - * section to know how to migrate this deprecated widget. - * - * - * - * - * An example for using HildonSortDialog - * - * HildonSortDialog *sort_dialog = HILDON_SORT_DIALOG (hildon_sort_dialog_new (parent)); - * - * gint response_id, add_sort_index; - * - * sort_by[0] = STR_SORT_BY_DATE; - * sort_by[1] = STR_SORT_BY_NAME; - * sort_by[2] = STR_SORT_BY_SIZE; - * sort_by[3] = NULL; - * - * sorting_order[0] = STR_SORTING_ORDER_ASCENDING; - * sorting_order[1] = STR_SORTING_ORDER_DESCENDING; - * sorting_order[2] = NULL; - * - * add_sort_index = hildon_sort_dialog_add_sort_key (sort_dialog, STR_SORT_BY_DATE); - * - * hildon_sort_dialog_add_sort_key (sort_dialog, STR_SORT_BY_NAME); - * - * hildon_sort_dialog_add_sort_key (sort_dialog, STR_SORT_BY_SIZE); - * - * if (dialog.first_time_clicked == TRUE) - * { - * hildon_sort_dialog_set_sort_key (sort_dialog, add_sort_index); - * } - * - * if (dialog.first_time_clicked == FALSE) - * { - * hildon_sort_dialog_set_sort_key (sort_dialog, dialog.sort_key); - * hildon_sort_dialog_set_sort_order (sort_dialog, dialog.sort_order); - * } - * - * gtk_widget_show (GTK_WIDGET (sort_dialog)); - * - * response_id = gtk_dialog_run (GTK_DIALOG (sort_dialog)); - * - * if (response_id == GTK_RESPONSE_OK) - * { - * dialog.sort_key = hildon_sort_dialog_get_sort_key (sort_dialog); - * - * gtk_label_set_text (GTK_LABEL (dialog.label1), sort_by [dialog.sort_key]); - * - * dialog.sort_order = hildon_sort_dialog_get_sort_order (sort_dialog); - * - * gtk_label_set_text (GTK_LABEL (dialog.label2), sorting_order [dialog.sort_order]); - * - * dialog.first_time_clicked = FALSE; - * } - * - * - */ - -#undef HILDON_DISABLE_DEPRECATED - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include "hildon-sort-dialog.h" -#include "hildon-caption.h" -#include "hildon-sort-dialog-private.h" - -#define _(String) \ - dgettext("hildon-libs", String) - -static GtkDialogClass* parent_class; - -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 void -sort_key_changed (GtkWidget *widget, - HildonSortDialog *dialog); - -static void -hildon_sort_dialog_finalize (GObject *object); - -static gint -hildon_sort_dialog_add_sort_key_with_sorting (HildonSortDialog *dialog, - const gchar *sort_key, - gboolean sorting); - -enum -{ - PROP_0, - PROP_SORT_KEY, - PROP_SORT_ORDER -}; - -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); - g_assert (priv); - - gint index = gtk_combo_box_get_active (GTK_COMBO_BOX (widget)); - g_return_if_fail (index < priv->index_counter && index > 0); - - 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; - - /** - * HildonSortDialog:sort-key: - * - * The currently active sort key. - */ - 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)); - - /** - * HildonSortDialog:sort-order: - * - * The sort order for the currently active sort key. - */ - 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); - g_return_val_if_fail (sort_key != NULL, -1); - - priv = HILDON_SORT_DIALOG_GET_PRIVATE (dialog); - g_assert (priv); - - 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); - g_assert (priv); - - 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); - g_assert (priv); - - 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), - _("wdgt_bd_sort"), - GTK_RESPONSE_OK); - /* 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 */ -} - -/** - * hildon_sort_dialog_get_type: - * - * Returns GType for HildonSortDialog as produced by - * g_type_register_static(). - * - * Returns: HildonSortDialog type - */ -GType G_GNUC_CONST -hildon_sort_dialog_get_type (void) -{ - 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); - g_assert (priv); - - 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); - g_assert (priv); - - 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); - g_assert (priv); - - 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); - g_assert (priv); - - 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 - * - */ -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; - - dialog = HILDON_SORT_DIALOG (object); - priv = HILDON_SORT_DIALOG_GET_PRIVATE (dialog); - g_assert (priv); - - 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 deleted file mode 100644 index 0653e89..0000000 --- a/src/hildon-sort-dialog.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#ifndef __HILDON_SORT_DIALOG_H__ -#define __HILDON_SORT_DIALOG_H__ - -#include - -G_BEGIN_DECLS - -typedef struct _HildonSortDialog HildonSortDialog; - -typedef struct _HildonSortDialogClass HildonSortDialogClass; - - -#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)) - -#define HILDON_SORT_DIALOG_GET_CLASS(obj) \ - ((HildonSortDialogClass *) G_OBJECT_GET_CLASS(obj)) - -struct _HildonSortDialog -{ - GtkDialog parent; -}; - -struct _HildonSortDialogClass -{ - GtkDialogClass parent_class; -}; - -GType G_GNUC_CONST -hildon_sort_dialog_get_type (void); - -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, - int 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); - -gint -hildon_sort_dialog_add_sort_key_reversed (HildonSortDialog *dialog, - const gchar *sort_key); - -G_END_DECLS - -#endif /* __HILDON_SORT_DIALOG_H__ */ - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-sound.c b/src/hildon-sound.c deleted file mode 100644 index 1bbc264..0000000 --- a/src/hildon-sound.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * This file is a part of libhildon - * - * Copyright (C) 2005-2008 Nokia Corporation. All rights reserved. - * - * Contact: Kimmo Hämäläinen - * - * 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, or (at your option) any later version. - * - * 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-sound - * @short_description: libcanberra-based utility function for playing a sound. - * - */ - -#include -#include -#include - -#include "hildon-sound.h" - -#define ALARM_GCONF_PATH "/apps/osso/sound/system_alert_volume" - -static ca_context *hildon_ca_context_get (void); - -/* - * hildon_ca_context_get: - * - * hildon maintains a single application-global ca_context object. - * - * This functions is based on ca_gtk_context_get - * - * Returns: a ca_context object - */ -static ca_context * -hildon_ca_context_get (void) -{ - static GStaticPrivate context_private = G_STATIC_PRIVATE_INIT; - ca_context *c = NULL; - const gchar *name = NULL; - gint ret; - - if ((c = g_static_private_get(&context_private))) - return c; - - if ((ret = ca_context_create(&c)) != CA_SUCCESS) { - g_warning("ca_context_create: %s\n", ca_strerror(ret)); - return NULL; - } - if ((ret = ca_context_open(c)) != CA_SUCCESS) { - g_warning("ca_context_open: %s\n", ca_strerror(ret)); - ca_context_destroy(c); - return NULL; - } - - if ((name = g_get_application_name())) - ca_context_change_props(c, CA_PROP_APPLICATION_NAME, name, NULL); - - g_static_private_set(&context_private, c, (GDestroyNotify) ca_context_destroy); - - return c; -} - -/** - * hildon_play_system_sound: - * @sample: sound file to play - * - * Plays the given sample using libcanberra. - * Volume level is received from gconf. - */ -void -hildon_play_system_sound(const gchar *sample) -{ - float volume = 0; - int ret; - ca_context *ca_con = NULL; - ca_proplist *pl = NULL; - -#if 0 /* FIXME: Check volume handling. Would be great not to use Gconf... */ - GConfClient *client; - GConfValue *value; - gint gconf_vol; - - /* - * The volume is from -0dB to -6dB, - The full volume is marked as 2 in gconf */ - 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) - gconf_vol = 2; - else - gconf_vol = gconf_value_get_int(value); - - if (value) - gconf_value_free(value); - g_object_unref (client); - - volume = ((1.0 - (float)gconf_vol / 2.0)) * (-6.0); -#endif - - ca_con = hildon_ca_context_get (); - - ca_proplist_create(&pl); - ca_proplist_sets(pl, CA_PROP_MEDIA_FILENAME, sample); - ca_proplist_setf(pl, CA_PROP_CANBERRA_VOLUME, "%f", volume); - - ret = ca_context_play_full(ca_con, 0, pl, NULL, NULL); - g_debug("ca_context_play_full (vol %f): %s\n", volume, ca_strerror(ret)); - - ca_proplist_destroy(pl); -} diff --git a/src/hildon-sound.h b/src/hildon-sound.h deleted file mode 100644 index 75b843f..0000000 --- a/src/hildon-sound.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_SOUND_H__ -#define __HILDON_SOUND_H__ - -#include - -G_BEGIN_DECLS - -void -hildon_play_system_sound (const gchar *sample); - -G_END_DECLS - -#endif /* __HILDON_SOUND_H__ */ diff --git a/src/hildon-stackable-window-private.h b/src/hildon-stackable-window-private.h deleted file mode 100644 index e32f8d2..0000000 --- a/src/hildon-stackable-window-private.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_STACKABLE_WINDOW_PRIVATE_H__ -#define __HILDON_STACKABLE_WINDOW_PRIVATE_H__ - -G_BEGIN_DECLS - -typedef struct _HildonStackableWindowPrivate HildonStackableWindowPrivate; - -struct _HildonStackableWindowPrivate -{ - HildonWindowStack *stack; - gint stack_position; -}; - -#define HILDON_STACKABLE_WINDOW_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ - HILDON_TYPE_STACKABLE_WINDOW, HildonStackableWindowPrivate)) - -void G_GNUC_INTERNAL -hildon_stackable_window_set_stack (HildonStackableWindow *self, - HildonWindowStack *stack, - gint position); - -G_END_DECLS - -#endif /* __HILDON_STACKABLE_WINDOW_PRIVATE_H__ */ diff --git a/src/hildon-stackable-window.c b/src/hildon-stackable-window.c deleted file mode 100644 index d047a96..0000000 --- a/src/hildon-stackable-window.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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-stackable-window - * @short_description: Widget representing a stackable, top-level window in the Hildon framework. - * @see_also: #HildonWindowStack, #HildonProgram, #HildonWindow - * - * The #HildonStackableWindow is a GTK+ widget which represents a - * top-level window in the Hildon framework. It is derived from - * #HildonWindow. Applications that use stackable windows are organized - * in a hierarchical way so users can go from any window back to the - * application's root window. - * - * The user can only see and interact with the window on top of the - * stack. Although all other windows are mapped and visible, they are - * obscured by the topmost one so in practice they appear as if they - * were hidden. - * - * To add a window to the stack, just use gtk_widget_show(). The - * previous one will be obscured by the new one. When the new window - * is destroyed, the previous one will appear again. - * - * Alternatively, you can remove a window from the top of the stack - * without destroying it by using hildon_window_stack_pop(). The - * window will be automatically hidden and the previous one will - * appear. - * - * For advanced details on stack handling, see #HildonWindowStack - * - * - * Basic HildonStackableWindow example - * - * static void - * show_new_window (void) - * { - * GtkWidget *win; - * - * win = hildon_stackable_window_new (); - * - * // ... configure new window - * - * gtk_widget_show (win); - * } - * - * int - * main (int argc, char **argv) - * { - * GtkWidget *win; - * GtkWidget *button; - * - * gtk_init (&argc, &args); - * - * win = hildon_stackable_window_new (); - * gtk_window_set_title (GTK_WINDOW (win), "Main window); - * - * // ... add some widgets to the window - * - * g_signal_connect (button, "clicked", G_CALLBACK (show_new_window), NULL); - * g_signal_connect (win, "destroy", G_CALLBACK (gtk_main_quit), NULL); - * - * gtk_widget_show_all (win); - * gtk_main (); - * - * return 0; - * } - * - * - */ - -#include -#include -#include - -#include "hildon-stackable-window.h" -#include "hildon-stackable-window-private.h" -#include "hildon-window-stack.h" -#include "hildon-window-stack-private.h" - -G_DEFINE_TYPE (HildonStackableWindow, hildon_stackable_window, HILDON_TYPE_WINDOW); - -void G_GNUC_INTERNAL -hildon_stackable_window_set_stack (HildonStackableWindow *self, - HildonWindowStack *stack, - gint position) -{ - HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (self); - - if (stack) - g_object_ref (stack); - - if (priv->stack) - g_object_unref (priv->stack); - - priv->stack = stack; - priv->stack_position = position; -} - -/** - * hildon_stackable_window_get_stack: - * @self: a #HildonStackableWindow - * - * Returns the stack where window @self is on, or %NULL if the window - * is not stacked. - * - * Return value: a #HildonWindowStack, or %NULL - * - * Since: 2.2 - **/ -HildonWindowStack * -hildon_stackable_window_get_stack (HildonStackableWindow *self) -{ - HildonStackableWindowPrivate *priv; - - g_return_val_if_fail (HILDON_IS_STACKABLE_WINDOW (self), NULL); - - priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (self); - - return priv->stack; -} - -/** - * hildon_stackable_window_set_main_menu: - * @self: a #HildonStackableWindow - * @menu: a #HildonAppMenu to be used for this window - * - * Deprecated: Hildon 2.2: use hildon_window_set_app_menu() - **/ -void -hildon_stackable_window_set_main_menu (HildonStackableWindow *self, - HildonAppMenu *menu) -{ - hildon_window_set_app_menu (HILDON_WINDOW (self), menu); -} - -static void -hildon_stackable_window_map (GtkWidget *widget) -{ - GdkDisplay *display; - Atom atom; - unsigned long val; - HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (widget); - - val = priv->stack_position; - - /* Set additional property "_HILDON_STACKABLE_WINDOW", to allow the WM to manage - it as a stackable window. */ - display = gdk_drawable_get_display (widget->window); - atom = gdk_x11_get_xatom_by_name_for_display (display, "_HILDON_STACKABLE_WINDOW"); - XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (widget->window), atom, - XA_INTEGER, 32, PropModeReplace, - (unsigned char *) &val, 1); - - GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->map (widget); -} - -static void -hildon_stackable_window_show (GtkWidget *widget) -{ - HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (widget); - - /* Stack the window if not already stacked */ - if (priv->stack == NULL) { - HildonWindowStack *stack = hildon_window_stack_get_default (); - _hildon_window_stack_do_push (stack, HILDON_STACKABLE_WINDOW (widget)); - } - - GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->show (widget); -} - -static void -hildon_stackable_window_hide (GtkWidget *widget) -{ - HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (widget); - - if (priv->stack) { - hildon_window_stack_remove (HILDON_STACKABLE_WINDOW (widget)); - } - - GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->hide (widget); -} - -static gboolean -hildon_stackable_window_delete_event (GtkWidget *widget, - GdkEventAny *event) -{ - HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (widget); - gboolean retvalue = FALSE; - - if (priv->stack && hildon_window_stack_peek (priv->stack) != widget) { - /* Ignore the delete event if this window is not the topmost one */ - retvalue = TRUE; - } else if (GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->delete_event) { - retvalue = GTK_WIDGET_CLASS (hildon_stackable_window_parent_class)->delete_event (widget, event); - } - - return retvalue; -} - -static void -hildon_stackable_window_class_init (HildonStackableWindowClass *klass) -{ - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - - widget_class->map = hildon_stackable_window_map; - widget_class->show = hildon_stackable_window_show; - widget_class->hide = hildon_stackable_window_hide; - widget_class->delete_event = hildon_stackable_window_delete_event; - - g_type_class_add_private (klass, sizeof (HildonStackableWindowPrivate)); -} - -static void -hildon_stackable_window_init (HildonStackableWindow *self) -{ - HildonStackableWindowPrivate *priv = HILDON_STACKABLE_WINDOW_GET_PRIVATE (self); - - priv->stack = NULL; - priv->stack_position = -1; -} - -/** - * hildon_stackable_window_new: - * - * Creates a new #HildonStackableWindow. - * - * Return value: A #HildonStackableWindow - * - * Since: 2.2 - **/ -GtkWidget* -hildon_stackable_window_new (void) -{ - HildonStackableWindow *newwindow = g_object_new (HILDON_TYPE_STACKABLE_WINDOW, NULL); - - return GTK_WIDGET (newwindow); -} diff --git a/src/hildon-stackable-window.h b/src/hildon-stackable-window.h deleted file mode 100644 index 2e2a712..0000000 --- a/src/hildon-stackable-window.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_STACKABLE_WINDOW_H__ -#define __HILDON_STACKABLE_WINDOW_H__ - -#include "hildon-window.h" -#include "hildon-app-menu.h" - -G_BEGIN_DECLS - -#define HILDON_TYPE_STACKABLE_WINDOW \ - (hildon_stackable_window_get_type()) - -#define HILDON_STACKABLE_WINDOW(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - HILDON_TYPE_STACKABLE_WINDOW, \ - HildonStackableWindow)) - -#define HILDON_STACKABLE_WINDOW_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - HILDON_TYPE_STACKABLE_WINDOW, \ - HildonStackableWindowClass)) - -#define HILDON_IS_STACKABLE_WINDOW(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ - HILDON_TYPE_STACKABLE_WINDOW)) - -#define HILDON_IS_STACKABLE_WINDOW_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), \ - HILDON_TYPE_STACKABLE_WINDOW)) - -#define HILDON_STACKABLE_WINDOW_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - HILDON_TYPE_STACKABLE_WINDOW, \ - HildonStackableWindowClass)) - -#ifndef _TYPEDEF_HILDON_WINDOW_STACK_ -#define _TYPEDEF_HILDON_WINDOW_STACK_ -typedef struct _HildonWindowStack HildonWindowStack; -#endif - -typedef struct _HildonStackableWindow HildonStackableWindow; -typedef struct _HildonStackableWindowClass HildonStackableWindowClass; - -struct _HildonStackableWindowClass -{ - HildonWindowClass parent_class; - - /* Padding for future extension */ - void (*_hildon_reserved1)(void); - void (*_hildon_reserved2)(void); - void (*_hildon_reserved3)(void); - void (*_hildon_reserved4)(void); -}; - -struct _HildonStackableWindow -{ - HildonWindow parent; -}; - -GType -hildon_stackable_window_get_type (void) G_GNUC_CONST; - -GtkWidget* -hildon_stackable_window_new (void); - -#ifndef HILDON_DISABLE_DEPRECATED -void -hildon_stackable_window_set_main_menu (HildonStackableWindow *self, - HildonAppMenu *menu); -#endif - -HildonWindowStack * -hildon_stackable_window_get_stack (HildonStackableWindow *self); - -G_END_DECLS - -#endif /* __HILDON_STACKABLE_WINDOW_H__ */ diff --git a/src/hildon-text-view.c b/src/hildon-text-view.c deleted file mode 100644 index 4630999..0000000 --- a/src/hildon-text-view.c +++ /dev/null @@ -1,342 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser Public License as published by - * the Free Software Foundation; version 2 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser Public License for more details. - * - */ - -/** - * SECTION:hildon-text-view - * @short_description: Widget representing a text view in the Hildon framework. - * - * The #HildonTextView is a GTK widget which represents a text - * view. It is derived from the #GtkTextView widget and provides - * additional commodities specific to the Hildon framework. - * - * Besides all the features inherited from #GtkTextView, a - * #HildonTextView can also have a placeholder text. This text will be - * shown if the text view is empty and doesn't have the input focus, - * but it's otherwise ignored. Thus, calls to - * hildon_text_view_get_buffer() will never return the placeholder - * text, not even when it's being displayed. - * - * Although #HildonTextView is derived from #GtkTextView, - * gtk_text_view_get_buffer() and gtk_text_view_set_buffer() must - * never be used to get/set the buffer in this - * widget. hildon_text_view_get_buffer() and - * hildon_text_view_set_buffer() must be used instead. - * - * - * Creating a HildonTextView with a placeholder - * - * GtkWidget * - * create_text_view (void) - * { - * GtkWidget *text_view; - * - * text_view = hildon_text_view_new (); - * hildon_text_view_set_placeholder (HILDON_TEXT_VIEW (text_view), - * "Type some text here"); - * - * return text_view; - * } - * - * - */ - -#include "hildon-text-view.h" -#include "hildon-helper.h" -#include - -#define HILDON_TEXT_VIEW_DRAG_THRESHOLD 16.0 - -G_DEFINE_TYPE (HildonTextView, hildon_text_view, GTK_TYPE_TEXT_VIEW); - -#define HILDON_TEXT_VIEW_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_TEXT_VIEW, HildonTextViewPrivate)); - -typedef struct _HildonTextViewPrivate HildonTextViewPrivate; - -struct _HildonTextViewPrivate -{ - GtkTextBuffer *main_buffer; /* Used to show the "real" contents */ - GtkTextBuffer *placeholder_buffer; /* Internal, used to display the placeholder */ - gulong changed_id; /* ID of the main_buffer::changed signal handler */ - gdouble x; /* tap x position */ - gdouble y; /* tap y position */ -}; - -/* Function used to decide whether to show the placeholder or not */ -static void -hildon_text_view_refresh_contents (GtkWidget *text_view) -{ - HildonTextViewPrivate *priv = HILDON_TEXT_VIEW_GET_PRIVATE (text_view); - gint bufsize = gtk_text_buffer_get_char_count (priv->main_buffer); - - if ((bufsize > 0) || GTK_WIDGET_HAS_FOCUS (text_view)) { - /* Display the main buffer if it contains text or the widget is focused */ - hildon_helper_set_logical_color (text_view, GTK_RC_TEXT, GTK_STATE_NORMAL, "ReversedTextColor"); - gtk_text_view_set_buffer (GTK_TEXT_VIEW (text_view), priv->main_buffer); - } else { - /* Otherwise, display the placeholder */ - hildon_helper_set_logical_color (text_view, GTK_RC_TEXT, GTK_STATE_NORMAL, "ReversedSecondaryTextColor"); - gtk_text_view_set_buffer (GTK_TEXT_VIEW (text_view), priv->placeholder_buffer); - } -} - -/** - * hildon_text_view_set_buffer: - * @text_view: a #HildonTextView - * @buffer: a #GtkTextBuffer - * - * Sets @buffer as the buffer being displayed by @text_view. The - * previous buffer displayed by the text view is unreferenced, and a - * reference is added to @buffer. If you owned a reference to @buffer - * before passing it to this function, you must remove that reference - * yourself - * - * Note that you must never use gtk_text_view_set_buffer() to set the - * buffer of a #HildonTextView. - * - * Since: 2.2 - */ -void -hildon_text_view_set_buffer (HildonTextView *text_view, - GtkTextBuffer *buffer) -{ - HildonTextViewPrivate *priv; - - g_return_if_fail (HILDON_IS_TEXT_VIEW (text_view)); - g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer)); - - priv = HILDON_TEXT_VIEW_GET_PRIVATE (text_view); - - /* If this is the same buffer, don't do anything */ - if (buffer == priv->main_buffer) - return; - - /* Disconnect the signal handler from the old buffer */ - g_signal_handler_disconnect (priv->main_buffer, priv->changed_id); - - /* Replace the old buffer with the new one */ - g_object_unref (priv->main_buffer); - priv->main_buffer = g_object_ref (buffer); - - /* Attach a callback to the new text buffer */ - priv->changed_id = - g_signal_connect_swapped (priv->main_buffer, "changed", - G_CALLBACK (hildon_text_view_refresh_contents), text_view); - - /* Refresh textview contents */ - hildon_text_view_refresh_contents (GTK_WIDGET (text_view)); -} - -/** - * hildon_text_view_get_buffer: - * @text_view: a #HildonTextView - * - * Returns the text buffer in @text_view. The reference count is not - * incremented; the caller of this function won't own a new reference. - * - * Note that you must never use gtk_text_view_get_buffer() to get the - * buffer from a #HildonTextView. - * - * Also note that placeholder text (set using - * hildon_text_view_set_placeholder()) is never contained in this - * buffer. - * - * Returns: a #GtkTextBuffer - * - * Since: 2.2 - */ -GtkTextBuffer * -hildon_text_view_get_buffer (HildonTextView *text_view) -{ - HildonTextViewPrivate *priv; - - g_return_val_if_fail (HILDON_IS_TEXT_VIEW (text_view), NULL); - - priv = HILDON_TEXT_VIEW_GET_PRIVATE (text_view); - - /* Always return priv->main_buffer even if the placeholder is - * being displayed */ - return priv->main_buffer; -} - -/** - * hildon_text_view_set_placeholder: - * @text_view: a #HildonTextView - * @text: the new text - * - * Sets the placeholder text in @text_view to @text. - * - * Since: 2.2 - */ -void -hildon_text_view_set_placeholder (HildonTextView *text_view, - const gchar *text) -{ - HildonTextViewPrivate *priv; - - g_return_if_fail (HILDON_IS_TEXT_VIEW (text_view) && text != NULL); - - priv = HILDON_TEXT_VIEW_GET_PRIVATE (text_view); - - gtk_text_buffer_set_text (priv->placeholder_buffer, text, -1); -} - -/** - * hildon_text_view_new: - * - * Creates a new text view. - * - * Returns: a new #HildonTextView - * - * Since: 2.2 - */ -GtkWidget * -hildon_text_view_new (void) -{ - GtkWidget *entry = g_object_new (HILDON_TYPE_TEXT_VIEW, NULL); - - return entry; -} - -static gboolean -hildon_text_view_focus_in_event (GtkWidget *widget, - GdkEventFocus *event) -{ - hildon_text_view_refresh_contents (widget); - - if (GTK_WIDGET_CLASS (hildon_text_view_parent_class)->focus_in_event) { - return GTK_WIDGET_CLASS (hildon_text_view_parent_class)->focus_in_event (widget, event); - } else { - return FALSE; - } -} - -static gboolean -hildon_text_view_focus_out_event (GtkWidget *widget, - GdkEventFocus *event) -{ - hildon_text_view_refresh_contents (widget); - - if (GTK_WIDGET_CLASS (hildon_text_view_parent_class)->focus_out_event) { - return GTK_WIDGET_CLASS (hildon_text_view_parent_class)->focus_out_event (widget, event); - } else { - return FALSE; - } -} - -static gint -hildon_text_view_button_press_event (GtkWidget *widget, - GdkEventButton *event) -{ - HildonTextViewPrivate *priv = HILDON_TEXT_VIEW_GET_PRIVATE (widget); - - if (GTK_TEXT_VIEW (widget)->editable && - hildon_gtk_im_context_filter_event (GTK_TEXT_VIEW (widget)->im_context, (GdkEvent*)event)) { - GTK_TEXT_VIEW (widget)->need_im_reset = TRUE; - return TRUE; - } - - if (event->button == 1 && event->type == GDK_BUTTON_PRESS) { - priv->x = event->x; - priv->y = event->y; - - return TRUE; - } - - return FALSE; -} - -static gint -hildon_text_view_button_release_event (GtkWidget *widget, - GdkEventButton *event) -{ - GtkTextView *text_view = GTK_TEXT_VIEW (widget); - HildonTextViewPrivate *priv = HILDON_TEXT_VIEW_GET_PRIVATE (widget); - GtkTextIter iter; - gint x, y; - - if (text_view->editable && - hildon_gtk_im_context_filter_event (text_view->im_context, (GdkEvent*)event)) { - text_view->need_im_reset = TRUE; - return TRUE; - } - - if (event->button == 1 && event->type == GDK_BUTTON_RELEASE) { - if (fabs (priv->x - event->x) < HILDON_TEXT_VIEW_DRAG_THRESHOLD && - fabs (priv->y - event->y) < HILDON_TEXT_VIEW_DRAG_THRESHOLD) { - GtkTextWindowType window_type; - - window_type = gtk_text_view_get_window_type (text_view, event->window); - gtk_text_view_window_to_buffer_coords (text_view, - window_type, - event->x, event->y, - &x, &y); - gtk_text_view_get_iter_at_location (text_view, &iter, x, y); - if (gtk_text_buffer_get_char_count (priv->main_buffer)) - gtk_text_buffer_place_cursor (priv->main_buffer, &iter); - - gtk_widget_grab_focus (GTK_WIDGET (text_view)); - - return TRUE; - } - } - return FALSE; -} - -static void -hildon_text_view_finalize (GObject *object) -{ - HildonTextViewPrivate *priv = HILDON_TEXT_VIEW_GET_PRIVATE (object); - - g_signal_handler_disconnect (priv->main_buffer, priv->changed_id); - g_object_unref (priv->main_buffer); - g_object_unref (priv->placeholder_buffer); - - if (G_OBJECT_CLASS (hildon_text_view_parent_class)->finalize) - G_OBJECT_CLASS (hildon_text_view_parent_class)->finalize (object); -} - -static void -hildon_text_view_class_init (HildonTextViewClass *klass) -{ - GObjectClass *gobject_class = (GObjectClass *)klass; - GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; - - gobject_class->finalize = hildon_text_view_finalize; - widget_class->focus_in_event = hildon_text_view_focus_in_event; - widget_class->focus_out_event = hildon_text_view_focus_out_event; - widget_class->motion_notify_event = NULL; - widget_class->button_press_event = hildon_text_view_button_press_event; - widget_class->button_release_event = hildon_text_view_button_release_event; - - g_type_class_add_private (klass, sizeof (HildonTextViewPrivate)); -} - -static void -hildon_text_view_init (HildonTextView *self) -{ - HildonTextViewPrivate *priv = HILDON_TEXT_VIEW_GET_PRIVATE (self); - - priv->main_buffer = gtk_text_buffer_new (NULL); - priv->placeholder_buffer = gtk_text_buffer_new (NULL); - - hildon_text_view_refresh_contents (GTK_WIDGET (self)); - - priv->changed_id = - g_signal_connect_swapped (priv->main_buffer, "changed", - G_CALLBACK (hildon_text_view_refresh_contents), self); -} diff --git a/src/hildon-text-view.h b/src/hildon-text-view.h deleted file mode 100644 index 87b78a6..0000000 --- a/src/hildon-text-view.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser Public License as published by - * the Free Software Foundation; version 2 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser Public License for more details. - * - */ - -#ifndef __HILDON_TEXT_VIEW_H__ -#define __HILDON_TEXT_VIEW_H__ - -#include - -G_BEGIN_DECLS - -#define HILDON_TYPE_TEXT_VIEW \ - (hildon_text_view_get_type()) - -#define HILDON_TEXT_VIEW(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - HILDON_TYPE_TEXT_VIEW, HildonTextView)) - -#define HILDON_TEXT_VIEW_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - HILDON_TYPE_TEXT_VIEW, HildonTextViewClass)) - -#define HILDON_IS_TEXT_VIEW(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_TEXT_VIEW)) - -#define HILDON_IS_TEXT_VIEW_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_TEXT_VIEW)) - -#define HILDON_TEXT_VIEW_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - HILDON_TYPE_TEXT_VIEW, HildonTextViewClass)) - -typedef struct _HildonTextView HildonTextView; - -typedef struct _HildonTextViewClass HildonTextViewClass; - -struct _HildonTextViewClass -{ - GtkTextViewClass parent_class; -}; - -struct _HildonTextView -{ - GtkTextView parent; -}; - - -GType -hildon_text_view_get_type (void) G_GNUC_CONST; - -GtkWidget * -hildon_text_view_new (void); - -void -hildon_text_view_set_buffer (HildonTextView *text_view, - GtkTextBuffer *buffer); - -GtkTextBuffer * -hildon_text_view_get_buffer (HildonTextView *text_view); - -void -hildon_text_view_set_placeholder (HildonTextView *text_view, - const gchar *text); - -G_END_DECLS - -#endif /* __HILDON_TEXT_VIEW_H__ */ diff --git a/src/hildon-time-button.c b/src/hildon-time-button.c deleted file mode 100644 index 86f13f2..0000000 --- a/src/hildon-time-button.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser Public License as published by - * the Free Software Foundation; version 2 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser Public License for more details. - * - */ - -/** - * SECTION:hildon-time-button - * @Short_Description: Button displaying and allowing selection of a time. - * @See_Also: #HildonPickerButton, #HildonDateButton - * - * #HildonTimeButton is a widget that shows a text label and a time, and allows - * the user to select a different time. Visually, it's a button that, once clicked, - * presents a #HildonPickerDialog containing a #HildonTimeSelector. Once the user selects - * a different time from the selector, this will be shown in the button. - */ - -#include - -#include "hildon-time-selector.h" -#include "hildon-touch-selector.h" -#include "hildon-picker-button.h" -#include "hildon-time-button.h" - -#define _(String) \ - dgettext("hildon-libs", String) - -#define c_(String) \ - dgettext("hildon-common-strings", String) - -G_DEFINE_TYPE (HildonTimeButton, hildon_time_button, HILDON_TYPE_PICKER_BUTTON) - -#if 0 -#define GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), HILDON_TYPE_TIME_BUTTON, HildonTimeButtonPrivate)) -typedef struct _HildonTimeButtonPrivate HildonTimeButtonPrivate; - -struct _HildonTimeButtonPrivate -{ -}; -#endif - -#if 0 -static void -hildon_time_button_get_property (GObject * object, guint property_id, - GValue * value, GParamSpec * pspec) -{ - switch (property_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - -static void -hildon_time_button_set_property (GObject * object, guint property_id, - const GValue * value, GParamSpec * pspec) -{ - switch (property_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} -#endif - -static void -hildon_time_button_class_init (HildonTimeButtonClass * klass) -{ -#if 0 - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (HildonTimeButtonPrivate)); - - object_class->get_property = hildon_time_button_get_property; - object_class->set_property = hildon_time_button_set_property; -#endif -} - -static void -hildon_time_button_init (HildonTimeButton * self) -{ -} - -/** - * hildon_time_button_new: - * @size: One of #HildonSizeType - * @arrangement: one of #HildonButtonArrangement - * - * Creates a new #HildonTimeButton. See hildon_button_new() for details on the - * parameters. - * - * Returns: a new #HildonTimeButton - * - * Since: 2.2 - **/ -GtkWidget * -hildon_time_button_new (HildonSizeType size, - HildonButtonArrangement arrangement) -{ - return hildon_time_button_new_step (size, arrangement, 1); -} - -/** - * hildon_time_button_new_step: - * @size: One of #HildonSizeType - * @arrangement: one of #HildonButtonArrangement - * @minutes_step: step between the minutes in the selector options - * - * Creates a new #HildonTimeButton. See hildon_button_new() for details on the - * parameters. - * - * Returns: a new #HildonTimeButton - * - * Since: 2.2 - **/ -GtkWidget * -hildon_time_button_new_step (HildonSizeType size, - HildonButtonArrangement arrangement, - guint minutes_step) -{ - return g_object_new (HILDON_TYPE_TIME_BUTTON, - "title", _("wdgt_ti_time"), - "arrangement", arrangement, - "size", size, - "touch-selector", hildon_time_selector_new_step (minutes_step), - NULL); -} - -/** - * hildon_time_button_get_time: - * @button: a #HildonTimeButton - * @hours: return location for the hours of the time selected - * @minutes: return location for the minutes of the time selected - * - * Retrieves the time from @button. - * - * Since: 2.2 - **/ -void -hildon_time_button_get_time (HildonTimeButton * button, - guint * hours, guint * minutes) -{ - HildonTouchSelector *selector; - - g_return_if_fail (HILDON_IS_TIME_BUTTON (button)); - - selector = hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (button)); - - hildon_time_selector_get_time (HILDON_TIME_SELECTOR (selector), hours, minutes); -} - -/** - * hildon_time_button_set_time: - * @button: a #HildonTimeButton - * @hours: the hours to be set - * @minutes: the time to be set - * - * Sets the time to be displayed in @button. This time will - * be selected by default on the #HildonTimeSelector. - * - * Since: 2.2 - **/ -void -hildon_time_button_set_time (HildonTimeButton * button, - guint hours, guint minutes) -{ - HildonTouchSelector *selector; - gchar *time; - - g_return_if_fail (HILDON_IS_TIME_BUTTON (button)); - - selector = hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (button)); - - hildon_time_selector_set_time (HILDON_TIME_SELECTOR (selector), hours, minutes); - - time = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector)); - hildon_button_set_value (HILDON_BUTTON (button), time); - g_free (time); -} diff --git a/src/hildon-time-button.h b/src/hildon-time-button.h deleted file mode 100644 index 4beb669..0000000 --- a/src/hildon-time-button.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser Public License as published by - * the Free Software Foundation; version 2 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser Public License for more details. - * - */ - -#ifndef __HILDON_TIME_BUTTON__ -#define __HILDON_TIME_BUTTON__ - -#include - -G_BEGIN_DECLS - -#define HILDON_TYPE_TIME_BUTTON \ - hildon_time_button_get_type() - -#define HILDON_TIME_BUTTON(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj),\ - HILDON_TYPE_TIME_BUTTON, HildonTimeButton)) - -#define HILDON_TIME_BUTTON_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - HILDON_TYPE_TIME_BUTTON, HildonTimeButtonClass)) - -#define HILDON_IS_TIME_BUTTON(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_TIME_BUTTON)) - -#define HILDON_IS_TIME_BUTTON_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), HILDON_TYPE_TIME_BUTTON)) - -#define HILDON_TIME_BUTTON_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - HILDON_TYPE_TIME_BUTTON, HildonTimeButtonClass)) - -typedef struct _HildonTimeButton HildonTimeButton; -typedef struct _HildonTimeButtonClass HildonTimeButtonClass; - -struct _HildonTimeButton -{ - HildonPickerButton parent; -}; - -struct _HildonTimeButtonClass -{ - HildonPickerButtonClass parent_class; -}; - -GType -hildon_time_button_get_type (void); - -GtkWidget* -hildon_time_button_new (HildonSizeType size, - HildonButtonArrangement arrangement); - -GtkWidget * -hildon_time_button_new_step (HildonSizeType size, - HildonButtonArrangement arrangement, - guint minutes_step); - -void -hildon_time_button_get_time (HildonTimeButton *button, - guint *hours, - guint *minutes); - -void -hildon_time_button_set_time (HildonTimeButton *button, - guint hours, - guint minutes); - -G_END_DECLS - -#endif /* _HILDON_TIME_BUTTON */ diff --git a/src/hildon-time-editor-private.h b/src/hildon-time-editor-private.h deleted file mode 100644 index db51b30..0000000 --- a/src/hildon-time-editor-private.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_PRIVATE_H__ -#define __HILDON_TIME_EDITOR_PRIVATE_H__ - -#include - -G_BEGIN_DECLS - -#define HILDON_TIME_EDITOR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ - HILDON_TYPE_TIME_EDITOR, HildonTimeEditorPrivate)); - -/* Indices for h/m/s entries in priv->entries */ -enum { - ENTRY_HOURS, - ENTRY_MINS, - ENTRY_SECS, - - ENTRY_COUNT -}; - -typedef struct _HildonTimeEditorPrivate HildonTimeEditorPrivate; - -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. */ -}; - -G_END_DECLS - -#endif /* __HILDON_TIME_EDITOR_H__ */ diff --git a/src/hildon-time-editor.c b/src/hildon-time-editor.c deleted file mode 100644 index 8e2112b..0000000 --- a/src/hildon-time-editor.c +++ /dev/null @@ -1,1936 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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. - * - * - * - * #HildonTimeEditor has been deprecated since Hildon 2.2 and should not - * be used in newly written code. See - * Migrating Time Widgets - * section to know how to migrate this deprecated widget. - * - * - * - * - * HildonTimePicker example - * - * - * editor = hildon_time_editor_new (); - * hildon_time_editor_set_time (editor, h, m, s); - * - * gtk_box_pack_start (..., editor) - * - * hildon_time_editor_get_time (editor, &h, &m, &s); - * - * - * - * - */ - -#undef HILDON_DISABLE_DEPRECATED - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include - -#include "hildon-time-editor.h" -#include "hildon-defines.h" -#include "hildon-time-picker.h" -#include "hildon-banner.h" -#include "hildon-private.h" -#include "hildon-marshalers.h" -#include "hildon-enum-types.h" -#include "hildon-time-editor-private.h" - -#define _(String) dgettext("hildon-libs", String) - -#define c_(String) dgettext("hildon-common-strings", String) - -#define TICKS(h,m,s) \ - ((h) * 3600 + (m) * 60 + (s)) - -#define TIME_EDITOR_HEIGHT 30 - -#define ICON_PRESSED 4 - -#define ICON_NAME "widgets_time_editor" - -#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; - -enum -{ - PROP_0, - PROP_TICKS, - PROP_DURATION_MODE, - PROP_DURATION_MIN, - PROP_DURATION_MAX, - PROP_SHOW_SECONDS, - PROP_SHOW_HOURS -}; - -/* 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] = { - HILDON_DATE_TIME_ERROR_MAX_HOURS, - HILDON_DATE_TIME_ERROR_MIN_HOURS, - HILDON_DATE_TIME_ERROR_EMPTY_HOURS }; - -static guint min_errors[NUM_ERROR_CODES] = { - HILDON_DATE_TIME_ERROR_MAX_MINS, - HILDON_DATE_TIME_ERROR_MIN_MINS, - HILDON_DATE_TIME_ERROR_EMPTY_MINS }; - -static guint sec_errors[NUM_ERROR_CODES] = { - HILDON_DATE_TIME_ERROR_MAX_SECS, - HILDON_DATE_TIME_ERROR_MIN_SECS, - HILDON_DATE_TIME_ERROR_EMPTY_SECS }; - -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); - -static gboolean -hildon_time_editor_entry_focus_out (GtkWidget *widget, - GdkEventFocus *event, - gpointer data); - -static gboolean -hildon_time_editor_entry_focus_in (GtkWidget *widget, - GdkEventFocus *event, - gpointer data); - -static gboolean -hildon_time_editor_time_error (HildonTimeEditor *editor, - HildonDateTimeError 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_focus (GtkWidget *widget, - GtkDirectionType direction); - -static gboolean -hildon_time_editor_entry_keypress (GtkEntry *entry, - GdkEventKey* event, - gpointer user_data); - -static gboolean -hildon_time_editor_check_locale (HildonTimeEditor *editor); - -#ifdef MAEMO_GTK -static void -hildon_time_editor_tap_and_hold_setup (GtkWidget *widget, - GtkWidget *menu, - GtkCallback func, - GtkWidgetTapAndHoldFlags flags); -#endif - -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); - -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); - -/** - * hildon_time_editor_get_type: - * - * Initializes and returns the type of a hildon time editor. - * - * Returns: GType of #HildonTimeEditor - */ -GType G_GNUC_CONST -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) -{ - HildonTimeEditorPrivate *priv; - - g_assert (HILDON_IS_TIME_EDITOR (container)); - g_assert (callback != NULL); - - priv = HILDON_TIME_EDITOR_GET_PRIVATE (container); - - g_assert (priv); - - 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); - g_assert (priv); - - 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->focus = hildon_time_editor_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_DATE_TIME_ERROR); - - /** - * 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) ); -} - -#ifdef MAEMO_GTK -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); -} -#endif - -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); - g_assert (priv); - - 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_SMALL); - 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); - -#ifdef MAEMO_GTK - /* Set the entries to accept only numeric characters */ - g_object_set (priv->entries[i], "hildon-input-mode", HILDON_GTK_INPUT_MODE_NUMERIC, NULL); -#endif - - /* 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_focus_in), editor); - g_signal_connect (priv->entries[i], "focus-out-event", - G_CALLBACK (hildon_time_editor_entry_focus_out), 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 (); - -#ifdef MAEMO_GTK - g_signal_connect (editor, "tap-and-hold-setup", - G_CALLBACK (hildon_time_editor_tap_and_hold_setup), - NULL); -#endif - -} - -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_assert (priv); - - if (priv->am_symbol) - g_free (priv->am_symbol); - - if (priv->pm_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: - * @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); - - /* 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++; - - if (hm_sep_label != NULL) - { - 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_return_if_fail (HILDON_IS_TIME_EDITOR (editor)); - - priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor); - g_assert (priv); - - /* 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_focus_out, 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_focus_out, 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 (HILDON_IS_TIME_EDITOR (editor), 0); - - priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor); - g_assert (priv); - - 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); - g_assert (priv); - - 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); - g_assert (priv); - - 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); - g_assert (priv); - - 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); - g_assert (priv); - - 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); - g_assert (priv); - - 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); - g_assert (priv); - - 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); - g_assert (priv); - - 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); - g_assert (priv); - - 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) -{ - g_return_if_fail (HILDON_IS_TIME_EDITOR (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); - g_assert (priv); - - /* 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); - g_assert (priv); - - *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); - g_assert (priv); - - /* 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_focus_in (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, - HildonDateTimeError 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); - g_assert (priv); - - /* 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, HILDON_DATE_TIME_ERROR_MIN_DURATION, &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, HILDON_DATE_TIME_ERROR_MAX_DURATION, &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); - g_assert (priv); - - 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_focus_out, 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_focus_out, 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); - g_assert (priv); - - /* 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); - g_assert (priv); - - /* 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_focus_out (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); - g_assert (priv); - - /* 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); - g_assert (priv); - - /* 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; - gboolean rtl; - - g_assert (priv); - - rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL); - 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 */ - if (rtl) - gtk_widget_get_child_requisition (priv->iconbutton, &req); - else - gtk_widget_get_child_requisition (priv->frame, &req); - - alloc.width = req.width; - alloc.height = max_req.height; - if (rtl) - gtk_widget_size_allocate (priv->iconbutton, &alloc); - else - gtk_widget_size_allocate (priv->frame, &alloc); - - /* allocate icon */ - if (GTK_WIDGET_VISIBLE (priv->iconbutton)) { - if (rtl) - gtk_widget_get_child_requisition (priv->frame, &req); - else - gtk_widget_get_child_requisition (priv->iconbutton, &req); - - alloc.x += alloc.width + HILDON_MARGIN_DEFAULT; - alloc.width = req.width; - - if (rtl) - gtk_widget_size_allocate (priv->frame, &alloc); - else - 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_focus (GtkWidget *widget, - GtkDirectionType direction) -{ - gboolean retval; - GtkDirectionType effective_direction; - - g_assert (HILDON_IS_TIME_EDITOR (widget)); - - retval = hildon_private_composite_focus (widget, direction, &effective_direction); - - if (retval == TRUE) - return GTK_WIDGET_CLASS (parent_class)->focus (widget, effective_direction); - else - return FALSE; -} - -static gboolean -hildon_time_editor_entry_keypress (GtkEntry *entry, - GdkEventKey *event, - gpointer data) -{ - switch (event->keyval) - { - case GDK_Return: - case GDK_ISO_Enter: - hildon_time_editor_icon_clicked (GTK_WIDGET (entry), data); - return TRUE; - default: - return FALSE; - } - - g_assert_not_reached (); -} - -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. - * @show_hours: Enable or disable showing of hours. - * - * This function shows or hides the hours field. - * - **/ -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); - g_assert (priv); - - 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: - * @editor: the @HildonTimeEditor widget. - * - * This function returns a boolean indicating the visibility of - * hours in the @HildonTimeEditor - * - * Return value: TRUE if hours are visible. - * - **/ -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); - g_assert (priv); - - return priv->show_hours; -} - -/* 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 deleted file mode 100644 index f1f09b9..0000000 --- a/src/hildon-time-editor.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#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 -{ - HILDON_DATE_TIME_ERROR_NO_ERROR = -1, - HILDON_DATE_TIME_ERROR_MAX_HOURS, - HILDON_DATE_TIME_ERROR_MAX_MINS, - HILDON_DATE_TIME_ERROR_MAX_SECS, - HILDON_DATE_TIME_ERROR_MAX_DAY, - HILDON_DATE_TIME_ERROR_MAX_MONTH, - HILDON_DATE_TIME_ERROR_MAX_YEAR, - HILDON_DATE_TIME_ERROR_MIN_HOURS, - HILDON_DATE_TIME_ERROR_MIN_MINS, - HILDON_DATE_TIME_ERROR_MIN_SECS, - HILDON_DATE_TIME_ERROR_MIN_DAY, - HILDON_DATE_TIME_ERROR_MIN_MONTH, - HILDON_DATE_TIME_ERROR_MIN_YEAR, - HILDON_DATE_TIME_ERROR_EMPTY_HOURS, - HILDON_DATE_TIME_ERROR_EMPTY_MINS, - HILDON_DATE_TIME_ERROR_EMPTY_SECS, - HILDON_DATE_TIME_ERROR_EMPTY_DAY, - HILDON_DATE_TIME_ERROR_EMPTY_MONTH, - HILDON_DATE_TIME_ERROR_EMPTY_YEAR, - HILDON_DATE_TIME_ERROR_MIN_DURATION, - HILDON_DATE_TIME_ERROR_MAX_DURATION, - HILDON_DATE_TIME_ERROR_INVALID_CHAR, - HILDON_DATE_TIME_ERROR_INVALID_DATE, - HILDON_DATE_TIME_ERROR_INVALID_TIME -} HildonDateTimeError; - -typedef struct _HildonTimeEditor HildonTimeEditor; - -typedef struct _HildonTimeEditorClass HildonTimeEditorClass; - -struct _HildonTimeEditor -{ - GtkContainer parent; -}; - -struct _HildonTimeEditorClass -{ - GtkContainerClass parent_class; - - gboolean (*time_error) (HildonTimeEditor *editor, - HildonDateTimeError type); -}; - -GType G_GNUC_CONST -hildon_time_editor_get_type (void); - -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); - -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); - -void -hildon_time_editor_get_time_separators (GtkLabel *hm_sep_label, - GtkLabel *ms_sep_label); - -G_END_DECLS - -#endif /* __HILDON_TIME_EDITOR_H__ */ - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-time-picker-private.h b/src/hildon-time-picker-private.h deleted file mode 100644 index af57d8c..0000000 --- a/src/hildon-time-picker-private.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_PRIVATE_H__ -#define __HILDON_TIME_PICKER_PRIVATE_H__ - -G_BEGIN_DECLS - -typedef struct _HildonTimePickerPrivate HildonTimePickerPrivate; - -#define HILDON_TIME_PICKER_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_TIME_PICKER, HildonTimePickerPrivate)) - -enum -{ - WIDGET_GROUP_HOURS, - WIDGET_GROUP_10_MINUTES, - WIDGET_GROUP_1_MINUTES, - WIDGET_GROUP_AMPM, - - WIDGET_GROUP_COUNT -}; - -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; - -struct _HildonTimePickerPrivate -{ - HildonTimePickerWidgetGroup widgets[WIDGET_GROUP_COUNT]; - - gchar *am_symbol; - gchar *pm_symbol; - - 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; -}; - -G_END_DECLS - -#endif /* __HILDON_TIME_PICKER_PRIVATE_H__ */ diff --git a/src/hildon-time-picker.c b/src/hildon-time-picker.c deleted file mode 100644 index 04855da..0000000 --- a/src/hildon-time-picker.c +++ /dev/null @@ -1,1019 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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. - * - * - * - * #HildonTimePicker has been deprecated since Hildon 2.2 and should not - * be used in newly written code. See - * Migrating Time Widgets - * section to know how to migrate this deprecated widget. - * - * - * - * - * HildonTimePicker example - * - * - * 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: - * hildon_time_picker_get_time(HILDON_TIME_PICKER (picker), &h, &m ); - * foo_set_time(h,m); - * break; - * default: - * break; - * } - * - * gtk_widget_destroy( picker ); - * - * - * - */ - -#undef HILDON_DISABLE_DEPRECATED - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hildon-time-picker.h" -#include "hildon-defines.h" -#include "hildon-time-picker-private.h" -#include "hildon-time-editor.h" - -#define _(String) \ - dgettext("hildon-libs", String) - -#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 - -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_realize (GtkWidget *widget); - -static void -hildon_time_picker_style_set (GtkWidget *widget, - GtkStyle *previous_style); - -static void -frame_size_request (GtkWidget *widget, - GtkRequisition *requistion); - -static GtkDialogClass* parent_class; - -enum -{ - PROP_0, - PROP_MINUTES -}; - -static const gint button_multipliers[WIDGET_GROUP_COUNT][2] = -{ - { MINS_IN_1H, -MINS_IN_1H }, - { 10, -10 }, - { 1, -1 }, - { 0, 0 } -}; - -/** - * hildon_time_picker_get_type: - * - * Returns the type of HildonTimePicker. - * - * Returns: HildonTimePicker type - */ -GType G_GNUC_CONST -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->realize = hildon_time_picker_realize; - widget_class->style_set = hildon_time_picker_style_set; - - /** - * 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]; - GtkDialog *dialog = GTK_DIALOG (picker); - GtkTable *table = NULL; - GtkWidget *maintocenter, *colon_label; - const struct tm *local = NULL; - time_t stamp; - gint i = 0; - - g_assert (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->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 (); - - /* 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, _("wdgt_bd_done"), - 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) -{ - HildonTimePickerPrivate *priv = HILDON_TIME_PICKER_GET_PRIVATE (object); - - g_assert (priv); - - /* Make sure the timer is stopped */ - if (priv->timer_id) - g_source_remove(priv->timer_id); - - g_free(priv->am_symbol); - g_free(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_GET_PRIVATE (object); - g_assert (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_realize (GtkWidget *widget) -{ - GTK_WIDGET_CLASS (parent_class)->realize(widget); - - /* We only want the border for the dialog. */ - gdk_window_set_decorations (widget->window, GDK_DECOR_BORDER); -} - -static void -hildon_time_picker_style_set (GtkWidget *widget, - GtkStyle *previous_style) -{ - guint width, height; - gint i, button; - HildonTimePickerPrivate *priv = HILDON_TIME_PICKER_GET_PRIVATE (widget); - g_assert (priv); - - GTK_WIDGET_CLASS (parent_class)->style_set(widget, previous_style); - - /* 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); - } - } - } -} - -/* - * Clicked hour/minute field. Move focus to it. - */ -static gboolean -hildon_time_picker_event_box_button_press (GtkWidget *widget, - GdkEventKey *event, - gpointer unused) -{ - gtk_widget_grab_focus (widget); - return FALSE; -} - -/* - * Clicked AM/PM label. Move focus to it and move the time by 12 hours. - */ -static gboolean -hildon_time_picker_ampm_release (GtkWidget *widget, - GdkEvent *event, - HildonTimePicker *picker) -{ - HildonTimePickerPrivate *priv = HILDON_TIME_PICKER_GET_PRIVATE (picker); - g_assert (priv); - - gtk_widget_grab_focus (widget); - hildon_time_picker_change_time (picker, priv->minutes > MINS_IN_12H ? - priv->minutes - MINS_IN_12H : - priv->minutes + MINS_IN_12H); - - return FALSE; -} - -static gboolean -hildon_time_picker_arrow_press (GtkWidget *widget, - GdkEvent *event, - HildonTimePicker *picker) -{ - HildonTimePickerPrivate *priv = HILDON_TIME_PICKER_GET_PRIVATE (picker); - gint i, button; - gint newval = 0; - gint key_repeat = 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); - - /* Get button press repeater timeout from settings (in milliseconds) */ - g_object_get (gtk_widget_get_settings (widget), - "gtk-timeout-repeat", &key_repeat, NULL); - - key_repeat *= 8; - - /* 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 (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 = HILDON_TIME_PICKER_GET_PRIVATE (picker); - g_assert (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; - HildonTimePickerPrivate *priv = HILDON_TIME_PICKER_GET_PRIVATE (picker); - - g_assert (priv); - - for (i = 0; i < WIDGET_GROUP_COUNT; i++) - { - if (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 = HILDON_TIME_PICKER_GET_PRIVATE (picker); - HildonTimePickerWidgetGroup *group; - gint group_idx; - - g_assert (priv); - - /* 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 : &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; - HildonTimePickerPrivate *priv = HILDON_TIME_PICKER_GET_PRIVATE (picker); - - g_assert (priv); - - /* 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 = &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; - gint key_repeat = 0; - - picker = HILDON_TIME_PICKER(tpicker); - g_assert(picker != NULL); - - priv = HILDON_TIME_PICKER_GET_PRIVATE (tpicker); - g_assert (priv); - - GDK_THREADS_ENTER (); - - /* 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) - { - /* Get button press repeater timeout from settings (in milliseconds) */ - g_object_get (gtk_widget_get_settings ((GtkWidget *) tpicker), - "gtk-timeout-repeat", &key_repeat, NULL); - - key_repeat *= 8; - - /* 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 (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 = HILDON_TIME_PICKER_GET_PRIVATE (picker); - - gchar str[3] = "00"; - guint hours = 0; - gboolean ampm = TRUE; - - g_assert (priv); - - /* 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)); - - HildonTimePickerPrivate *priv = HILDON_TIME_PICKER_GET_PRIVATE (picker); - g_assert (priv); - - current = 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 deleted file mode 100644 index e36d777..0000000 --- a/src/hildon-time-picker.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#ifndef __HILDON_TIME_PICKER_H__ -#define __HILDON_TIME_PICKER_H__ - -#include - -G_BEGIN_DECLS - -typedef struct _HildonTimePicker HildonTimePicker; - -typedef struct _HildonTimePickerClass HildonTimePickerClass; - -#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)) - -#define HILDON_TIME_PICKER_GET_CLASS(obj) \ - ((HildonTimePickerClass *) G_OBJECT_GET_CLASS(obj)) - -struct _HildonTimePicker -{ - GtkDialog parent; -}; - -struct _HildonTimePickerClass -{ - GtkDialogClass parent_class; -}; - -GType G_GNUC_CONST -hildon_time_picker_get_type (void); - -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__ */ - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-time-selector.c b/src/hildon-time-selector.c deleted file mode 100644 index e605d40..0000000 --- a/src/hildon-time-selector.c +++ /dev/null @@ -1,731 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2008 Nokia Corporation. - * - * 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; either - * version 2 of the License, or (at your option) any later version. or (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/** - * SECTION:hildon-time-selector - * @short_description: A widget to select the current time. - * - * #HildonTimeSelector allows users to choose a time by selecting hour - * and minute. It also allows choosing between AM or PM format. - * - * The currently selected time can be altered with - * hildon_time_selector_set_time(), and retrieved using - * hildon_time_selector_get_time(). - * - * Use this widget instead of deprecated HildonTimeEditor widget. - */ - -#define _GNU_SOURCE /* needed for GNU nl_langinfo_l */ -#define __USE_GNU /* needed for locale */ - -#ifdef HAVE_SYS_TIME_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include "hildon-enum-types.h" -#include "hildon-time-selector.h" -#include "hildon-touch-selector-private.h" - -#define HILDON_TIME_SELECTOR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_TIME_SELECTOR, HildonTimeSelectorPrivate)) - -G_DEFINE_TYPE (HildonTimeSelector, hildon_time_selector, HILDON_TYPE_TOUCH_SELECTOR) - -#define INIT_YEAR 100 -#define LAST_YEAR 50 /* since current year */ - -#define _(String) dgettext("hildon-libs", String) -#define N_(String) String - - -/* FIXME: we should get this two props from the clock ui headers */ -#define CLOCK_GCONF_PATH "/apps/clock" -#define CLOCK_GCONF_IS_24H_FORMAT CLOCK_GCONF_PATH "/time-format" - -enum { - COLUMN_STRING, - COLUMN_INT, - TOTAL_MODEL_COLUMNS -}; - -enum { - COLUMN_HOURS = 0, - COLUMN_MINUTES, - COLUMN_AMPM, - TOTAL_TIME_COLUMNS -}; - -enum -{ - PROP_0, - PROP_MINUTES_STEP, - PROP_TIME_FORMAT_POLICY -}; - -struct _HildonTimeSelectorPrivate -{ - GtkTreeModel *hours_model; - GtkTreeModel *minutes_model; - GtkTreeModel *ampm_model; - - guint minutes_step; - HildonTimeSelectorFormatPolicy format_policy; - gboolean ampm_format; /* if using am/pm format or 24 h one */ - - gboolean pm; /* if we are on pm (only useful if ampm_format == TRUE) */ - - gint creation_hours; - gint creation_minutes; -}; - -static void hildon_time_selector_finalize (GObject * object); -static GObject* hildon_time_selector_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_params); -static void hildon_time_selector_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec); -static void hildon_time_selector_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec); - -/* private functions */ -static GtkTreeModel *_create_hours_model (HildonTimeSelector * selector); -static GtkTreeModel *_create_minutes_model (guint minutes_step); -static GtkTreeModel *_create_ampm_model (HildonTimeSelector * selector); - -static void _get_real_time (gint * hours, gint * minutes); -static void _manage_ampm_selection_cb (HildonTouchSelector * selector, - gint num_column, gpointer data); -static void _set_pm (HildonTimeSelector * selector, gboolean pm); - -static gchar *_custom_print_func (HildonTouchSelector * selector, - gpointer user_data); - -static void -check_automatic_ampm_format (HildonTimeSelector * selector); - -static void -update_format_policy (HildonTimeSelector *selector, - HildonTimeSelectorFormatPolicy new_policy); -static void -update_format_dependant_columns (HildonTimeSelector *selector, - guint hours, - guint minutes); - -static void -hildon_time_selector_class_init (HildonTimeSelectorClass * class) -{ - GObjectClass *gobject_class; - GtkObjectClass *object_class; - GtkWidgetClass *widget_class; - GtkContainerClass *container_class; - - gobject_class = (GObjectClass *) class; - object_class = (GtkObjectClass *) class; - widget_class = (GtkWidgetClass *) class; - container_class = (GtkContainerClass *) class; - - /* GObject */ - gobject_class->get_property = hildon_time_selector_get_property; - gobject_class->set_property = hildon_time_selector_set_property; - gobject_class->constructor = hildon_time_selector_constructor; - gobject_class->finalize = hildon_time_selector_finalize; - - g_object_class_install_property (gobject_class, - PROP_MINUTES_STEP, - g_param_spec_uint ("minutes-step", - "Step between minutes in the model", - "Step between the minutes in the list of" - " options of the widget ", - 1, 30, 1, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); - - /** - * HildonTimeSelector:time-format-policy: - * - * The visual policy of the time format - * - * Since: 2.2 - */ - g_object_class_install_property (gobject_class, - PROP_TIME_FORMAT_POLICY, - g_param_spec_enum ("time_format_policy", - "time format policy", - "Visual policy of the time format", - HILDON_TYPE_TIME_SELECTOR_FORMAT_POLICY, - HILDON_TIME_SELECTOR_FORMAT_POLICY_AUTOMATIC, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); - - /* GtkWidget */ - - /* GtkContainer */ - - /* signals */ - - g_type_class_add_private (object_class, sizeof (HildonTimeSelectorPrivate)); -} - -/* FIXME: the constructor was required because as we need the initial values - of the properties passed on g_object_new. But, probably use the method - constructed could be easier */ -static GObject* -hildon_time_selector_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_params) -{ - GObject *object; - HildonTimeSelector *selector; - HildonTouchSelectorColumn *column; - - object = (* G_OBJECT_CLASS (hildon_time_selector_parent_class)->constructor) - (type, n_construct_properties, construct_params); - - selector = HILDON_TIME_SELECTOR (object); - - selector->priv->hours_model = _create_hours_model (selector); - - column = hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), - selector->priv->hours_model, TRUE); - g_object_set (column, "text-column", 0, NULL); - - - /* we need initialization parameters in order to create minute models*/ - selector->priv->minutes_step = selector->priv->minutes_step ? selector->priv->minutes_step : 1; - - selector->priv->minutes_model = _create_minutes_model (selector->priv->minutes_step); - - column = hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), - selector->priv->minutes_model, TRUE); - g_object_set (column, "text-column", 0, NULL); - - if (selector->priv->ampm_format) { - selector->priv->ampm_model = _create_ampm_model (selector); - - hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), - selector->priv->ampm_model, TRUE); - - g_signal_connect (G_OBJECT (selector), - "changed", G_CALLBACK (_manage_ampm_selection_cb), - NULL); - } - - - /* By default we should select the current day */ - hildon_time_selector_set_time (selector, - selector->priv->creation_hours, - selector->priv->creation_minutes); - - return object; - -} - -static void -hildon_time_selector_init (HildonTimeSelector * selector) -{ - selector->priv = HILDON_TIME_SELECTOR_GET_PRIVATE (selector); - - GTK_WIDGET_SET_FLAGS (GTK_WIDGET (selector), GTK_NO_WINDOW); - gtk_widget_set_redraw_on_allocate (GTK_WIDGET (selector), FALSE); - - hildon_touch_selector_set_print_func (HILDON_TOUCH_SELECTOR (selector), - _custom_print_func); - - /* By default we use the automatic ampm format */ - selector->priv->pm = TRUE; - check_automatic_ampm_format (selector); - - _get_real_time (&selector->priv->creation_hours, - &selector->priv->creation_minutes); -} - -static void -hildon_time_selector_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - HildonTimeSelectorPrivate *priv = HILDON_TIME_SELECTOR_GET_PRIVATE (object); - - switch (param_id) - { - case PROP_MINUTES_STEP: - g_value_set_uint (value, priv->minutes_step); - break; - case PROP_TIME_FORMAT_POLICY: - g_value_set_enum (value, priv->format_policy); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - -static void -hildon_time_selector_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec) -{ - HildonTimeSelectorPrivate *priv = HILDON_TIME_SELECTOR_GET_PRIVATE (object); - - switch (param_id) - { - case PROP_MINUTES_STEP: - priv->minutes_step = g_value_get_uint (value); - break; - case PROP_TIME_FORMAT_POLICY: - update_format_policy (HILDON_TIME_SELECTOR (object), - g_value_get_enum (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - -static void -hildon_time_selector_finalize (GObject * object) -{ - /* Note: we don't require to free the models. We don't manage it using own - references, so will be freed on the hildon-touch-selector finalize code. - See the implementation notes related to that on the touch selector - code. */ - - (*G_OBJECT_CLASS (hildon_time_selector_parent_class)->finalize) (object); -} - -/* ------------------------------ PRIVATE METHODS ---------------------------- */ - -static gchar * -_custom_print_func (HildonTouchSelector * touch_selector, - gpointer user_data) -{ - gchar *result = NULL; - struct tm tm = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - HildonTimeSelector *selector = NULL; - static gchar string[255]; - guint hours = 0; - guint minutes = 0; - - selector = HILDON_TIME_SELECTOR (touch_selector); - - hildon_time_selector_get_time (selector, &hours, &minutes); - - tm.tm_min = minutes; - tm.tm_hour = hours; - - if (selector->priv->ampm_format) { - if (selector->priv->pm) { - strftime (string, 255, _("wdgt_va_12h_time_pm"), &tm); - } else { - strftime (string, 255, _("wdgt_va_12h_time_am"), &tm); - } - } else { - strftime (string, 255, _("wdgt_va_24h_time"), &tm); - } - - - result = g_strdup (string); - - return result; -} - -static GtkTreeModel * -_create_minutes_model (guint minutes_step) -{ - GtkListStore *store_minutes = NULL; - gint i = 0; - static gchar label[255]; - struct tm tm = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - GtkTreeIter iter; - - store_minutes = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT); - for (i = 0; i <= 59; i=i+minutes_step) { - tm.tm_min = i; - strftime (label, 255, _("wdgt_va_minutes"), &tm); - - gtk_list_store_append (store_minutes, &iter); - gtk_list_store_set (store_minutes, &iter, - COLUMN_STRING, label, COLUMN_INT, i, -1); - } - - return GTK_TREE_MODEL (store_minutes); -} - -static GtkTreeModel * -_create_hours_model (HildonTimeSelector * selector) -{ - GtkListStore *store_hours = NULL; - gint i = 0; - GtkTreeIter iter; - struct tm tm = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - static gchar label[255]; - static gint range_12h[12] = {12, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11}; - static gint range_24h[24] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11, - 12,13,14,15,16,17,18,19,20,21,22,23}; - gint *range = NULL; - gint num_elements = 0; - gchar *format_string = NULL; - - if (selector->priv->ampm_format) { - range = range_12h; - num_elements = 12; - format_string = N_("wdgt_va_12h_hours"); - } else { - range = range_24h; - num_elements = 24; - format_string = N_("wdgt_va_24h_hours"); - } - - store_hours = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT); - for (i = 0; i < num_elements; i++) { - tm.tm_hour = range[i]; - strftime (label, 255, _(format_string), &tm); - - gtk_list_store_append (store_hours, &iter); - gtk_list_store_set (store_hours, &iter, - COLUMN_STRING, label, COLUMN_INT, range[i], -1); - } - - return GTK_TREE_MODEL (store_hours); -} - -static GtkTreeModel * -_create_ampm_model (HildonTimeSelector * selector) -{ - GtkListStore *store_ampm = NULL; - GtkTreeIter iter; - static gchar label[255]; - - store_ampm = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT); - - snprintf (label, 255, _("wdgt_va_am")); - gtk_list_store_append (store_ampm, &iter); - gtk_list_store_set (store_ampm, &iter, - COLUMN_STRING, label, - COLUMN_INT, 0, -1); - - snprintf (label, 255, _("wdgt_va_pm")); - gtk_list_store_append (store_ampm, &iter); - gtk_list_store_set (store_ampm, &iter, - COLUMN_STRING, label, - COLUMN_INT, 1, -1); - - return GTK_TREE_MODEL (store_ampm); -} - -static void -_get_real_time (gint * hours, gint * minutes) -{ - time_t secs; - struct tm *tm = NULL; - - secs = time (NULL); - tm = localtime (&secs); - - if (hours != NULL) { - *hours = tm->tm_hour; - } - - if (minutes != NULL) { - *minutes = tm->tm_min; - } -} - -static void -_manage_ampm_selection_cb (HildonTouchSelector * touch_selector, - gint num_column, gpointer data) -{ - HildonTimeSelector *selector = NULL; - gint pm; - GtkTreeIter iter; - - g_return_if_fail (HILDON_IS_TIME_SELECTOR (touch_selector)); - selector = HILDON_TIME_SELECTOR (touch_selector); - - if (num_column == COLUMN_AMPM && - hildon_touch_selector_get_selected (HILDON_TOUCH_SELECTOR (selector), - COLUMN_AMPM, &iter)) { - gtk_tree_model_get (selector->priv->ampm_model, &iter, COLUMN_INT, &pm, -1); - - selector->priv->pm = pm; - } -} - -static void -check_automatic_ampm_format (HildonTimeSelector * selector) -{ - GConfClient *client = NULL; - gboolean value = TRUE; - GError *error = NULL; - - client = gconf_client_get_default (); - value = gconf_client_get_bool (client, CLOCK_GCONF_IS_24H_FORMAT, &error); - if (error != NULL) { - g_warning - ("Error trying to get gconf variable %s, using 24h format by default", - CLOCK_GCONF_IS_24H_FORMAT); - g_error_free (error); - } - - selector->priv->ampm_format = !value; -} - -static void -_set_pm (HildonTimeSelector * selector, gboolean pm) -{ - GtkTreeIter iter; - - selector->priv->pm = pm; - - if (selector->priv->ampm_model != NULL) { - gtk_tree_model_iter_nth_child (selector->priv->ampm_model, &iter, NULL, pm); - - hildon_touch_selector_select_iter (HILDON_TOUCH_SELECTOR (selector), - COLUMN_AMPM, &iter, FALSE); - } -} - -static void -update_format_policy (HildonTimeSelector *selector, - HildonTimeSelectorFormatPolicy new_policy) -{ - gboolean prev_ampm_format = FALSE; - guint hours; - guint minutes; - gint num_columns = -1; - - num_columns = hildon_touch_selector_get_num_columns (HILDON_TOUCH_SELECTOR (selector)); - prev_ampm_format = selector->priv->ampm_format; - - if (new_policy != selector->priv->format_policy) { - selector->priv->format_policy = new_policy; - - /* We get the hour previous all the changes, to avoid problems with the - changing widget structure */ - if (num_columns >= 2) {/* we are on the object construction */ - hildon_time_selector_get_time (selector, &hours, &minutes); - } - - switch (new_policy) - { - case HILDON_TIME_SELECTOR_FORMAT_POLICY_AMPM: - selector->priv->ampm_format = TRUE; - break; - case HILDON_TIME_SELECTOR_FORMAT_POLICY_24H: - selector->priv->ampm_format = FALSE; - break; - case HILDON_TIME_SELECTOR_FORMAT_POLICY_AUTOMATIC: - check_automatic_ampm_format (selector); - break; - } - } - - if (prev_ampm_format != selector->priv->ampm_format) { - update_format_dependant_columns (selector, hours, minutes); - } -} - -static void -update_format_dependant_columns (HildonTimeSelector *selector, - guint hours, - guint minutes) -{ - gint num_columns = -1; - - num_columns = hildon_touch_selector_get_num_columns (HILDON_TOUCH_SELECTOR (selector)); - if (num_columns < 2) {/* we are on the object construction */ - return; - } - - /* To avoid an extra and wrong VALUE_CHANGED signal on the model update */ - hildon_touch_selector_block_changed (HILDON_TOUCH_SELECTOR(selector)); - - selector->priv->hours_model = _create_hours_model (selector); - hildon_touch_selector_set_model (HILDON_TOUCH_SELECTOR (selector), - 0, - selector->priv->hours_model); - - /* We need to set NOW the correct hour on the hours column, because the number of - columns will be updated too, so a signal COLUMNS_CHANGED will be emitted. Some - other widget could have connected to this signal and ask for the hour, so this - emission could have a wrong hour. We could use a custom func to only modify the - hours selection, but hildon_time_selector_time manage yet all the ampm issues - to select the correct one */ - hildon_time_selector_set_time (selector, hours, minutes); - - /* if we are at this function, we are sure that a change on the number of columns - will happen, so check the column number is not required */ - if (selector->priv->ampm_format) { - selector->priv->ampm_model = _create_ampm_model (selector); - - hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), - selector->priv->ampm_model, TRUE); - - g_signal_connect (G_OBJECT (selector), - "changed", G_CALLBACK (_manage_ampm_selection_cb), - NULL); - } else { - selector->priv->ampm_model = NULL; - hildon_touch_selector_remove_column (HILDON_TOUCH_SELECTOR (selector), 2); - } - - _set_pm (selector, hours >= 12); - - hildon_touch_selector_unblock_changed (HILDON_TOUCH_SELECTOR (selector)); -} -/* ------------------------------ PUBLIC METHODS ---------------------------- */ - -/** - * hildon_time_selector_new: - * - * Creates a new #HildonTimeSelector - * - * Returns: a new #HildonTimeSelector - * - * Since: 2.2 - **/ -GtkWidget * -hildon_time_selector_new () -{ - return g_object_new (HILDON_TYPE_TIME_SELECTOR, NULL); -} - - -/** - * hildon_time_selector_new_step: - * - * Creates a new #HildonTimeSelector - * @minutes_step: step between the minutes we are going to show in the - * selector - * - * Returns: a new #HildonTimeSelector - * - * Since: 2.2 - **/ -GtkWidget * -hildon_time_selector_new_step (guint minutes_step) -{ - return g_object_new (HILDON_TYPE_TIME_SELECTOR, "minutes-step", - minutes_step, NULL); -} - -/** - * hildon_time_selector_set_time - * @selector: the #HildonTimeSelector - * @hours: the current hour (0-23) - * @minutes: the current minute (0-59) - * - * Sets the current active hour on the #HildonTimeSelector widget - * - * The format of the hours accepted is always 24h format, with a range - * (0-23):(0-59). - * - * Since: 2.2 - * - * Returns: %TRUE on success, %FALSE otherwise - **/ -gboolean -hildon_time_selector_set_time (HildonTimeSelector * selector, - guint hours, guint minutes) -{ - GtkTreeIter iter; - gint hours_item = 0; - - g_return_val_if_fail (HILDON_IS_TIME_SELECTOR (selector), FALSE); - g_return_val_if_fail (hours <= 23, FALSE); - g_return_val_if_fail (minutes <= 59, FALSE); - - _set_pm (selector, hours >= 12); - - if (selector->priv->ampm_format) { - hours_item = hours - selector->priv->pm * 12; - } else { - hours_item = hours; - } - - gtk_tree_model_iter_nth_child (selector->priv->hours_model, &iter, NULL, - hours_item); - hildon_touch_selector_select_iter (HILDON_TOUCH_SELECTOR (selector), - COLUMN_HOURS, &iter, FALSE); - - g_assert (selector->priv->minutes_step>0); - minutes = minutes/selector->priv->minutes_step; - gtk_tree_model_iter_nth_child (selector->priv->minutes_model, &iter, NULL, - minutes); - hildon_touch_selector_select_iter (HILDON_TOUCH_SELECTOR (selector), - COLUMN_MINUTES, &iter, FALSE); - - return TRUE; -} - -/** - * hildon_time_selector_get_time - * @selector: the #HildonTimeSelector - * @hours: to set the current hour (0-23) - * @minutes: to set the current minute (0-59) - * - * Gets the current active hour on the #HildonTimeSelector widget. Both @year - * and @minutes can be NULL. - * - * This method returns the date always in 24h format, with a range (0-23):(0-59) - * - * Since: 2.2 - **/ -void -hildon_time_selector_get_time (HildonTimeSelector * selector, - guint * hours, guint * minutes) -{ - GtkTreeIter iter; - - g_return_if_fail (HILDON_IS_TIME_SELECTOR (selector)); - - if (hours != NULL) { - if (hildon_touch_selector_get_selected (HILDON_TOUCH_SELECTOR (selector), - COLUMN_HOURS, &iter)) { - - gtk_tree_model_get (selector->priv->hours_model, - &iter, COLUMN_INT, hours, -1); - } - if (selector->priv->ampm_format) { - *hours %= 12; - *hours += selector->priv->pm * 12; - } - } - - if (minutes != NULL) { - if (hildon_touch_selector_get_selected (HILDON_TOUCH_SELECTOR (selector), - COLUMN_MINUTES, &iter)) { - gtk_tree_model_get (selector->priv->minutes_model, - &iter, COLUMN_INT, minutes, -1); - } - } -} diff --git a/src/hildon-time-selector.h b/src/hildon-time-selector.h deleted file mode 100644 index f01b704..0000000 --- a/src/hildon-time-selector.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2008 Nokia Corporation. - * - * 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; either - * version 2 of the License, or (at your option) any later version. or (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __HILDON_TIME_SELECTOR_H__ -#define __HILDON_TIME_SELECTOR_H__ - -#include "hildon-touch-selector.h" - -G_BEGIN_DECLS - -#define HILDON_TYPE_TIME_SELECTOR \ - (hildon_time_selector_get_type ()) - -#define HILDON_TIME_SELECTOR(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - HILDON_TYPE_TIME_SELECTOR, HildonTimeSelector)) - -#define HILDON_TIME_SELECTOR_CLASS(vtable) \ - (G_TYPE_CHECK_CLASS_CAST ((vtable), \ - HILDON_TYPE_TIME_SELECTOR, HildonTimeSelectorClass)) - -#define HILDON_IS_TIME_SELECTOR(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HILDON_TYPE_TIME_SELECTOR)) - -#define HILDON_IS_TIME_SELECTOR_CLASS(vtable) \ - (G_TYPE_CHECK_CLASS_TYPE ((vtable), HILDON_TYPE_TIME_SELECTOR)) - -#define HILDON_TIME_SELECTOR_GET_CLASS(inst) \ - (G_TYPE_INSTANCE_GET_CLASS ((inst), \ - HILDON_TYPE_TIME_SELECTOR, HildonTimeSelectorClass)) - -typedef struct _HildonTimeSelector HildonTimeSelector; -typedef struct _HildonTimeSelectorClass HildonTimeSelectorClass; -typedef struct _HildonTimeSelectorPrivate HildonTimeSelectorPrivate; - -struct _HildonTimeSelector -{ - HildonTouchSelector parent_instance; - - /*< private > */ - HildonTimeSelectorPrivate *priv; -}; - -struct _HildonTimeSelectorClass -{ - HildonTouchSelectorClass parent_class; - - /* signals */ -}; - - -/** - * HildonTimeSelectorFormatPolicy: - * @HILDON_TIME_SELECTOR_FORMAT_POLICY_AMPM: The time selector will use a AMPM time format - * @HILDON_TIME_SELECTOR_FORMAT_POLICY_24H: The time selector will use a 24H time format - * @HILDON_TIME_SELECTOR_FORMAT_POLICY_AUTOMATIC: The time selector will use AMPM or 24H depending - * on the current environment - * - * Describes the time format used at #HildonTimeSelector - **/ -typedef enum { - HILDON_TIME_SELECTOR_FORMAT_POLICY_AMPM, - HILDON_TIME_SELECTOR_FORMAT_POLICY_24H, - HILDON_TIME_SELECTOR_FORMAT_POLICY_AUTOMATIC -} HildonTimeSelectorFormatPolicy; - -/* construction */ -GType -hildon_time_selector_get_type (void) G_GNUC_CONST; - -GtkWidget* -hildon_time_selector_new (void); - -GtkWidget* -hildon_time_selector_new_step (guint minutes_step); - -/* time management */ -gboolean -hildon_time_selector_set_time (HildonTimeSelector *selector, - guint hours, - guint minutes); - -void -hildon_time_selector_get_time (HildonTimeSelector *selector, - guint *hours, - guint *minutes); - -G_END_DECLS - -#endif /* __HILDON_TIME_SELECTOR_H__ */ diff --git a/src/hildon-touch-selector-column.h b/src/hildon-touch-selector-column.h deleted file mode 100644 index 0ee68d5..0000000 --- a/src/hildon-touch-selector-column.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2008 Nokia Corporation. - * - * 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; either - * version 2 of the License, or (at your option) any later version. or (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __HILDON_TOUCH_SELECTOR_COLUMN_H__ -#define __HILDON_TOUCH_SELECTOR_COLUMN_H__ - -#include - -G_BEGIN_DECLS - -#define HILDON_TYPE_TOUCH_SELECTOR_COLUMN \ - (hildon_touch_selector_column_get_type ()) - -#define HILDON_TOUCH_SELECTOR_COLUMN(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - HILDON_TYPE_TOUCH_SELECTOR_COLUMN, HildonTouchSelectorColumn)) - -#define HILDON_TOUCH_SELECTOR_COLUMN_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - HILDON_TYPE_TOUCH_SELECTOR_COLUMN, HildonTouchSelectorColumnClass)) - -#define HILDON_IS_TOUCH_SELECTOR_COLUMN(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ - HILDON_TYPE_TOUCH_SELECTOR_COLUMN)) - -#define HILDON_IS_TOUCH_SELECTOR_COLUMN_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), \ - HILDON_TYPE_TOUCH_SELECTOR_COLUMN)) - -#define HILDON_TOUCH_SELECTOR_COLUMN_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - HILDON_TYPE_TOUCH_SELECTOR_COLUMN, HildonTouchSelectorColumnClass)) - -typedef struct _HildonTouchSelectorColumn HildonTouchSelectorColumn; -typedef struct _HildonTouchSelectorColumnClass HildonTouchSelectorColumnClass; -typedef struct _HildonTouchSelectorColumnPrivate HildonTouchSelectorColumnPrivate; - -struct _HildonTouchSelectorColumn -{ - GObject parent; - - /* < private > */ - HildonTouchSelectorColumnPrivate *priv; -}; - -struct _HildonTouchSelectorColumnClass -{ - GObjectClass parent_class; -}; - -GType -hildon_touch_selector_column_get_type (void) G_GNUC_CONST; - -G_END_DECLS - - -#endif /*__HILDON_TOUCH_SELECTOR_COLUMN_H__ */ diff --git a/src/hildon-touch-selector-entry.c b/src/hildon-touch-selector-entry.c deleted file mode 100644 index 9e4913d..0000000 --- a/src/hildon-touch-selector-entry.c +++ /dev/null @@ -1,533 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation. - * - * 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; either - * version 2 of the License, or (at your option) any later version. or (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/** - * SECTION:hildon-touch-selector-entry - * @short_description: A selector widget with one column and a text entry - * @see_also: #HildonTouchSelector, #HildonPickerButton - * - * #HildonTouchSelectorEntry is a selector widget with a text entry, similar in - * behaviour to #GtkComboBoxEntry, that allows user to select an item from a - * predefined list or to enter a different one in a #HildonEntry. Items can also - * be searched and selected by typing in the entry. For more specific use cases, - * the #HildonEntry can be accessed directly with hildon_touch_selector_get_entry(). - * - * The main difference between the #GtkTreeModel used by #HildonTouchSelector - * and #HildonTouchSelectorEntry, is that the latter must always include a text - * column. You should set it with hildon_touch_selector_entry_set_text_column(). - * - * Normally, you would use #HildonTouchSelectorEntry together with a - * #HildonPickerDialog activated from a button. For the most common - * cases, you should use #HildonPickerButton. - * - * If you only need a text only, one column selector, you can create it with - * hildon_touch_selector_entry_new_text() and populate it with - * hildon_touch_selector_append_text(), hildon_touch_selector_prepend_text(), - * and hildon_touch_selector_insert_text(). - * - */ - -#include "hildon-touch-selector.h" -#include "hildon-touch-selector-entry.h" -#include "hildon-entry.h" - -G_DEFINE_TYPE (HildonTouchSelectorEntry, hildon_touch_selector_entry, HILDON_TYPE_TOUCH_SELECTOR) - -#define HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), HILDON_TYPE_TOUCH_SELECTOR_ENTRY, HildonTouchSelectorEntryPrivate)) - -typedef struct _HildonTouchSelectorEntryPrivate HildonTouchSelectorEntryPrivate; - -static void entry_on_text_changed (GtkEditable * editable, gpointer userdata); -static void hildon_touch_selector_entry_changed (HildonTouchSelector * selector, - gint column, - gpointer user_data); -static void hildon_touch_selector_entry_set_model (HildonTouchSelector * selector, - gint column, GtkTreeModel *model); -static gboolean hildon_touch_selector_entry_has_multiple_selection (HildonTouchSelector * selector); - -static void -_text_column_modified (GObject *pspec, GParamSpec *gobject, gpointer data); - - -struct _HildonTouchSelectorEntryPrivate { - gulong signal_id; - GtkWidget *entry; -}; - -enum { - PROP_TEXT_COLUMN = 1 -}; - -static void -hildon_touch_selector_entry_get_property (GObject *object, guint property_id, - GValue *value, GParamSpec *pspec) -{ - switch (property_id) { - case PROP_TEXT_COLUMN: - g_value_set_int (value, - hildon_touch_selector_entry_get_text_column (HILDON_TOUCH_SELECTOR_ENTRY (object))); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - -static void -hildon_touch_selector_entry_set_property (GObject *object, guint property_id, - const GValue *value, GParamSpec *pspec) -{ - switch (property_id) { - case PROP_TEXT_COLUMN: - hildon_touch_selector_entry_set_text_column (HILDON_TOUCH_SELECTOR_ENTRY (object), - g_value_get_int (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - -static void -hildon_touch_selector_entry_class_init (HildonTouchSelectorEntryClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - HildonTouchSelectorClass *selector_class = HILDON_TOUCH_SELECTOR_CLASS (klass); - - g_type_class_add_private (klass, sizeof (HildonTouchSelectorEntryPrivate)); - - selector_class->set_model = hildon_touch_selector_entry_set_model; - selector_class->has_multiple_selection = hildon_touch_selector_entry_has_multiple_selection; - - object_class->get_property = hildon_touch_selector_entry_get_property; - object_class->set_property = hildon_touch_selector_entry_set_property; - - /** - * HildonTouchSelectorEntry:text-column: - * - * Deprecated: now this property is in HildonTouchSelectorColumn use - * hildon_touch_selector_entry_set_text_column() and - * hildon_touch_selector_entry_get_text_column() to manage this. - * - * Since: 2.2 - **/ - g_object_class_install_property (G_OBJECT_CLASS (klass), - PROP_TEXT_COLUMN, - g_param_spec_int ("text-column", - "Text Column", - "A column in the data source model to get the strings from.", - -1, - G_MAXINT, - -1, - G_PARAM_READWRITE)); -} - -static gchar * -hildon_touch_selector_entry_print_func (HildonTouchSelector * selector, gpointer user_data) -{ - HildonTouchSelectorEntryPrivate *priv; - GtkTreeModel *model; - GtkTreeIter iter; - gint column; - gchar *text = NULL; - - priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector); - - if (*(gtk_entry_get_text (GTK_ENTRY (priv->entry))) != '\0') { - text = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->entry))); - } else { - model = hildon_touch_selector_get_model (selector, 0); - if (hildon_touch_selector_get_selected (selector, 0, &iter)) { - column = hildon_touch_selector_entry_get_text_column (HILDON_TOUCH_SELECTOR_ENTRY (selector)); - gtk_tree_model_get (model, &iter, column, &text, -1); - } - } - - return text; -} - -static void -hildon_touch_selector_entry_init (HildonTouchSelectorEntry *self) -{ - HildonTouchSelectorEntryPrivate *priv; - GtkEntryCompletion *completion; - HildonGtkInputMode input_mode; - - priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (self); - - priv->entry = hildon_entry_new (HILDON_SIZE_AUTO); - gtk_entry_set_activates_default (GTK_ENTRY (priv->entry), TRUE); - input_mode = hildon_gtk_entry_get_input_mode (GTK_ENTRY (priv->entry)); - - /* Disable unsupported input modes. */ - input_mode &= ~HILDON_GTK_INPUT_MODE_MULTILINE; - input_mode &= ~HILDON_GTK_INPUT_MODE_INVISIBLE; - input_mode &= ~HILDON_GTK_INPUT_MODE_DICTIONARY; - - hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry), input_mode); - - completion = gtk_entry_completion_new (); - gtk_entry_completion_set_inline_completion (completion, TRUE); - gtk_entry_completion_set_popup_completion (completion, FALSE); - gtk_entry_set_completion (GTK_ENTRY (priv->entry), completion); - - gtk_widget_show (priv->entry); - g_signal_connect (G_OBJECT (priv->entry), "changed", - G_CALLBACK (entry_on_text_changed), self); - priv->signal_id = g_signal_connect (G_OBJECT (self), "changed", - G_CALLBACK (hildon_touch_selector_entry_changed), NULL); - - hildon_touch_selector_set_print_func (HILDON_TOUCH_SELECTOR (self), hildon_touch_selector_entry_print_func); - gtk_box_pack_start (GTK_BOX (self), priv->entry, FALSE, FALSE, 0); -} - -/** - * hildon_touch_selector_entry_new: - * - * Creates a #HildonTouchSelectorEntry - * - * Returns: A new #HildonTouchSelectorEntry - * - * Since: 2.2 - **/ -GtkWidget * -hildon_touch_selector_entry_new (void) -{ - return g_object_new (HILDON_TYPE_TOUCH_SELECTOR_ENTRY, NULL); -} - -/** - * hildon_touch_selector_entry_new_text: - * - * Creates a #HildonTouchSelectorEntry with a single text column that - * can be populated conveniently through hildon_touch_selector_append_text(), - * hildon_touch_selector_prepend_text(), hildon_touch_selector_insert_text(). - * - * Returns: A new #HildonTouchSelectorEntry - * - * Since: 2.2 - **/ -GtkWidget * -hildon_touch_selector_entry_new_text (void) -{ - GtkListStore *model; - GtkWidget *selector; - GtkEntryCompletion *completion; - HildonTouchSelectorEntryPrivate *priv; - HildonTouchSelectorColumn *column = NULL; - - selector = hildon_touch_selector_entry_new (); - - priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector); - - model = gtk_list_store_new (1, G_TYPE_STRING); - completion = gtk_entry_get_completion (GTK_ENTRY (priv->entry)); - gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (model)); - column = hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), - GTK_TREE_MODEL (model), FALSE); - - g_signal_connect (column, "notify::text-column", G_CALLBACK (_text_column_modified), - selector); - hildon_touch_selector_entry_set_text_column (HILDON_TOUCH_SELECTOR_ENTRY (selector), 0); - - return selector; -} - -static void -_text_column_modified (GObject *pspec, GParamSpec *gobject, gpointer data) -{ - HildonTouchSelectorEntry *selector; - HildonTouchSelectorEntryPrivate *priv; - GtkEntryCompletion *completion; - gint text_column = -1; - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (data)); - selector = HILDON_TOUCH_SELECTOR_ENTRY (data); - - priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (HILDON_TOUCH_SELECTOR_ENTRY(selector)); - completion = gtk_entry_get_completion (GTK_ENTRY (priv->entry)); - - text_column = hildon_touch_selector_entry_get_text_column (selector); - - gtk_entry_completion_set_text_column (completion, text_column); -} - -/** - * hildon_touch_selector_entry_set_text_column: - * @selector: A #HildonTouchSelectorEntry - * @text_column: A column in model to get the strings from - * - * Sets the model column which touch selector box should use to get strings - * from to be @text_column. - * - * Since: 2.2 - **/ -void -hildon_touch_selector_entry_set_text_column (HildonTouchSelectorEntry *selector, - gint text_column) -{ - HildonTouchSelectorColumn *column = NULL; - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector)); - g_return_if_fail (text_column >= -1); - - column = hildon_touch_selector_get_column (HILDON_TOUCH_SELECTOR (selector), 0); - - g_object_set (G_OBJECT (column), "text-column", text_column, NULL); -} - -/** - * hildon_touch_selector_entry_get_text_column: - * @selector: A #HildonTouchSelectorEntry - * - * Gets the text column that @selector is using as a text column. - * - * Returns: the number of the column used as a text column. - * - * Since: 2.2 - **/ -gint -hildon_touch_selector_entry_get_text_column (HildonTouchSelectorEntry *selector) -{ - HildonTouchSelectorColumn *column = NULL; - gint text_column = -1; - - g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector), -1); - - column = hildon_touch_selector_get_column (HILDON_TOUCH_SELECTOR (selector), - 0); - - g_object_get (G_OBJECT (column), "text-column", &text_column, NULL); - - return text_column; -} - -/** - * hildon_touch_selector_entry_set_input_mode: - * @selector: a #HildonTouchSelectorEntry - * @input_mode: #HildonGtkInputMode mask - * - * Sets the input mode to be used in the #GtkEntry in @selector. See hildon_gtk_entry_set_input_mode() - * for details. - * - * It must be noted that not all input modes are available for the - * entry in @selector. In particular, - * %HILDON_GTK_INPUT_MODE_MULTILINE, %HILDON_GTK_INPUT_MODE_INVISIBLE, - * %HILDON_GTK_INPUT_MODE_DICTIONARY are disabled, since these are irrelevant - * for #HildonTouchSelectorEntry. - * - * Since: 2.2 - **/ -void -hildon_touch_selector_entry_set_input_mode (HildonTouchSelectorEntry * selector, - HildonGtkInputMode input_mode) -{ - HildonTouchSelectorEntryPrivate *priv; - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector)); - g_return_if_fail (!(input_mode & (HILDON_GTK_INPUT_MODE_MULTILINE | - HILDON_GTK_INPUT_MODE_INVISIBLE | - HILDON_GTK_INPUT_MODE_DICTIONARY))); - - priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector); - - hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry), input_mode); -} - -/** - * hildon_touch_selector_entry_get_input_mode: - * @selector: a #HildonTouchSelectorEntry - * - * Gets the input mode used in the #GtkEntry in @selector. See hildon_gtk_entry_get_input_mode() - * for details. - * - * Returns: a mask of #HildonGtkInputMode - * - * Since: 2.2 - **/ -HildonGtkInputMode -hildon_touch_selector_entry_get_input_mode (HildonTouchSelectorEntry * selector) -{ - HildonTouchSelectorEntryPrivate *priv; - - g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector), HILDON_GTK_INPUT_MODE_ALPHA); - - priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector); - - return hildon_gtk_entry_get_input_mode (GTK_ENTRY (priv->entry)); -} - -static void -entry_on_text_changed (GtkEditable * editable, - gpointer userdata) -{ - HildonTouchSelector *selector; - HildonTouchSelectorEntryPrivate *priv; - GtkTreeModel *model; - GtkTreeIter iter; - GtkEntry *entry; - const gchar *prefix; - gchar *text; - gboolean found = FALSE; - gint text_column = -1; - - entry = GTK_ENTRY (editable); - selector = HILDON_TOUCH_SELECTOR (userdata); - priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector); - - text_column = - hildon_touch_selector_entry_get_text_column (HILDON_TOUCH_SELECTOR_ENTRY (selector)); - - prefix = gtk_entry_get_text (entry); - - if (prefix[0] == '\0') { - return; - } - - model = hildon_touch_selector_get_model (selector, 0); - - if (!gtk_tree_model_get_iter_first (model, &iter)) { - return; - } - - do { - gtk_tree_model_get (model, &iter, text_column, &text, -1); - found = g_str_has_prefix (text, prefix); - g_free (text); - } while (found != TRUE && gtk_tree_model_iter_next (model, &iter)); - - g_signal_handler_block (selector, priv->signal_id); - { - /* We emit the HildonTouchSelector::changed signal because a change in the - GtkEntry represents a change in current selection, and therefore, users - should be notified. */ - if (found) { - hildon_touch_selector_select_iter (selector, 0, &iter, TRUE); - } - g_signal_emit_by_name (selector, "changed", 0); - } - g_signal_handler_unblock (selector, priv->signal_id); - -} - -/* FIXME: This is actually a very ugly way to retrieve the text. Ideally, - we would have API to retrieve it from the base clase (HildonTouchSelector). - In the meantime, leaving it here. - */ -static gchar * -hildon_touch_selector_get_text_from_model (HildonTouchSelectorEntry * selector) -{ - GtkTreeModel *model; - GtkTreeIter iter; - GtkTreePath *path; - GList *selected_rows; - gchar *text; - gint text_column = -1; - - model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0); - text_column = hildon_touch_selector_entry_get_text_column (selector); - selected_rows = hildon_touch_selector_get_selected_rows (HILDON_TOUCH_SELECTOR (selector), 0); - - if (selected_rows == NULL) { - return NULL; - } - - /* We are in single selection mode */ - g_assert (selected_rows->next == NULL); - - path = (GtkTreePath *)selected_rows->data; - gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_model_get (model, &iter, text_column, &text, -1); - - gtk_tree_path_free (path); - g_list_free (selected_rows); - - return text; -} - -static void -hildon_touch_selector_entry_changed (HildonTouchSelector * selector, - gint column, gpointer user_data) -{ - HildonTouchSelectorEntryPrivate *priv; - gchar *text; - - priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector); - - text = hildon_touch_selector_get_text_from_model (HILDON_TOUCH_SELECTOR_ENTRY (selector)); - if (text != NULL) { - gtk_entry_set_text (GTK_ENTRY (priv->entry), text); - gtk_editable_select_region (GTK_EDITABLE (priv->entry), 0, -1); - g_free (text); - } -} - -static void -hildon_touch_selector_entry_set_model (HildonTouchSelector * selector, - gint column, GtkTreeModel *model) -{ - GtkEntryCompletion *completion; - HildonTouchSelectorEntryPrivate *priv; - gint text_column = -1; - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector)); - g_return_if_fail (column == 0); - g_return_if_fail (GTK_IS_TREE_MODEL (model)); - - HILDON_TOUCH_SELECTOR_CLASS (hildon_touch_selector_entry_parent_class)->set_model (selector, column, model); - - priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector); - - completion = gtk_entry_get_completion (GTK_ENTRY (priv->entry)); - gtk_entry_completion_set_model (completion, model); - - text_column = hildon_touch_selector_entry_get_text_column (HILDON_TOUCH_SELECTOR_ENTRY (selector)); - - gtk_entry_completion_set_text_column (completion, text_column); -} - -static gboolean -hildon_touch_selector_entry_has_multiple_selection (HildonTouchSelector * selector) -{ - /* Always TRUE, given the GtkEntry. */ - return TRUE; -} - -/** - * hildon_touch_selector_entry_get_entry: - * @selector: a #HildonTouchSelectorEntry. - * - * Provides access to the #HildonEntry in @selector. Use to programmatically - * change the contents in entry or modify its behavior. - * - * Returns: a #HildonEntry. - * - * Since: 2.2 - **/ -HildonEntry * -hildon_touch_selector_entry_get_entry (HildonTouchSelectorEntry * selector) -{ - HildonTouchSelectorEntryPrivate *priv; - - g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector), NULL); - - priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector); - - return HILDON_ENTRY (priv->entry); -} diff --git a/src/hildon-touch-selector-entry.h b/src/hildon-touch-selector-entry.h deleted file mode 100644 index a244330..0000000 --- a/src/hildon-touch-selector-entry.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation. - * - * 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; either - * version 2 of the License, or (at your option) any later version. or (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __HILDON_TOUCH_SELECTOR_ENTRY__ -#define __HILDON_TOUCH_SELECTOR_ENTRY__ - -#include "hildon-touch-selector.h" -#include "hildon-entry.h" - -G_BEGIN_DECLS - -#define HILDON_TYPE_TOUCH_SELECTOR_ENTRY \ - (hildon_touch_selector_entry_get_type()) - -#define HILDON_TOUCH_SELECTOR_ENTRY(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - HILDON_TYPE_TOUCH_SELECTOR_ENTRY, HildonTouchSelectorEntry)) - -#define HILDON_TOUCH_SELECTOR_ENTRY_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - HILDON_TYPE_TOUCH_SELECTOR_ENTRY, HildonTouchSelectorEntryClass)) - -#define HILDON_IS_TOUCH_SELECTOR_ENTRY(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ - HILDON_TYPE_TOUCH_SELECTOR_ENTRY)) - -#define HILDON_IS_TOUCH_SELECTOR_ENTRY_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), \ - HILDON_TYPE_TOUCH_SELECTOR_ENTRY)) - -#define HILDON_TOUCH_SELECTOR_ENTRY_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - HILDON_TYPE_TOUCH_SELECTOR_ENTRY, HildonTouchSelectorEntryClass)) - -typedef struct _HildonTouchSelectorEntry HildonTouchSelectorEntry; -typedef struct _HildonTouchSelectorEntryClass HildonTouchSelectorEntryClass; - -struct _HildonTouchSelectorEntry -{ - HildonTouchSelector parent; - - /*< private > */ -}; - -struct _HildonTouchSelectorEntryClass -{ - HildonTouchSelectorClass parent_class; -}; - -GType -hildon_touch_selector_entry_get_type (void); - -GtkWidget* -hildon_touch_selector_entry_new (void); - -GtkWidget* -hildon_touch_selector_entry_new_text (void); - -void -hildon_touch_selector_entry_set_text_column (HildonTouchSelectorEntry *selector, - gint text_column); -gint -hildon_touch_selector_entry_get_text_column (HildonTouchSelectorEntry *selector); - -HildonGtkInputMode -hildon_touch_selector_entry_get_input_mode (HildonTouchSelectorEntry * selector); - -void -hildon_touch_selector_entry_set_input_mode (HildonTouchSelectorEntry * selector, - HildonGtkInputMode input_mode); - -HildonEntry * -hildon_touch_selector_entry_get_entry (HildonTouchSelectorEntry * selector); - -G_END_DECLS - -#endif /* __HILDON_TOUCH_SELECTOR_ENTRY__ */ - diff --git a/src/hildon-touch-selector-private.h b/src/hildon-touch-selector-private.h deleted file mode 100644 index eeee475..0000000 --- a/src/hildon-touch-selector-private.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2009 Nokia Corporation. - * - * Contact: Rodrigo Novo - * - * 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; either - * version 2 of the License, or (at your option) any later version. or (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#ifndef __HILDON_TOUCH_SELECTOR_PRIVATE_H__ -#define __HILDON_TOUCH_SELECTOR_PRIVATE_H__ - - -G_BEGIN_DECLS - -void G_GNUC_INTERNAL -hildon_touch_selector_block_changed (HildonTouchSelector *selector); - -void G_GNUC_INTERNAL -hildon_touch_selector_unblock_changed (HildonTouchSelector *selector); - -G_END_DECLS - -#endif diff --git a/src/hildon-touch-selector.c b/src/hildon-touch-selector.c deleted file mode 100644 index 4ab005d..0000000 --- a/src/hildon-touch-selector.c +++ /dev/null @@ -1,2120 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2008 Nokia Corporation. - * - * 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; either - * version 2 of the License, or (at your option) any later version. or (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/** - * SECTION:hildon-touch-selector - * @short_description: A selector widget with several columns. - * - * #HildonTouchSelector is a selector widget, that allows users to - * select items from one to many predefined lists. It is very similar - * to #GtkComboBox, but with several individual pannable columns. - * - * Normally, you would use #HildonTouchSelector together with a - * #HildonPickerDialog activated from a button. For the most common - * cases, you should use #HildonPickerButton. - * - * The composition of each column in the selector is represented by a - * #GtkTreeModel. To add a new column to a #HildonTouchSelector, use - * hildon_touch_selector_append_column(). If you want to add a - * text-only column, without special attributes, use - * hildon_touch_selector_append_text_column(). - * - * It is highly recommended that you use only one column - * #HildonTouchSelectors. - * If you only need a text only, one column selector, you can create it with - * hildon_touch_selector_new_text() and populate with - * hildon_touch_selector_append_text(), hildon_touch_selector_prepend_text(), - * and hildon_touch_selector_insert_text(). - * - * If you need a selector widget that also accepts user inputs, you - * can use #HildonTouchSelectorEntry. - * - * The current selection has a string representation. In the most common cases, - * each column model will contain a text column. You can configure - * which column in particular using the #HildonTouchSelectorColumn property - * #HildonTouchSelectorColumn:text-column - * - * You can get this string representation using - * hildon_touch_selector_get_current_text(). - * You can configure how the selection is printed with - * hildon_touch_selector_set_print_func(), that sets the current hildon touch - * selector print function. The widget has a default print function, that - * uses the #HildonTouchSelectorColumn:text-column property on each - * #HildonTouchSelectorColumn to compose the final representation. - * - * If you create the selector using hildon_touch_selector_new_text() you - * don't need to take care of this property, as the model is created internally. - * If you create the selector using hildon_touch_selector_new(), you - * need to specify properly the property for your custom model in order to get a - * non-empty string representation, or define your custom print function. - * - * - * Creating a HildonTouchSelector - * - * void - * selection_changed (HildonTouchSelector * selector, - * gpointer *user_data) - * { - * gchar *current_selection = NULL; - * - * current_selection = hildon_touch_selector_get_current_text (selector); - * g_debug ("Current selection : %s", current_selection); - * } - * - * static GtkWidget * - * create_customized_selector () - * { - * GtkWidget *selector = NULL; - * GSList *icon_list = NULL; - * GtkListStore *store_icons = NULL; - * GSList *item = NULL; - * GtkCellRenderer *renderer = NULL; - * HildonTouchSelectorColumn *column = NULL; - * - * selector = hildon_touch_selector_new (); - * - * icon_list = gtk_stock_list_ids (); - * - * store_icons = gtk_list_store_new (1, G_TYPE_STRING); - * for (item = icon_list; item; item = g_slist_next (item)) { - * GtkTreeIter iter; - * gchar *label = item->data; - * - * gtk_list_store_append (store_icons, &iter); - * gtk_list_store_set (store_icons, &iter, 0, label, -1); - * g_free (label); - * } - * g_slist_free (icon_list); - * - * renderer = gtk_cell_renderer_pixbuf_new (); - * gtk_cell_renderer_set_fixed_size (renderer, -1, 100); - * - * column = hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), - * GTK_TREE_MODEL (store_icons), - * renderer, "stock-id", 0, NULL); - * - * g_object_set (G_OBJECT (column), "text-column", 0, NULL); - * - * hildon_touch_selector_set_column_selection_mode (HILDON_TOUCH_SELECTOR (selector), - * HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE); - * - * g_signal_connect (G_OBJECT (selector), "changed", - * G_CALLBACK (selection_changed), NULL); - * - * return selector; - * } - * - * static GtkWidget * - * create_simple_selector () - * { - * GtkWidget *selector = NULL; - * gint i; - * - * selector = hildon_touch_selector_new_text (); - * hildon_touch_selector_set_column_selection_mode (HILDON_TOUCH_SELECTOR (selector), - * HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE); - * - * g_signal_connect (G_OBJECT (selector), "changed", - * G_CALLBACK (selection_changed), NULL); - * - * for (i = 1; i <= 10 ; i++) { - * gchar *label = g_strdup_printf ("Item &percnt;d", i); - * - * hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), - * label); - * - * g_free (label); - * } - * - * return selector; - * } - * - * - */ - -/** - * SECTION:hildon-touch-selector-column - * @short_description: A visible column in a #HildonTouchSelector - * - * #HildonTouchSelectorColumn object represents a visible column in - * #HildonTouchSelector. It allows to manage the cell renderers related to each - * column. - */ - -#undef HILDON_DISABLE_DEPRECATED - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include - -#include "hildon-gtk.h" - -#include "hildon-pannable-area.h" -#include "hildon-touch-selector.h" -#include "hildon-touch-selector-private.h" - -#define HILDON_TOUCH_SELECTOR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_TOUCH_SELECTOR, HildonTouchSelectorPrivate)) - -G_DEFINE_TYPE (HildonTouchSelector, hildon_touch_selector, GTK_TYPE_VBOX) - -/* - * IMPLEMENTATION NOTES: - * Struct to maintain the data of each column. The columns are the elements - * of the widget that belongs properly to the selection behaviour. Although - * internally the columns are arranged in a private #GtkHBox, as the selector - * itself is a #GtkVBox, you can add more widgets, like buttons etc., so - * you finally could have a widget with more elements that the columns, but - * this doesn't belongs to the selection logic - */ -struct _HildonTouchSelectorColumnPrivate -{ - HildonTouchSelector *parent; /* the selector that contains this column */ - GtkTreeModel *model; - gint text_column; - GtkTreeView *tree_view; - gulong realize_handler; - GtkTreePath *initial_path; - - GtkWidget *panarea; /* the pannable widget */ -}; - -struct _HildonTouchSelectorPrivate -{ - GSList *columns; /* the selection columns */ - GtkWidget *hbox; /* the container for the selector's columns */ - gboolean initial_scroll; /* whether initial fancy scrolling to selection */ - - gboolean changed_blocked; - - HildonTouchSelectorPrintFunc print_func; - gpointer print_user_data; - GDestroyNotify print_destroy_func; -}; - -enum -{ - PROP_HAS_MULTIPLE_SELECTION = 1, - PROP_INITIAL_SCROLL -}; - -enum -{ - CHANGED, - COLUMNS_CHANGED, - LAST_SIGNAL -}; - -static gint hildon_touch_selector_signals[LAST_SIGNAL] = { 0 }; - -static void -hildon_touch_selector_dispose (GObject * object); - -static void -hildon_touch_selector_get_property (GObject * object, - guint prop_id, - GValue * value, - GParamSpec * pspec); -static void -hildon_touch_selector_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -/* gtkwidget */ - -/* gtkcontainer */ -static void hildon_touch_selector_remove (GtkContainer * container, - GtkWidget * widget); -/* private functions */ -static void _row_tapped_cb (GtkTreeView * tree_view, - GtkTreePath * path, - gpointer user_data); -static gchar *_default_print_func (HildonTouchSelector * selector, - gpointer user_data); - -static HildonTouchSelectorColumn *_create_new_column (HildonTouchSelector * selector, - GtkTreeModel * model, - gboolean *emit_changed, - GtkCellRenderer * renderer, - va_list args); -static gboolean -on_realize_cb (GtkWidget *widget, - gpointer data); -static void -hildon_touch_selector_scroll_to (HildonTouchSelectorColumn *column, - GtkTreeView *tv, - GtkTreePath *path); -static gboolean -_hildon_touch_selector_center_on_selected_items (HildonTouchSelector *selector, - HildonTouchSelectorColumn *column); -static void -_hildon_touch_selector_set_model (HildonTouchSelector * selector, - gint num_column, - GtkTreeModel * model); -static gboolean -_hildon_touch_selector_has_multiple_selection (HildonTouchSelector * selector); - -static void -hildon_touch_selector_emit_value_changed (HildonTouchSelector *selector, - gint column); - -/* GtkCellLayout implementation (HildonTouchSelectorColumn)*/ -static void hildon_touch_selector_column_cell_layout_init (GtkCellLayoutIface *iface); - -static void hildon_touch_selector_column_cell_layout_pack_start (GtkCellLayout *cell_layout, - GtkCellRenderer *cell, - gboolean expand); -static void hildon_touch_selector_column_cell_layout_pack_end (GtkCellLayout *cell_layout, - GtkCellRenderer *cell, - gboolean expand); -static void hildon_touch_selector_column_cell_layout_clear (GtkCellLayout *cell_layout); -static void hildon_touch_selector_column_cell_layout_add_attribute(GtkCellLayout *cell_layout, - GtkCellRenderer *cell, - const gchar *attribute, - gint column); -static void hildon_touch_selector_column_cell_layout_set_cell_data_func (GtkCellLayout *cell_layout, - GtkCellRenderer *cell, - GtkCellLayoutDataFunc func, - gpointer func_data, - GDestroyNotify destroy); -static void hildon_touch_selector_column_cell_layout_clear_attributes (GtkCellLayout *cell_layout, - GtkCellRenderer *cell); -static void hildon_touch_selector_column_cell_layout_reorder (GtkCellLayout *cell_layout, - GtkCellRenderer *cell, - gint position); -static GList *hildon_touch_selector_column_cell_layout_get_cells (GtkCellLayout *cell_layout); - - -static void -hildon_touch_selector_class_init (HildonTouchSelectorClass * class) -{ - GObjectClass *gobject_class; - GtkObjectClass *object_class; - GtkContainerClass *container_class; - - gobject_class = G_OBJECT_CLASS (class); - object_class = GTK_OBJECT_CLASS (class); - container_class = GTK_CONTAINER_CLASS (class); - - /* GObject */ - gobject_class->dispose = hildon_touch_selector_dispose; - gobject_class->get_property = hildon_touch_selector_get_property; - gobject_class->set_property = hildon_touch_selector_set_property; - - /* GtkWidget */ - - /* GtkContainer */ - container_class->remove = hildon_touch_selector_remove; - - /* HildonTouchSelector */ - class->changed = NULL; - class->set_model = _hildon_touch_selector_set_model; - - class->has_multiple_selection = _hildon_touch_selector_has_multiple_selection; - - /* signals */ - /** - * HildonTouchSelector::changed: - * @widget: the object which received the signal - * @column: the number of the column that has changed - * - * The "changed" signal is emitted when the active item on any column is changed. - * This can be due to the user selecting a different item from the list, or - * due to a call to hildon_touch_selector_select_iter() on one of the columns. - * - * Since: 2.2 - */ - hildon_touch_selector_signals[CHANGED] = - g_signal_new ("changed", - G_OBJECT_CLASS_TYPE (class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (HildonTouchSelectorClass, changed), - NULL, NULL, - g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); - - /** - * HildonTouchSelector::columns-changed: - * @selector: the object which received the signal - * - * The "columns-changed" signal is emitted when the number - * of columns in the #HildonTouchSelector change. - * - * Since: 2.2 - */ - hildon_touch_selector_signals[COLUMNS_CHANGED] = - g_signal_new ("columns-changed", - G_OBJECT_CLASS_TYPE (class), - G_SIGNAL_RUN_LAST, 0, - NULL, NULL, - g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - - /* properties */ - - g_object_class_install_property (gobject_class, PROP_HAS_MULTIPLE_SELECTION, - g_param_spec_boolean ("has-multiple-selection", - "has multiple selection", - "Whether the widget has multiple " - "selection (like multiple columns, " - "multiselection mode, or multiple " - "internal widgets) and therefore " - "it may need a confirmation button, " - "for instance.", - FALSE, - G_PARAM_READABLE)); - - g_object_class_install_property (G_OBJECT_CLASS (gobject_class), - PROP_INITIAL_SCROLL, - g_param_spec_boolean ("initial-scroll", - "Initial scroll", - "Whether to scroll to the" - "current selection when" - "the selector is first" - "shown", - TRUE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - /* style properties */ - /* We need to ensure fremantle mode for the treeview in order to work - properly. This is not about the appearance, this is about behaviour */ - gtk_rc_parse_string ("style \"fremantle-htst\" {\n" - " GtkWidget::hildon-mode = 1\n" - "} widget \"*.fremantle-htst\" style \"fremantle-htst\"" - "widget_class \"*.GtkTreeView\" style :highest \"fremantle-htst\""); - - g_type_class_add_private (object_class, sizeof (HildonTouchSelectorPrivate)); -} - -static void -hildon_touch_selector_get_property (GObject * object, - guint prop_id, - GValue * value, GParamSpec * pspec) -{ - HildonTouchSelectorPrivate *priv = HILDON_TOUCH_SELECTOR (object)->priv; - - switch (prop_id) { - case PROP_HAS_MULTIPLE_SELECTION: - g_value_set_boolean (value, - hildon_touch_selector_has_multiple_selection (HILDON_TOUCH_SELECTOR (object))); - break; - case PROP_INITIAL_SCROLL: - g_value_set_boolean (value, priv->initial_scroll); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -hildon_touch_selector_set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - HildonTouchSelectorPrivate *priv = HILDON_TOUCH_SELECTOR (object)->priv; - - switch (prop_id) { - case PROP_INITIAL_SCROLL: - priv->initial_scroll = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - - -static void -hildon_touch_selector_init (HildonTouchSelector * selector) -{ - selector->priv = HILDON_TOUCH_SELECTOR_GET_PRIVATE (selector); - - GTK_WIDGET_SET_FLAGS (GTK_WIDGET (selector), GTK_NO_WINDOW); - gtk_widget_set_redraw_on_allocate (GTK_WIDGET (selector), FALSE); - - selector->priv->columns = NULL; - - selector->priv->print_func = NULL; - selector->priv->print_user_data = NULL; - selector->priv->print_destroy_func = NULL; - selector->priv->initial_scroll = TRUE; - selector->priv->hbox = gtk_hbox_new (FALSE, 0); - - selector->priv->changed_blocked = FALSE; - - gtk_box_pack_end (GTK_BOX (selector), selector->priv->hbox, - TRUE, TRUE, 0); - gtk_widget_show (selector->priv->hbox); -} - -static void -hildon_touch_selector_dispose (GObject * object) -{ - GObjectClass *gobject_class; - - hildon_touch_selector_set_print_func_full (HILDON_TOUCH_SELECTOR (object), - NULL, NULL, NULL); - - gobject_class = G_OBJECT_CLASS (hildon_touch_selector_parent_class); - - if (gobject_class->dispose) - (* gobject_class->dispose) (object); -} - -/* - * IMPLEMENTATION NOTES: - * Some people sent questions regarding a missing dispose/finalize function on - * this widget that could lead to leak memory, so we will clarify this topic. - * - * This is not required as #HildonTouchSelector extends #GtkContainer. When the - * widget is freed, the #GtkContainer freeing memory functions are called. This - * process includes remove each widget individually, so all the widgets are - * properly freed. - * - * In the same way, this widget redefines gtk_container->remove function, in - * order to free the column related information if it is required. - * - * Please take a look to hildon_touch_selector_remove for more information. - */ - -/*------------------------------ GtkContainer ------------------------------ */ - -/* - * Required in order to free the column at the columns list - */ -static void -hildon_touch_selector_remove (GtkContainer * container, GtkWidget * widget) -{ - HildonTouchSelector *selector = NULL; - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (container)); - selector = HILDON_TOUCH_SELECTOR (container); - - /* Remove the extra data related to the columns, if required. */ - if (widget == selector->priv->hbox) { - g_slist_foreach (selector->priv->columns, (GFunc) g_object_unref, NULL); - - g_slist_free (selector->priv->columns); - - selector->priv->columns = NULL; - } else { - g_debug ("Freeing a widget outside the columns logic"); - } - - /* Now remove the widget itself from the container */ - GTK_CONTAINER_CLASS (hildon_touch_selector_parent_class)->remove (container, widget); -} - -/* ------------------------------ PRIVATE METHODS ---------------------------- */ -void -hildon_touch_selector_block_changed (HildonTouchSelector *selector) -{ - selector->priv->changed_blocked = TRUE; -} - -void -hildon_touch_selector_unblock_changed (HildonTouchSelector *selector) -{ - selector->priv->changed_blocked = FALSE; -} - -static void -hildon_touch_selector_emit_value_changed (HildonTouchSelector *selector, - gint column) -{ - if (!selector->priv->changed_blocked) { - g_signal_emit (selector, hildon_touch_selector_signals[CHANGED], 0, column); - } -} - -/** - * default_print_func: - * @selector: a #HildonTouchSelector - * - * Default print function - * - * Returns: a new string that represents the selected items - * - * Since: 2.2 - **/ -static gchar * -_default_print_func (HildonTouchSelector * selector, gpointer user_data) -{ - gchar *result = NULL; - gchar *aux = NULL; - gint num_columns = 0; - GtkTreeIter iter; - GtkTreeModel *model = NULL; - gchar *current_string = NULL; - gint i; - HildonTouchSelectorSelectionMode mode; - GList *item = NULL; - GtkTreePath *current_path = NULL; - GList *selected_rows = NULL; - gint initial_value = 0; - gint text_column = -1; - HildonTouchSelectorColumn *column = NULL; - - num_columns = hildon_touch_selector_get_num_columns (selector); - - mode = hildon_touch_selector_get_column_selection_mode (selector); - - if ((mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE) - && (num_columns > 0)) { - /* In this case we get the first column first */ - selected_rows = hildon_touch_selector_get_selected_rows (selector, 0); - model = hildon_touch_selector_get_model (selector, 0); - column = hildon_touch_selector_get_column (selector, 0); - g_object_get (G_OBJECT(column), "text-column", &text_column, NULL); - - result = g_strdup_printf ("("); - i = 0; - for (item = selected_rows; item; item = g_list_next (item)) { - current_path = item->data; - gtk_tree_model_get_iter (model, &iter, current_path); - - if (text_column != -1) { - gtk_tree_model_get (model, &iter, text_column, ¤t_string, -1); - } - - if (i < g_list_length (selected_rows) - 1) { - aux = g_strconcat (result, current_string, ",", NULL); - g_free (result); - result = aux; - } else { - aux = g_strconcat (result, current_string, NULL); - g_free (result); - result = aux; - } - - if (current_string) { - g_free (current_string); - current_string = NULL; - } - - i++; - } - - aux = g_strconcat (result, ")", NULL); - g_free (result); - result = aux; - - g_list_foreach (selected_rows, (GFunc) (gtk_tree_path_free), NULL); - g_list_free (selected_rows); - initial_value = 1; - } else { - initial_value = 0; - } - - for (i = initial_value; i < num_columns; i++) { - model = hildon_touch_selector_get_model (selector, i); - column = hildon_touch_selector_get_column (selector, i); - g_object_get (G_OBJECT(column), "text-column", &text_column, NULL); - - if (hildon_touch_selector_get_selected (selector, i, &iter)) { - if (text_column == -1 ) { - g_warning ("Trying to use the default print function in HildonTouchSelector, but " - "\"text-column\" property is not set for HildonTouchSelectorColumn %p.", column); - current_string = NULL; - } else { - gtk_tree_model_get (model, &iter, text_column, ¤t_string, -1); - } - - if (i == 0) { - result = current_string; - } else { - aux = g_strconcat (result, ":", current_string, NULL); - g_free (result); - g_free (current_string); - current_string = NULL; - result = aux; - } - } - } - - return result; -} - -static void -_row_tapped_cb (GtkTreeView * tree_view, GtkTreePath * path, gpointer user_data) -{ - HildonTouchSelector *selector = NULL; - HildonTouchSelectorColumn *column = NULL; - gint num_column = -1; - - column = HILDON_TOUCH_SELECTOR_COLUMN (user_data); - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (column->priv->parent)); - - selector = column->priv->parent; - - num_column = g_slist_index (selector->priv->columns, column); - - hildon_touch_selector_emit_value_changed (selector, num_column); -} - - -static HildonTouchSelectorColumn * -_create_new_column (HildonTouchSelector * selector, - GtkTreeModel * model, - gboolean *emit_changed, - GtkCellRenderer * renderer, va_list args) -{ - HildonTouchSelectorColumn *new_column = NULL; - GtkTreeViewColumn *tree_column = NULL; - GtkTreeView *tv = NULL; - GtkWidget *panarea = NULL; - GtkTreeSelection *selection = NULL; - GtkTreeIter iter; - gchar *attribute; - gint value; - - tree_column = gtk_tree_view_column_new (); - - if (renderer != NULL) { - gtk_tree_view_column_pack_start (tree_column, renderer, TRUE); - - attribute = va_arg (args, gchar *); - while (attribute != NULL) { - value = va_arg (args, gint); - gtk_tree_view_column_add_attribute (tree_column, renderer, attribute, - value); - attribute = va_arg (args, gchar *); - } - } - -#ifdef MAEMO_GTK - tv = GTK_TREE_VIEW (hildon_gtk_tree_view_new (HILDON_UI_MODE_EDIT)); -#else - tv = GTK_TREE_VIEW (gtk_tree_view_new ()); -#endif /* MAEMO_GTK */ - - gtk_tree_view_set_enable_search (tv, FALSE); - GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (tv), GTK_CAN_FOCUS); - - gtk_tree_view_set_model (tv, model); - gtk_tree_view_set_rules_hint (tv, TRUE); - - gtk_tree_view_append_column (GTK_TREE_VIEW (tv), tree_column); - - new_column = g_object_new (HILDON_TYPE_TOUCH_SELECTOR_COLUMN, NULL); - new_column->priv->parent = selector; - - panarea = hildon_pannable_area_new (); - - g_object_set (G_OBJECT (panarea), - "initial-hint", FALSE, NULL); - - gtk_container_add (GTK_CONTAINER (panarea), GTK_WIDGET (tv)); - - new_column->priv->model = model; - new_column->priv->tree_view = tv; - new_column->priv->panarea = panarea; - new_column->priv->realize_handler = 0; - new_column->priv->initial_path = NULL; - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv)); - gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE); - - /* select the first item */ - *emit_changed = FALSE; - if (gtk_tree_model_get_iter_first (model, &iter)) { - gtk_tree_selection_select_iter (selection, &iter); - *emit_changed = TRUE; - } - - gtk_widget_grab_focus (GTK_WIDGET (tv)); - - /* connect to the hildon-row-tapped signal connection */ - g_signal_connect (G_OBJECT (tv), "hildon-row-tapped", - G_CALLBACK (_row_tapped_cb), new_column); - - return new_column; -} - - -/* ------------------------ HildonTouchSelectorColumn implementation ---------------------- */ -G_DEFINE_TYPE_WITH_CODE (HildonTouchSelectorColumn, hildon_touch_selector_column, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT, - hildon_touch_selector_column_cell_layout_init)) - -enum -{ - PROP_TEXT_COLUMN = 1 -}; - -static void -hildon_touch_selector_column_class_init (HildonTouchSelectorColumnClass *klass); - -static void -hildon_touch_selector_column_get_property (GObject *object, guint property_id, - GValue *value, GParamSpec *pspec); - -static void -hildon_touch_selector_column_set_property (GObject *object, guint property_id, - const GValue *value, GParamSpec *pspec); - -static void -hildon_touch_selector_column_set_text_column (HildonTouchSelectorColumn *column, - gint text_column); -static gint -hildon_touch_selector_column_get_text_column (HildonTouchSelectorColumn *column); - - -static void -hildon_touch_selector_column_class_init (HildonTouchSelectorColumnClass *klass) -{ - GObjectClass *gobject_class = NULL; - - gobject_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (gobject_class, sizeof (HildonTouchSelectorColumnPrivate)); - - /* GObject */ - gobject_class->get_property = hildon_touch_selector_column_get_property; - gobject_class->set_property = hildon_touch_selector_column_set_property; - - g_object_class_install_property (G_OBJECT_CLASS(klass), - PROP_TEXT_COLUMN, - g_param_spec_int ("text-column", - "Text Column", - "A column in the data source model to get the strings from.", - -1, - G_MAXINT, - -1, - G_PARAM_READWRITE)); -} - -static void -hildon_touch_selector_column_init (HildonTouchSelectorColumn *column) -{ - column->priv = G_TYPE_INSTANCE_GET_PRIVATE (column, HILDON_TYPE_TOUCH_SELECTOR_COLUMN, - HildonTouchSelectorColumnPrivate); - column->priv->text_column = -1; -} - -static void -hildon_touch_selector_column_set_text_column (HildonTouchSelectorColumn *column, - gint text_column) -{ - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (column)); - g_return_if_fail (text_column >= -1); - - column->priv->text_column = text_column; - - g_object_notify (G_OBJECT (column), "text-column"); -} - -static gint -hildon_touch_selector_column_get_text_column (HildonTouchSelectorColumn *column) -{ - g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (column), -1); - - return column->priv->text_column; -} - -static void -hildon_touch_selector_column_get_property (GObject *object, guint property_id, - GValue *value, GParamSpec *pspec) -{ - switch (property_id) { - case PROP_TEXT_COLUMN: - g_value_set_int (value, - hildon_touch_selector_column_get_text_column (HILDON_TOUCH_SELECTOR_COLUMN (object))); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - -static void -hildon_touch_selector_column_set_property (GObject *object, guint property_id, - const GValue *value, GParamSpec *pspec) -{ - switch (property_id) { - case PROP_TEXT_COLUMN: - hildon_touch_selector_column_set_text_column (HILDON_TOUCH_SELECTOR_COLUMN (object), - g_value_get_int (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - -/* ------------------------ GtkCellLayout implementation -------------------- */ -static void -hildon_touch_selector_column_cell_layout_init (GtkCellLayoutIface *iface) -{ - iface->pack_start = hildon_touch_selector_column_cell_layout_pack_start; - iface->pack_end = hildon_touch_selector_column_cell_layout_pack_end; - iface->clear = hildon_touch_selector_column_cell_layout_clear; - iface->add_attribute = hildon_touch_selector_column_cell_layout_add_attribute; - iface->set_cell_data_func = hildon_touch_selector_column_cell_layout_set_cell_data_func; - iface->clear_attributes = hildon_touch_selector_column_cell_layout_clear_attributes; - iface->reorder = hildon_touch_selector_column_cell_layout_reorder; - iface->get_cells = hildon_touch_selector_column_cell_layout_get_cells; -} - -static void -hildon_touch_selector_column_cell_layout_pack_start (GtkCellLayout *cell_layout, - GtkCellRenderer *cell, - gboolean expand) -{ - HildonTouchSelectorColumn *sel_column = NULL; - GtkTreeViewColumn *view_column = NULL; - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout)); - sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout); - - view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0); - - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT(view_column), cell, expand); - -} - -static void -hildon_touch_selector_column_cell_layout_pack_end (GtkCellLayout *cell_layout, - GtkCellRenderer *cell, - gboolean expand) -{ - HildonTouchSelectorColumn *sel_column = NULL; - GtkTreeViewColumn *view_column = NULL; - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout)); - sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout); - - view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0); - - gtk_cell_layout_pack_end (GTK_CELL_LAYOUT(view_column), cell, expand); -} - -static void -hildon_touch_selector_column_cell_layout_clear (GtkCellLayout *cell_layout) -{ - HildonTouchSelectorColumn *sel_column = NULL; - GtkTreeViewColumn *view_column = NULL; - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout)); - sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout); - - view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0); - - gtk_cell_layout_clear (GTK_CELL_LAYOUT(view_column)); -} - -static void -hildon_touch_selector_column_cell_layout_add_attribute (GtkCellLayout *cell_layout, - GtkCellRenderer *cell, - const gchar *attribute, - gint column) -{ - HildonTouchSelectorColumn *sel_column = NULL; - GtkTreeViewColumn *view_column = NULL; - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout)); - sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout); - - view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0); - - gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT(view_column), cell, attribute, column); -} - - -static void -hildon_touch_selector_column_cell_layout_set_cell_data_func (GtkCellLayout *cell_layout, - GtkCellRenderer *cell, - GtkCellLayoutDataFunc func, - gpointer func_data, - GDestroyNotify destroy) -{ - HildonTouchSelectorColumn *sel_column = NULL; - GtkTreeViewColumn *view_column = NULL; - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout)); - sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout); - - view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0); - - gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT(view_column), cell, func, - func_data, destroy); -} - -static void -hildon_touch_selector_column_cell_layout_clear_attributes (GtkCellLayout *cell_layout, - GtkCellRenderer *cell) -{ - HildonTouchSelectorColumn *sel_column = NULL; - GtkTreeViewColumn *view_column = NULL; - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout)); - sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout); - - view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0); - - gtk_cell_layout_clear_attributes (GTK_CELL_LAYOUT (view_column), cell); -} - -static void -hildon_touch_selector_column_cell_layout_reorder (GtkCellLayout *cell_layout, - GtkCellRenderer *cell, - gint position) -{ - HildonTouchSelectorColumn *sel_column = NULL; - GtkTreeViewColumn *view_column = NULL; - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout)); - sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout); - - view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0); - - gtk_cell_layout_reorder (GTK_CELL_LAYOUT(view_column), cell, position); -} - -static GList* -hildon_touch_selector_column_cell_layout_get_cells (GtkCellLayout *cell_layout) -{ - HildonTouchSelectorColumn *sel_column = NULL; - GtkTreeViewColumn *view_column = NULL; - - g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout), NULL); - sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout); - - view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0); - - return gtk_cell_layout_get_cells (GTK_CELL_LAYOUT(view_column)); -} - -/* ------------------------------ PUBLIC METHODS ---------------------------- */ - -/** - * hildon_touch_selector_new: - * - * Creates a new empty #HildonTouchSelector. - * - * Returns: a new #HildonTouchSelector. - * - * Since: 2.2 - **/ -GtkWidget * -hildon_touch_selector_new (void) -{ - return g_object_new (HILDON_TYPE_TOUCH_SELECTOR, NULL); -} - -/** - * hildon_touch_selector_new_text: - * - * Creates a #HildonTouchSelector with a single text column that - * can be populated conveniently through hildon_touch_selector_append_text(), - * hildon_touch_selector_prepend_text(), hildon_touch_selector_insert_text(). - * - * Returns: A new #HildonTouchSelector - * - * Since: 2.2 - **/ -GtkWidget * -hildon_touch_selector_new_text (void) -{ - GtkWidget *selector; - GtkListStore *store; - HildonTouchSelectorColumn *column = NULL; - - selector = hildon_touch_selector_new (); - store = gtk_list_store_new (1, G_TYPE_STRING); - - column = hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), - GTK_TREE_MODEL (store), TRUE); - - g_object_set (G_OBJECT (column), "text-column", 0, NULL); - - return selector; -} - -/** - * hildon_touch_selector_append_text: - * @selector: A #HildonTouchSelector. - * @text: a non %NULL text string. - * - * Appends a new entry in a #HildonTouchSelector created with - * hildon_touch_selector_new_text(). - * - * Since: 2.2 - **/ -void -hildon_touch_selector_append_text (HildonTouchSelector * selector, - const gchar * text) -{ - GtkTreeIter iter; - GtkTreeModel *model; - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); - g_return_if_fail (text != NULL); - - model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0); - - g_return_if_fail (GTK_IS_LIST_STORE (model)); - - gtk_list_store_append (GTK_LIST_STORE (model), &iter); - gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, text, -1); -} - -/** - * hildon_touch_selector_prepend_text: - * @selector: A #HildonTouchSelector. - * @text: a non %NULL text string. - * - * Prepends a new entry in a #HildonTouchSelector created with - * hildon_touch_selector_new_text(). - * - * Since: 2.2 - **/ -void -hildon_touch_selector_prepend_text (HildonTouchSelector * selector, - const gchar * text) -{ - GtkTreeIter iter; - GtkTreeModel *model; - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); - g_return_if_fail (text != NULL); - - model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0); - - g_return_if_fail (GTK_IS_LIST_STORE (model)); - - gtk_list_store_prepend (GTK_LIST_STORE (model), &iter); - gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, text, -1); -} - -/** - * hildon_touch_selector_insert_text: - * @selector: a #HildonTouchSelector. - * @position: the position to insert @text. - * @text: A non %NULL text string. - * - * Inserts a new entry in a particular position of a - * #HildonTouchSelector created with hildon_touch_selector_new_text(). - * - * Since: 2.2 - **/ -void -hildon_touch_selector_insert_text (HildonTouchSelector * selector, - gint position, const gchar * text) -{ - GtkTreeIter iter; - GtkTreeModel *model; - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); - g_return_if_fail (text != NULL); - g_return_if_fail (position >= 0); - - model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0); - - g_return_if_fail (GTK_IS_LIST_STORE (model)); - - gtk_list_store_insert (GTK_LIST_STORE (model), &iter, position); - gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, text, -1); -} - -/** - * hildon_touch_selector_append_column - * @selector: a #HildonTouchSelector - * @model: the #GtkTreeModel with the data of the column - * @cell_renderer: The #GtkCellRenderer where to draw each row contents. - * @Varargs: a %NULL-terminated pair of attributes and column numbers. - * - * This functions adds a new column to the widget, whose data will - * be obtained from the model. Only widgets added this way should used on - * the selection logic, i.e., the print function, the #HildonTouchPicker::changed - * signal, etc. - * - * You can optionally pass a #GtkCellRenderer in @cell_renderer, - * together with a %NULL-terminated list of pairs property/value, in - * the same way you would use gtk_tree_view_column_set_attributes(). - * This will pack @cell_renderer at the start of the column, expanded by default. - * If you prefer not to add it this way, you can simply pass %NULL to @cell_renderer - * and use the #GtkCellLayout interface on the returned #HildonTouchSelectorColumn - * to set your renderers. - * - * There is a prerequisite to be considered on models used: text data must - * be in the first column. - * - * This method basically adds a #GtkTreeView to the widget, using the model and - * the data received. - * - * Returns: the new column added added, %NULL otherwise. - * - * Since: 2.2 - **/ - -HildonTouchSelectorColumn* -hildon_touch_selector_append_column (HildonTouchSelector * selector, - GtkTreeModel * model, - GtkCellRenderer * cell_renderer, ...) -{ - va_list args; - HildonTouchSelectorColumn *new_column = NULL; - gboolean emit_changed = FALSE; - gint colnum; - - g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL); - g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL); - - if (model != NULL) { - - va_start (args, cell_renderer); - new_column = _create_new_column (selector, model, &emit_changed, cell_renderer, args); - va_end (args); - - selector->priv->columns = g_slist_append (selector->priv->columns, - new_column); - gtk_box_pack_start (GTK_BOX (selector->priv->hbox), - new_column->priv->panarea, - TRUE, TRUE, 6); - - gtk_widget_show_all (new_column->priv->panarea); - - if (selector->priv->initial_scroll) { - _hildon_touch_selector_center_on_selected_items (selector, new_column); - } - - } else { - return NULL; - } - - g_signal_emit (selector, hildon_touch_selector_signals[COLUMNS_CHANGED], 0); - if (emit_changed) { - colnum = g_slist_length (selector->priv->columns); - hildon_touch_selector_emit_value_changed (selector, colnum); - } - - return new_column; -} - -/** - * hildon_touch_selector_append_text_column - * @selector: a #HildonTouchSelector - * @model: a #GtkTreeModel with data for the column - * @center: whether to center the text on the column - * - * Equivalent to hildon_touch_selector_append_column(), but using a - * default text cell renderer. This is the most common use case of the - * widget. - * - * Returns: the new column added, NULL otherwise. - * - * Since: 2.2 - **/ -HildonTouchSelectorColumn* -hildon_touch_selector_append_text_column (HildonTouchSelector * selector, - GtkTreeModel * model, gboolean center) -{ - gfloat xalign = center ? 0.5 : 0.0; - GtkCellRenderer *renderer; - - g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL); - g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL); - - renderer = gtk_cell_renderer_text_new (); - - g_object_set (renderer, - "width", 1, - "xalign", xalign, - NULL); - - return hildon_touch_selector_append_column (selector, model, renderer, - "text", 0, NULL); -} - -/** - * hildon_touch_selector_remove_column: - * @selector: a #HildonTouchSelector - * @column: the position of the column to be removed - * - * Removes a column from @selector. - * - * Returns: %TRUE if the column was removed, %FALSE otherwise - * - * Since: 2.2 - **/ -gboolean -hildon_touch_selector_remove_column (HildonTouchSelector * selector, gint column) -{ - HildonTouchSelectorColumn *current_column = NULL; - HildonTouchSelectorPrivate *priv; - - g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE); - g_return_val_if_fail (column < - hildon_touch_selector_get_num_columns (selector), FALSE); - - priv = HILDON_TOUCH_SELECTOR_GET_PRIVATE (selector); - current_column = g_slist_nth_data (priv->columns, column); - - gtk_container_remove (GTK_CONTAINER (priv->hbox), current_column->priv->panarea); - priv->columns = g_slist_remove (priv->columns, current_column); - g_object_unref (current_column); - - g_signal_emit (selector, hildon_touch_selector_signals[COLUMNS_CHANGED], 0); - - return TRUE; -} - -/** - * hildon_touch_selector_set_column_attributes: - * @selector: a #HildonTouchSelector - * @num_column: the number of the column whose attributes we're setting - * @cell_renderer: the #GtkCellRendere we're setting the attributes of - * @Varargs: A %NULL-terminated list of attributes. - * - * Sets the attributes for the given column. The attributes must be given - * in attribute/column pairs, just like in gtk_tree_view_column_set_attributes(). - * All existing attributes are removed and replaced with the new ones. - * - * Deprecated: #HildonTouchSelectorColumn implements #GtkCellLayout, use this - * interface instead. See - * hildon_touch_selector_get_column(). - * - * Since: 2.2 - **/ -void -hildon_touch_selector_set_column_attributes (HildonTouchSelector * selector, - gint num_column, - GtkCellRenderer * cell_renderer, - ...) -{ - va_list args; - GtkTreeViewColumn *tree_column = NULL; - HildonTouchSelectorColumn *current_column = NULL; - gchar *attribute = NULL; - gint value = 0; - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); - g_return_if_fail (num_column < - hildon_touch_selector_get_num_columns (selector)); - - current_column = g_slist_nth_data (selector->priv->columns, num_column); - - tree_column = gtk_tree_view_get_column (current_column->priv->tree_view, 0); - gtk_tree_view_remove_column (current_column->priv->tree_view, tree_column); - - tree_column = gtk_tree_view_column_new (); - gtk_tree_view_column_pack_start (tree_column, cell_renderer, TRUE); - - va_start (args, cell_renderer); - attribute = va_arg (args, gchar *); - - gtk_tree_view_column_clear_attributes (tree_column, cell_renderer); - - while (attribute != NULL) { - value = va_arg (args, gint); - gtk_tree_view_column_add_attribute (tree_column, cell_renderer, - attribute, value); - attribute = va_arg (args, gchar *); - } - - va_end (args); - - gtk_tree_view_append_column (current_column->priv->tree_view, tree_column); -} - -/** - * hildon_touch_selector_get_num_columns: - * @selector: a #HildonTouchSelector - * - * Gets the number of columns in the #HildonTouchSelector. - * - * Returns: the number of columns in @selector. - * - * Since: 2.2 - **/ -gint -hildon_touch_selector_get_num_columns (HildonTouchSelector * selector) -{ - g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), -1); - - return g_slist_length (selector->priv->columns); -} - -/** - * hildon_touch_selector_get_column_selection_mode: - * @selector: a #HildonTouchSelector - * - * Gets the selection mode of @selector. - * - * Returns: one of #HildonTouchSelectorSelectionMode - * - * Since: 2.2 - **/ -HildonTouchSelectorSelectionMode -hildon_touch_selector_get_column_selection_mode (HildonTouchSelector * selector) -{ - HildonTouchSelectorSelectionMode result = - HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE; - GtkSelectionMode treeview_mode = GTK_SELECTION_BROWSE; - HildonTouchSelectorColumn *column = NULL; - GtkTreeSelection *selection = NULL; - - g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), result); - g_return_val_if_fail (hildon_touch_selector_get_num_columns (selector) > 0, - result); - - column = HILDON_TOUCH_SELECTOR_COLUMN (selector->priv->columns->data); - - selection = gtk_tree_view_get_selection (column->priv->tree_view); - treeview_mode = gtk_tree_selection_get_mode (selection); - - - if (treeview_mode == GTK_SELECTION_MULTIPLE) { - result = HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE; - } else { - result = HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE; - } - - return result; -} - -/** - * hildon_touch_selector_set_column_selection_mode: - * @selector: a #HildonTouchSelector - * @mode: the #HildonTouchSelectorMode for @selector - * - * Sets the selection mode for @selector. See #HildonTouchSelectorSelectionMode. - * - * Since: 2.2 - **/ -void -hildon_touch_selector_set_column_selection_mode (HildonTouchSelector * selector, - HildonTouchSelectorSelectionMode mode) -{ - GtkTreeView *tv = NULL; - HildonTouchSelectorColumn *column = NULL; - GtkTreeSelection *selection = NULL; - GtkSelectionMode treeview_mode = GTK_SELECTION_MULTIPLE; - GtkTreeIter iter; - HildonTouchSelectorSelectionMode current_mode; - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); - g_return_if_fail (hildon_touch_selector_get_num_columns (selector) > 0); - - current_mode = hildon_touch_selector_get_column_selection_mode (selector); - - if (current_mode == mode) { - return; - } - - column = HILDON_TOUCH_SELECTOR_COLUMN ((g_slist_nth (selector->priv->columns, 0))->data); - tv = column->priv->tree_view; - - if (tv) { - switch (mode) { - case HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE: - treeview_mode = GTK_SELECTION_BROWSE; - break; - case HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE: - treeview_mode = GTK_SELECTION_MULTIPLE; - break; - } - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv)); - gtk_tree_selection_set_mode (selection, treeview_mode); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv)); - gtk_tree_model_get_iter_first (column->priv->model, &iter); - gtk_tree_selection_unselect_all (selection); - gtk_tree_selection_select_iter (selection, &iter); - - /* the column changed was the first one */ - hildon_touch_selector_emit_value_changed (selector, 0); - } - -} - -/** - * hildon_touch_selector_set_print_func: - * @selector: a #HildonTouchSelector - * @func: a #HildonTouchSelectorPrintFunc function - * - * Sets the function to be used by hildon_touch_selector_get_current_text() - * to produce a text representation of the currently selected items in @selector. - * The default function will return a concatenation of comma separated items - * selected in each column in @selector. Use this to override this method if you - * need a particular representation for your application. - * - * Since: 2.2 - **/ -void -hildon_touch_selector_set_print_func (HildonTouchSelector * selector, - HildonTouchSelectorPrintFunc func) -{ - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); - - hildon_touch_selector_set_print_func_full (selector, func, NULL, NULL); -} - -/** - * hildon_touch_selector_set_print_func_full: - * @selector: a #HildonTouchSelector - * @func: a #HildonTouchSelectorPrintFunc function - * @user_data: a pointer to user data or %NULL - * @destroy_func: a callback for freeing the user data or %NULL - * - * Sets the function to be used by hildon_touch_selector_get_current_text() - * to produce a text representation of the currently selected items in @selector. - * The default function will return a concatenation of comma separated items - * selected in each column in @selector. Use this to override this method if you - * need a particular representation for your application. - * - * Since: 2.2 - **/ -void -hildon_touch_selector_set_print_func_full (HildonTouchSelector *selector, - HildonTouchSelectorPrintFunc func, - gpointer user_data, - GDestroyNotify destroy_func) -{ - gpointer old_user_data; - GDestroyNotify old_destroy_func; - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); - - old_user_data = selector->priv->print_user_data; - old_destroy_func = selector->priv->print_destroy_func; - - selector->priv->print_func = func; - selector->priv->print_user_data = user_data; - selector->priv->print_destroy_func = destroy_func; - - if (old_destroy_func && old_user_data != user_data) - (*old_destroy_func) (old_user_data); -} - -/** - * hildon_touch_selector_get_print_func: - * @selector: a #HildonTouchSelector - * - * Gets the #HildonTouchSelectorPrintFunc currently used. See - * hildon_touch_selector_set_print_func(). - * - * Returns: a #HildonTouchSelectorPrintFunc or %NULL if the default - * one is currently used. - **/ -HildonTouchSelectorPrintFunc -hildon_touch_selector_get_print_func (HildonTouchSelector * selector) -{ - g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL); - - return selector->priv->print_func; -} - -/** - * hildon_touch_selector_set_active: - * @selector: a #HildonTouchSelector - * @column: column number - * @index: the index of the item to select, or -1 to have no active item - * - * Sets the active item of the #HildonTouchSelector to @index. The - * column number is taken from @column. - * - * @selector must be in %HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE - * - * Since: 2.2 - **/ -void -hildon_touch_selector_set_active (HildonTouchSelector *selector, - gint column, - gint index) -{ - GtkTreeSelection *selection = NULL; - HildonTouchSelectorColumn *current_column = NULL; - HildonTouchSelectorSelectionMode mode; - GtkTreePath *path; - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); - g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector)); - mode = hildon_touch_selector_get_column_selection_mode (selector); - g_return_if_fail (mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE); - - current_column = g_slist_nth_data (selector->priv->columns, column); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (current_column->priv->tree_view)); - path = gtk_tree_path_new_from_indices (index, -1); - gtk_tree_selection_unselect_all (selection); - if (index != -1) - gtk_tree_selection_select_path (selection, path); - - hildon_touch_selector_emit_value_changed (selector, column); - - gtk_tree_path_free (path); -} - -/** - * hildon_touch_selector_get_active: - * @selector: a #HildonTouchSelector - * @column: column number - * - * Returns the index of the currently active item in column number - * @column, or -1 if there's no active item. - * - * @selector must be in %HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE - * - * Returns: an integer which is the index of the currently active - * item, or -1 if there's no active item. - * - * Since: 2.2 - **/ -gint -hildon_touch_selector_get_active (HildonTouchSelector *selector, - gint column) -{ - GtkTreeSelection *selection = NULL; - HildonTouchSelectorColumn *current_column = NULL; - HildonTouchSelectorSelectionMode mode; - GtkTreeModel *model; - GtkTreeIter iter; - GtkTreePath *path; - gint index; - - g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), -1); - g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector), -1); - mode = hildon_touch_selector_get_column_selection_mode (selector); - g_return_val_if_fail (mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE, -1); - - current_column = g_slist_nth_data (selector->priv->columns, column); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (current_column->priv->tree_view)); - g_return_val_if_fail (gtk_tree_selection_get_selected (selection, NULL, &iter), -1); - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (current_column->priv->tree_view)); - path = gtk_tree_model_get_path (model, &iter); - index = (gtk_tree_path_get_indices (path))[0]; - - gtk_tree_path_free (path); - - return index; -} - -/** - * hildon_touch_selector_get_selected: - * @selector: a #HildonTouchSelector - * @column: the column number we want to get the element - * @iter: #GtkTreeIter currently selected - * - * Sets @iter to the currently selected node on the nth-column, if selection is - * set to %HILDON_TOUCH_SELECTOR_SINGLE or %HILDON_TOUCH_SELECTOR_MULTIPLE with - * a column different that the first one. @iter may be %NULL if you just want to - * test if selection has any selected items. - * - * This function will not work if selection is in - * %HILDON_TOUCH_SELECTOR_MULTIPLE mode and the column is the first one. - * - * See gtk_tree_selection_get_selected() for more information. - * - * Returns: %TRUE if @iter was correctly set, %FALSE otherwise - * - * Since: 2.2 - **/ -gboolean -hildon_touch_selector_get_selected (HildonTouchSelector * selector, - gint column, GtkTreeIter * iter) -{ - GtkTreeSelection *selection = NULL; - HildonTouchSelectorColumn *current_column = NULL; - HildonTouchSelectorSelectionMode mode; - - g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE); - g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector), - FALSE); - mode = hildon_touch_selector_get_column_selection_mode (selector); - g_return_val_if_fail - ((mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE) || - ((mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)&&(column>0)), - FALSE); - - current_column = g_slist_nth_data (selector->priv->columns, column); - - selection = - gtk_tree_view_get_selection (GTK_TREE_VIEW (current_column->priv->tree_view)); - - return gtk_tree_selection_get_selected (selection, NULL, iter); -} - -/** - * hildon_touch_selector_select_iter - * @selector: a #HildonTouchSelector - * @column: the column to selects - * @iter: the #GtkTreeIter to be selected - * @scroll_to: whether to smoothly scroll to the item - * - * Sets the currently selected item in the column @column to the one pointed by @iter, - * optionally smoothly scrolling to it. - * - * Since: 2.2 - **/ -void -hildon_touch_selector_select_iter (HildonTouchSelector * selector, - gint column, GtkTreeIter * iter, - gboolean scroll_to) -{ - GtkTreePath *path; - GtkTreeModel *model; - HildonTouchSelectorColumn *current_column = NULL; - GtkTreeView *tv = NULL; - GtkTreeSelection *selection = NULL; - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); - g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector)); - - current_column = g_slist_nth_data (selector->priv->columns, column); - - tv = current_column->priv->tree_view; - selection = gtk_tree_view_get_selection (tv); - model = gtk_tree_view_get_model (tv); - path = gtk_tree_model_get_path (model, iter); - - gtk_tree_selection_select_iter (selection, iter); - - if (scroll_to) { - hildon_touch_selector_scroll_to (current_column, tv, path); - } - - hildon_touch_selector_emit_value_changed (selector, column); - - gtk_tree_path_free (path); -} - -/** - * hildon_touch_selector_unselect_iter - * @selector: a #HildonTouchSelector - * @column: the column to unselects from - * @iter: the #GtkTreeIter to be unselected - * - * Unselect the item pointed by @iter in the column @column - * - * Since: 2.2 - **/ - -void hildon_touch_selector_unselect_iter (HildonTouchSelector * selector, - gint column, - GtkTreeIter * iter) -{ - HildonTouchSelectorColumn *current_column = NULL; - GtkTreeSelection *selection = NULL; - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); - g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector)); - - current_column = g_slist_nth_data (selector->priv->columns, column); - selection = gtk_tree_view_get_selection (current_column->priv->tree_view); - gtk_tree_selection_unselect_iter (selection, iter); - - hildon_touch_selector_emit_value_changed (selector, column); -} - -/** - * hildon_touch_selector_unselect_all: - * @selector: a #HildonTouchSelector - * @column: the position of the column to get the selected rows from - * - * Unselects all the selected items in the column @column. - * - * Since: 2.2 - **/ -void -hildon_touch_selector_unselect_all (HildonTouchSelector * selector, - gint column) -{ - HildonTouchSelectorColumn *current_column = NULL; - GtkTreeSelection *selection = NULL; - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); - g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector)); - - current_column = g_slist_nth_data (selector->priv->columns, column); - selection = gtk_tree_view_get_selection (current_column->priv->tree_view); - gtk_tree_selection_unselect_all (selection); - - hildon_touch_selector_emit_value_changed (selector, column); -} - -/** - * hildon_touch_selector_get_selected_rows: - * @selector: a #HildonTouchSelector - * @column: the position of the column to get the selected rows from - * - * Creates a list of #GtkTreePaths of all selected rows in a column. Additionally, - * if you to plan to modify the model after calling this function, you may - * want to convert the returned list into a list of GtkTreeRowReferences. To do this, - * you can use gtk_tree_row_reference_new(). - * - * See gtk_tree_selection_get_selected_rows() for more information. - * - * Returns: A new #GList containing a #GtkTreePath for each selected row in the column @column. - * - * Since: 2.2 - **/ -GList * -hildon_touch_selector_get_selected_rows (HildonTouchSelector * selector, - gint column) -{ - GList *result = NULL; - HildonTouchSelectorColumn *current_column = NULL; - GtkTreeSelection *selection = NULL; - - g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL); - g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector), - NULL); - - current_column = g_slist_nth_data (selector->priv->columns, column); - selection = gtk_tree_view_get_selection (current_column->priv->tree_view); - - result = gtk_tree_selection_get_selected_rows (selection, NULL); - - return result; -} - -/** - * hildon_touch_selector_get_model: - * @selector: a #HildonTouchSelector - * @column: the position of the column in @selector - * - * Gets the model of a column of @selector. - * - * Returns: the #GtkTreeModel for the column @column of @selector. - * - * Since: 2.2 - **/ -GtkTreeModel * -hildon_touch_selector_get_model (HildonTouchSelector * selector, gint column) -{ - HildonTouchSelectorColumn *current_column = NULL; - - g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL); - g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector), - NULL); - - current_column = g_slist_nth_data (selector->priv->columns, column); - - return current_column->priv->model; -} - -static void -_hildon_touch_selector_set_model (HildonTouchSelector * selector, - gint column, GtkTreeModel * model) -{ - HildonTouchSelectorColumn *current_column = NULL; - - current_column = - HILDON_TOUCH_SELECTOR_COLUMN (g_slist_nth_data (selector->priv->columns, column)); - - current_column->priv->model = model; - gtk_tree_view_set_model (current_column->priv->tree_view, - current_column->priv->model); -} - -/** - * hildon_touch_selector_set_model: - * @selector: a #HildonTouchSelector - * @column: the position of the column to set the model to - * @model: a #GtkTreeModel - * - * Sets the #GtkTreeModel for a particular column in @model. - * - * Since: 2.2 - **/ -void -hildon_touch_selector_set_model (HildonTouchSelector * selector, - gint column, GtkTreeModel * model) -{ - g_return_if_fail (HILDON_TOUCH_SELECTOR (selector)); - g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector)); - - HILDON_TOUCH_SELECTOR_GET_CLASS (selector)->set_model (selector, column, model); -} - -/** - * hildon_touch_selector_get_current_text: - * @selector: a #HildonTouchSelector - * - * Returns a string representing the currently selected items for - * each column of @selector. See hildon_touch_selector_set_print_func(). - * - * Returns: a newly allocated string. - * - * Since: 2.2 - **/ -gchar * -hildon_touch_selector_get_current_text (HildonTouchSelector * selector) -{ - gchar *result = NULL; - g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL); - - if (selector->priv->print_func) { - result = (*selector->priv->print_func) (selector, selector->priv->print_user_data); - } else { - result = _default_print_func (selector, NULL); - } - - return result; -} - -static void -search_nearest_element (HildonPannableArea *panarea, - GtkTreeView *tv, - GList *selected_rows, - GtkTreePath **nearest_path) -{ - GtkAdjustment *adj = NULL; - gdouble target_value = 0; - GdkRectangle rect; - GList *iter = NULL; - GtkTreePath *path = NULL; - gint y = -1; - gdouble nearest_distance = -1; - gdouble current_distance = -1; - GtkTreePath *result_path = NULL; - - g_assert (nearest_path != NULL); - - if (selected_rows == NULL) { - *nearest_path = NULL; - return; - } - - adj = hildon_pannable_area_get_vadjustment (panarea); - g_return_if_fail (adj != NULL); - - /* we add this in order to check the nearest to the center of - the visible area */ - target_value = gtk_adjustment_get_value (adj) + adj->page_size/2; - - path = result_path = selected_rows->data; - gtk_tree_view_get_background_area (tv, path, NULL, &rect); - gtk_tree_view_convert_bin_window_to_tree_coords (tv, 0, rect.y, NULL, &y); - nearest_distance = abs (target_value - y); - - for (iter = selected_rows->next; iter; iter = g_list_next (iter)) { - gtk_tree_view_get_background_area (tv, path, NULL, &rect); - gtk_tree_view_convert_bin_window_to_tree_coords (tv, 0, rect.y, NULL, &y); - current_distance = abs (target_value - y); - if (current_distance < nearest_distance) { - nearest_distance = current_distance; - result_path = path; - } - } - - *nearest_path = result_path; -} - -static gboolean -on_realize_cb (GtkWidget *widget, - gpointer data) -{ - HildonTouchSelectorColumn *column = NULL; - GdkRectangle rect; - gint y; - - column = HILDON_TOUCH_SELECTOR_COLUMN (data); - - if (column->priv->initial_path) { - gtk_tree_view_get_background_area (GTK_TREE_VIEW (column->priv->tree_view), - column->priv->initial_path, NULL, &rect); - gtk_tree_view_convert_bin_window_to_tree_coords - (GTK_TREE_VIEW (column->priv->tree_view), - 0, rect.y, NULL, &y); - - hildon_pannable_area_scroll_to (HILDON_PANNABLE_AREA (column->priv->panarea), - -1, y); - - gtk_tree_path_free (column->priv->initial_path); - - column->priv->initial_path = NULL; - - } - - g_signal_handler_disconnect (column->priv->panarea, - column->priv->realize_handler); - - return FALSE; -} - -static void -hildon_touch_selector_scroll_to (HildonTouchSelectorColumn *column, - GtkTreeView *tv, - GtkTreePath *path) -{ - if (GTK_WIDGET_REALIZED (column->priv->panarea)) { - GdkRectangle rect; - gint y; - - gtk_tree_view_get_background_area (tv, - path, NULL, &rect); - gtk_tree_view_convert_bin_window_to_tree_coords (tv, - 0, rect.y, NULL, &y); - - hildon_pannable_area_scroll_to (HILDON_PANNABLE_AREA - (column->priv->panarea), -1, y); - } else { - if (column->priv->realize_handler != 0) { - - if (column->priv->initial_path) { - gtk_tree_path_free (column->priv->initial_path); - column->priv->initial_path = NULL; - } - - g_signal_handler_disconnect (column->priv->panarea, - column->priv->realize_handler); - column->priv->realize_handler = 0; - } - - column->priv->initial_path = gtk_tree_path_copy (path); - column->priv->realize_handler = - g_signal_connect_after (G_OBJECT (column->priv->panarea), "realize", - G_CALLBACK (on_realize_cb), - column); - } -} - -/** - * - * Center on the selected item of a concrete column - * - * Returns: TRUE if was able to do that - * FALSE otherwise - */ -static gboolean -_hildon_touch_selector_center_on_selected_items (HildonTouchSelector *selector, - HildonTouchSelectorColumn *column) -{ - GtkTreePath *path = NULL; - GList *selected_rows = NULL; - gint num_column = -1; - - num_column = g_slist_index (selector->priv->columns, column); - - selected_rows = hildon_touch_selector_get_selected_rows (selector, num_column); - if (selected_rows) { - search_nearest_element (HILDON_PANNABLE_AREA (column->priv->panarea), - GTK_TREE_VIEW (column->priv->tree_view), - selected_rows, - &path); - - if (path != NULL) { - hildon_touch_selector_scroll_to (column, - GTK_TREE_VIEW (column->priv->tree_view), - path); - } else { - return FALSE; - } - - g_list_foreach (selected_rows, (GFunc) (gtk_tree_path_free), NULL); - g_list_free (selected_rows); - } - - return TRUE; -} - -static gboolean -_hildon_touch_selector_has_multiple_selection (HildonTouchSelector * selector) -{ - HildonTouchSelectorSelectionMode mode; - gint n_columns; - - n_columns = hildon_touch_selector_get_num_columns (selector); - mode = hildon_touch_selector_get_column_selection_mode (selector); - - return ((n_columns > 1) || (mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)); -} - -/** - * hildon_touch_selector_has_multiple_selection: - * @selector: A #HildonTouchSelector - * - * Determines whether @selector is complex enough to actually require an - * extra selection step than only picking an item. This is normally %TRUE - * if @selector has multiple columns, multiple selection, or when it is a - * more complex widget, like #HildonTouchSelectorEntry. - * - * This information is useful for widgets containing a #HildonTouchSelector, - * like #HildonPickerDialog, that could need a "Done" button, in case that - * its internal #HildonTouchSelector has multiple columns, for instance. - * - * Returns: %TRUE if @selector requires multiple selection steps. - * - * Since: 2.2 - **/ -gboolean -hildon_touch_selector_has_multiple_selection (HildonTouchSelector * selector) -{ - g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE); - - return HILDON_TOUCH_SELECTOR_GET_CLASS (selector)->has_multiple_selection (selector); -} - - -/** - * hildon_touch_selector_get_column: - * @selector: A #HildonTouchSelector - * @column: a column number - * - * Use this method to retrieve a #HildonTouchSelectorColumn. Then, you can use - * the #GtkCellLayout interface to set up the layout of the column. - * - * Returns: the @column-th #HildonTouchSelectorColumn in @selector - * - * Since: 2.2 - **/ -HildonTouchSelectorColumn * -hildon_touch_selector_get_column (HildonTouchSelector * selector, - gint column) -{ - gint num_columns = -1; - - g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL); - num_columns = hildon_touch_selector_get_num_columns (selector); - g_return_val_if_fail (column < num_columns && column >= 0, NULL); - - return g_slist_nth_data (selector->priv->columns, column); -} - - -/** - * hildon_touch_selector_center_on_selected: - * @selector: a #HildonTouchSelector - * - * Ensures all the columns in a #HildonTouchSelector show a selected - * item. If one of the columns is in - * %HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE mode, that column - * will be scrolled to ensure the selected item that is closest to the - * currently visible area is shown. - * - * Since: 2.2 - **/ -void -hildon_touch_selector_center_on_selected (HildonTouchSelector *selector) -{ - GSList *iter = NULL; - - g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector)); - - for (iter = selector->priv->columns; iter; iter = g_slist_next (iter)) { - _hildon_touch_selector_center_on_selected_items (selector, - HILDON_TOUCH_SELECTOR_COLUMN (iter->data)); - } -} diff --git a/src/hildon-touch-selector.h b/src/hildon-touch-selector.h deleted file mode 100644 index 14b4d9f..0000000 --- a/src/hildon-touch-selector.h +++ /dev/null @@ -1,220 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2008 Nokia Corporation. - * - * 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; either - * version 2 of the License, or (at your option) any later version. or (at your option) any later version. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __HILDON_TOUCH_SELECTOR_H__ -#define __HILDON_TOUCH_SELECTOR_H__ - -#include -#include "hildon-touch-selector-column.h" - -G_BEGIN_DECLS - -#define HILDON_TYPE_TOUCH_SELECTOR \ - (hildon_touch_selector_get_type ()) - -#define HILDON_TOUCH_SELECTOR(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - HILDON_TYPE_TOUCH_SELECTOR, HildonTouchSelector)) - -#define HILDON_TOUCH_SELECTOR_CLASS(vtable) \ - (G_TYPE_CHECK_CLASS_CAST ((vtable), \ - HILDON_TYPE_TOUCH_SELECTOR, HildonTouchSelectorClass)) - -#define HILDON_IS_TOUCH_SELECTOR(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ - HILDON_TYPE_TOUCH_SELECTOR)) - -#define HILDON_IS_TOUCH_SELECTOR_CLASS(vtable) \ - (G_TYPE_CHECK_CLASS_TYPE ((vtable), HILDON_TYPE_TOUCH_SELECTOR)) - -#define HILDON_TOUCH_SELECTOR_GET_CLASS(inst) \ - (G_TYPE_INSTANCE_GET_CLASS ((inst), \ - HILDON_TYPE_TOUCH_SELECTOR, HildonTouchSelectorClass)) - -typedef struct _HildonTouchSelector HildonTouchSelector; -typedef struct _HildonTouchSelectorClass HildonTouchSelectorClass; -typedef struct _HildonTouchSelectorPrivate HildonTouchSelectorPrivate; - -typedef gchar *(*HildonTouchSelectorPrintFunc) (HildonTouchSelector * selector, - gpointer user_data); - -struct _HildonTouchSelector -{ - GtkVBox parent_instance; - - /*< private > */ - HildonTouchSelectorPrivate *priv; -}; - -struct _HildonTouchSelectorClass -{ - GtkVBoxClass parent_class; - - /* signals */ - void (*changed) (HildonTouchSelector *selector, - gint column); - - /* virtual methods */ - void (*set_model) (HildonTouchSelector *selector, - gint column, - GtkTreeModel *model); - - gboolean (*has_multiple_selection) (HildonTouchSelector *selector); -}; - -/** - * HildonTouchSelectorSelectionMode: - * @HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE: Users can select one item - * @HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE: Users can select one to many items - * - * Describes the selection mode of a #HildonTouchSelector. - **/ -typedef enum -{ - HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE, - HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE -} HildonTouchSelectorSelectionMode; - -/* construction */ -GType -hildon_touch_selector_get_type (void) G_GNUC_CONST; - -GtkWidget * -hildon_touch_selector_new (void); - -/* Simple (and recommended) API for one-text-column selectors. */ -GtkWidget * -hildon_touch_selector_new_text (void); - -void -hildon_touch_selector_append_text (HildonTouchSelector *selector, - const gchar *text); -void -hildon_touch_selector_prepend_text (HildonTouchSelector *selector, - const gchar *text); -void -hildon_touch_selector_insert_text (HildonTouchSelector *selector, - gint position, - const gchar *text); - -/* column related */ -HildonTouchSelectorColumn* -hildon_touch_selector_append_text_column (HildonTouchSelector *selector, - GtkTreeModel * model, - gboolean center); - -HildonTouchSelectorColumn* -hildon_touch_selector_append_column (HildonTouchSelector *selector, - GtkTreeModel *model, - GtkCellRenderer *cell_renderer, - ...); -#ifndef HILDON_DISABLE_DEPRECATED -void -hildon_touch_selector_set_column_attributes (HildonTouchSelector *selector, - gint num_column, - GtkCellRenderer *cell_renderer, - ...); -#endif - -gboolean -hildon_touch_selector_remove_column (HildonTouchSelector *selector, - gint column); - -gint -hildon_touch_selector_get_num_columns (HildonTouchSelector *selector); - -void -hildon_touch_selector_set_column_selection_mode (HildonTouchSelector *selector, - HildonTouchSelectorSelectionMode mode); - -HildonTouchSelectorSelectionMode -hildon_touch_selector_get_column_selection_mode (HildonTouchSelector *selector); - -HildonTouchSelectorColumn * -hildon_touch_selector_get_column (HildonTouchSelector *selector, - gint column); - -/* get/set active item */ -void -hildon_touch_selector_set_active (HildonTouchSelector *selector, - gint column, - gint index); -gint -hildon_touch_selector_get_active (HildonTouchSelector *selector, - gint column); - -gboolean -hildon_touch_selector_get_selected (HildonTouchSelector *selector, - gint column, - GtkTreeIter *iter); - -void -hildon_touch_selector_select_iter (HildonTouchSelector *selector, - gint column, - GtkTreeIter *iter, - gboolean scroll_to); - -void -hildon_touch_selector_unselect_iter (HildonTouchSelector *selector, - gint column, - GtkTreeIter *iter); - -void -hildon_touch_selector_unselect_all (HildonTouchSelector * selector, - gint column); - -GList * -hildon_touch_selector_get_selected_rows (HildonTouchSelector *selector, - gint column); -/* model */ -void -hildon_touch_selector_set_model (HildonTouchSelector *selector, - gint column, - GtkTreeModel *model); -GtkTreeModel * -hildon_touch_selector_get_model (HildonTouchSelector *selector, - gint column); - -/* show the current element selected */ -gchar * -hildon_touch_selector_get_current_text (HildonTouchSelector *selector); - -void -hildon_touch_selector_set_print_func (HildonTouchSelector *selector, - HildonTouchSelectorPrintFunc func); - -void -hildon_touch_selector_set_print_func_full (HildonTouchSelector *selector, - HildonTouchSelectorPrintFunc func, - gpointer user_data, - GDestroyNotify destroy_func); - -HildonTouchSelectorPrintFunc -hildon_touch_selector_get_print_func (HildonTouchSelector *selector); - -gboolean -hildon_touch_selector_has_multiple_selection (HildonTouchSelector *selector); - -void -hildon_touch_selector_center_on_selected (HildonTouchSelector *selector); - -G_END_DECLS - -#endif /* __HILDON_TOUCH_SELECTOR_H__ */ diff --git a/src/hildon-version.h.in b/src/hildon-version.h.in deleted file mode 100644 index 6fec0ff..0000000 --- a/src/hildon-version.h.in +++ /dev/null @@ -1,39 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006, 2007 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, or (at your option) any later version. - * - * 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_VERSION_H__ -#define __HILDON_VERSION_H__ - -#define HILDON_MAJOR_VERSION (@PACKAGE_VERSION_MAJOR@) -#define HILDON_MINOR_VERSION (@PACKAGE_VERSION_MINOR@) -#define HILDON_MICRO_VERSION (@PACKAGE_VERSION_MICRO@) - -#define HILDON_CHECK_VERSION(major,minor,micro) \ - (HILDON_MAJOR_VERSION > (major) || \ - (HILDON_MAJOR_VERSION == (major) && HILDON_MINOR_VERSION > (minor)) || \ - (HILDON_MAJOR_VERSION == (major) && HILDON_MINOR_VERSION == (minor) && \ - HILDON_MICRO_VERSION >= (micro))) - -#endif /* __HILDON_VERSION_H__ */ - diff --git a/src/hildon-volumebar-private.h b/src/hildon-volumebar-private.h deleted file mode 100644 index 62a5095..0000000 --- a/src/hildon-volumebar-private.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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 "hildon-volumebar-range.h" - -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 G_GNUC_INTERNAL -hildon_volumebar_mute_toggled (HildonVolumebar * self); - -void G_GNUC_INTERNAL -hildon_volumebar_level_change (HildonVolumebar *self); - -G_END_DECLS - -#endif /* __HILDON_VOLUMEBAR_PRIVATE__ */ diff --git a/src/hildon-volumebar-range.c b/src/hildon-volumebar-range.c deleted file mode 100644 index 11ff1f1..0000000 --- a/src/hildon-volumebar-range.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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-range - * @short_description: 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]. - * - * - * - * #HildonVolumebarRange has been deprecated since Hildon 2.2 and should not - * be used in newly written code. See - * Migrating Volume Bars - * section to know how to migrate this deprecated widget. - * - * - */ - -#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_0, - PROP_LEVEL -}; - -/** - * hildon_volumebar_range_get_type: - * - * Initializes and returns the type of a hildon volumebar range. - * - * Returns: GType of #HildonVolumebarRange - */ -GType G_GNUC_CONST -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; - - /** - * HildonVolumebarRange:level: - * - * Current volume level. - */ - 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) -{ - /* do nothing. */ -} - -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 deleted file mode 100644 index 9e5eb59..0000000 --- a/src/hildon-volumebar-range.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_TYPE_VOLUMEBAR_RANGE - * - * Macro for getting type of volumebar range. - */ -#define HILDON_TYPE_VOLUMEBAR_RANGE \ - (hildon_volumebar_range_get_type()) - -#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 G_GNUC_CONST -hildon_volumebar_range_get_type (void); - -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 deleted file mode 100644 index 42ae2a7..0000000 --- a/src/hildon-volumebar.c +++ /dev/null @@ -1,806 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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. - * - * - * - * #HildonVolumebar has been deprecated since Hildon 2.2 and should not - * be used in newly written code. See - * Migrating Volume Bars - * section to know how to migrate this deprecated widget. - * - * - */ - -#undef HILDON_DISABLE_DEPRECATED - -#ifdef HAVE_CONFIG_H -#include -#endif - -#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_grab_focus (GtkWidget *widget); - -static gboolean -hildon_volumebar_focus (GtkWidget *widget, - GtkDirectionType direction); - -static void -hildon_volumebar_notify (GObject *self, GParamSpec *param); - -enum -{ - MUTE_TOGGLED_SIGNAL, - LEVEL_CHANGED_SIGNAL, - LAST_SIGNAL -}; - -enum { - PROP_0, - PROP_HILDON_HAS_MUTE, - PROP_HILDON_LEVEL, - PROP_HILDON_MUTE -}; - -static guint signals [LAST_SIGNAL] = { 0 }; - -/** - * hildon_volumebar_get_type: - * - * Initializes and returns the type of a hildon volumebar. - * - * Returns: GType of #HildonVolumebar - */ -GType G_GNUC_CONST -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->grab_focus = hildon_volumebar_grab_focus; - widget_class->focus = hildon_volumebar_focus; - 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, - g_cclosure_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, - g_cclosure_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; - - /** - * HildonVolumebar:has-mute: - * - * Whether the mute button is visibile. - */ - 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)); - - /** - * HildonVolumebar:level: - * - * Current volume level. - */ - 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)); - - /** - * HildonVolumebar:mute: - * - * Whether volume is muted. - */ - 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); - g_assert (priv); - - /* Should set GTK_NO_WINDOW flag, because widget is derived from - GtkContainer */ - GTK_WIDGET_SET_FLAGS (GTK_WIDGET (volumebar), GTK_NO_WINDOW); - GTK_WIDGET_SET_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); - g_assert (priv); - - 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); - g_assert (priv); - - 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); - g_assert (priv); - - 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); - g_assert (priv); - - 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); - g_assert (priv); - - gdk_window_hide (priv->event_window); - - GTK_WIDGET_CLASS (parent_class)->unmap(widget); -} - -static void -hildon_volumebar_grab_focus (GtkWidget *widget) -{ - HildonVolumebarPrivate *priv; - - priv = HILDON_VOLUMEBAR_GET_PRIVATE (widget); - g_assert (priv); - - if (GTK_WIDGET_CAN_FOCUS (widget)) { - if (gtk_toggle_button_get_active (priv->tbutton)) - gtk_widget_grab_focus (GTK_WIDGET (priv->tbutton)); - else - gtk_widget_grab_focus (GTK_WIDGET (priv->volumebar)); - } -} - -static gboolean -hildon_volumebar_focus (GtkWidget *widget, - GtkDirectionType direction) -{ - HildonVolumebarPrivate *priv; - GtkOrientation orientation; - gboolean has_focus; - - priv = HILDON_VOLUMEBAR_GET_PRIVATE (widget); - g_assert (priv); - - orientation = GTK_RANGE (priv->volumebar)->orientation; - - has_focus = (GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (priv->volumebar)) || - GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (priv->tbutton))); - - switch (direction) { - case GTK_DIR_UP: - case GTK_DIR_DOWN: - case GTK_DIR_TAB_FORWARD: - case GTK_DIR_TAB_BACKWARD: - if (has_focus && orientation == GTK_ORIENTATION_HORIZONTAL) - return FALSE; - break; - - case GTK_DIR_LEFT: - case GTK_DIR_RIGHT: - if (has_focus && orientation == GTK_ORIENTATION_VERTICAL) - return FALSE; - break; - - default: - break; - } - - return GTK_WIDGET_CLASS (parent_class)->focus (widget, direction); -} - -static void -hildon_child_forall (GtkContainer *container, - gboolean include_internals, - GtkCallback callback, - gpointer callback_data) -{ - HildonVolumebarPrivate *priv; - - priv = HILDON_VOLUMEBAR_GET_PRIVATE (container); - g_assert (callback != NULL); - g_assert (priv); - - /* 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); - g_assert (priv); - - if (g_str_equal (param->name, "can-focus")) { - /* call set_mute() because that updates the widget's UI state */ - hildon_volumebar_set_mute (HILDON_VOLUMEBAR (self), - hildon_volumebar_get_mute (HILDON_VOLUMEBAR (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); - g_assert (priv); - - 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); - g_assert (priv); - - 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_LEVEL: - hildon_volumebar_set_level (HILDON_VOLUMEBAR (object), - g_value_get_double (value)); - break; - - case PROP_HILDON_MUTE: - hildon_volumebar_set_mute (HILDON_VOLUMEBAR (object), - 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) -{ - HildonVolumebarPrivate *priv; - HildonVolumebar *vb; - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(object); - g_assert (priv); - - vb = HILDON_VOLUMEBAR (object); - - switch (prop_id) { - - case PROP_HILDON_HAS_MUTE: - g_value_set_boolean (value, GTK_WIDGET_VISIBLE (priv->tbutton)); - 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_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); - g_assert (priv); - - 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); - g_assert (priv); - - 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 has_focus; - - g_return_if_fail (HILDON_IS_VOLUMEBAR (self)); - - priv = HILDON_VOLUMEBAR_GET_PRIVATE (self); - g_assert (priv); - - has_focus = (GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (priv->volumebar)) || - GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (priv->tbutton))); - - /* Slider should be insensitive when mute is on */ - gtk_widget_set_sensitive (GTK_WIDGET (priv->volumebar), !mute); - - if (mute) { - /* Make mute button focusable since the slider isn't anymore */ - g_object_set (G_OBJECT (priv->tbutton), "can-focus", TRUE, NULL); - - if (has_focus) - gtk_widget_grab_focus (GTK_WIDGET (priv->tbutton)); - } - else - { - g_object_set (G_OBJECT (priv->tbutton), "can-focus", FALSE, NULL); - - if (has_focus) - gtk_widget_grab_focus (GTK_WIDGET (priv->volumebar)); - } - - /* Update mute button state and redraw */ - gtk_toggle_button_set_active (priv->tbutton, mute); -} - -/** - * 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); - g_assert (priv); - - 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 pass to hildon_appview_set_connected_adjustment which - * will allow changing the volume with 'increase' / 'decrease' - * hardware buttons. - * - * 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); - g_assert (priv); - - 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); - g_assert (priv != NULL); - - /* 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. - */ -void G_GNUC_INTERNAL -hildon_volumebar_mute_toggled (HildonVolumebar * self) -{ - g_return_if_fail (HILDON_IS_VOLUMEBAR (self)); - /* FIXME Emit by id */ - g_signal_emit_by_name (self, "mute_toggled"); -} - -void G_GNUC_INTERNAL -hildon_volumebar_level_change (HildonVolumebar *self) -{ - g_return_if_fail (HILDON_IS_VOLUMEBAR (self)); - - /* FIXME Use numerical val, id */ - g_signal_emit_by_name (GTK_WIDGET (self), "level_changed"); -} - -/** - * hildon_volumebar_set_range_insensitive_message: - * @widget: A @GtkWidget to assign the banner to - * @message: A message to display to the user - * - * Used to asign an insensitive message to the slider of the given volumebar. - * It simply calls hildon_helper_set_insensitive_message on the slider/range of - * the volumebar. - * - * Deprecated: As of hildon 2.2, it is strongly discouraged to use insensitive messages. - */ -void -hildon_volumebar_set_range_insensitive_message (HildonVolumebar *widget, - const gchar *message) -{ - g_return_if_fail (HILDON_IS_VOLUMEBAR (widget)); - - HildonVolumebarPrivate *priv; - priv = HILDON_VOLUMEBAR_GET_PRIVATE (widget); - - hildon_helper_set_insensitive_message ((GtkWidget *) priv->volumebar, message); -} - -/** - * hildon_volumebar_set_range_insensitive_messagef: - * @widget: A @GtkWidget to assign the banner to - * @format : a printf-like format string - * @varargs : arguments for the format string - * - * A helper printf-like variant of hildon_helper_set_insensitive_message. - * - * Deprecated: As of hildon 2.2, it is strongly discouraged to use insensitive messages. - */ -void -hildon_volumebar_set_range_insensitive_messagef (HildonVolumebar *widget, - const gchar *format, - ...) -{ - g_return_if_fail (HILDON_IS_VOLUMEBAR (widget)); - - HildonVolumebarPrivate *priv; - priv = HILDON_VOLUMEBAR_GET_PRIVATE (widget); - - gchar *message; - va_list args; - - va_start (args, format); - message = g_strdup_vprintf (format, args); - va_end (args); - - hildon_helper_set_insensitive_message ((GtkWidget *) priv->volumebar, message); - - g_free (message); -} - - diff --git a/src/hildon-volumebar.h b/src/hildon-volumebar.h deleted file mode 100644 index 510f7ab..0000000 --- a/src/hildon-volumebar.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#ifndef __HILDON_VOLUMEBAR_H__ -#define __HILDON_VOLUMEBAR_H__ - -#include - -#include "hildon-helper.h" - -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)) - -#define HILDON_VOLUMEBAR_GET_CLASS(obj) \ - ((HildonVolumebarClass *) G_OBJECT_GET_CLASS(obj)) - -typedef struct _HildonVolumebar HildonVolumebar; - -typedef struct _HildonVolumebarClass HildonVolumebarClass; - -struct _HildonVolumebar -{ - GtkContainer parent; -}; - -struct _HildonVolumebarClass -{ - GtkContainerClass parent_class; - - /* signals */ - void (*mute_toggled) (HildonVolumebar * self); - void (*level_changed) (HildonVolumebar * self); -}; - -GType G_GNUC_CONST -hildon_volumebar_get_type (void); - -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); - -GtkAdjustment* -hildon_volumebar_get_adjustment (HildonVolumebar *self); - -#ifndef HILDON_DISABLE_DEPRECATED -void -hildon_volumebar_set_range_insensitive_message (HildonVolumebar *widget, - const gchar *message); - -void -hildon_volumebar_set_range_insensitive_messagef (HildonVolumebar *widget, - const gchar *format, - ...); -#endif - -G_END_DECLS - -#endif /* __HILDON_VOLUMEBAR_H__ */ - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-vvolumebar.c b/src/hildon-vvolumebar.c deleted file mode 100644 index 5e0cec4..0000000 --- a/src/hildon-vvolumebar.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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. - * - * - * - * #HildonVVolumebar has been deprecated since Hildon 2.2 and should not - * be used in newly written code. See - * Migrating Volume Bars - * section to know how to migrate this deprecated widget. - * - * - * - * Here is an example that creates a vertical volume bar and connects - * both its signals. - * - * - * HildonVVolumebar example - * - * GtkWidget *volbar = hildon_vvolumebar_new (); - * g_signal_connect (G_OBJECT (volbar), "mute_toggled", G_CALLBACK (mute_toggle), NULL); - * g_signal_connect (G_OBJECT (volbar), "level_changed", G_CALLBACK (level_change), NULL); - * - * - */ - -#undef HILDON_DISABLE_DEPRECATED - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "hildon-vvolumebar.h" -#include "hildon-volumebar-range.h" -#include "hildon-volumebar-private.h" - -/* Volume bar */ -#define DEFAULT_BAR_WIDTH 60 - -#define MINIMUM_BAR_HEIGHT 165 - -/* Toggle button */ - -#define DEFAULT_VERTICAL_TBUTTON_WIDTH 60 - -#define DEFAULT_VERTICAL_TBUTTON_HEIGHT 60 - -#define DEFAULT_ENDING_SIZE 0 - -/* Gap to leave for mute button */ - -#define HORIZONTAL_MUTE_GAP 0 - -#define VERTICAL_MUTE_GAP 0 - -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); - -/** - * hildon_vvolumebar_get_type: - * - * Initializes and returns the type of a hildon vvolumebar. - * - * Returns: GType of #HildonVVolumebar - */ -GType G_GNUC_CONST -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); - g_assert (priv); - - priv->volumebar = HILDON_VOLUMEBAR_RANGE (hildon_volumebar_range_new - (GTK_ORIENTATION_VERTICAL)); - - 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); - - /* FIXME Not sure why this is here */ - 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; - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(HILDON_VOLUMEBAR(widget)); - g_assert (priv); - - 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) -{ - 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; - - priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget); - g_assert (priv); - - /* 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 - - DEFAULT_VERTICAL_TBUTTON_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 deleted file mode 100644 index ba1c471..0000000 --- a/src/hildon-vvolumebar.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#ifndef __HILDON_VVOLUMEBAR_H__ -#define __HILDON_VVOLUMEBAR_H__ - -#include "hildon-volumebar.h" - -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)) - -#define HILDON_VVOLUMEBAR_GET_CLASS(obj) \ - ((HildonVVolumebarClass *) G_OBJECT_GET_CLASS(obj)) - -typedef struct _HildonVVolumebar HildonVVolumebar; - -typedef struct _HildonVVolumebarClass HildonVVolumebarClass; - -struct _HildonVVolumebar -{ - HildonVolumebar parent; -}; - -struct _HildonVVolumebarClass -{ - HildonVolumebarClass parent_class; -}; - -GType G_GNUC_CONST -hildon_vvolumebar_get_type (void); - -GtkWidget* -hildon_vvolumebar_new (void); - -G_END_DECLS - -#endif /* __HILDON_VVOLUMEBAR_H__ */ - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-weekday-picker-private.h b/src/hildon-weekday-picker-private.h deleted file mode 100644 index a97ca29..0000000 --- a/src/hildon-weekday-picker-private.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_PRIVATE_H__ -#define __HILDON_WEEKDAY_PICKER_PRIVATE_H__ - -G_BEGIN_DECLS - -typedef struct _HildonWeekdayPickerPrivate HildonWeekdayPickerPrivate; - -#define HILDON_WEEKDAY_PICKER_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_WEEKDAY_PICKER, HildonWeekdayPickerPrivate)); - -struct _HildonWeekdayPickerPrivate -{ - GtkWidget *buttons[8]; /* weekday buttons in show order */ - GtkWidget *day_order_buttons[8]; /* weekday buttons in glib day order */ -}; - -G_END_DECLS - -#endif /* __HILDON_WEEKDAY_PICKER_PRIVATE_H__ */ diff --git a/src/hildon-weekday-picker.c b/src/hildon-weekday-picker.c deleted file mode 100644 index d357c91..0000000 --- a/src/hildon-weekday-picker.c +++ /dev/null @@ -1,565 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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. - * - * - * - * #HildonWeekdayPicker has been deprecated since Hildon 2.2 and should not - * be used in newly written code. See - * Migrating Date Widgets - * section to know how to migrate this deprecated widget. - * - * - * - * - * HildonWeekdayPicker example - * - * gint i; - * HildonWeekdayPicker *picker = hildon_weekday_picker_new (); - * - * hildon_weekday_picker_set_day (picker, i); - * hildon_weekday_picker_unset_day (picker, i); - * hildon_weekday_picker_toggle_day (picker, i); - * hildon_weekday_picker_set_all (picker); - * - * hildon_weekday_picker_unset_all( picker ); - * - * - * - */ - - /* 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 */ - -#undef HILDON_DISABLE_DEPRECATED - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hildon-weekday-picker.h" -#include "hildon-private.h" -#include "hildon-weekday-picker-private.h" - -static GtkContainerClass* parent_class; - -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 gboolean -hildon_weekday_picker_focus (GtkWidget *widget, - GtkDirectionType direction); -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); - -enum -{ - SELECTION_CHANGED_SIGNAL, - LAST_SIGNAL -}; - -static guint signals [LAST_SIGNAL] = { 0 } ; - -/** - * hildon_weekday_picker_get_type: - * - * Initializes and returns the type of a hildon weekday picker. - * - * Returns: GType of #HildonWeekdayPicker - */ -GType G_GNUC_CONST -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_weekday_picker_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, - g_cclosure_marshal_VOID__INT, - G_TYPE_NONE, 1, G_TYPE_INT); -} - -static void -hildon_weekday_picker_init (HildonWeekdayPicker *picker) -{ - HildonWeekdayPickerPrivate *priv; - gint i, day; - - priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (picker); - g_assert (priv); - - /* 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); - - - /* 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); - g_assert (priv); - - /* 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); - g_assert (priv); - - /* 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); - g_assert (priv); - - 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); - g_assert (priv); - - 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 gboolean -hildon_weekday_picker_focus (GtkWidget *widget, - GtkDirectionType direction) -{ - gboolean retval; - GtkDirectionType effective_direction; - - g_assert (HILDON_IS_WEEKDAY_PICKER (widget)); - - retval = hildon_private_composite_focus (widget, direction, &effective_direction); - - if (retval == TRUE) - return GTK_WIDGET_CLASS (parent_class)->focus (widget, effective_direction); - else - return FALSE; -} - -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); - g_assert (picker); - priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (picker); - g_assert (priv); - - 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 (HILDON_IS_WEEKDAY_PICKER (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 - * - * Unselect specified weekday. - */ -void -hildon_weekday_picker_unset_day (HildonWeekdayPicker *picker, - GDateWeekday day) -{ - HildonWeekdayPickerPrivate *priv; - - g_return_if_fail (HILDON_IS_WEEKDAY_PICKER (picker)); - g_return_if_fail (g_date_valid_weekday (day)); - - priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (picker); - g_assert (priv); - - 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 (HILDON_IS_WEEKDAY_PICKER (picker)); - g_return_if_fail (g_date_valid_weekday (day)); - - priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (picker); - g_assert (priv); - - 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 (HILDON_IS_WEEKDAY_PICKER (picker)); - - priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (picker); - g_assert (priv); - - 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 (HILDON_IS_WEEKDAY_PICKER (picker)); - - priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (picker); - g_assert (priv); - - 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 (HILDON_IS_WEEKDAY_PICKER (picker), FALSE); - g_return_val_if_fail (g_date_valid_weekday (day), FALSE); - - priv = HILDON_WEEKDAY_PICKER_GET_PRIVATE (picker); - g_assert (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 deleted file mode 100644 index afba2a9..0000000 --- a/src/hildon-weekday-picker.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_DISABLE_DEPRECATED - -#ifndef __HILDON_WEEKDAY_PICKER_H__ -#define __HILDON_WEEKDAY_PICKER_H__ - -#include - -G_BEGIN_DECLS - -typedef struct _HildonWeekdayPicker HildonWeekdayPicker; - -typedef struct _HildonWeekdayPickerClass HildonWeekdayPickerClass; - -#define HILDON_TYPE_WEEKDAY_PICKER \ - (hildon_weekday_picker_get_type()) - -#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)) - -#define HILDON_WEEKDAY_PICKER_GET_CLASS(obj) \ - ((HildonWeekdayPickerClass *) G_OBJECT_GET_CLASS(obj)) - -struct _HildonWeekdayPicker -{ - GtkContainer parent; -}; - -struct _HildonWeekdayPickerClass -{ - GtkContainerClass parent_class; - - void (*selection_changed) (HildonWeekdayPicker *self); -}; - -GType G_GNUC_CONST -hildon_weekday_picker_get_type (void); - -GtkWidget* -hildon_weekday_picker_new (void); - -void -hildon_weekday_picker_set_day (HildonWeekdayPicker *picker, - GDateWeekday day); - -void -hildon_weekday_picker_unset_day (HildonWeekdayPicker *picker, - GDateWeekday day); - -void -hildon_weekday_picker_toggle_day (HildonWeekdayPicker *picker, - GDateWeekday day); - -void -hildon_weekday_picker_set_all (HildonWeekdayPicker *picker); - -void -hildon_weekday_picker_unset_all (HildonWeekdayPicker *picker); - -gboolean -hildon_weekday_picker_isset_day (HildonWeekdayPicker * picker, - GDateWeekday day); - -G_END_DECLS - -#endif /* __HILDON_WEEKDAY_PICKER_H__ */ - -#endif /* HILDON_DISABLE_DEPRECATED */ diff --git a/src/hildon-window-private.h b/src/hildon-window-private.h deleted file mode 100644 index 97034a6..0000000 --- a/src/hildon-window-private.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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__ - -#include "hildon-program.h" - -#include - -G_BEGIN_DECLS - -typedef struct _HildonWindowPrivate HildonWindowPrivate; - -struct _HildonWindowPrivate -{ - GtkMenu *menu; - HildonAppMenu *app_menu; - GtkWidget *vbox; - GtkWidget *edit_toolbar; - - GtkBorder *borders; - GtkBorder *toolbar_borders; - - GtkAllocation allocation; - - gchar *markup; - - guint fullscreen; - guint is_topmost; - guint escape_timeout; - gint visible_toolbars; - gint previous_vbox_y; - - HildonProgram *program; -}; - -#define HILDON_WINDOW_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ - HILDON_TYPE_WINDOW, HildonWindowPrivate)) - -void G_GNUC_INTERNAL -hildon_window_set_program (HildonWindow *self, - GObject *program); - -void G_GNUC_INTERNAL -hildon_window_unset_program (HildonWindow *self); - -void G_GNUC_INTERNAL -hildon_window_set_can_hibernate_property (HildonWindow *self, - gpointer can_hibernate); - -void G_GNUC_INTERNAL -hildon_window_take_common_toolbar (HildonWindow *self); - -void G_GNUC_INTERNAL -hildon_window_update_topmost (HildonWindow *self, - Window window_id); - -Window G_GNUC_INTERNAL -hildon_window_get_active_window (void); - -void G_GNUC_INTERNAL -hildon_window_update_title (HildonWindow *window); - -G_END_DECLS - -#endif /* __HILDON_WINDOW_PRIVATE_H__ */ diff --git a/src/hildon-window-stack-private.h b/src/hildon-window-stack-private.h deleted file mode 100644 index fb453b6..0000000 --- a/src/hildon-window-stack-private.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * 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, or (at your option) any later version. - * - * 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_STACK_PRIVATE_H__ -#define __HILDON_WINDOW_STACK_PRIVATE_H__ - -G_BEGIN_DECLS - -void G_GNUC_INTERNAL -hildon_window_stack_remove (HildonStackableWindow *win); - -gboolean G_GNUC_INTERNAL -_hildon_window_stack_do_push (HildonWindowStack *stack, - HildonStackableWindow *win); - -G_END_DECLS - -#endif /* __HILDON_WINDOW_STACK_PRIVATE_H__ */ diff --git a/src/hildon-window-stack.c b/src/hildon-window-stack.c deleted file mode 100644 index 925d9fd..0000000 --- a/src/hildon-window-stack.c +++ /dev/null @@ -1,679 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * 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, or (at your option) any later version. - * - * 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-window-stack - * @short_description: Object representing a stack of windows in the Hildon framework - * @see_also: #HildonStackableWindow - * - * The #HildonWindowStack is an object used to represent a stack of - * windows in the Hildon framework. - * - * Stacks contain all #HildonStackableWindows that are being - * shown. The user can only interact with the topmost window from each - * stack (as it covers all the others), but all of them are mapped and - * visible from the Gtk point of view. - * - * Each window can only be in one stack at a time. All stacked windows - * are visible and all visible windows are stacked. - * - * Each application has a default stack, and windows are automatically - * added to it when they are shown with gtk_widget_show(). - * - * Additional stacks can be created at any time using - * hildon_window_stack_new(). To add a window to a specific stack, use - * hildon_window_stack_push_1() (remember that, for the default stack, - * gtk_widget_show() can be used instead). - * - * To remove a window from a stack use hildon_window_stack_pop_1(), or - * simply gtk_widget_hide(). - * - * For more complex layout changes, applications can push and/or pop - * several windows at the same time in a single step. See - * hildon_window_stack_push(), hildon_window_stack_pop() and - * hildon_window_stack_pop_and_push() for more details. - */ - -#include "hildon-window-stack.h" -#include "hildon-window-stack-private.h" -#include "hildon-stackable-window-private.h" - -struct _HildonWindowStackPrivate -{ - GList *list; - GtkWindowGroup *group; - GdkWindow *leader; /* X Window group hint for all windows in a group */ -}; - -#define HILDON_WINDOW_STACK_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\ - HILDON_TYPE_WINDOW_STACK, HildonWindowStackPrivate)) - -G_DEFINE_TYPE (HildonWindowStack, hildon_window_stack, G_TYPE_OBJECT); - -enum { - PROP_GROUP = 1, -}; - -static void -hildon_window_stack_set_window_group (HildonWindowStack *stack, - GtkWindowGroup *group) -{ - g_return_if_fail (HILDON_IS_WINDOW_STACK (stack)); - g_return_if_fail (!group || GTK_IS_WINDOW_GROUP (group)); - - /* The window group is only to be set once during construction */ - g_return_if_fail (stack->priv->group == NULL); - - if (!group) - group = gtk_window_group_new (); - - stack->priv->group = group; -} - -static GtkWindowGroup * -hildon_window_stack_get_window_group (HildonWindowStack *stack) -{ - g_return_val_if_fail (HILDON_IS_WINDOW_STACK (stack), NULL); - - return stack->priv->group; -} - -/** - * hildon_window_stack_get_default: - * - * Returns the default window stack. This stack always exists and - * doesn't need to be created by the application. - * - * Return value: the default #HildonWindowStack - * - * Since: 2.2 - **/ -HildonWindowStack * -hildon_window_stack_get_default (void) -{ - static HildonWindowStack *stack = NULL; - if (G_UNLIKELY (stack == NULL)) { - stack = g_object_new (HILDON_TYPE_WINDOW_STACK, - "window-group", gtk_window_get_group (NULL), - NULL); - } - return stack; -} - -/** - * hildon_window_stack_new: - * - * Creates a new #HildonWindowStack. The stack is initially empty. - * - * Return value: a new #HildonWindowStack - * - * Since: 2.2 - **/ -HildonWindowStack * -hildon_window_stack_new (void) -{ - HildonWindowStack *stack = g_object_new (HILDON_TYPE_WINDOW_STACK, NULL); - return stack; -} - -/** - * hildon_window_stack_size: - * @stack: A #HildonWindowStack - * - * Returns the number of windows in @stack - * - * Return value: Number of windows in @stack - * - * Since: 2.2 - **/ -gint -hildon_window_stack_size (HildonWindowStack *stack) -{ - g_return_val_if_fail (HILDON_IS_WINDOW_STACK (stack), 0); - - return g_list_length (stack->priv->list); -} - -static GdkWindow * -hildon_window_stack_get_leader_window (HildonWindowStack *stack, - GtkWidget *win) -{ - /* Create the X Window group (leader) if we haven't. */ - if (!stack->priv->leader) { - if (stack == hildon_window_stack_get_default ()) { - GdkDisplay *dpy; - - /* We're the default stack, use the default group. */ - dpy = gtk_widget_get_display (win); - stack->priv->leader = gdk_display_get_default_group (dpy); - } else { - static GdkWindowAttr attr = { - .window_type = GDK_WINDOW_TOPLEVEL, - .x = 10, .y = 10, .width = 10, .height = 10, - .wclass = GDK_INPUT_OUTPUT, .event_mask = 0, - }; - GdkWindow *root; - - /* Create a new X Window group. */ - root = gtk_widget_get_root_window (win); - stack->priv->leader = gdk_window_new (root, &attr, GDK_WA_X | GDK_WA_Y); - } - } - - return stack->priv->leader; -} - -/* Set the X Window group of a window when it is realized. */ -static void -hildon_window_stack_window_realized (GtkWidget *win, - HildonWindowStack *stack) -{ - GdkWindow *leader = hildon_window_stack_get_leader_window (stack, win); - gdk_window_set_group (win->window, leader); -} - -/* Remove a window from its stack, no matter its position */ -void G_GNUC_INTERNAL -hildon_window_stack_remove (HildonStackableWindow *win) -{ - HildonWindowStack *stack = hildon_stackable_window_get_stack (win); - - /* If the window is stacked */ - if (stack) { - GList *pos; - - hildon_stackable_window_set_stack (win, NULL, -1); - gtk_window_set_transient_for (GTK_WINDOW (win), NULL); - if (GTK_WIDGET (win)->window) { - gdk_window_set_group (GTK_WIDGET (win)->window, NULL); - } - - /* If the window removed is in the middle of the stack, update - * transiency of other windows */ - pos = g_list_find (stack->priv->list, win); - g_assert (pos != NULL); - if (pos->prev) { - GtkWindow *upper = GTK_WINDOW (pos->prev->data); - GtkWindow *lower = pos->next ? GTK_WINDOW (pos->next->data) : NULL; - gtk_window_set_transient_for (upper, lower); - } - - stack->priv->list = g_list_remove (stack->priv->list, win); - - g_signal_handlers_disconnect_by_func (win, hildon_window_stack_window_realized, stack); - } -} - -/** - * hildon_window_stack_get_windows: - * @stack: a #HildonWindowStack - * - * Returns the list of windows on this stack (topmost first). The - * widgets in the list are not individually referenced. Once you are - * done with the list you must call g_list_free(). - * - * Returns: a newly-allocated list of #HildonStackableWindows - * - * Since: 2.2 - **/ -GList * -hildon_window_stack_get_windows (HildonWindowStack *stack) -{ - g_return_val_if_fail (HILDON_IS_WINDOW_STACK (stack), NULL); - - return g_list_copy (stack->priv->list); -} - -/** - * hildon_window_stack_peek: - * @stack: A %HildonWindowStack - * - * Returns the window on top of @stack. The stack is never modified. - * - * Return value: the window on top of the stack, or %NULL if the stack - * is empty. - * - * Since: 2.2 - **/ -GtkWidget * -hildon_window_stack_peek (HildonWindowStack *stack) -{ - GtkWidget *win = NULL; - - g_return_val_if_fail (HILDON_IS_WINDOW_STACK (stack), NULL); - - if (stack->priv->list != NULL) { - win = GTK_WIDGET (stack->priv->list->data); - } - - return win; -} - -/* This function does everything to push a window to the stack _but_ - * actually calling gtk_widget_show(). - * It's up to each specific push function to decide the order in which - * to show windows. */ -gboolean G_GNUC_INTERNAL -_hildon_window_stack_do_push (HildonWindowStack *stack, - HildonStackableWindow *win) -{ - HildonWindowStack *current_stack; - - g_return_val_if_fail (HILDON_IS_WINDOW_STACK (stack), FALSE); - g_return_val_if_fail (HILDON_IS_STACKABLE_WINDOW (win), FALSE); - - current_stack = hildon_stackable_window_get_stack (win); - - if (current_stack == NULL) { - GtkWidget *parent = hildon_window_stack_peek (stack); - - /* Push the window */ - hildon_stackable_window_set_stack (win, stack, g_list_length (stack->priv->list)); - stack->priv->list = g_list_prepend (stack->priv->list, win); - - /* Make the window part of the same group as its parent */ - if (parent) { - gtk_window_set_transient_for (GTK_WINDOW (win), GTK_WINDOW (parent)); - } else { - gtk_window_group_add_window (stack->priv->group, GTK_WINDOW (win)); - } - - /* Set win's group after it's been realized. */ - g_signal_connect (win, "realize", - G_CALLBACK (hildon_window_stack_window_realized), - stack); - - return TRUE; - } else { - g_warning ("Trying to push a window that is already on a stack"); - return FALSE; - } -} - -static GtkWidget * -_hildon_window_stack_do_pop (HildonWindowStack *stack) -{ - GtkWidget *win = hildon_window_stack_peek (stack); - - if (win) - hildon_window_stack_remove (HILDON_STACKABLE_WINDOW (win)); - - return win; -} - -/** - * hildon_window_stack_push_1: - * @stack: A %HildonWindowStack - * @win: A %HildonStackableWindow - * - * Adds @win to the top of @stack, and shows it. The window must not - * be already stacked. - * - * Since: 2.2 - **/ -void -hildon_window_stack_push_1 (HildonWindowStack *stack, - HildonStackableWindow *win) -{ - if (_hildon_window_stack_do_push (stack, win)) - gtk_widget_show (GTK_WIDGET (win)); -} - -/** - * hildon_window_stack_pop_1: - * @stack: A %HildonWindowStack - * - * Removes the window on top of @stack, and hides it. If the stack is - * empty nothing happens. - * - * Return value: the window on top of the stack, or %NULL if the stack - * is empty. - * - * Since: 2.2 - **/ -GtkWidget * -hildon_window_stack_pop_1 (HildonWindowStack *stack) -{ - GtkWidget *win = _hildon_window_stack_do_pop (stack); - if (win) - gtk_widget_hide (win); - return win; -} - -/** - * hildon_window_stack_push_list: - * @stack: A %HildonWindowStack - * @list: A list of %HildonStackableWindows to push - * - * Pushes all windows in @list to the top of @stack, and shows - * them. Everything is done in a single transition, so the user will - * only see the last window in @list during this operation. None of - * the windows must be already stacked. - * - * Since: 2.2 - **/ -void -hildon_window_stack_push_list (HildonWindowStack *stack, - GList *list) -{ - HildonStackableWindow *win; - GList *l; - GList *pushed = NULL; - - g_return_if_fail (HILDON_IS_WINDOW_STACK (stack)); - - /* Stack all windows */ - for (l = list; l != NULL; l = g_list_next (l)) { - win = HILDON_STACKABLE_WINDOW (l->data); - if (win) { - _hildon_window_stack_do_push (stack, win); - pushed = g_list_prepend (pushed, win); - } else { - g_warning ("Trying to stack a non-stackable window!"); - } - } - - /* Show windows in reverse order (topmost first) */ - g_list_foreach (pushed, (GFunc) gtk_widget_show, NULL); - - g_list_free (pushed); -} - -/** - * hildon_window_stack_push: - * @stack: A %HildonWindowStack - * @win1: The first window to push - * @Varargs: A %NULL-terminated list of additional #HildonStackableWindows to push. - * - * Pushes all windows to the top of @stack, and shows them. Everything - * is done in a single transition, so the user will only see the last - * window. None of the windows must be already stacked. - * - * Since: 2.2 - **/ -void -hildon_window_stack_push (HildonWindowStack *stack, - HildonStackableWindow *win1, - ...) -{ - HildonStackableWindow *win = win1; - GList *list = NULL; - va_list args; - - va_start (args, win1); - - while (win != NULL) { - list = g_list_prepend (list, win); - win = va_arg (args, HildonStackableWindow *); - } - - va_end (args); - - list = g_list_reverse (list); - - hildon_window_stack_push_list (stack, list); - g_list_free (list); -} - -/** - * hildon_window_stack_pop: - * @stack: A %HildonWindowStack - * @nwindows: Number of windows to pop - * @popped_windows: if non-%NULL, the list of popped windows is stored here - * - * Pops @nwindows windows from @stack, and hides them. Everything is - * done in a single transition, so the user will not see any of the - * windows being popped in this operation. - * - * If @popped_windows is not %NULL, the list of popped windows is - * stored there (ordered bottom-up). That list must be freed by the - * user. - * - * Since: 2.2 - **/ -void -hildon_window_stack_pop (HildonWindowStack *stack, - gint nwindows, - GList **popped_windows) -{ - gint i; - GList *popped = NULL; - - g_return_if_fail (HILDON_IS_WINDOW_STACK (stack)); - g_return_if_fail (nwindows > 0); - g_return_if_fail (g_list_length (stack->priv->list) >= nwindows); - - /* Pop windows */ - for (i = 0; i < nwindows; i++) { - GtkWidget *win = _hildon_window_stack_do_pop (stack); - popped = g_list_prepend (popped, win); - } - - /* Hide windows in reverse order (topmost last) */ - g_list_foreach (popped, (GFunc) gtk_widget_hide, NULL); - - if (popped_windows) { - *popped_windows = popped; - } else { - g_list_free (popped); - } -} - -/** - * hildon_window_stack_pop_and_push_list: - * @stack: A %HildonWindowStack - * @nwindows: Number of windows to pop. - * @popped_windows: if non-%NULL, the list of popped windows is stored here - * @list: A list of %HildonStackableWindows to push - * - * Pops @nwindows windows from @stack (and hides them), then pushes - * all windows in @list (and shows them). Everything is done in a - * single transition, so the user will only see the last window from - * @list. None of the pushed windows must be already stacked. - * - * If @popped_windows is not %NULL, the list of popped windows is - * stored there (ordered bottom-up). That list must be freed by the - * user. - * - * Since: 2.2 - **/ -void -hildon_window_stack_pop_and_push_list (HildonWindowStack *stack, - gint nwindows, - GList **popped_windows, - GList *list) -{ - gint i; - GList *l; - GList *popped = NULL; - GList *pushed = NULL; - - g_return_if_fail (HILDON_IS_WINDOW_STACK (stack)); - g_return_if_fail (nwindows > 0); - g_return_if_fail (g_list_length (stack->priv->list) >= nwindows); - - /* Pop windows */ - for (i = 0; i < nwindows; i++) { - GtkWidget *win = _hildon_window_stack_do_pop (stack); - popped = g_list_prepend (popped, win); - } - - /* Push windows */ - for (l = list; l != NULL; l = g_list_next (l)) { - HildonStackableWindow *win = HILDON_STACKABLE_WINDOW (l->data); - if (win) { - _hildon_window_stack_do_push (stack, win); - pushed = g_list_prepend (pushed, win); - } else { - g_warning ("Trying to stack a non-stackable window!"); - } - } - - /* Show windows in reverse order (topmost first) */ - g_list_foreach (pushed, (GFunc) gtk_widget_show, NULL); - - /* Hide windows in reverse order (topmost last) */ - g_list_foreach (popped, (GFunc) gtk_widget_hide, NULL); - - g_list_free (pushed); - if (popped_windows) { - *popped_windows = popped; - } else { - g_list_free (popped); - } -} - -/** - * hildon_window_stack_pop_and_push: - * @stack: A %HildonWindowStack - * @nwindows: Number of windows to pop. - * @popped_windows: if non-%NULL, the list of popped windows is stored here - * @win1: The first window to push - * @Varargs: A %NULL-terminated list of additional #HildonStackableWindows to push. - * - * Pops @nwindows windows from @stack (and hides them), then pushes - * all passed windows (and shows them). Everything is done in a single - * transition, so the user will only see the last pushed window. None - * of the pushed windows must be already stacked. - * - * If @popped_windows is not %NULL, the list of popped windows is - * stored there (ordered bottom-up). That list must be freed by the - * user. - * - * Since: 2.2 - **/ -void -hildon_window_stack_pop_and_push (HildonWindowStack *stack, - gint nwindows, - GList **popped_windows, - HildonStackableWindow *win1, - ...) -{ - HildonStackableWindow *win = win1; - GList *list = NULL; - va_list args; - - va_start (args, win1); - - while (win != NULL) { - list = g_list_prepend (list, win); - win = va_arg (args, HildonStackableWindow *); - } - - va_end (args); - - list = g_list_reverse (list); - - hildon_window_stack_pop_and_push_list (stack, nwindows, popped_windows, list); - g_list_free (list); -} - -static void -hildon_window_stack_finalize (GObject *object) -{ - HildonWindowStack *stack = HILDON_WINDOW_STACK (object); - - if (stack->priv->list) - hildon_window_stack_pop (stack, hildon_window_stack_size (stack), NULL); - - if (stack->priv->group) - g_object_unref (stack->priv->group); - - /* Since the default group stack shouldn't be finalized, - * it's safe to destroy the X Window group we created. */ - if (stack->priv->leader) - gdk_window_destroy (stack->priv->leader); - - G_OBJECT_CLASS (hildon_window_stack_parent_class)->finalize (object); -} - -static void -hildon_window_stack_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - HildonWindowStack *stack = HILDON_WINDOW_STACK (object); - - switch (prop_id) - { - case PROP_GROUP: - hildon_window_stack_set_window_group (stack, g_value_get_object (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -hildon_window_stack_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - HildonWindowStack *stack = HILDON_WINDOW_STACK (object); - - switch (prop_id) - { - case PROP_GROUP: - g_value_set_object (value, hildon_window_stack_get_window_group (stack)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -hildon_window_stack_class_init (HildonWindowStackClass *klass) -{ - GObjectClass *gobject_class = (GObjectClass *)klass; - - gobject_class->set_property = hildon_window_stack_set_property; - gobject_class->get_property = hildon_window_stack_get_property; - gobject_class->finalize = hildon_window_stack_finalize; - - g_object_class_install_property ( - gobject_class, - PROP_GROUP, - g_param_spec_object ( - "window-group", - "GtkWindowGroup for this stack", - "GtkWindowGroup that all windows on this stack belong to", - GTK_TYPE_WINDOW_GROUP, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_type_class_add_private (klass, sizeof (HildonWindowStackPrivate)); -} - -static void -hildon_window_stack_init (HildonWindowStack *self) -{ - HildonWindowStackPrivate *priv; - - priv = self->priv = HILDON_WINDOW_STACK_GET_PRIVATE (self); - - priv->list = NULL; - priv->group = NULL; -} diff --git a/src/hildon-window-stack.h b/src/hildon-window-stack.h deleted file mode 100644 index 98219a6..0000000 --- a/src/hildon-window-stack.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2008 Nokia Corporation, all rights reserved. - * - * 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, or (at your option) any later version. - * - * 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_STACK_H__ -#define __HILDON_WINDOW_STACK_H__ - -#include "hildon-stackable-window.h" - -G_BEGIN_DECLS - -#define HILDON_TYPE_WINDOW_STACK \ - (hildon_window_stack_get_type()) - -#define HILDON_WINDOW_STACK(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - HILDON_TYPE_WINDOW_STACK, \ - HildonWindowStack)) - -#define HILDON_WINDOW_STACK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - HILDON_TYPE_WINDOW_STACK, \ - HildonWindowStackClass)) - -#define HILDON_IS_WINDOW_STACK(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ - HILDON_TYPE_WINDOW_STACK)) - -#define HILDON_IS_WINDOW_STACK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), \ - HILDON_TYPE_WINDOW_STACK)) - -#define HILDON_WINDOW_STACK_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - HILDON_TYPE_WINDOW_STACK, \ - HildonWindowStackClass)) - -typedef struct _HildonWindowStackPrivate HildonWindowStackPrivate; - -#ifndef _TYPEDEF_HILDON_WINDOW_STACK_ -#define _TYPEDEF_HILDON_WINDOW_STACK_ -typedef struct _HildonWindowStack HildonWindowStack; -#endif -typedef struct _HildonWindowStackClass HildonWindowStackClass; - -struct _HildonWindowStack -{ - GObject parent; - - /* private */ - HildonWindowStackPrivate *priv; -}; - -struct _HildonWindowStackClass -{ - GObjectClass parent_class; - - /* Padding for future extension */ - void (*_hildon_reserved1)(void); - void (*_hildon_reserved2)(void); - void (*_hildon_reserved3)(void); - void (*_hildon_reserved4)(void); -}; - -GType -hildon_window_stack_get_type (void) G_GNUC_CONST; - -HildonWindowStack * -hildon_window_stack_get_default (void); - -HildonWindowStack * -hildon_window_stack_new (void); - -gint -hildon_window_stack_size (HildonWindowStack *stack); - -GList * -hildon_window_stack_get_windows (HildonWindowStack *stack); - -GtkWidget * -hildon_window_stack_peek (HildonWindowStack *stack); - -void -hildon_window_stack_push (HildonWindowStack *stack, - HildonStackableWindow *win1, - ...); - -void -hildon_window_stack_push_list (HildonWindowStack *stack, - GList *list); - -void -hildon_window_stack_push_1 (HildonWindowStack *stack, - HildonStackableWindow *win); - -void -hildon_window_stack_pop (HildonWindowStack *stack, - gint nwindows, - GList **popped_windows); - -GtkWidget * -hildon_window_stack_pop_1 (HildonWindowStack *stack); - -void -hildon_window_stack_pop_and_push (HildonWindowStack *stack, - gint nwindows, - GList **popped_windows, - HildonStackableWindow *win1, - ...); - -void -hildon_window_stack_pop_and_push_list (HildonWindowStack *stack, - gint nwindows, - GList **popped_windows, - GList *list); - -G_END_DECLS - -#endif /* __HILDON_WINDOW_STACK_H__ */ diff --git a/src/hildon-window.c b/src/hildon-window.c deleted file mode 100644 index 8d8e2f5..0000000 --- a/src/hildon-window.c +++ /dev/null @@ -1,2176 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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-window - * @short_description: Widget representing a top-level window in the Hildon framework. - * @see_also: #HildonProgram, #HildonStackableWindow - * - * #HildonWindow is a GTK widget which represents a top-level - * window in the Hildon framework. It is derived from #GtkWindow - * and provides additional commodities specific to the Hildon - * framework. - * - * #HildonWindows can have a menu attached, which is toggled - * with a hardware key or by tapping on the window frame. This menu - * can be either a #GtkMenu or a #HildonAppMenu (set with - * hildon_window_set_main_menu() and hildon_window_set_app_menu() - * respectively). Only one type of menu can be used at the same time. - * In Hildon 2.2, #HildonAppMenu is the recommended menu to use. - * - * Similarly, a #HildonWindow can have several toolbars - * attached. These can be added with hildon_window_add_toolbar(). In - * addition to those, a #HildonWindow can also have a - * #HildonEditToolbar. To add it to the window use - * hildon_window_set_edit_toolbar(). - * - * - * Creating a HildonWindow - * - * HildonWindow *window; - * GtkToolbar *toolbar; - * HildonAppMenu *menu; - * GdkPixbuf *icon_pixbuf; - * - * window = HILDON_WINDOW (hildon_window_new()); - * - * toolbar = create_toolbar(); - * - * menu = create_menu(); - * - * icon_pixbuf = create_icon(); - * - * hildon_window_set_app_menu (window, menu); - * - * hildon_window_add_toolbar (window, toolbar); - * - * // Can be used to set the window fullscreen - * gtk_window_fullscreen (GTK_WINDOW (window)); - * - * // Used to trigger the blinking of the window's icon in the task navigator - * gtk_window_set_urgency_hint (GTK_WINDOW (window), TRUE); - * - * // Change the window's icon in the task navigator - * gtk_window_set_icon (GTK_WINDOW (window), icon_pixbuf); - * - * - */ - -#undef HILDON_DISABLE_DEPRECATED - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hildon-window.h" -#include "hildon-window-private.h" -#include "hildon-app-menu-private.h" -#include "hildon-find-toolbar.h" -#include "hildon-defines.h" - -#define _(String) gettext(String) - -#define TOOLBAR_HEIGHT 70 - -#define TOOLBAR_MIDDLE 0 - -/*FIXME*/ -#define CAN_HIBERNATE "CANKILL" - -#define CAN_HIBERNATE_LENGTH 7 - -#define CAN_HIBERNATE_PROPERTY "_HILDON_ABLE_TO_HIBERNATE" - -#define TITLE_SEPARATOR " - " - -typedef void (*HildonWindowSignal) (HildonWindow *, gint, gpointer); - -static void -hildon_window_init (HildonWindow * self); - -static void -hildon_window_class_init (HildonWindowClass * window_class); - -static void -hildon_window_menu_popup_func (GtkMenu *menu, - gint *x, - gint *y, - gboolean *push_in, - GtkWidget *widget); -static void -hildon_window_menu_popup_func_full (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_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec); - -static void -hildon_window_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec); - -static void -hildon_window_update_markup (HildonWindow *window); - -static void -hildon_window_destroy (GtkObject *obj); - -static void -hildon_window_realize (GtkWidget *widget); - -static void -hildon_window_unrealize (GtkWidget *widget); - -static void -hildon_window_map (GtkWidget *widget); - -static void -hildon_window_unmap (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 gboolean -hildon_window_focus_out_event (GtkWidget *widget, - GdkEventFocus *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, - guint button, - guint32 time); - -static gboolean -hildon_window_toggle_menu_real (HildonWindow * self, - guint button, - guint32 time); - -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); - -static void -paint_edit_toolbar (GtkWidget *widget, - GtkWidget *toolbar, - GdkEventExpose *event, - gboolean fullscreen); - -enum -{ - PROP_0, - PROP_IS_TOPMOST, - PROP_MARKUP -}; - -enum -{ - WIN_TYPE = 0, - WIN_TYPE_MESSAGE, - MAX_WIN_MESSAGES -}; - -G_DEFINE_TYPE (HildonWindow, hildon_window, GTK_TYPE_WINDOW); - -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); - - object_class->get_property = hildon_window_get_property; - object_class->set_property = hildon_window_set_property; - object_class->notify = hildon_window_notify; - 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; - widget_class->focus_out_event = hildon_window_focus_out_event; - widget_class->map = hildon_window_map; - widget_class->unmap = hildon_window_unmap; - - /* now the object stuff */ - object_class->finalize = hildon_window_finalize; - - /* To the container */ - container_class->forall = hildon_window_forall; - - /* To this class */ - window_class->toggle_menu = hildon_window_toggle_menu_real; - - /* 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)); - - g_object_class_install_property (object_class, PROP_MARKUP, - g_param_spec_string ("markup", - "Marked up text for the window title", - "Marked up text for the window title", - NULL, - G_PARAM_READWRITE)); - - 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, - G_TYPE_INT); -} - -static void -hildon_window_init (HildonWindow *self) -{ - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (self); - g_assert (priv != NULL); - - priv->vbox = gtk_vbox_new (TRUE, TOOLBAR_MIDDLE); - gtk_widget_set_parent (priv->vbox, GTK_WIDGET(self)); - priv->menu = NULL; - priv->app_menu = NULL; - priv->edit_toolbar = NULL; - priv->visible_toolbars = 0; - priv->is_topmost = FALSE; - priv->borders = NULL; - priv->toolbar_borders = NULL; - priv->escape_timeout = 0; - priv->markup = NULL; - - 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) -{ - HildonWindowPrivate *priv; - - g_return_if_fail (HILDON_WINDOW (obj_self)); - - priv = HILDON_WINDOW_GET_PRIVATE (obj_self); - g_assert (priv != NULL); - - g_free (priv->markup); - - if (priv->escape_timeout) { - g_source_remove (priv->escape_timeout); - priv->escape_timeout = 0; - } - - if (priv->borders) - gtk_border_free (priv->borders); - - if (priv->toolbar_borders) - gtk_border_free (priv->toolbar_borders); - - if (G_OBJECT_CLASS (hildon_window_parent_class)->finalize) - G_OBJECT_CLASS (hildon_window_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; - HildonWindowPrivate *priv; - - GTK_WIDGET_CLASS (hildon_window_parent_class)->realize (widget); - - priv = HILDON_WINDOW_GET_PRIVATE (widget); - g_assert (priv != NULL); - - gtk_widget_realize (GTK_WIDGET (priv->vbox)); - - if (priv->edit_toolbar != NULL) - gtk_widget_realize (priv->edit_toolbar); - - /* 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 (priv->program) { - gboolean can_hibernate = hildon_program_get_can_hibernate (priv->program); - - hildon_window_set_can_hibernate_property (HILDON_WINDOW (widget), - &can_hibernate); - } - - if (priv->markup) - hildon_window_update_markup (HILDON_WINDOW (widget)); - - /* Update the topmost status */ - active_window = hildon_window_get_active_window(); - hildon_window_update_topmost (HILDON_WINDOW (widget), active_window); -} - -static void -hildon_window_unrealize (GtkWidget *widget) -{ - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (widget); - g_assert (priv != NULL); - - gdk_window_remove_filter (widget->window, hildon_window_event_filter, - widget); - - gtk_widget_unrealize (GTK_WIDGET (priv->vbox)); - - if (priv->edit_toolbar != NULL) - gtk_widget_unrealize (priv->edit_toolbar); - - GTK_WIDGET_CLASS(hildon_window_parent_class)->unrealize(widget); -} - -static void -hildon_window_map (GtkWidget *widget) -{ - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (widget); - g_assert (priv != NULL); - - if (GTK_WIDGET_CLASS (hildon_window_parent_class)->map) - GTK_WIDGET_CLASS (hildon_window_parent_class)->map (widget); - - if (priv->vbox != NULL && GTK_WIDGET_VISIBLE (priv->vbox)) - gtk_widget_map (priv->vbox); - - if (priv->edit_toolbar != NULL && GTK_WIDGET_VISIBLE (priv->edit_toolbar)) - gtk_widget_map (priv->edit_toolbar); -} - -static void -hildon_window_unmap (GtkWidget *widget) -{ - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (widget); - g_assert (priv != NULL); - - gtk_widget_unmap (priv->vbox); - - if (priv->edit_toolbar != NULL) - gtk_widget_unmap (priv->edit_toolbar); - - if (GTK_WIDGET_CLASS (hildon_window_parent_class)->unmap) - GTK_WIDGET_CLASS (hildon_window_parent_class)->unmap (widget); -} - -static void -hildon_window_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec * pspec) -{ - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (object); - g_assert (priv != NULL); - - switch (property_id) { - - case PROP_IS_TOPMOST: - g_value_set_boolean (value, priv->is_topmost); - break; - - case PROP_MARKUP: - g_value_set_string (value, priv->markup); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); - break; - } -} - -static void -hildon_window_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - - case PROP_MARKUP: - hildon_window_set_markup (HILDON_WINDOW (object), g_value_get_string (value)); - 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) -{ - GtkBorder zero = {0, 0, 0, 0}; - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (window); - g_assert (priv); - - GtkBorder *borders = NULL; - GtkBorder *toolbar_borders = NULL; - - if (priv->borders) - gtk_border_free (priv->borders); - if (priv->toolbar_borders) - gtk_border_free (priv->toolbar_borders); - - priv->borders = NULL; - priv->toolbar_borders = NULL; - - gtk_widget_style_get (GTK_WIDGET (window), "borders",&borders, - "toolbar-borders", &toolbar_borders, - NULL); - - // We're doing a copy here instead of reusing the pointer, - // as we don't know where it comes from (has it been allocated using - // malloc or slices... and we want to free it sanely. Blowing on - // cold probbably. - - if (borders) { - priv->borders = gtk_border_copy (borders); - gtk_border_free (borders); - } else - priv->borders = g_boxed_copy (GTK_TYPE_BORDER, &zero); - - if (toolbar_borders) { - priv->toolbar_borders = gtk_border_copy (toolbar_borders); - gtk_border_free (toolbar_borders); - } else - priv->toolbar_borders = g_boxed_copy (GTK_TYPE_BORDER, &zero); -} - -static gboolean -hildon_window_expose (GtkWidget *widget, - GdkEventExpose * event) -{ - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (widget); - g_assert (priv); - - GtkWidget *bx = priv->vbox; - GtkBox *box = GTK_BOX(bx); - GtkBorder *b = priv->borders; - GtkBorder *tb = priv->toolbar_borders; - gint tb_height = 0; - - if (! priv->borders) { - hildon_window_get_borders (HILDON_WINDOW (widget)); - b = priv->borders; - tb = priv->toolbar_borders; - } - - tb_height = bx->allocation.height + tb->top + tb->bottom; - - paint_toolbar (widget, box, - event, priv->fullscreen); - - if (priv->edit_toolbar != NULL) - { - paint_edit_toolbar (widget, priv->edit_toolbar, - event, priv->fullscreen); - } - - if (! priv->fullscreen) { - - /* Draw the left and right window border */ - gint side_borders_height = widget->allocation.height - b->top; - - if (priv->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 (! priv->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 (hildon_window_parent_class))->expose_event (widget, event); - - /* FIXME Not sure why this is commented out - * GTK_WIDGET_CLASS (hildon_window_parent_class))-> - * expose_event (widget, event); - */ - - return FALSE; -} - -static void -hildon_window_size_request (GtkWidget *widget, - GtkRequisition *requisition) -{ - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (widget); - g_assert (priv); - - GtkWidget *child = GTK_BIN (widget)->child; - GtkRequisition req2 = { 0 }; - 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 (priv->vbox != NULL) - gtk_widget_size_request (priv->vbox, &req2); - - requisition->height += req2.height; - requisition->width = MAX (requisition->width, req2.width); - - if (priv->edit_toolbar != NULL && GTK_WIDGET_VISIBLE (priv->edit_toolbar)) - { - GtkRequisition req; - gtk_widget_size_request (priv->edit_toolbar, &req); - requisition->height += req.height; - requisition->width = MAX (requisition->width, req.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_GET_PRIVATE (widget); - g_assert (priv); - - GtkAllocation box_alloc = { 0 }; - GtkAllocation edittb_alloc = { 0 }; - GtkAllocation alloc = *allocation; - - GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget)); - GtkBorder *tb; - - if (!priv->borders) - hildon_window_get_borders (HILDON_WINDOW (widget)); - - tb = priv->toolbar_borders; - - widget->allocation = *allocation; - - /* Calculate allocation of edit toolbar */ - if (priv->edit_toolbar != NULL && GTK_WIDGET_VISIBLE (priv->edit_toolbar)) - { - GtkRequisition req; - gtk_widget_get_child_requisition (priv->edit_toolbar, &req); - edittb_alloc.width = alloc.width - tb->left - tb->right; - edittb_alloc.height = MIN (req.height, alloc.height); - edittb_alloc.x = alloc.x + tb->left; - edittb_alloc.y = alloc.y + tb->top; - - if (edittb_alloc.height > 0) - { - alloc.y += tb->top + tb->bottom + edittb_alloc.height; - alloc.height -= tb->top + tb->bottom + edittb_alloc.height; - gtk_widget_size_allocate (priv->edit_toolbar, &edittb_alloc); - } - } - - /* Calculate allocation of normal toolbars */ - if (priv->vbox != NULL && GTK_WIDGET_VISIBLE (priv->vbox)) - { - GtkRequisition req; - gtk_widget_get_child_requisition (priv->vbox, &req); - box_alloc.width = alloc.width - tb->left - tb->right; - box_alloc.height = MIN (req.height, alloc.height); - box_alloc.x = alloc.x + tb->left; - box_alloc.y = alloc.y + alloc.height - box_alloc.height - tb->bottom; - - if (box_alloc.height > 0) - { - alloc.height -= tb->top + tb->bottom + box_alloc.height; - gtk_widget_size_allocate (priv->vbox, &box_alloc); - } - } - - /* Calculate allocation of the child widget */ - if (child != NULL && GTK_WIDGET_VISIBLE (child)) - { - guint border_width = gtk_container_get_border_width (GTK_CONTAINER (widget)); - alloc.x += border_width; - alloc.y += border_width; - alloc.width -= (border_width * 2); - alloc.height -= (border_width * 2); - - if (! priv->fullscreen) - { - GtkBorder *b = priv->borders; - alloc.x += b->left; - alloc.width -= (b->left + b->right); - - /* Use the top border if there's no edit toolbar */ - if (edittb_alloc.height <= 0) - { - alloc.y += b->top; - alloc.height -= b->top; - } - - /* Use the top border if there are no standard toolbars */ - if (box_alloc.height <= 0) - alloc.height -= b->bottom; - } - - gtk_widget_size_allocate (child, &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 = MIN (priv->previous_vbox_y, 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); - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (self); - - g_return_if_fail (callback != NULL); - g_assert (priv); - - GTK_CONTAINER_CLASS (hildon_window_parent_class)->forall (container, include_internals, - callback, callback_data); - - if (include_internals && priv->vbox != NULL) - (* callback)(GTK_WIDGET (priv->vbox), callback_data); - - if (include_internals && priv->edit_toolbar != NULL) - (* callback)(GTK_WIDGET (priv->edit_toolbar), callback_data); -} - -static void -hildon_window_show_all (GtkWidget *widget) -{ - HildonWindow *self = HILDON_WINDOW (widget); - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (self); - - g_assert (priv != NULL); - - GTK_WIDGET_CLASS (hildon_window_parent_class)->show_all (widget); - - gtk_widget_show_all (priv->vbox); - - if (priv->edit_toolbar) - gtk_widget_show_all (priv->edit_toolbar); -} - -static void -hildon_window_destroy (GtkObject *obj) -{ - HildonWindow *self = HILDON_WINDOW (obj); - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (obj); - GList *menu_list = NULL; - GList *menu_node = NULL; - - g_assert (priv != NULL); - - if (priv->vbox != NULL) - { - if (priv->program) - { - GtkWidget * common_toolbar = - GTK_WIDGET (hildon_program_get_common_toolbar (priv->program)); - if (common_toolbar && common_toolbar->parent == priv->vbox) - { - gtk_container_remove (GTK_CONTAINER (priv->vbox), - common_toolbar); - } - } - - gtk_widget_unparent (priv->vbox); - priv->vbox = NULL; - - } - - if (priv->edit_toolbar != NULL) - { - gtk_widget_unparent (priv->edit_toolbar); - priv->edit_toolbar = NULL; - } - - if (priv->app_menu) - { - hildon_app_menu_set_parent_window (priv->app_menu, NULL); - g_object_unref (priv->app_menu); - priv->app_menu = NULL; - } - - menu_list = g_list_copy (gtk_menu_get_for_attach_widget (GTK_WIDGET (obj))); - menu_node = menu_list; - - while (menu_node) - { - if (GTK_IS_MENU (menu_node->data)) - { - if (GTK_WIDGET_VISIBLE (GTK_WIDGET (menu_node->data))) - { - gtk_menu_popdown (GTK_MENU (menu_node->data)); - gtk_menu_shell_deactivate (GTK_MENU_SHELL (menu_node->data)); - } - gtk_menu_detach (GTK_MENU (menu_node->data)); - - /* Destroy it, but only if it's not a common menu */ - if (priv->program && - hildon_program_get_common_menu (priv->program) != menu_node->data) { - gtk_object_destroy (GTK_OBJECT (menu_node->data)); - g_object_unref (menu_node->data); - } - } - menu_node = menu_node->next; - } - - g_list_free (menu_list); - menu_list = NULL; - - if (priv->program) - { - hildon_program_remove_window (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 (hildon_window_parent_class)->destroy (obj); -} - -static void -hildon_window_notify (GObject *gobject, - GParamSpec *param) -{ - HildonWindow *window = HILDON_WINDOW (gobject); - - if (g_str_equal (param->name, "is-topmost")) - { - hildon_window_is_topmost_notify (window); - } - - if (G_OBJECT_CLASS(hildon_window_parent_class)->notify) - G_OBJECT_CLASS(hildon_window_parent_class)->notify (gobject, param); -} - - -static void -visible_toolbar (gpointer data, - gpointer user_data) -{ - if (GTK_WIDGET_VISIBLE (((GtkBoxChild *)data)->widget)) - (*((gint *)user_data))++; -} - -static void -paint_toolbar (GtkWidget *widget, - GtkBox *box, - GdkEventExpose * event, - gboolean fullscreen) -{ - gint toolbar_num = 0; - gint count; - - /* collect info to help on painting the boxes */ - g_list_foreach (box->children, visible_toolbar, - (gpointer) &toolbar_num); - - if(toolbar_num <= 0) - return; - - /*top most toolbar painting*/ - gtk_paint_box (widget->style, widget->window, - GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, - &event->area, widget, "toolbar-primary", - widget->allocation.x, - GTK_WIDGET(box)->allocation.y, - widget->allocation.width, - TOOLBAR_HEIGHT); - - /*multi toolbar painting*/ - for (count = 0; count < toolbar_num - 1; count++) - { - gtk_paint_box (widget->style, widget->window, - GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT, - &event->area, widget, "toolbar-secondary", - widget->allocation.x, - GTK_WIDGET(box)->allocation.y + - (1 + count) * (TOOLBAR_HEIGHT), - widget->allocation.width, - TOOLBAR_HEIGHT); - } -} - -static void -paint_edit_toolbar (GtkWidget *widget, - GtkWidget *toolbar, - GdkEventExpose *event, - gboolean fullscreen) -{ - if (!GTK_WIDGET_VISIBLE (toolbar)) - return; - - gtk_paint_box (widget->style, widget->window, - GTK_WIDGET_STATE (widget), GTK_SHADOW_OUT, - &event->area, widget, "toolbar-edit-mode", - toolbar->allocation.x, - toolbar->allocation.y, - toolbar->allocation.width, - toolbar->allocation.height); -} - -/* - * Checks the root window to know which is the topped window - */ -Window -hildon_window_get_active_window (void) -{ - Atom realtype; - gint xerror; - 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; - - gdk_error_trap_push (); - status = XGetWindowProperty (GDK_DISPLAY(), GDK_ROOT_WINDOW(), - active_app_atom, 0L, 16L, - 0, XA_WINDOW, &realtype, &format, - &n, &extra, &win.char_pointer); - xerror = gdk_error_trap_pop (); - if (xerror || !(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); -} - -/* - * 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 ), cm->data.l[2], cm->data.l[0]); - 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; -} - -/* - * Handle the menu hardware key here - */ -static gboolean -hildon_window_key_press_event (GtkWidget *widget, - GdkEventKey *event) -{ - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (widget); - - g_return_val_if_fail (HILDON_IS_WINDOW (widget),FALSE); - g_assert (priv); - - switch (event->keyval) - { - case HILDON_HARDKEY_MENU: - if (hildon_window_toggle_menu (HILDON_WINDOW (widget), 0, GDK_CURRENT_TIME)) - 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 (hildon_window_parent_class)->key_press_event (widget, event); -} - -static gboolean -hildon_window_key_release_event (GtkWidget *widget, - GdkEventKey *event) -{ - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (widget); - - g_return_val_if_fail (HILDON_IS_WINDOW (widget), FALSE); - g_assert (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 (hildon_window_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) -{ - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (widget); - g_assert (priv != NULL); - - if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) - priv->fullscreen = event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN; - - if (GTK_WIDGET_CLASS (hildon_window_parent_class)->window_state_event) - { - return GTK_WIDGET_CLASS (hildon_window_parent_class)->window_state_event ( - widget, - event); - } - else - { - return FALSE; - } -} - -/* - * 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. - */ -static gboolean -hildon_window_focus_out_event (GtkWidget *widget, - GdkEventFocus *event) -{ - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (widget); - - if (priv->escape_timeout) - { - g_source_remove (priv->escape_timeout); - priv->escape_timeout = 0; - } - - return GTK_WIDGET_CLASS (hildon_window_parent_class)->focus_out_event (widget, event); -} - -/* - * The menu popuping needs a menu popup-function - */ -static void -hildon_window_menu_popup_func (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); - - if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) - { - *x = GTK_WIDGET (widget)->allocation.width + window_x - GTK_WIDGET (menu)->allocation.width - *x; - } - else - *x += window_x; - - *y += window_y; - -} - -static void -hildon_window_menu_popup_func_full (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); - - if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) - *x = GTK_WIDGET (widget)->allocation.width - GTK_WIDGET (menu)->allocation.width - *x; - else - *x = MAX (0, *x); - - *y = MAX (0, *y); -} - - -/* - * Takes the common toolbar when we acquire the top-most status - */ -static void -hildon_window_is_topmost_notify (HildonWindow *window) -{ - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (window); - - g_assert (priv); - - if (priv->is_topmost) - { - hildon_window_take_common_toolbar (window); - } -} - -/* - * Sets the program to which the window belongs. This should only be called - * by hildon_program_add_window - */ -void G_GNUC_INTERNAL -hildon_window_set_program (HildonWindow *self, - GObject *program) -{ - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (self); - - g_return_if_fail (HILDON_IS_WINDOW (self)); - g_assert (priv != NULL); - - if (priv->program) - { - g_object_unref (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); - - 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_remove_window - */ -void G_GNUC_INTERNAL -hildon_window_unset_program (HildonWindow *self) -{ - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (self); - - g_return_if_fail(HILDON_IS_WINDOW (self)); - g_assert (priv != NULL); - - if (priv->program) - { - g_object_unref (priv->program); - 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 ); - } - - 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 G_GNUC_INTERNAL -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 G_GNUC_INTERNAL -hildon_window_take_common_toolbar (HildonWindow *self) -{ - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (self); - - g_return_if_fail(HILDON_IS_WINDOW (self)); - g_assert (priv); - - if (priv->program) - { - GtkWidget *common_toolbar = - GTK_WIDGET (hildon_program_get_common_toolbar (priv->program)); - - if (common_toolbar && common_toolbar->parent != 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(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 (priv->vbox); - - } - } -} - -/* - * Compare the window that was last topped, and act consequently - */ -void -hildon_window_update_topmost (HildonWindow *self, - Window window_id) -{ - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (self); - - GdkWindow *my_window; - - g_return_if_fail (HILDON_IS_WINDOW (self)); - g_assert (priv); - - my_window = GTK_WIDGET (self)->window; - - if (my_window && window_id == GDK_WINDOW_XID (my_window)) - { - if (! priv->is_topmost) - { - priv->is_topmost = TRUE; - hildon_window_is_topmost_notify (self); - g_object_notify (G_OBJECT (self), "is-topmost"); - } - } - else if (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); - - priv->is_topmost = FALSE; - hildon_window_is_topmost_notify (self); - g_object_notify (G_OBJECT (self), "is-topmost"); - } -} - -static void -detach_menu_func (GtkWidget *attach_widget, - GtkMenu *menu) -{ - /* FIXME Why is this even needed here? */ -} - -static gboolean -hildon_window_toggle_menu (HildonWindow *self, - guint button, - guint32 time) -{ - g_return_val_if_fail (HILDON_IS_WINDOW (self), FALSE); - - if (HILDON_WINDOW_GET_CLASS (self)->toggle_menu != NULL) - { - return HILDON_WINDOW_GET_CLASS (self)->toggle_menu (self, button, time); - } - else - { - return FALSE; - } -} - - -static gboolean -hildon_window_toggle_gtk_menu (HildonWindow *self, - GtkMenu *menu, - guint button, - guint32 time) -{ - gboolean retvalue = FALSE; - - g_return_val_if_fail (HILDON_IS_WINDOW (self), FALSE); - g_return_val_if_fail (GTK_IS_MENU (menu), FALSE); - - if (gtk_menu_get_attach_widget (menu) != GTK_WIDGET (self)) - { - g_object_ref (menu); - if (gtk_menu_get_attach_widget (menu)) - { - gtk_menu_detach (menu); - } - gtk_menu_attach_to_widget (menu, GTK_WIDGET (self), &detach_menu_func); - g_object_unref (menu); - } - - if (GTK_WIDGET_MAPPED (menu)) - { - gtk_menu_popdown (menu); - gtk_menu_shell_deactivate (GTK_MENU_SHELL (menu)); - retvalue = TRUE; - } - else - { - /* Check if the menu has items */ - GList *menu_children = gtk_container_get_children (GTK_CONTAINER (menu)); - - if (menu_children) - { - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (self); - g_list_free (menu_children); - - /* Apply right theming */ - gtk_widget_set_name (GTK_WIDGET (menu), "menu_force_with_corners"); - - if (priv->fullscreen) - { - gtk_menu_popup (menu, NULL, NULL, - (GtkMenuPositionFunc) - hildon_window_menu_popup_func_full, - self, button, time); - } - else - { - gtk_menu_popup (menu, NULL, NULL, - (GtkMenuPositionFunc) - hildon_window_menu_popup_func, - self, button, time); - } - gtk_menu_shell_select_first (GTK_MENU_SHELL (menu), TRUE); - retvalue = TRUE; - } - } - - return retvalue; -} - -static gboolean -hildon_window_toggle_app_menu (HildonWindow *self, - HildonAppMenu *menu) -{ - g_return_val_if_fail (HILDON_IS_WINDOW (self), FALSE); - g_return_val_if_fail (HILDON_IS_APP_MENU (menu), FALSE); - - if (self != hildon_app_menu_get_parent_window (menu)) - { - gtk_widget_hide (GTK_WIDGET (menu)); - } - - if (GTK_WIDGET_MAPPED (menu)) - { - gtk_widget_hide (GTK_WIDGET (menu)); - } - else - { - hildon_app_menu_popup (menu, GTK_WINDOW (self)); - } - - return TRUE; -} - -/* - * 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_real (HildonWindow * self, - guint button, - guint32 time) -{ - gboolean retvalue = FALSE; - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (self); - - g_return_val_if_fail (HILDON_IS_WINDOW (self), FALSE); - - /* Select which menu to use, Window specific has highest priority, - * then program specific */ - if (priv->menu) - { - retvalue = hildon_window_toggle_gtk_menu (self, priv->menu, button, time); - } - else if (priv->app_menu) - { - retvalue = hildon_window_toggle_app_menu (self, priv->app_menu); - } - else if (priv->program) - { - GtkMenu *gtkmenu = hildon_program_get_common_menu (priv->program); - HildonAppMenu *appmenu = hildon_program_get_common_app_menu (priv->program); - - if (gtkmenu) - { - retvalue = hildon_window_toggle_gtk_menu (self, gtkmenu, button, time); - } - else if (appmenu) - { - retvalue = hildon_window_toggle_app_menu (self, appmenu); - } - } - - return retvalue; -} - -/* - * If the ESC key was not released when the timeout expires, - * close the window - */ -static gboolean -hildon_window_escape_timeout (gpointer data) -{ - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (data); - GdkEvent *event; - - g_assert (priv); - - GDK_THREADS_ENTER (); - - /* 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; -} - -/** - * hildon_window_new: - * - * Creates 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 @child to the #HildonWindow and creates a scrollbar for - * it. Similar to adding first a #GtkScrolledWindow and then @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)); -} - -static void -calculate_visible_toolbars (gpointer data, - gpointer user_data) -{ - if (GTK_WIDGET_VISIBLE (GTK_WIDGET (((GtkBoxChild *)data)->widget))) - (*((gint *)user_data)) ++; -} - -static void -toolbar_visible_notify (GtkWidget *toolbar, GParamSpec *pspec, - HildonWindow *window) -{ - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (window); - - g_assert (priv); - - /* Recalculate from scratch the value just in case */ - priv->visible_toolbars = 0; - - g_list_foreach (GTK_BOX (priv->vbox)->children, calculate_visible_toolbars, - &priv->visible_toolbars); - - if (priv->visible_toolbars == 0) - gtk_widget_hide (priv->vbox); - else - gtk_widget_show (priv->vbox); -} - -/** - * hildon_window_add_toolbar: - * @self: A #HildonWindow - * @toolbar: A #GtkToolbar to add to the #HildonWindow - * - * Adds a toolbar to the window. Note that the toolbar is not automatically - * shown. You need to call gtk_widget_show_all() on it to make it visible. - * It's also possible to hide the toolbar (without removing it) by calling - * gtk_widget_hide() - **/ -void -hildon_window_add_toolbar (HildonWindow *self, - GtkToolbar *toolbar) -{ - GtkBox *vbox; - HildonWindowPrivate *priv; - - g_return_if_fail (HILDON_IS_WINDOW (self)); - g_return_if_fail (toolbar && GTK_IS_TOOLBAR (toolbar)); - - priv = HILDON_WINDOW_GET_PRIVATE (self); - - vbox = GTK_BOX (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); - - g_signal_connect (G_OBJECT (toolbar), "notify::visible", - G_CALLBACK (toolbar_visible_notify), self); - - if (GTK_WIDGET_VISIBLE (toolbar)) - { - priv->visible_toolbars++; - gtk_widget_show (priv->vbox); - } - - 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. Note that this decreases the refference - * count on the widget. If you want to keep the toolbar alive call g_object_ref() - * before calling this function. - **/ -void -hildon_window_remove_toolbar (HildonWindow *self, - GtkToolbar *toolbar) -{ - HildonWindowPrivate *priv; - - g_return_if_fail (HILDON_IS_WINDOW (self)); - - priv = HILDON_WINDOW_GET_PRIVATE (self); - - if (GTK_WIDGET_VISIBLE (toolbar)) - { - if (--(priv->visible_toolbars) == 0) - gtk_widget_hide (priv->vbox); - } - - g_signal_handlers_disconnect_by_func (toolbar, toolbar_visible_notify, self); - - gtk_container_remove (GTK_CONTAINER (priv->vbox), GTK_WIDGET (toolbar)); -} - -/** - * hildon_window_set_edit_toolbar: - * @self: A #HildonWindow - * @toolbar: A #HildonEditToolbar, or %NULL to remove the current one. - * - * Adds a #HildonEditToolbar to the window. Note that the toolbar is - * not automatically shown. You need to call gtk_widget_show() on it - * to make it visible. It's also possible to hide the toolbar (without - * removing it) by calling gtk_widget_hide(). - * - * A window can only have at most one edit toolbar at a time, so the - * previous toolbar (if any) is replaced after calling this function. - * - * Since: 2.2 - **/ -void -hildon_window_set_edit_toolbar (HildonWindow *self, - HildonEditToolbar *toolbar) -{ - HildonWindowPrivate *priv; - - g_return_if_fail (HILDON_IS_WINDOW (self)); - g_return_if_fail (toolbar == NULL || HILDON_IS_EDIT_TOOLBAR (toolbar)); - - priv = HILDON_WINDOW_GET_PRIVATE (self); - - if (priv->edit_toolbar != GTK_WIDGET (toolbar)) - { - GtkWidget *old_toolbar = priv->edit_toolbar; - priv->edit_toolbar = GTK_WIDGET (toolbar); - - if (priv->edit_toolbar) - gtk_widget_set_parent (priv->edit_toolbar, GTK_WIDGET (self)); - - if (old_toolbar) - gtk_widget_unparent (old_toolbar); - } -} - -/** - * hildon_window_get_main_menu: - * @self: a #HildonWindow - * - * Gets the #GtkMenu assigned to the #HildonAppview. Note that the - * window is still the owner of the menu. - * - * Note that if you're using a #HildonAppMenu rather than a #GtkMenu - * you should use hildon_window_get_app_menu() instead. - * - * Return value: The #GtkMenu assigned to this application view. - * - * Since: 2.2 - **/ -GtkMenu* -hildon_window_get_main_menu (HildonWindow * self) -{ - HildonWindowPrivate *priv; - - g_return_val_if_fail (HILDON_IS_WINDOW (self), NULL); - - priv = HILDON_WINDOW_GET_PRIVATE (self); - - return priv->menu; -} - -/** - * hildon_window_get_menu: - * @self: a #HildonWindow - * - * Return value: a #GtkMenu - * - * Deprecated: In Hildon 2.2 this function has been renamed to - * hildon_window_get_main_menu() for consistency - **/ -GtkMenu* -hildon_window_get_menu (HildonWindow * self) -{ - return hildon_window_get_main_menu (self); -} - -/* Since we've been asking developers to call gtk_window_add_accel_group() - * themselves, do not trigger criticals by trying it again. - */ -static void -hildon_window_add_accel_group (HildonWindow *self, - GtkAccelGroup *accel_group) -{ - GSList *groups, *l; - - groups = gtk_accel_groups_from_object (G_OBJECT (self)); - for (l = groups; l != NULL; l = l->next) - if (l->data == (gpointer)accel_group) - /* Maybe print a warning here? */ - return; - - gtk_window_add_accel_group (GTK_WINDOW (self), accel_group); -} - -/** - * hildon_window_set_main_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. #HildonWindow takes ownership of the passed menu and you're - * not supposed to free it yourself anymore. - * - * Note that if you're using a #HildonAppMenu rather than a #GtkMenu - * you should use hildon_window_set_app_menu() instead. - **/ -void -hildon_window_set_main_menu (HildonWindow* self, - GtkMenu * menu) -{ - HildonWindowPrivate *priv; - GtkAccelGroup *accel_group; - - g_return_if_fail (HILDON_IS_WINDOW (self)); - - priv = HILDON_WINDOW_GET_PRIVATE (self); - - if (priv->menu != NULL) - { - accel_group = gtk_menu_get_accel_group (priv->menu); - if (accel_group != NULL) - gtk_window_remove_accel_group (GTK_WINDOW (self), accel_group); - - gtk_menu_detach (priv->menu); - g_object_unref (priv->menu); - } - - priv->menu = menu; - if (priv->menu != NULL) - { - gtk_widget_set_name (GTK_WIDGET (priv->menu), "menu_force_with_corners"); - gtk_menu_attach_to_widget (priv->menu, GTK_WIDGET (self), &detach_menu_func); - g_object_ref (priv->menu); - - accel_group = gtk_menu_get_accel_group (priv->menu); - if (accel_group != NULL) - hildon_window_add_accel_group (self, accel_group); - } -} - -/** - * 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. HildonWindow takes ownership of the passed menu and you're - * not supposed to free it yourself anymore. - * - * Note: hildon_window_set_menu() calls gtk_widget_show_all() for the - * #GtkMenu. To pass control about visibility to the application - * developer, hildon_window_set_main_menu() was introduced, which - * doesn't do this. - * - * Deprecated: Hildon 2.2: use hildon_window_set_main_menu() - **/ -void -hildon_window_set_menu (HildonWindow *self, - GtkMenu *menu) -{ - HildonWindowPrivate *priv; - - g_return_if_fail (HILDON_IS_WINDOW (self)); - - hildon_window_set_main_menu (self, menu); - - priv = HILDON_WINDOW_GET_PRIVATE (self); - - if (priv->menu != NULL) - gtk_widget_show_all (GTK_WIDGET (priv->menu)); -} - -/** - * hildon_window_get_is_topmost: - * @self: A #HildonWindow - * - * Returns whether the #HildonWindow is currenty activated by the - * window manager. - * - * Return value: %TRUE if @self is currently activated, %FALSE otherwise. - **/ -gboolean -hildon_window_get_is_topmost (HildonWindow *self) -{ - HildonWindowPrivate *priv; - - g_return_val_if_fail (HILDON_IS_WINDOW (self), FALSE); - - priv = HILDON_WINDOW_GET_PRIVATE (self); - return priv->is_topmost; -} - -/** - * hildon_window_set_app_menu: - * @self: a #HildonWindow - * @menu: a #HildonAppMenu to be used for this window - * - * Sets the menu to be used for this window. Pass %NULL to remove the - * current menu. Any reference to a previous menu will be dropped. - * #HildonWindow takes ownership of the passed menu and - * you're not supposed to free it yourself anymore. - * - * Note that if you're using a #GtkMenu rather than a #HildonAppMenu - * you should use hildon_window_set_main_menu() instead. - * - * Since: 2.2 - **/ -void -hildon_window_set_app_menu (HildonWindow *self, - HildonAppMenu *menu) -{ - HildonWindowPrivate *priv; - HildonAppMenu *old_menu; - - g_return_if_fail (HILDON_IS_WINDOW (self)); - g_return_if_fail (!menu || HILDON_IS_APP_MENU (menu)); - priv = HILDON_WINDOW_GET_PRIVATE (self); - - old_menu = priv->app_menu; - - /* Add new menu */ - priv->app_menu = menu; - if (menu) - g_object_ref_sink (menu); - - /* Unref old menu */ - if (old_menu) - g_object_unref (old_menu); -} - -/** - * hildon_window_get_app_menu: - * @self: a #HildonWindow - * - * Returns the #HildonAppMenu assigned to @self, or %NULL if it's - * unset. Note that the window is still the owner of the menu. - * - * Note that if you're using a #GtkMenu rather than a #HildonAppMenu - * you should use hildon_window_get_main_menu() instead. - * - * Returns: a #HildonAppMenu - * - * Since: 2.2 - **/ -HildonAppMenu * -hildon_window_get_app_menu (HildonWindow *self) -{ - HildonWindowPrivate *priv; - - g_return_val_if_fail (HILDON_IS_WINDOW (self), NULL); - - priv = HILDON_WINDOW_GET_PRIVATE (self); - - return priv->app_menu; -} - -static void -hildon_window_update_markup (HildonWindow *window) -{ - HildonWindowPrivate *priv = HILDON_WINDOW_GET_PRIVATE (window); - GdkAtom markup_atom = gdk_atom_intern ("_HILDON_WM_NAME", FALSE); - GdkAtom utf8_atom = gdk_atom_intern ("UTF8_STRING", FALSE); - GdkWindow *gdkwin = GTK_WIDGET (window)->window; - - if (priv->markup) { - gdk_property_change (gdkwin, markup_atom, utf8_atom, 8, - GDK_PROP_MODE_REPLACE, (const guchar *) priv->markup, - strlen (priv->markup)); - } else { - gdk_property_delete (gdkwin, markup_atom); - } -} - -/** - * hildon_window_get_markup: - * @window: a #HildonWindow - * - * Gets the marked up title of the window title. See hildon_window_set_markup() - * - * Returns: the marked up title of the window, or %NULL if none has - * been set explicitely. The returned string is owned by the widget - * and must not be modified or freed. - * - * Since: 2.2 - **/ -const gchar * -hildon_window_get_markup (HildonWindow *window) -{ - HildonWindowPrivate *priv; - - g_return_val_if_fail (HILDON_IS_WINDOW (window), NULL); - - priv = HILDON_WINDOW_GET_PRIVATE (window); - - return priv->markup; -} - -/** - * hildon_window_set_markup: - * @window: a #HildonWindow - * @markup: the marked up title of the window, or %NULL to unset the - * current one - * - * Sets the marked up title of @window. The accepted format is the one - * used in Pango (see #PangoMarkupFormat) with the exception of - * <span>. - * - * Note that you need support from the window manager for this title - * to be used. See gtk_window_set_title() for the standard way of - * setting the title of a window. - * - * Since: 2.2 - **/ -void -hildon_window_set_markup (HildonWindow *window, - const gchar *markup) -{ - HildonWindowPrivate *priv; - gchar *new_markup; - - g_return_if_fail (HILDON_IS_WINDOW (window)); - - priv = HILDON_WINDOW_GET_PRIVATE (window); - - new_markup = g_strdup (markup); - g_free (priv->markup); - priv->markup = new_markup; - - if (GTK_WIDGET_REALIZED (window)) - hildon_window_update_markup (window); - - g_object_notify (G_OBJECT (window), "markup"); -} diff --git a/src/hildon-window.h b/src/hildon-window.h deleted file mode 100644 index e5d8d49..0000000 --- a/src/hildon-window.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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 "hildon-app-menu.h" -#include "hildon-edit-toolbar.h" - -G_BEGIN_DECLS - -#define HILDON_WINDOW_LONG_PRESS_TIME 800 /* 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)) - -#define HILDON_WINDOW_GET_CLASS(obj) \ - ((HildonWindowClass *) G_OBJECT_GET_CLASS(obj)) - -typedef struct _HildonWindow HildonWindow; - -typedef struct _HildonWindowClass HildonWindowClass; - -typedef enum -{ - HILDON_WINDOW_CO_COPY, - HILDON_WINDOW_CO_CUT, - HILDON_WINDOW_CO_PASTE -} HildonWindowClipboardOperation; - -struct _HildonWindow -{ - GtkWindow parent; -}; - -struct _HildonWindowClass -{ - GtkWindowClass parent_class; - - /* opera hacks for clip board operation */ - void (*clipboard_operation)(HildonWindow *hwindow, int operation); - gboolean (*toggle_menu)(HildonWindow * self, guint button, guint32 time); - /* Padding for future extension */ - void (*_hildon_reserved1)(void); - void (*_hildon_reserved2)(void); -}; - -GType G_GNUC_CONST -hildon_window_get_type (void); - -GtkWidget* -hildon_window_new (void); - -void -hildon_window_add_with_scrollbar (HildonWindow *self, - GtkWidget *child); - -void -hildon_window_set_main_menu (HildonWindow *self, - GtkMenu *menu); - -GtkMenu* -hildon_window_get_main_menu (HildonWindow *self); - -void -hildon_window_set_app_menu (HildonWindow *self, - HildonAppMenu *menu); - -HildonAppMenu * -hildon_window_get_app_menu (HildonWindow *self); - -#ifndef HILDON_DISABLE_DEPRECATED -void -hildon_window_set_menu (HildonWindow *self, - GtkMenu *menu); - -GtkMenu* -hildon_window_get_menu (HildonWindow *self); -#endif - -void -hildon_window_add_toolbar (HildonWindow *self, - GtkToolbar *toolbar); - -void -hildon_window_remove_toolbar (HildonWindow *self, - GtkToolbar *toolbar); - -void -hildon_window_set_edit_toolbar (HildonWindow *self, - HildonEditToolbar *toolbar); - -gboolean -hildon_window_get_is_topmost (HildonWindow *self); - -const gchar * -hildon_window_get_markup (HildonWindow *window); - -void -hildon_window_set_markup (HildonWindow *window, - const gchar *markup); - -G_END_DECLS - -#endif /* __HILDON_WINDOW_H__ */ diff --git a/src/hildon-wizard-dialog-private.h b/src/hildon-wizard-dialog-private.h deleted file mode 100644 index deed7c9..0000000 --- a/src/hildon-wizard-dialog-private.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * 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, or (at your option) any later version. - * - * 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_PRIVATE_H__ -#define __HILDON_WIZARD_DIALOG_PRIVATE_H__ - -G_BEGIN_DECLS - -#define HILDON_WIZARD_DIALOG_GET_PRIVATE(obj)\ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ - HILDON_TYPE_WIZARD_DIALOG, \ - HildonWizardDialogPrivate)); - -typedef struct _HildonWizardDialogPrivate HildonWizardDialogPrivate; - -struct _HildonWizardDialogPrivate -{ - gchar *wizard_name; - GtkNotebook *notebook; - gboolean autotitle; - - HildonWizardDialogPageFunc forward_function; - gpointer forward_function_data; - GDestroyNotify forward_data_destroy; -}; - -G_END_DECLS - -#endif /* __HILDON_WIZARD_DIALOG_PRIVATE_H__ */ - diff --git a/src/hildon-wizard-dialog.c b/src/hildon-wizard-dialog.c deleted file mode 100644 index 8a8ee83..0000000 --- a/src/hildon-wizard-dialog.c +++ /dev/null @@ -1,555 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * 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, or (at your option) any later version. - * - * 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 three standard buttons, previous, next, - * finish, and contains several pages. - * - * Response buttons are dimmed/undimmed automatically. The notebook - * widget provided by users contains the actual wizard pages. - * - * Usage of the API is very simple, it has only one function to create it - * and the rest of it is handled by developers notebook. - * Also, the response is returned, either cancel or finish. - * Next and previous buttons are handled by the wizard dialog it self, by - * switching the page either forward or backward in the notebook. - * - * It is possible to determinate whether users can go to the next page - * by setting a #HildonWizardDialogPageFunc function with - * hildon_wizard_dialog_set_forward_page_func() - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "hildon-wizard-dialog.h" -#include "hildon-defines.h" -#include "hildon-wizard-dialog-private.h" - -#define _(String) dgettext("hildon-libs", String) - -static GtkDialogClass* parent_class; - -static void -hildon_wizard_dialog_class_init (HildonWizardDialogClass *wizard_dialog_class); - -static void -hildon_wizard_dialog_init (HildonWizardDialog *wizard_dialog); - -static void -create_title (HildonWizardDialog *wizard_dialog); - -static void -hildon_wizard_dialog_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec); - -static void -hildon_wizard_dialog_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec); - -static void -finalize (GObject *object); - -static void -destroy (GtkObject *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_0, - PROP_NAME, - PROP_NOTEBOOK, - PROP_AUTOTITLE -}; - -/** - * hildon_wizard_dialog_get_type: - * - * Initializes and returns the type of a hildon wizard dialog. - * - * Returns: GType of #HildonWzardDialog - */ -GType G_GNUC_CONST -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) hildon_wizard_dialog_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (HildonWizardDialog), - 0, /* n_preallocs */ - (GInstanceInitFunc) hildon_wizard_dialog_init, - }; - - wizard_dialog_type = g_type_register_static (GTK_TYPE_DIALOG, - "HildonWizardDialog", - &wizard_dialog_info, - 0); - } - - return wizard_dialog_type; -} - -static void -hildon_wizard_dialog_class_init (HildonWizardDialogClass *wizard_dialog_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (wizard_dialog_class); - GtkObjectClass *gtk_object_class = GTK_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 = hildon_wizard_dialog_set_property; - object_class->get_property = hildon_wizard_dialog_get_property; - object_class->finalize = finalize; - gtk_object_class->destroy = destroy; - - /** - * HildonWizardDialog:wizard-name: - * - * The name of the wizard. - */ - g_object_class_install_property (object_class, PROP_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_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_AUTOTITLE, - g_param_spec_boolean - ("autotitle", - "AutoTitle", - "If the wizard should autotitle itself", - TRUE, - G_PARAM_READWRITE)); -} - -static void -finalize (GObject *object) -{ - HildonWizardDialogPrivate *priv = HILDON_WIZARD_DIALOG_GET_PRIVATE (object); - - g_assert (priv); - - if (priv->wizard_name != NULL) - g_free (priv->wizard_name); - - if (G_OBJECT_CLASS (parent_class)->finalize) - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -destroy (GtkObject *object) -{ - HildonWizardDialogPrivate *priv = HILDON_WIZARD_DIALOG_GET_PRIVATE (object); - - g_assert (priv); - - if (priv->forward_function) - { - if (priv->forward_function_data && - priv->forward_data_destroy) - priv->forward_data_destroy (priv->forward_function_data); - - priv->forward_function = NULL; - priv->forward_function_data = NULL; - priv->forward_data_destroy = NULL; - } -} - -/* 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 -hildon_wizard_dialog_init (HildonWizardDialog *wizard_dialog) -{ - /* Initialize private structure for faster member access */ - HildonWizardDialogPrivate *priv = HILDON_WIZARD_DIALOG_GET_PRIVATE (wizard_dialog); - g_assert (priv); - - GtkDialog *dialog = GTK_DIALOG (wizard_dialog); - - /* Init internal widgets */ - gtk_dialog_set_has_separator (dialog, FALSE); - - /* Default values for user provided properties */ - priv->notebook = NULL; - priv->wizard_name = NULL; - priv->autotitle = TRUE; - - priv->forward_function = NULL; - priv->forward_function_data = NULL; - priv->forward_data_destroy = NULL; - - /* Add response buttons: finish, previous, next */ - gtk_dialog_add_button (dialog, _("wdgt_bd_finish"), HILDON_WIZARD_DIALOG_FINISH); - gtk_dialog_add_button (dialog, _("wdgt_bd_previous"), HILDON_WIZARD_DIALOG_PREVIOUS); - gtk_dialog_add_button (dialog, _("wdgt_bd_next"), HILDON_WIZARD_DIALOG_NEXT); - - /* 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 -hildon_wizard_dialog_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - HildonWizardDialogPrivate *priv = HILDON_WIZARD_DIALOG_GET_PRIVATE (object); - GtkDialog *dialog = GTK_DIALOG (object); - - g_assert (priv); - - switch (property_id) { - - case PROP_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_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_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 (dialog->vbox), 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 (GTK_WIDGET (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 -hildon_wizard_dialog_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - HildonWizardDialogPrivate *priv = HILDON_WIZARD_DIALOG_GET_PRIVATE (object); - g_assert (priv); - - switch (property_id) { - - case PROP_NAME: - g_value_set_string (value, priv->wizard_name); - break; - - case PROP_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 = HILDON_WIZARD_DIALOG_GET_PRIVATE (wizard_dialog); - GtkNotebook *notebook; - - g_assert (priv); - 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); - } else { - const gchar *steps = gtk_notebook_get_tab_label_text (notebook, - gtk_notebook_get_nth_page (notebook, current)); - - if (steps) { - str = g_strdup_printf ("%s: %s", priv->wizard_name, steps); - } else { - str = g_strdup (priv->wizard_name); - } - } - - /* 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 = HILDON_WIZARD_DIALOG_GET_PRIVATE (wizard_dialog); - GtkNotebook *notebook = priv->notebook; - gint current = 0; - gint last = gtk_notebook_get_n_pages (notebook) - 1; - gboolean is_first, is_last; - - g_assert (priv); - - current = gtk_notebook_current_page (notebook); - - switch (response_id) { - - case HILDON_WIZARD_DIALOG_PREVIOUS: - --current; - is_last = (current == last); - is_first = (current == 0); - make_buttons_sensitive (wizard_dialog, - !is_first, !is_first, !is_last); - gtk_notebook_prev_page (notebook); /* go to previous page */ - break; - - case HILDON_WIZARD_DIALOG_NEXT: - - if (!priv->forward_function || - (*priv->forward_function) (priv->notebook, current, priv->forward_function_data)) { - ++current; - is_last = (current == last); - is_first = (current == 0); - make_buttons_sensitive (wizard_dialog, - !is_first, !is_first, !is_last); - gtk_notebook_next_page (notebook); /* go to next page */ - } - break; - - case HILDON_WIZARD_DIALOG_FINISH: - return; - - } - - current = gtk_notebook_get_current_page (notebook); - is_last = current == last; - is_first = current == 0; - - /* Don't let the dialog close */ - g_signal_stop_emission_by_name (wizard_dialog, "response"); - - /* 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; -} - -/** - * hildon_wizard_dialog_set_forward_page_func: - * @wizard_dialog: a #HildonWizardDialog - * @page_func: the #HildonWizardDialogPageFunc - * @data: user data for @page_func - * @destroy: destroy notifier for @data - * - * Sets the page forwarding function to be @page_func. This function - * will be used to determine whether it is possible to go to the next page - * when the user presses the forward button. Setting @page_func to %NULL - * wil make the wizard to simply go always to the next page. - * - * Since: 2.2 - **/ -void -hildon_wizard_dialog_set_forward_page_func (HildonWizardDialog *wizard_dialog, - HildonWizardDialogPageFunc page_func, - gpointer data, - GDestroyNotify destroy) -{ - g_return_if_fail (HILDON_IS_WIZARD_DIALOG (wizard_dialog)); - - HildonWizardDialogPrivate *priv = HILDON_WIZARD_DIALOG_GET_PRIVATE (wizard_dialog); - - if (priv->forward_data_destroy && - priv->forward_function_data) { - (*priv->forward_data_destroy) (priv->forward_function_data); - } - - priv->forward_function = page_func; - priv->forward_function_data = data; - priv->forward_data_destroy = destroy; -} diff --git a/src/hildon-wizard-dialog.h b/src/hildon-wizard-dialog.h deleted file mode 100644 index a39abe4..0000000 --- a/src/hildon-wizard-dialog.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * 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, or (at your option) any later version. - * - * 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 - -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; - -/* HILDON_WIZARD_DIALOG_CANCEL should be marked as deprecated */ - -/** - * HildonWizardDialogResponse: - * @HILDON_WIZARD_DIALOG_CANCEL: Returned by the 'Cancel' button. - * @HILDON_WIZARD_DIALOG_PREVIOUS: Returned by the 'Previous' button. - * @HILDON_WIZARD_DIALOG_NEXT: Returned by the 'Next' button. - * @HILDON_WIZARD_DIALOG_FINISH: Returned by the 'Finish' button. - * - * Predefined values for use as response ids for #HildonWizardDialog. - * - * - * - * HILDON_WIZARD_DIALOG_CANCEL is deprecated and should not be used in newly-written code. - * - * - **/ -typedef enum -{ - HILDON_WIZARD_DIALOG_CANCEL = GTK_RESPONSE_CANCEL, - HILDON_WIZARD_DIALOG_PREVIOUS = 0, - HILDON_WIZARD_DIALOG_NEXT, - HILDON_WIZARD_DIALOG_FINISH -} HildonWizardDialogResponse; - -struct _HildonWizardDialog -{ - GtkDialog parent; -}; - -struct _HildonWizardDialogClass -{ - GtkDialogClass parent_class; -}; - -typedef gboolean (*HildonWizardDialogPageFunc) (GtkNotebook *notebook, gint current_page, gpointer data); - -GType G_GNUC_CONST -hildon_wizard_dialog_get_type (void); - -GtkWidget* -hildon_wizard_dialog_new (GtkWindow *parent, - const char *wizard_name, - GtkNotebook *notebook); - -void -hildon_wizard_dialog_set_forward_page_func (HildonWizardDialog *wizard_dialog, - HildonWizardDialogPageFunc page_func, - gpointer data, - GDestroyNotify destroy); - -G_END_DECLS - -#endif /* __HILDON_WIZARD_DIALOG_H__ */ - diff --git a/src/hildon.h b/src/hildon.h deleted file mode 100644 index b593c0e..0000000 --- a/src/hildon.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * This file is a part of hildon - * - * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. - * - * Contact: Rodrigo Novo - * - * 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, or (at your option) any later version. - * - * 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_H__ -#define __HILDON_H__ - -#include "hildon-version.h" -#include "hildon-banner.h" -#include "hildon-calendar-popup.h" -#include "hildon-caption.h" -#include "hildon-code-dialog.h" -#include "hildon-color-button.h" -#include "hildon-color-chooser-dialog.h" -#include "hildon-color-chooser.h" -#include "hildon-controlbar.h" -#include "hildon-date-editor.h" -#include "hildon-defines.h" -#include "hildon-helper.h" -#include "hildon-enum-types.h" -#include "hildon-find-toolbar.h" -#include "hildon-edit-toolbar.h" -#include "hildon-font-selection-dialog.h" -#include "hildon-get-password-dialog.h" -#include "hildon-hvolumebar.h" -#include "hildon-login-dialog.h" -#include "hildon-marshalers.h" -#include "hildon-note.h" -#include "hildon-number-editor.h" -#include "hildon-program.h" -#include "hildon-range-editor.h" -#include "hildon-seekbar.h" -#include "hildon-set-password-dialog.h" -#include "hildon-sort-dialog.h" -#include "hildon-sound.h" -#include "hildon-time-editor.h" -#include "hildon-time-picker.h" -#include "hildon-date-selector.h" -#include "hildon-time-selector.h" -#include "hildon-touch-selector.h" -#include "hildon-touch-selector-entry.h" -#include "hildon-picker-dialog.h" -#include "hildon-picker-button.h" -#include "hildon-date-button.h" -#include "hildon-time-button.h" -#include "hildon-volumebar-range.h" -#include "hildon-volumebar.h" -#include "hildon-vvolumebar.h" -#include "hildon-weekday-picker.h" -#include "hildon-window.h" -#include "hildon-stackable-window.h" -#include "hildon-window-stack.h" -#include "hildon-animation-actor.h" -#include "hildon-wizard-dialog.h" -#include "hildon-calendar.h" -#include "hildon-bread-crumb-trail.h" -#include "hildon-pannable-area.h" -#include "hildon-entry.h" -#include "hildon-text-view.h" -#include "hildon-app-menu.h" -#include "hildon-button.h" -#include "hildon-check-button.h" -#include "hildon-gtk.h" -#include "hildon-dialog.h" -#include "hildon-main.h" - -#endif -- 1.7.9.5