aboutsummaryrefslogtreecommitdiffstats
path: root/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'widgets')
-rw-r--r--widgets/ChangeLog579
-rw-r--r--widgets/Makefile.am66
-rw-r--r--widgets/ROADMAP.e-table113
-rw-r--r--widgets/TODO24
-rw-r--r--widgets/add-col.xpm22
-rw-r--r--widgets/check-empty.xpm21
-rw-r--r--widgets/check-filled.xpm21
-rw-r--r--widgets/e-cell-checkbox.c44
-rw-r--r--widgets/e-cell-checkbox.h24
-rw-r--r--widgets/e-cell-string.c9
-rw-r--r--widgets/e-cell-text.c508
-rw-r--r--widgets/e-cell-text.h28
-rw-r--r--widgets/e-cell-toggle.c298
-rw-r--r--widgets/e-cell-toggle.h35
-rw-r--r--widgets/e-cell.c176
-rw-r--r--widgets/e-cell.h73
-rw-r--r--widgets/e-table-col-dnd.h10
-rw-r--r--widgets/e-table-col.c64
-rw-r--r--widgets/e-table-col.h44
-rw-r--r--widgets/e-table-column-item.c199
-rw-r--r--widgets/e-table-column-item.h20
-rw-r--r--widgets/e-table-column-model.h5
-rw-r--r--widgets/e-table-column.c293
-rw-r--r--widgets/e-table-group.c269
-rw-r--r--widgets/e-table-group.h63
-rw-r--r--widgets/e-table-header-item.c793
-rw-r--r--widgets/e-table-header-item.h56
-rw-r--r--widgets/e-table-header.c342
-rw-r--r--widgets/e-table-header.h65
-rw-r--r--widgets/e-table-item.c1316
-rw-r--r--widgets/e-table-item.h106
-rw-r--r--widgets/e-table-model.c176
-rw-r--r--widgets/e-table-model.h58
-rw-r--r--widgets/e-table-render.c20
-rw-r--r--widgets/e-table-render.h21
-rw-r--r--widgets/e-table-simple.c111
-rw-r--r--widgets/e-table-simple.h37
-rw-r--r--widgets/e-table-sorted.c89
-rw-r--r--widgets/e-table-sorted.h29
-rw-r--r--widgets/e-table-subset.c178
-rw-r--r--widgets/e-table-subset.h32
-rw-r--r--widgets/e-table-tree.h19
-rw-r--r--widgets/e-table.c558
-rw-r--r--widgets/e-table.h48
-rw-r--r--widgets/e-table/Makefile.am22
-rw-r--r--widgets/e-table/e-cell-checkbox.c2
-rw-r--r--widgets/e-table/e-cell-text.c2
-rw-r--r--widgets/e-table/e-cell-toggle.c2
-rw-r--r--widgets/e-table/e-cell.c2
-rw-r--r--widgets/e-table/e-table-col.c2
-rw-r--r--widgets/e-table/e-table-group.c2
-rw-r--r--widgets/e-table/e-table-sorted.c2
-rw-r--r--widgets/e-table/e-table-subset.c2
-rw-r--r--widgets/e-table/e-table.c2
-rw-r--r--widgets/e-util.h24
-rw-r--r--widgets/image1.pngbin1858 -> 0 bytes
-rw-r--r--widgets/image2.pngbin1987 -> 0 bytes
-rw-r--r--widgets/image3.pngbin2051 -> 0 bytes
-rw-r--r--widgets/remove-col.xpm22
-rw-r--r--widgets/sample.table11
-rw-r--r--widgets/shortcut-bar/Makefile.am30
-rw-r--r--widgets/shortcut-bar/e-clipped-label.c361
-rw-r--r--widgets/shortcut-bar/e-clipped-label.h90
-rw-r--r--widgets/shortcut-bar/e-group-bar.c1498
-rw-r--r--widgets/shortcut-bar/e-group-bar.h171
-rw-r--r--widgets/shortcut-bar/e-icon-bar-bg-item.c361
-rw-r--r--widgets/shortcut-bar/e-icon-bar-bg-item.h72
-rw-r--r--widgets/shortcut-bar/e-icon-bar-text-item.c1696
-rw-r--r--widgets/shortcut-bar/e-icon-bar-text-item.h158
-rw-r--r--widgets/shortcut-bar/e-icon-bar.c1450
-rw-r--r--widgets/shortcut-bar/e-icon-bar.h221
-rw-r--r--widgets/shortcut-bar/e-shortcut-bar.c563
-rw-r--r--widgets/shortcut-bar/e-shortcut-bar.h114
-rw-r--r--widgets/shortcut-bar/e-vscrolled-bar.c652
-rw-r--r--widgets/shortcut-bar/e-vscrolled-bar.h97
-rw-r--r--widgets/shortcut-bar/test-shortcut-bar.c445
-rw-r--r--widgets/table-test.c43
-rw-r--r--widgets/table-test.h4
-rw-r--r--widgets/table/e-cell-checkbox.c2
-rw-r--r--widgets/table/e-cell-text.c2
-rw-r--r--widgets/table/e-cell-toggle.c2
-rw-r--r--widgets/table/e-cell.c2
-rw-r--r--widgets/table/e-table-col.c2
-rw-r--r--widgets/table/e-table-group.c2
-rw-r--r--widgets/table/e-table-sorted.c2
-rw-r--r--widgets/table/e-table-subset.c2
-rw-r--r--widgets/table/e-table.c2
-rw-r--r--widgets/test-check.c153
-rw-r--r--widgets/test-cols.c196
-rw-r--r--widgets/test-table.c304
-rw-r--r--widgets/test.c17
91 files changed, 8007 insertions, 7866 deletions
diff --git a/widgets/ChangeLog b/widgets/ChangeLog
deleted file mode 100644
index 47e410e613..0000000000
--- a/widgets/ChangeLog
+++ /dev/null
@@ -1,579 +0,0 @@
-1999-12-30 Miguel de Icaza <miguel@gnu.org>
-
- * e-table-item.c (eti_attach_cell_views): New routine, creates the
- cell views.
- (eti_detach_cell_views): Detaches the cell_views from the
- ETableItem.
- (eti_realize_cell_views, eti_unrealize_cell_views): Simplified to
- just do realize/unrealize notification.
- (eti_add_table_model): Only attach the cells when we have both the
- table model and the header model.
-
- * e-cell.h (ECellClass): Added two new methods: new_view and
- kill_view which drive the view process (instead of putting that on
- realize/unrealize).
-
- * e-cell.c: Adapt the code to use the new scheme for view
- instantiation.
-
- * e-cell-text.c, e-cell-toggle.c: Adapted to the new class
- changes.
-
-1999-12-22 Miguel de Icaza <miguel@helixcode.com>
-
- * e-table-item.c (e_table_item_focus): grab focus here with the
- canvas method.
-
-1999-12-20 Miguel de Icaza <miguel@helixcode.com>
-
- * e-table-group.c (etg_update): Change the dimensions only if the
- child changes its own.
-
- * e-table-item.c (eti_table_model_changed): Emit new signal on
- table height change.
- (eti_class_init): Register new "height_change" signal.
-
-1999-12-19 Damon Chaplin <damon@karuna.freeserve.co.uk>
-
- * Makefile.am (SUBDIRS): created SUBDIRS with meeting-time-sel.
-
- * meeting-time-sel/Makefile.am:
- * meeting-time-sel/.cvsignore:
- * meeting-time-sel/e-meeting-time-sel.h:
- * meeting-time-sel/e-meeting-time-sel.c:
- * meeting-time-sel/e-meeting-time-sel-item.h:
- * meeting-time-sel/e-meeting-time-sel-item.c:
- * meeting-time-sel/e-meeting-time-sel-list-item.h:
- * meeting-time-sel/e-meeting-time-sel-list-item.c:
- * meeting-time-sel/e-meeting-time-sel-mail.xpm:
- * meeting-time-sel/e-meeting-time-sel-no-mail.xpm:
- * meeting-time-sel/test-meeting-time-sel.c: new files implementing
- the meeting time selector.
-
-1999-12-12 Miguel de Icaza <miguel@helixcode.com>
-
- * e-table-item.c (eti_class_init): X and Y arguments are now
- doubles (to make it consistent with the rest of the canvas x, y
- arguments).
-
- * e-table.c (e_table_create_leaf): Use new argument values here
-
- * test-*.c: Update to new argument types for x and y
-
- * e-table-group.c: New implementation as a canvas item used to
- group childs.
-
- * e-table-item.c (eti_update): Make this play nicely with groups.
- (eti_draw): ditto.
- (eti_request_region_redraw): ditto.
- (eti_item_region_redraw): New function.
-
- * e-table-subset.c (etss_proxy_model_row_changed): Added model
- proxying.
-
- * e-cell.h: Drop ETableModel from the ECell;
- (realize): Now takes an ETableModel
-
- * e-cell-checkbox.c: Adapted to new class
- changes;
- * e-cell-toggle.c: ditto
-
- * e-table-subset.c (etss_row_count): Fix this guy.
-
-1999-12-11 Miguel de Icaza <miguel@helixcode.com>
-
- * e-table-item.c (eti_unrealize_cell_views): Null the cell views.
- (eti_header_structure_changed): Only unrealize/realize if we were
- realized before.
-
- * e-table-header.c (e_table_header_add_column): Allow -1 as an
- insert position
-
-1999-12-11 Miguel de Icaza <miguel@helixcode.com>
-
- * e-table.c: Massive fixage.
-
- * test-table.c: Updates to test the mega widget.
-
-1999-12-10 Miguel de Icaza <miguel@helixcode.com>
-
- * e-table.c: New file, implements the mega widget.
-
-1999-12-09 Miguel de Icaza <miguel@gnu.org>
-
- * e-table-header.c (e_table_header_col_diff): fix this routine.
-
-1999-12-04 Miguel de Icaza <miguel@gnu.org>
-
- * e-table-header-item.c (ethi_event): Started drag and drop
- support.
-
- * e-table-item.c (eti_table_model_changed): The columns are
- controled by the Header, not by the TableModel.
-
- * e-table-header-item.c (ethi_draw): Fixed redraw logic to support
- arbitrary header positioning.
-
- * e-cell.h: Revamped e-cell interface. We now provide the model
- column and the view column to all methods (so that the methods can
- talk to the view and to the model at the same time).
-
- * e-table-item.c: Update to new API
- * e-cell-test.c: Update to new API
-
-1999-12-03 Miguel de Icaza <miguel@gnu.org>
-
- * e-cell.c (e_cell_class_init): Provide emtpy methods for
- enter_edit, and leave_edit.
-
- * e-table-item.c: Killed draw cell.
- (eti_draw): Perform column mapping here.
- (e_table_item_leave_edit): ditto.
- (e_table_item_enter_edit): ditto.
- (eti_event): ditto.
-
-1999-12-02 Miguel de Icaza <miguel@gnu.org>
-
- * e-table-header.c (e_table_header_index): fixed api.
-
-1999-12-01 Miguel de Icaza <miguel@gnu.org>
-
- * test-cols.c (multi_cols_test): Update to simplified API.
- * test-check.c (check_test): ditto
- * test-table.c (table_browser_test): ditto
-
- * e-table-simple.c (e_table_simple_class_init): Kill column_name method.
-
- * e-table-model.h: Kill column_name method.
-
- * e-table-col.c (e_table_col_new): Instead of using a column name,
- use a column index.
-
- * e-cell-text.c (ect_draw): Keep track of the originally allocated
- piece of code.
-
- * e-table-header-item.c (ethi_unrealize): Removed change cursor
- from here.
-
- * e-cell-text.c (ect_draw): Memory leak fix.
-
- * table-test.c (main): Enhance the demo to load sample.table
- automatically, to get memprof working.
-
- * e-table-header.c (eth_do_remove): Take an argument: do -remove.
-
- * e-table-header.c (e_table_header_add_column): Sink ETableCol to
- own the object.
-
- * e-table-col.h: Made ETableCol a GtkObject to make reference
- counting the lifecycle method for these objects.
-
- * e-table-col.c (e_table_col_destroy): New API call.
-
- * e-table-subset.c (e_table_subset_get_toplevel): New API call.
-
-1999-11-30 Miguel de Icaza <miguel@gnu.org>
-
- * e-cell-checkbox.c (e_cell_checkbox_new): This one derives from
- e-cell-toggle.
-
- * check-emtpy.xpm, check-filled.xpm: new files.
-
- * e-cell-toggle.c (etog_draw): Paint in white.
- If we have transparency enabled, do the nice alpha computation.
-
- * test-table.c, test-cols.c: new files; They implement the split
- tests.
-
-1999-11-29 Miguel de Icaza <miguel@gnu.org>
-
- * e-table-col.c (e_table_col_new): Set etc->resizeable.
-
- * e-table-header-item.c (ethi_event): Handle non-resizeables
- columns; Add support for minimum width.
-
- * e-cell-toggle.c, e-cell-toggle.h: New file. Implement a
- multi-state image toggle cell object.
-
- * e-cell-text.c (ect_leave_edit): Handle the case of us calling
- leave edit manually.
- (ect_stop_editing): Leave manually editing here.
- (ect_draw): Add one pixel to the border for left and right;
- Handle off-screen cursor (must be improved).
- (ect_edit_select_all): New function.
- (ect_event): Select all text on editing start
-
- * e-table-item.c (eti_event): Map mouse events and dispatch them.
- (eti_event): Add spreadsheet mode for editing; Enter editing only
- with visual characters;
- Leave editing mode when a different row has been selected.
- (eti_get_height): Fix the computation for this; Fix logic for the
- length_threshold.
-
- (eti_draw): Add borders on all sides of the box;
- Only draw focus if the cell is not being edited.
-
-1999-11-28 Miguel de Icaza <miguel@gnu.org>
-
- * e-table-item.c (eti_draw): Focus inside, not outside.
- (eti_realize): Enhance our focus gc.
-
- * e-cell-text.c (ect_enter_edit, ect_leave_edit): New methods;
- They implement editing.
-
- * e-cell.h: new methods: enter_edit, leave_edit
-
- * e-table-model.h (set_value_at): make val argument const.
-
- * e-table-simple.c (simple_set_value_at): Make value argument const;
-
- * e-table-item.c (eti_set_arg): Add new mode: draw_focus;
-
-1999-11-27 Miguel de Icaza <miguel@gnu.org>
-
- * e-table-item.c (eti_event): beginning of the keyboard navigation.
-
- * e-table-model.c (e_table_model_row_changed): new function.
- (e_table_model_cell_changed): new function.
- (e_table_model_class_init): New signals.
-
- * e-table-item.c (eti_request_region_redraw): x2, y2 offsets were
- wrong.
- (eti_select): Repaint selected region.
- (eti_request_region_redraw): Fix range.
- (eti_draw): Correct offset computation here.
- (e_table_item_class_init): New method: row_selection, handles the
- selection.
-
- Now it implement GTK_SELECTION_SINGLE and GTK_SELECTION_MULTIPLE.
-
- Focusing and selection should be correct now.
-
-1999-11-26 Miguel de Icaza <miguel@gnu.org>
-
- * e-table-item.c (eti_realize): Compute height using the ecell
- methods here.
- (eti_get_height): new method to compute dimensions.
-
- * e-cursors.c: use a different cursor.
-
- * e-table-model.h: kill height and row_height methods.
-
- * e-cell.c (ec_height): New method.
-
- * e-cell-text.c (ect_realize): Load the font from the canvas.
- (ect_draw): New color setup.
- Center in the row.
- (ect_height): Implement new method.
-
-1999-11-26 Michael Meeks <mmeeks@gnu.org>
-
- * ROADMAP.e-table: small spelling/typo fixes.
-
-1999-11-25 Miguel de Icaza <miguel@gnu.org>
-
- * e-table-item.c (eti_event): Work on mouse-button event
- propagation to cells.
-
- * e-cell-text.c (ect_draw): Use CellViews now.
-
- * e-table-item.c (eti_realize_cell_views): New routine: Realizes
- the cell views
- (eti_unrealize_cell_views): New routine: unrealizes the cell views.
-
- * e-table-item.h: Move cell_views array here.
-
- * table-test.c (value_at): Fix return value.
- (main): use new invocation method.
-
- * e-table-header-item.c (ethi_realize): Realize cells.
-
- * e-table-item.c (eti_header_dim_changed): redraw before and after.
-
- * e-table-header-item.c (ethi_event): Add continuous resizing.
-
-1999-11-24 Miguel de Icaza <miguel@gnu.org>
-
- * e-table-subset.h, e-table-subset.c: New files, used to implement
- subset tables.
-
- * e-table-sorted.h, e-table-sorted.c: Now they derive from
- e-table-subset.
-
- * e-cell.c, e-cell.h: realize method now return per view instance
- data.
-
-1999-11-20 Miguel de Icaza <miguel@gnu.org>
-
- * e-table-item.c (eti_draw): WOOOOHOOOOOoO! It took me quite a
- while to figure this one out. Fixed.
-
- * e-table-header-item.c (ethi_set_arg): Compute width, keep track
- of it.
- (ethi_add_table_header): Monitor changes to the Header model;
- Queue updates.
- (ethi_draw): Fix the redraw logic here.
-
- * table-test.c (main): Change the sample code, so we can better
- debug this.
-
- * e-table-item.c (eti_header_structure_changed): Keep track of
- width;
- (eti_header_dim_changed): ditto.
- (eti_draw): Many redraw fixes.
-
-1999-11-19 Miguel de Icaza <miguel@gnu.org>
-
- * e-table-item.c (eti_realize): Hook up; Load gcs.
- (eti_unrealize): Hook up.
-
- * e-table-sorted.c: Finished implementing.
-
-1999-11-18 Miguel de Icaza <miguel@gnu.org>
-
- * e-table-model.c (e_table_model_class_init): Add model_changed
- signal here.
-
- * e-table-item.c, e-table-item.h: New files. They implement the
- view of the ETableModel as Canvas Items.
-
- * e-table-header-item.c (ethi_set_arg): Ref header here.
- (ethi_destroy): Unref it here.
-
-1999-11-17 Ettore Perazzoli <ettore@gnu.org>
-
- * e-msg-composer-address-dialog.c: Moved to `$(srcdir)/composer'.
- * e-msg-composer-address-dialog.h: Likewise.
- * e-msg-composer-address-entry.c: Likewise.
- * e-msg-composer-address-entry.h: Likewise.
- * e-msg-composer-attachment-bar.c: Likewise.
- * e-msg-composer-attachment-bar.h: Likewise.
- * e-msg-composer-attachment.c: Likewise.
- * e-msg-composer-attachment.h: Likewise.
- * e-msg-composer-hdrs.c: Likewise.
- * e-msg-composer-hdrs.h: Likewise.
- * e-msg-composer.c: Likewise.
- * e-msg-composer.h: Likewise.
- * e-msg-composer-address-dialog.glade: Likewise.
- * e-msg-composer-attachment.glade: Likewise.
- * e-msg-composer.glade: Likewise.
- * Makefile.am: Updated accordingly.
-
-Nov 14 1999 Elliot Lee
- * Makefile.am: It's libevolutionwidgets.la, not .a
-
-1999-11-14 Miguel de Icaza <miguel@gnu.org>
-
- * e-table-header-item.c (is_pointer_on_division): Add resizing
- capabilities.
-
- * e-table-sorted.c: Finish implementation.
-
-1999-11-13 Miguel de Icaza <miguel@gnu.org>
-
- * e-table-sorted.c: Implement e-table-sorted object.
-
-1999-11-12 Miguel de Icaza <miguel@gnu.org>
-
- * e-table-header-item.c: Make the thing configurable.
-
- * e-table-header-item.h: Add font field, location, height.
-
-1999-11-12 Ettore Perazzoli <ettore@gnu.org>
-
- * e-msg-composer-hdrs.c: New member `tooltips' in `struct
- _EMsgComposerHdrsPrivate'.
- (init): Initialize it.
- (destroy): New function.
- (class_init): Install it as the `destroy' GtkObject method.
- (add_header): New parameters `tip', `tip_private'. Setup a
- tooltip for the entry with them.
- (setup_headers): Updated accordingly.
-
-1999-11-11 Miguel de Icaza <miguel@gnu.org>
-
- * e-table-header.c (e_table_header_add_column): Update offsets.
- (eth_update_offsets): New routine.
-
- * e-table-col.h, e-table-col.c: New files.
-
- * e-table-header.h (e_table_header_get_selected_indexes):
- Pretify.
-
- * table-test.c (main): New file; used for testing ETable package.
-
- * e-table-simple.h: Fix type.
-
-1999-11-12 Ettore Perazzoli <ettore@gnu.org>
-
- * e-msg-composer-address-dialog.glade: Cosmetical changes.
-
- * e-msg-composer-attachment-bar.c (size_to_string): New helper
- function.
- (update): Put the size in the icon's label using this function.
- (ICON_SEPARATORS): Remove '.' to avoid wrapping of the size string
- on the decimal dot. But gnome-libs is broken and this has no real
- effect! :-(
- (e_msg_composer_attachment_bar_new): No longer make text editable.
- Use the `GTK_SELECTION_MULTIPLE' selection mode.
- (remove_selected): No longer assume only one attachment is
- selected.
-
- * e-msg-composer-attachment.c: #include <sys/stat.h>
- (init): Initialize all the members.
- (e_msg_composer_attachment_new): Set size using `stat()'.
-
- * e-msg-composer-attachment.h: New member `size' in `struct
- _EMsgComposerAttachment'.
-
- * e-msg-composer.c (setup_signals): Connect `address_dialog_cb' to
- the "show_address_dialog" signal of the header widget.
-
- * e-msg-composer-hdrs.c (add_address_header): Renamed to
- `add_header'. New parameter `addrbook_button': if true, use a
- button instead of a label and make it trigger an
- "show_address_dialog" signal.
- (address_button_clicked_cb): Signal handler to handle this on a
- "clicked" signal from the button.
- (setup_headers): Updated accordingly. Also, make "Subject" the
- last item. (This makes it look more like Outlook and friends.)
-
- * e-msg-composer-hdrs.c: New signal "show_address_dialog".
- * e-msg-composer-hdrs.h: Updated accordingly.
-
- * e-msg-composer-hdrs.c (add_address_header): Reduce padding
- considerably.
-
- * e-msg-composer.c (e_msg_composer_construct): Do not use any
- padding in the main vbox.
-
- * Makefile.am: Moved the `e-table*' sources to `EXTRA_DIST'.
- Compile as a shared library.
-
-1999-11-08 Ettore Perazzoli <ettore@gnu.org>
-
- * e-msg-composer-address-dialog.c: Implemented cut & paste for the
- recipient lists.
- (init): Initialize `cut_buffer'.
- (destroy): Free it.
- (recipient_clist_selection_get_cb): New function.
- (recipient_clist_selection_received_cb): New function.
- (recipient_clist_selection_clear_event_cb): New function.
- (setup_recipient_list_signals): Install them as signal handlers
- for "selection_get", "selection_received" and
- "selection_clear_event" respectively.
- (copy_recipient_cb): New function implementing the "copy"
- operation.
- (cut_recipient_cb): New function implementing the "cut" operation.
- (paste_recipient_cb): New function implementing the "paste"
- operation.
-
- * e-msg-composer-address-dialog.h: New member `cut_buffer' in
- `struct _EMsgComposerAddressDialog'.
-
-1999-11-07 Ettore Perazzoli <ettore@gnu.org>
-
- * e-msg-composer-address-dialog.c: New context menu
- `recipient_list_popup_info' for the recipient CLists.
- (recipient_clist_button_press_cb): New function.
- (setup_signals): Install it as the "button_press_event" signal
- handler for popping up the CList context menu.
-
- * e-msg-composer.c (free_string_list): New helper function.
- (setup_address_dialog): Setup the initial values in the address
- dialog according to the ones in the header widget.
-
- * e-msg-composer-hdrs.c (e_msg_composer_hdrs_get_to): New function.
- (e_msg_composer_hdrs_get_cc): New function.
- (e_msg_composer_hdrs_get_bcc): New function.
-
- * e-msg-composer.c (setup_address_dialog): New helper function.
- (address_dialog_cb): Use it.
-
- * e-msg-composer-address-dialog.c (add_address): Do not set the
- row data anymore. Instead, put the full address description
- (i.e. complete with the email address, not just the full name) in
- the CList.
- (add_address): Do nothing if no item is selected in the address
- CList.
- (get_list): Get the address list from the CList without passing
- through the address CList.
- (set_list): New helper function.
- (e_msg_composer_address_dialog_set_to_list): New function.
- (e_msg_composer_address_dialog_set_cc_list): New function.
- (e_msg_composer_address_dialog_set_bcc_list): New function.
-
- * e-msg-composer.c (address_dialog_apply_cb): Apply values from
- the address dialog into the composer.
-
- * e-msg-composer-hdrs.c (e_msg_composer_hdrs_set_to): New function.
- (e_msg_composer_hdrs_set_cc): New function.
- (e_msg_composer_hdrs_set_bcc): New function.
-
- * e-msg-composer-address-entry.c
- (e_msg_composer_address_entry_set_list): New function.
-
- * e-msg-composer-address-dialog.c (apply): New helper function.
- (clicked): New function, `clicked' method for the `GnomeDialog'
- class.
- (class_init): Install it.
-
-1999-11-06 Ettore Perazzoli <ettore@gnu.org>
-
- * e-msg-composer-attachment-bar.c (destroy): Call the destroy
- method of the parent class.
-
- * e-msg-composer.c: #include "e-msg-composer-address-dialog.h".
- (address_dialog_cb): New callback to start the address dialog.
- (setup_signals): Connect it to the appropriate button/menu item.
- (init): Initialize the new `address_dialog' member to NULL.
- (destroy): Destroy the `address_dialog' if not NULL.
-
- * e-msg-composer.h: New member `address_dialog' in `struct
- _EMsgComposer'.
-
- * e-msg-composer.glade: Added button to activate the address
- composition dialog.
-
- * e-msg-composer-address-dialog.h, e-msg-composer-address-dialog.c:
- New files implementing the address composition dialog for Evolution.
-
- * e-msg-composer-address-dialog.glade: New file.
-
- * e-msg-composer-attachment.c: `signals' made static.
-
-1999-11-05 Ettore Perazzoli <ettore@gnu.org>
-
- * Makefile.am: Compile the new files in a `libevolutionwidgets'
- library.
- (CPPFLAGS): #define `E_GUIDIR'.
-
- * e-msg-composer.c, e-msg-composer.h: New files implementing an
- initial version of the Evolution message composer widget.
-
- * e-msg-composer-address-entry.c, e-msg-composer-address-entry.h:
- New files implementing a GtkEntry customized for entering email
- address lists.
-
- * e-msg-composer-attachment-bar.c, e-msg-composer-attachment-bar.h:
- New files implementing a widget for editing mail attachments.
-
- * e-msg-composer-attachment.c, e-msg-composer-attachment.h: New
- files implementing file attachment objects for the message
- composer.
-
- * e-msg-composer-hdrs.c, e-msg-composer-hdrs.h: New files
- implementing a widget for editing of email message headers.
-
- * e-msg-composer-attachment.glade: New file.
- * e-msg-composer.glade: New file.
-
-1999-10-31 Miguel de Icaza <miguel@gnu.org>
-
- * widgets/e-table-column.c, e-table-column.h: New file, implements the
- e-table-column object.
-
- * widget/e-table-model.h, e-table-model.c, e-table-simple.c,
- e-table-simple.h: New files. Implements the column model and
- a simple table wrapper.
-
diff --git a/widgets/Makefile.am b/widgets/Makefile.am
index 73bd54ee2c..f8fd9b1c08 100644
--- a/widgets/Makefile.am
+++ b/widgets/Makefile.am
@@ -1,65 +1,3 @@
-SUBDIRS =
- meeting-time-sel
-
-INCLUDES = \
- -I$(top_srcdir)/camel \
- -I$(top_builddir)/camel \
- $(GNOME_INCLUDEDIR)
-
-noinst_LIBRARIES = \
- libevolutionwidgets.a
-
-libevolutionwidgets_a_SOURCES = \
- e-cell.c \
- e-cell.h \
- e-cell-checkbox.c \
- e-cell-checkbox.h \
- e-cell-text.c \
- e-cell-text.h \
- e-cell-toggle.c \
- e-cell-toggle.h \
- e-cursors.c \
- e-cursors.h \
- e-table.c \
- e-table.h \
- e-table-col.c \
- e-table-col.h \
- e-table-group.c \
- e-table-group.h \
- e-table-header.c \
- e-table-header.h \
- e-table-header-item.c \
- e-table-header-item.h \
- e-table-item.c \
- e-table-item.h \
- e-table-model.c \
- e-table-model.h \
- e-table-simple.c \
- e-table-simple.h \
- e-table-sorted.c \
- e-table-sorted.h \
- e-table-subset.c \
- e-table-subset.h
-
-noinst_PROGRAMS = \
- table-test
-
-table_test_SOURCES = \
- test-table.c \
- test-check.c \
- test-cols.c \
- table-test.c
-
-table_test_LDADD = \
- $(EXTRA_GNOME_LIBS) \
- libevolutionwidgets.a
-
-table_test_LDFLAGS = `gnome-config --libs gdk_pixbuf`
-
-EXTRA_DIST = \
- sample.table \
- add-col.xpm \
- check-empty.xpm \
- check-filled.xpm \
- remove-col.xpm
+SUBDIRS = \
+ util meeting-time-sel shortcut-bar e-table
diff --git a/widgets/ROADMAP.e-table b/widgets/ROADMAP.e-table
deleted file mode 100644
index 4edacced86..0000000000
--- a/widgets/ROADMAP.e-table
+++ /dev/null
@@ -1,113 +0,0 @@
-
-The E-Table package implements an editable table that provides
-user-defined rendering, user-defined editing, sorting and grouping of
-the objects displayed.
-
-It is inspired by Java's Swing JTable object. There are models for
-the actual table contents and for the table headers; they are the
-actual repository of information.
-
-The objects are rendered by various view objects. In the current code
-base, we use we use GnomeCanvasItems to do the rendering. One for
-each table and one for the headers.
-
-* The main widget
-
-e-table.c, e-table.h:
-
- Implements a full widget. Uses various components described
- below. Handles column display as well as grouping/nesting
-
-* The Models
-
-All of them are GtkObjects.
-
-e-table-model.h, e-table-model.c:
-
- These implement the abstract E-Table-Model class. You
- can derive this object to create your own data repository.
-
- These emits signals to notify the views about selection, and
- changes in the model.
-
-e-table-simple.h, e-table-simple.c:
-
- A simple implementation of e-table-model that uses callback
- routines (you provide the callbacks). For lazy people, like
- me.
-
-e-cell.c, e-cell.h:
-
- These are actually mis-named. Objects of type e-cell know
- about rendering a single cell, and these are attached to the
- e-table-cols (described next).
-
- The user provides the various rendering modes as e-cells (they
- are actually column-rendering repositories).
-
- This is just an abstract class. I will provide various
- e-cells: a text cell, a checkbox cell, an image cell, and
- perhaps an n-state image cell (one that switches the image when
- the cell is clicked).
-
-e-table-col.h, e-table-col.c:
-
- Describes a single column (the size, the string displayed, the
- rendering function for each row and comparison function for
- this field).
-
-
-* The Views
-
-e-table-header.h, e-table-header.c:
-
- These implement the ETableHeaderItem canvas item. This item is
- used both to control the columns displayed as well as displaying them.
-
- They describe what columns are shown in the screen and in
- which order.
-
- These emit signals: column-size-changed and structure-changed
- (if a column is added/removed)
-
-e-table-item.c, e-table-item.h
-
- This is a canvas item that renders the contents of a
- ETableModel into the screen.
-
-e-table-header-item.c, e-table-header-item.h
-
- This canvas item renders the ETableHeader headings.
-
-e-cell-text.c, e-cell-text.h
-
- Not really a view, but actually a derivative of e-cell that
- implements text display: supports justification and font
- setting. Will add color in the future most likely
-
-e-cell-toggle.c, e-cell-toggle.h
-
- A derivative of e-cell as well that support N-toggle values
- using images.
-
-e-cell-check.c, e-cell-check.h
-
- An e-cell-toggle with two states only (for checkboxes).
-
-* The Filters
-
-e-table-sorted.c, e-table-sorted.h
-
- This is an ETableModel that can sort an existing ETableModel.
-
-e-table-subset.c, e-table-subset.h
-
- Not finished, but it is just an ETableModel that happens to be
- a subset of another ETableModel.
-
-* Everything
-
-e-table.c, e-table.h
-
- In the future these guys will implement the whole widget for
- doing table editing. Nothing done about these yet.
diff --git a/widgets/TODO b/widgets/TODO
deleted file mode 100644
index 29dbd454e5..0000000000
--- a/widgets/TODO
+++ /dev/null
@@ -1,24 +0,0 @@
-Implement e-cell-height
-Implement computation of heights from the e-cell-heights
-Make sure we compute the height from that
-Include spacing in columns and rows for the decoration lines
-Add threshold to compute a "global" size
-Implement the two methods for row finding: by full thing, or by a factor.
-
-
-Add editing
-mouse grabbing for scrolling
-
-
-1. Make sure that all values are updated on header changes and table
- model changes (they are slightly out of sync now)
-
-* Correctness
-
- * Make sure we can boot and shutdown with no memory leaks.
-
- * Run Insure on the thing.
-
-* Propagation
-
- * Row changes should be reflected in the subsets.
diff --git a/widgets/add-col.xpm b/widgets/add-col.xpm
deleted file mode 100644
index 9c5f314c8e..0000000000
--- a/widgets/add-col.xpm
+++ /dev/null
@@ -1,22 +0,0 @@
-/* XPM */
-static char * add_col_xpm[] = {
-"16 16 3 1",
-" c None",
-". c #000000",
-"+ c #FFFFFF",
-" ",
-" ",
-" ",
-" ",
-" .............. ",
-" .++++++++++++. ",
-" .++++++++++++. ",
-" ....+++....... ",
-" .+. ",
-" . ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" "};
diff --git a/widgets/check-empty.xpm b/widgets/check-empty.xpm
deleted file mode 100644
index 2dd873e137..0000000000
--- a/widgets/check-empty.xpm
+++ /dev/null
@@ -1,21 +0,0 @@
-/* XPM */
-static char * check_empty_xpm[] = {
-"16 16 2 1",
-" c None",
-". c #000000",
-" ",
-" ",
-" ............ ",
-" . . ",
-" . . ",
-" . . ",
-" . . ",
-" . . ",
-" . . ",
-" . . ",
-" . . ",
-" . . ",
-" . . ",
-" ............ ",
-" ",
-" "};
diff --git a/widgets/check-filled.xpm b/widgets/check-filled.xpm
deleted file mode 100644
index 689d7a7967..0000000000
--- a/widgets/check-filled.xpm
+++ /dev/null
@@ -1,21 +0,0 @@
-/* XPM */
-static char * check_filled_xpm[] = {
-"16 16 2 1",
-" c None",
-". c #000000",
-" ",
-" ",
-" ............ ",
-" . . ",
-" . . . ",
-" . .. . ",
-" . ... . ",
-" . . ... . ",
-" . .. ... . ",
-" . ..... . ",
-" . ... . ",
-" . . . ",
-" . . ",
-" ............ ",
-" ",
-" "};
diff --git a/widgets/e-cell-checkbox.c b/widgets/e-cell-checkbox.c
deleted file mode 100644
index 6e4b597abf..0000000000
--- a/widgets/e-cell-checkbox.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * e-cell-checkbox.c: Checkbox cell renderer
- *
- * Author:
- * Miguel de Icaza (miguel@kernel.org)
- *
- * (C) 1999 Helix Code, Inc
- */
-#include <config.h>
-#include <gtk/gtkenums.h>
-#include <gtk/gtkentry.h>
-#include <gtk/gtkwindow.h>
-#include <gtk/gtksignal.h>
-#include <gdk/gdkkeysyms.h>
-#include <libgnomeui/gnome-canvas.h>
-#include "e-cell-checkbox.h"
-#include "e-util.h"
-#include "e-table-item.h"
-
-#include "check-empty.xpm"
-#include "check-filled.xpm"
-
-#define PARENT_TYPE e_cell_toggle_get_type()
-
-static GdkPixbuf *checks [2];
-
-static void
-e_cell_checkbox_class_init (GtkObjectClass *object_class)
-{
- checks [0] = gdk_pixbuf_new_from_xpm_data (check_empty_xpm);
- checks [1] = gdk_pixbuf_new_from_xpm_data (check_filled_xpm);
-}
-
-E_MAKE_TYPE(e_cell_checkbox, "ECellCheckbox", ECellCheckbox, e_cell_checkbox_class_init, NULL, PARENT_TYPE);
-
-ECell *
-e_cell_checkbox_new (void)
-{
- ECellCheckbox *eccb = gtk_type_new (e_cell_checkbox_get_type ());
-
- e_cell_toggle_construct (E_CELL_TOGGLE (eccb), 2, 2, checks);
-
- return (ECell *) eccb;
-}
diff --git a/widgets/e-cell-checkbox.h b/widgets/e-cell-checkbox.h
deleted file mode 100644
index 969e4a5edc..0000000000
--- a/widgets/e-cell-checkbox.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef _E_CELL_CHECKBOX_H_
-#define _E_CELL_CHECKBOX_H_
-
-#include "e-cell-toggle.h"
-
-#define E_CELL_CHECKBOX_TYPE (e_cell_checkbox_get_type ())
-#define E_CELL_CHECKBOX(o) (GTK_CHECK_CAST ((o), E_CELL_CHECKBOX_TYPE, ECellCheckbox))
-#define E_CELL_CHECKBOX_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_CELL_CHECKBOX_TYPE, ECellCheckboxClass))
-#define E_IS_CELL_CHECKBOX(o) (GTK_CHECK_TYPE ((o), E_CELL_CHECKBOX_TYPE))
-#define E_IS_CELL_CHECKBOX_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_CELL_CHECKBOX_TYPE))
-
-typedef struct {
- ECellToggle parent;
-} ECellCheckbox;
-
-typedef struct {
- ECellToggleClass parent_class;
-} ECellCheckboxClass;
-
-GtkType e_cell_checkbox_get_type (void);
-ECell *e_cell_checkbox_new (void);
-
-#endif /* _E_CELL_CHECKBOX_H_ */
-
diff --git a/widgets/e-cell-string.c b/widgets/e-cell-string.c
deleted file mode 100644
index 992b1bd10e..0000000000
--- a/widgets/e-cell-string.c
+++ /dev/null
@@ -1,9 +0,0 @@
-ECell *
-e_cell_string_new (void)
-{
- ECell *ecell;
-
- ecell = gtk_type_new (ecell);
-
- return ecell;
-}
diff --git a/widgets/e-cell-text.c b/widgets/e-cell-text.c
deleted file mode 100644
index 1b2205ba51..0000000000
--- a/widgets/e-cell-text.c
+++ /dev/null
@@ -1,508 +0,0 @@
-/*
- * e-cell-text.c: Text cell renderer
- *
- * Author:
- * Miguel de Icaza (miguel@kernel.org)
- *
- * (C) 1999 Helix Code, Inc
- */
-#include <config.h>
-#include <gtk/gtkenums.h>
-#include <gtk/gtkentry.h>
-#include <gtk/gtkwindow.h>
-#include <gtk/gtksignal.h>
-#include <gdk/gdkkeysyms.h>
-#include <libgnomeui/gnome-canvas.h>
-#include <stdio.h>
-#include "e-cell-text.h"
-#include "e-util.h"
-#include "e-table-item.h"
-
-#define PARENT_TYPE e_cell_get_type()
-
-#define TEXT_PAD 2
-
-typedef struct {
- char *old_text;
- GtkWidget *entry_top;
- GtkEntry *entry;
-
- /*
- * Where the editing is taking place
- */
- int model_col, view_col, row;
-} CellEdit;
-
-typedef struct {
- ECellView cell_view;
- GdkGC *gc;
- GdkFont *font;
- GnomeCanvas *canvas;
-
- /*
- * During edition.
- */
- CellEdit *edit;
-} ECellTextView;
-
-static ECellClass *parent_class;
-
-static void
-ect_queue_redraw (ECellTextView *text_view, int view_col, int view_row)
-{
- e_table_item_redraw_range (
- text_view->cell_view.e_table_item_view,
- view_col, view_row, view_col, view_row);
-}
-
-/*
- * Accept the currently edited text
- */
-static void
-ect_accept_edits (ECellTextView *text_view)
-{
- const char *text = gtk_entry_get_text (text_view->edit->entry);
- CellEdit *edit = text_view->edit;
-
- e_table_model_set_value_at (text_view->cell_view.e_table_model, edit->model_col, edit->row, text);
-}
-
-/*
- * Shuts down the editing process
- */
-static void
-ect_stop_editing (ECellTextView *text_view)
-{
- CellEdit *edit = text_view->edit;
-
- g_free (edit->old_text);
- edit->old_text = NULL;
- gtk_widget_destroy (edit->entry_top);
- edit->entry_top = NULL;
- edit->entry = NULL;
-
- g_free (edit);
-
- text_view->edit = NULL;
-
- e_table_item_leave_edit (text_view->cell_view.e_table_item_view);
-}
-
-/*
- * Cancels the edits
- */
-static void
-ect_cancel_edit (ECellTextView *text_view)
-{
- ect_queue_redraw (text_view, text_view->edit->view_col, text_view->edit->row);
- ect_stop_editing (text_view);
-}
-
-/*
- * ECell::new_view method
- */
-static ECellView *
-ect_new_view (ECell *ecell, ETableModel *table_model, void *e_table_item_view)
-{
- ECellText *ect = E_CELL_TEXT (ecell);
- ECellTextView *text_view = g_new0 (ECellTextView, 1);
- GnomeCanvas *canvas = GNOME_CANVAS_ITEM (e_table_item_view)->canvas;
-
- text_view->cell_view.ecell = ecell;
- text_view->cell_view.e_table_model = table_model;
- text_view->cell_view.e_table_item_view = e_table_item_view;
-
- if (ect->font_name){
- GdkFont *f;
-
- f = gdk_fontset_load (ect->font_name);
- text_view->font = f;
- }
- if (!text_view->font){
- text_view->font = GTK_WIDGET (canvas)->style->font;
-
- gdk_font_ref (text_view->font);
- }
-
- text_view->canvas = canvas;
-
- return (ECellView *)text_view;
-}
-
-/*
- * ECell::kill_view method
- */
-static void
-ect_kill_view (ECellView *ecv)
-{
- ECellTextView *text_view = (ECellTextView *) ecv;
-
- gdk_font_unref (text_view->font);
- text_view->font = NULL;
-
- g_free (text_view);
-}
-
-/*
- * ECell::realize method
- */
-static void
-ect_realize (ECellView *ecell_view)
-{
- ECellTextView *text_view = (ECellTextView *) ecell_view;
-
- text_view->gc = gdk_gc_new (GTK_WIDGET (text_view->canvas)->window);
-}
-
-/*
- * ECell::unrealize method
- */
-static void
-ect_unrealize (ECellView *ecv)
-{
- ECellTextView *text_view = (ECellTextView *) ecv;
-
- gdk_gc_unref (text_view->gc);
- text_view->gc = NULL;
-}
-
-/*
- * ECell::draw method
- */
-static void
-ect_draw (ECellView *ecell_view, GdkDrawable *drawable,
- int model_col, int view_col, int row, gboolean selected,
- int x1, int y1, int x2, int y2)
-{
- ECellText *ect = E_CELL_TEXT (ecell_view->ecell);
- ECellTextView *text_view = (ECellTextView *) ecell_view;
- GtkWidget *w = GTK_WIDGET (text_view->canvas);
- GdkRectangle rect;
- const char *str = e_table_model_value_at (ecell_view->e_table_model, model_col, row);
- GdkFont *font = text_view->font;
- const int height = font->ascent + font->descent;
- int xoff;
- gboolean edit_display = FALSE;
-
- /*
- * Figure if this cell is being edited
- */
- if (text_view->edit){
- CellEdit *edit = text_view->edit;
-
- if ((edit->view_col == view_col) && (edit->row == row))
- edit_display = TRUE;
- }
-
- /*
- * Be a nice citizen: clip to the region we are supposed to draw on
- */
- rect.x = x1;
- rect.y = y1;
- rect.width = x2 - x1;
- rect.height = y2 - y1;
- gdk_gc_set_clip_rectangle (text_view->gc, &rect);
-
- if (edit_display){
- CellEdit *edit = text_view->edit;
- const char *text = gtk_entry_get_text (edit->entry);
- GdkWChar *p, *text_wc = g_new (GdkWChar, strlen (text) + 1);
- int text_wc_len = gdk_mbstowcs (text_wc, text, strlen (text));
- const int cursor_pos = GTK_EDITABLE (edit->entry)->current_pos;
- const int left_len = gdk_text_width_wc (text_view->font, text_wc, cursor_pos);
-
- text_wc [text_wc_len] = 0;
- /*
- * Paint
- */
- gdk_gc_set_foreground (text_view->gc, &w->style->base [GTK_STATE_NORMAL]);
- gdk_draw_rectangle (drawable, text_view->gc, TRUE,
- rect.x, rect.y, rect.width, rect.height);
- gdk_gc_set_foreground (text_view->gc, &w->style->text [GTK_STATE_NORMAL]);
-
- {
- GdkGC *gc = text_view->gc;
- const int y = y2 - font->descent - ((y2-y1-height)/2);
- int px, i;
-
- /*
- * Border
- */
- x1 += 2;
- x2--;
-
- px = x1;
-
- /*
- * If the cursor is outside the visible range
- *
- * FIXME: we really want a better behaviour.
- */
- if ((px + left_len) > x2)
- px -= left_len - (x2-x1);
-
- /*
- * Draw
- */
- for (i = 0, p = text_wc; *p; p++, i++){
- gdk_draw_text_wc (
- drawable, font, gc, px, y, p, 1);
-
- if (i == cursor_pos){
- gdk_draw_line (
- drawable, gc,
- px, y - font->ascent,
- px, y + font->descent - 1);
- }
-
- px += gdk_text_width_wc (font, p, 1);
- }
-
- if (i == cursor_pos){
- gdk_draw_line (
- drawable, gc,
- px, y - font->ascent,
- px, y + font->descent - 1);
- }
- }
- g_free (text_wc);
- } else {
- /*
- * Regular cell
- */
- GdkColor *background, *foreground;
- int width;
-
- /*
- * Border
- */
- x1++;
- x2--;
-
- /*
- * Compute draw mode
- */
- switch (ect->justify){
- case GTK_JUSTIFY_LEFT:
- xoff = 1;
- break;
-
- case GTK_JUSTIFY_RIGHT:
- width = 1 + gdk_text_width (font, str, strlen (str));
- xoff = (x2 - x1) - width;
- break;
-
- case GTK_JUSTIFY_CENTER:
- xoff = ((x2 - x1) - gdk_text_width (font, str, strlen (str))) / 2;
- break;
- default:
- xoff = 0;
- g_warning ("Can not handle GTK_JUSTIFY_FILL");
- break;
- }
-
-
- if (selected){
- background = &w->style->bg [GTK_STATE_SELECTED];
- foreground = &w->style->text [GTK_STATE_SELECTED];
- } else {
- background = &w->style->base [GTK_STATE_NORMAL];
- foreground = &w->style->text [GTK_STATE_NORMAL];
- }
-
- gdk_gc_set_foreground (text_view->gc, background);
- gdk_draw_rectangle (drawable, text_view->gc, TRUE,
- rect.x, rect.y, rect.width, rect.height);
- gdk_gc_set_foreground (text_view->gc, foreground);
-
- gdk_draw_string (
- drawable, font, text_view->gc,
- x1 + xoff,
- y2 - font->descent - ((y2-y1-height)/2), str);
- }
-}
-
-/*
- * Selects the entire string
- */
-static void
-ect_edit_select_all (ECellTextView *text_view)
-{
- g_assert (text_view->edit);
-
- gtk_editable_select_region (GTK_EDITABLE (text_view->edit->entry), 0, -1);
-}
-
-/*
- * ECell::event method
- */
-static gint
-ect_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row)
-{
- ECellTextView *text_view = (ECellTextView *) ecell_view;
-
- switch (event->type){
- case GDK_BUTTON_PRESS:
- /*
- * Adjust for the border we use
- */
- event->button.x++;
-
- printf ("Button pressed at %g %g\n", event->button.x, event->button.y);
- if (text_view->edit){
- printf ("FIXME: Should handle click here\n");
- } else
- e_table_item_enter_edit (text_view->cell_view.e_table_item_view, view_col, row);
- break;
-
- case GDK_BUTTON_RELEASE:
- /*
- * Adjust for the border we use
- */
- event->button.x++;
- printf ("Button released at %g %g\n", event->button.x, event->button.y);
- return TRUE;
-
- case GDK_KEY_PRESS:
- if (event->key.keyval == GDK_Escape){
- ect_cancel_edit (text_view);
- return TRUE;
- }
-
- if (!text_view->edit){
- e_table_item_enter_edit (text_view->cell_view.e_table_item_view, view_col, row);
- ect_edit_select_all (text_view);
- }
-
- gtk_widget_event (GTK_WIDGET (text_view->edit->entry), event);
- ect_queue_redraw (text_view, view_col, row);
- break;
-
- case GDK_KEY_RELEASE:
- break;
-
- default:
- return FALSE;
- }
- return TRUE;
-}
-
-/*
- * ECell::height method
- */
-static int
-ect_height (ECellView *ecell_view, int model_col, int view_col, int row)
-{
- ECellTextView *text_view = (ECellTextView *) ecell_view;
-
- return (text_view->font->ascent + text_view->font->descent) + TEXT_PAD;
-}
-
-/*
- * Callback: invoked when the user pressed "enter" on the GtkEntry
- */
-static void
-ect_entry_activate (GtkEntry *entry, ECellTextView *text_view)
-{
- e_table_item_leave_edit (text_view->cell_view.e_table_item_view);
-}
-
-/*
- * ECellView::enter_edit method
- */
-static void *
-ect_enter_edit (ECellView *ecell_view, int model_col, int view_col, int row)
-{
- ECellTextView *text_view = (ECellTextView *) ecell_view;
- const char *str = e_table_model_value_at (ecell_view->e_table_model, model_col, row);
- CellEdit *edit;
-
- edit = g_new (CellEdit, 1);
- text_view->edit = edit;
-
- edit->model_col = model_col;
- edit->view_col = view_col;
- edit->row = row;
-
- edit->entry = (GtkEntry *) gtk_entry_new ();
- gtk_entry_set_text (edit->entry, str);
- edit->old_text = g_strdup (str);
- gtk_signal_connect (GTK_OBJECT (edit->entry), "activate",
- GTK_SIGNAL_FUNC (ect_entry_activate), text_view);
-
- /*
- * The hack: create this window off-screen
- */
- edit->entry_top = gtk_window_new (GTK_WINDOW_POPUP);
- gtk_container_add (GTK_CONTAINER (edit->entry_top), GTK_WIDGET (edit->entry));
- gtk_widget_set_uposition (edit->entry_top, 20000, 20000);
- gtk_widget_show_all (edit->entry_top);
-
- ect_queue_redraw (text_view, view_col, row);
-
- return NULL;
-}
-
-/*
- * ECellView::leave_edit method
- */
-static void
-ect_leave_edit (ECellView *ecell_view, int model_col, int view_col, int row, void *edit_context)
-{
- ECellTextView *text_view = (ECellTextView *) ecell_view;
-
- if (text_view->edit){
- ect_accept_edits (text_view);
- ect_stop_editing (text_view);
- } else {
- /*
- * We did invoke this leave edit internally
- */
- }
-}
-
-/*
- * GtkObject::destroy method
- */
-static void
-ect_destroy (GtkObject *object)
-{
- ECellText *ect = E_CELL_TEXT (object);
-
- g_free (ect->font_name);
-
- GTK_OBJECT_CLASS (parent_class)->destroy (object);
-}
-
-static void
-e_cell_text_class_init (GtkObjectClass *object_class)
-{
- ECellClass *ecc = (ECellClass *) object_class;
-
- object_class->destroy = ect_destroy;
-
- ecc->new_view = ect_new_view;
- ecc->kill_view = ect_kill_view;
- ecc->realize = ect_realize;
- ecc->unrealize = ect_unrealize;
- ecc->draw = ect_draw;
- ecc->event = ect_event;
- ecc->height = ect_height;
- ecc->enter_edit = ect_enter_edit;
- ecc->leave_edit = ect_leave_edit;
-
- parent_class = gtk_type_class (PARENT_TYPE);
-}
-
-E_MAKE_TYPE(e_cell_text, "ECellText", ECellText, e_cell_text_class_init, NULL, PARENT_TYPE);
-
-ECell *
-e_cell_text_new (ETableModel *etm, const char *fontname, GtkJustification justify)
-{
- ECellText *ect = gtk_type_new (e_cell_text_get_type ());
-
- ect->font_name = g_strdup (fontname);
- ect->justify = justify;
-
- return (ECell *) ect;
-}
diff --git a/widgets/e-cell-text.h b/widgets/e-cell-text.h
deleted file mode 100644
index de9629b97b..0000000000
--- a/widgets/e-cell-text.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef _E_CELL_TEXT_H_
-#define _E_CELL_TEXT_H_
-
-#include <libgnomeui/gnome-canvas.h>
-#include "e-cell.h"
-
-#define E_CELL_TEXT_TYPE (e_cell_text_get_type ())
-#define E_CELL_TEXT(o) (GTK_CHECK_CAST ((o), E_CELL_TEXT_TYPE, ECellText))
-#define E_CELL_TEXT_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_CELL_TEXT_TYPE, ECellTextClass))
-#define E_IS_CELL_TEXT(o) (GTK_CHECK_TYPE ((o), E_CELL_TEXT_TYPE))
-#define E_IS_CELL_TEXT_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_CELL_TEXT_TYPE))
-
-typedef struct {
- ECell parent;
-
- GtkJustification justify;
- char *font_name;
-} ECellText;
-
-typedef struct {
- ECellClass parent_class;
-} ECellTextClass;
-
-GtkType e_cell_text_get_type (void);
-ECell *e_cell_text_new (ETableModel *model, const char *fontname, GtkJustification justify);
-
-#endif /* _E_CELL_TEXT_H_ */
-
diff --git a/widgets/e-cell-toggle.c b/widgets/e-cell-toggle.c
deleted file mode 100644
index 6ea181ea40..0000000000
--- a/widgets/e-cell-toggle.c
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * e-cell-toggle.c: Multi-state image toggle cell object.
- *
- * Author:
- * Miguel de Icaza (miguel@kernel.org)
- *
- * (C) 1999 Helix Code, Inc
- */
-#include <config.h>
-#include <gtk/gtkenums.h>
-#include <gtk/gtkentry.h>
-#include <gtk/gtkwindow.h>
-#include <gtk/gtksignal.h>
-#include <gdk/gdkkeysyms.h>
-#include <libgnomeui/gnome-canvas.h>
-#include "e-cell-toggle.h"
-#include "e-util.h"
-#include "e-table-item.h"
-
-#define PARENT_TYPE e_cell_get_type()
-
-typedef struct {
- ECellView cell_view;
- GdkGC *gc;
- GnomeCanvas *canvas;
-} ECellToggleView;
-
-static ECellClass *parent_class;
-
-static void
-etog_queue_redraw (ECellToggleView *text_view, int view_col, int view_row)
-{
- e_table_item_redraw_range (
- text_view->cell_view.e_table_item_view,
- view_col, view_row, view_col, view_row);
-}
-
-/*
- * ECell::realize method
- */
-static ECellView *
-etog_new_view (ECell *ecell, ETableModel *table_model, void *e_table_item_view)
-{
- ECellToggleView *toggle_view = g_new0 (ECellToggleView, 1);
- ETableItem *eti = E_TABLE_ITEM (e_table_item_view);
- GnomeCanvas *canvas = GNOME_CANVAS_ITEM (eti)->canvas;
-
- toggle_view->cell_view.ecell = ecell;
- toggle_view->cell_view.e_table_model = table_model;
- toggle_view->cell_view.e_table_item_view = e_table_item_view;
- toggle_view->canvas = canvas;
-
- return (ECellView *) toggle_view;
-}
-
-static void
-etog_kill_view (ECellView *ecell_view)
-{
- g_free (ecell_view);
-}
-
-static void
-etog_realize (ECellView *ecell_view)
-{
- ECellToggleView *toggle_view = (ECellToggleView *) ecell_view;
-
- toggle_view->gc = gdk_gc_new (GTK_WIDGET (toggle_view->canvas)->window);
-}
-
-/*
- * ECell::unrealize method
- */
-static void
-etog_unrealize (ECellView *ecv)
-{
- ECellToggleView *toggle_view = (ECellToggleView *) ecv;
-
- gdk_gc_unref (toggle_view->gc);
- toggle_view->gc = NULL;
-}
-
-/*
- * ECell::draw method
- */
-static void
-etog_draw (ECellView *ecell_view, GdkDrawable *drawable,
- int model_col, int view_col, int row, gboolean selected,
- int x1, int y1, int x2, int y2)
-{
- ECellToggle *toggle = E_CELL_TOGGLE (ecell_view->ecell);
- ECellToggleView *toggle_view = (ECellToggleView *) ecell_view;
- GdkPixbuf *image;
- ArtPixBuf *art;
- int x, y, width, height;
- const int value = GPOINTER_TO_INT (
- e_table_model_value_at (ecell_view->e_table_model, model_col, row));
-
- if (value >= toggle->n_states){
- g_warning ("Value from the table model is %d, the states we support are [0..%d)\n",
- value, toggle->n_states);
- return;
- }
-
- /*
- * Paint the background
- */
- gdk_draw_rectangle (drawable, GTK_WIDGET (toggle_view->canvas)->style->white_gc, TRUE, x1, y1, x2 - x1, y2 - y1);
-
- image = toggle->images [value];
- art = image->art_pixbuf;
-
- if ((x2 - x1) < art->width){
- x = x1;
- width = x2 - x1;
- } else {
- x = x1 + ((x2 - x1) - art->width) / 2;
- width = art->width;
- }
-
- if ((y2 - y1) < art->height){
- y = y1;
- height = y2 - y1;
- } else {
- y = y1 + ((y2 - y1) - art->height) / 2;
- height = art->height;
- }
-
- width = y2 - y1;
-
- if (image->art_pixbuf->has_alpha){
- GdkColor background;
- guchar *buffer;
- int alpha, ix, iy;
-
- buffer = g_malloc (art->rowstride * art->height * 3);
-
- background.red = 255;
- background.green = 255;
- background.blue = 255;
-
- for (iy = 0; iy < art->height; iy++){
- unsigned char *dest;
- unsigned char *src;
-
- dest = buffer + (iy * art->rowstride);
- src = art->pixels + (iy * art->rowstride);
-
- for (ix = 0; ix < art->width; ix++){
- alpha = src [3];
- if (alpha == 0){
- *dest++ = background.red;
- *dest++ = background.green;
- *dest++ = background.blue;
- src += 3;
- } else if (alpha == 255){
- *dest++ = *src++;
- *dest++ = *src++;
- *dest++ = *src++;
- } else {
- *dest++ = (background.red + ((*src++ - background.red) * alpha + 0x80)) >> 8;
- *dest++ = (background.green + ((*src++ - background.green) * alpha + 0x80)) >> 8;
- *dest++ = (background.blue + ((*src++ - background.blue) * alpha + 0x80)) >> 8;
- }
- src++;
- }
- }
-
- gdk_draw_rgb_image_dithalign (
- drawable, toggle_view->gc, x, y, width, height,
- GDK_RGB_DITHER_NORMAL, buffer, art->rowstride, 0, 0);
-
- g_free (buffer);
- } else
- gdk_draw_rgb_image_dithalign (
- drawable, toggle_view->gc, x, y, width, height,
- GDK_RGB_DITHER_NORMAL, art->pixels, art->rowstride, 0, 0);
-}
-
-static void
-etog_set_value (ECellToggleView *toggle_view, int model_col, int view_col, int row, int value)
-{
- ECell *ecell = toggle_view->cell_view.ecell;
- ECellToggle *toggle = E_CELL_TOGGLE (ecell);
-
- if (value >= toggle->n_states)
- value = 0;
-
- e_table_model_set_value_at (toggle_view->cell_view.e_table_model,
- model_col, row, GINT_TO_POINTER (value));
- etog_queue_redraw (toggle_view, view_col, row);
-}
-
-/*
- * ECell::event method
- */
-static gint
-etog_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row)
-{
- ECellToggleView *toggle_view = (ECellToggleView *) ecell_view;
- void *_value = e_table_model_value_at (ecell_view->e_table_model, model_col, row);
- const int value = GPOINTER_TO_INT (_value);
-
- switch (event->type){
- case GDK_BUTTON_RELEASE:
- etog_set_value (toggle_view, model_col, view_col, row, value + 1);
- return TRUE;
-
- case GDK_KEY_PRESS:
- if (event->key.keyval == GDK_space){
- etog_set_value (toggle_view, model_col, view_col, row, value + 1);
- return TRUE;
- }
- return FALSE;
-
- default:
- return FALSE;
- }
- return TRUE;
-}
-
-/*
- * ECell::height method
- */
-static int
-etog_height (ECellView *ecell_view, int model_col, int view_col, int row)
-{
- ECellToggle *toggle = E_CELL_TOGGLE (ecell_view->ecell);
-
- return toggle->height;
-}
-
-static void
-etog_destroy (GtkObject *object)
-{
- ECellToggle *etog = E_CELL_TOGGLE (object);
- int i;
-
- for (i = 0; i < etog->n_states; i++)
- gdk_pixbuf_unref (etog->images [i]);
-
- g_free (etog->images);
-
- GTK_OBJECT_CLASS (parent_class)->destroy (object);
-}
-
-static void
-e_cell_toggle_class_init (GtkObjectClass *object_class)
-{
- ECellClass *ecc = (ECellClass *) object_class;
-
- object_class->destroy = etog_destroy;
-
- ecc->new_view = etog_new_view;
- ecc->kill_view = etog_kill_view;
- ecc->realize = etog_realize;
- ecc->unrealize = etog_unrealize;
- ecc->draw = etog_draw;
- ecc->event = etog_event;
- ecc->height = etog_height;
-
- parent_class = gtk_type_class (PARENT_TYPE);
-}
-
-E_MAKE_TYPE(e_cell_toggle, "ECellToggle", ECellToggle, e_cell_toggle_class_init, NULL, PARENT_TYPE);
-
-void
-e_cell_toggle_construct (ECellToggle *etog, int border, int n_states, GdkPixbuf **images)
-{
- int max_height = 0;
- int i;
-
- etog->border = border;
- etog->n_states = n_states;
-
- etog->images = g_new (GdkPixbuf *, n_states);
-
- for (i = 0; i < n_states; i++){
- etog->images [i] = images [i];
- gdk_pixbuf_ref (images [i]);
-
- if (images [i]->art_pixbuf->height > max_height)
- max_height = images [i]->art_pixbuf->height;
- }
-
- etog->height = max_height;
-}
-
-ECell *
-e_cell_toggle_new (int border, int n_states, GdkPixbuf **images)
-{
- ECellToggle *etog = gtk_type_new (e_cell_toggle_get_type ());
-
- e_cell_toggle_construct (etog, border, n_states, images);
-
- return (ECell *) etog;
-}
-
-
diff --git a/widgets/e-cell-toggle.h b/widgets/e-cell-toggle.h
deleted file mode 100644
index d5773b454a..0000000000
--- a/widgets/e-cell-toggle.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef _E_CELL_TOGGLE_H_
-#define _E_CELL_TOGGLE_H_
-
-#include <libgnomeui/gnome-canvas.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
-#include "e-cell.h"
-
-#define E_CELL_TOGGLE_TYPE (e_cell_toggle_get_type ())
-#define E_CELL_TOGGLE(o) (GTK_CHECK_CAST ((o), E_CELL_TOGGLE_TYPE, ECellToggle))
-#define E_CELL_TOGGLE_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_CELL_TOGGLE_TYPE, ECellToggleClass))
-#define E_IS_CELL_TOGGLE(o) (GTK_CHECK_TYPE ((o), E_CELL_TOGGLE_TYPE))
-#define E_IS_CELL_TOGGLE_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_CELL_TOGGLE_TYPE))
-
-typedef struct {
- ECell parent;
-
- int border;
- int n_states;
- GdkPixbuf **images;
-
- int height;
-} ECellToggle;
-
-typedef struct {
- ECellClass parent_class;
-} ECellToggleClass;
-
-GtkType e_cell_toggle_get_type (void);
-ECell *e_cell_toggle_new (int border, int n_states, GdkPixbuf **images);
-void e_cell_toggle_construct (ECellToggle *etog, int border,
- int n_states, GdkPixbuf **images);
-
-#endif /* _E_CELL_TOGGLE_H_ */
-
-
diff --git a/widgets/e-cell.c b/widgets/e-cell.c
deleted file mode 100644
index 0f9297ecba..0000000000
--- a/widgets/e-cell.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * e-cell.c: base class for cell renderers in e-table
- *
- * Author:
- * Miguel de Icaza (miguel@kernel.org)
- *
- * (C) 1999 Helix Code, Inc
- */
-#include <config.h>
-#include "e-cell.h"
-#include "e-util.h"
-
-#define PARENT_TYPE gtk_object_get_type()
-
-static ECellView *
-ec_new_view (ECell *ecell, ETableModel *table_model, void *e_table_item_view)
-{
- return NULL;
-}
-
-static void
-ec_realize (ECellView *e_cell)
-{
-}
-
-static void
-ec_kill_view (ECellView *ecell_view)
-{
-}
-
-static void
-ec_unrealize (ECellView *e_cell)
-{
-}
-
-static void
-ec_draw (ECellView *ecell_view, GdkDrawable *drawable,
- int model_col, int view_col, int row, gboolean selected,
- int x1, int y1, int x2, int y2)
-{
- g_error ("e-cell-draw invoked\n");
-}
-
-static gint
-ec_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row)
-{
- g_error ("e-cell-event invoked\n");
- return 0;
-}
-
-static gint
-ec_height (ECellView *ecell_view, int model_col, int view_col, int row)
-{
- g_error ("e-cell-event invoked\n");
- return 0;
-}
-
-static void
-ec_focus (ECellView *ecell_view, int model_col, int view_col, int row, int x1, int y1, int x2, int y2)
-{
- ecell_view->focus_col = view_col;
- ecell_view->focus_row = row;
- ecell_view->focus_x1 = x1;
- ecell_view->focus_y1 = y1;
- ecell_view->focus_x2 = x2;
- ecell_view->focus_y2 = y2;
-}
-
-static void
-ec_unfocus (ECellView *ecell_view)
-{
- ecell_view->focus_col = -1;
- ecell_view->focus_row = -1;
- ecell_view->focus_x1 = -1;
- ecell_view->focus_y1 = -1;
- ecell_view->focus_x2 = -1;
- ecell_view->focus_y2 = -1;
-}
-
-static void *
-ec_enter_edit (ECellView *ecell_view, int model_col, int view_col, int row)
-{
- return NULL;
-}
-
-static void
-ec_leave_edit (ECellView *ecell_view, int model_col, int view_col, int row, void *context)
-{
-}
-
-static void
-e_cell_class_init (GtkObjectClass *object_class)
-{
- ECellClass *ecc = (ECellClass *) object_class;
-
- ecc->realize = ec_realize;
- ecc->unrealize = ec_unrealize;
- ecc->new_view = ec_new_view;
- ecc->kill_view = ec_kill_view;
- ecc->draw = ec_draw;
- ecc->event = ec_event;
- ecc->focus = ec_focus;
- ecc->unfocus = ec_unfocus;
- ecc->height = ec_height;
- ecc->enter_edit = ec_enter_edit;
- ecc->leave_edit = ec_leave_edit;
-}
-
-static void
-e_cell_init (GtkObject *object)
-{
-}
-
-E_MAKE_TYPE(e_cell, "ECell", ECell, e_cell_class_init, e_cell_init, PARENT_TYPE);
-
-
-void
-e_cell_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row)
-{
- E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->event (
- ecell_view, event, model_col, view_col, row);
-}
-
-ECellView *
-e_cell_new_view (ECell *ecell, ETableModel *table_model, void *e_table_item_view)
-{
- return E_CELL_CLASS (GTK_OBJECT (ecell)->klass)->new_view (
- ecell, table_model, e_table_item_view);
-}
-
-void
-e_cell_view_realize (ECellView *ecell_view)
-{
- return E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->realize (ecell_view);
-}
-
-void
-e_cell_kill_view (ECellView *ecell_view)
-{
- E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->kill_view (ecell_view);
-}
-
-void
-e_cell_unrealize (ECellView *ecell_view)
-{
- E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->unrealize (ecell_view);
-}
-
-void
-e_cell_draw (ECellView *ecell_view, GdkDrawable *drawable,
- int model_col, int view_col, int row, gboolean selected, int x1, int y1, int x2, int y2)
-{
- E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->draw (
- ecell_view, drawable, model_col, view_col, row, selected, x1, y1, x2, y2);
-}
-
-int
-e_cell_height (ECellView *ecell_view, int model_col, int view_col, int row)
-{
- return E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->height (
- ecell_view, model_col, view_col, row);
-}
-
-void *
-e_cell_enter_edit (ECellView *ecell_view, int model_col, int view_col, int row)
-{
- return E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->enter_edit (
- ecell_view, model_col, view_col, row);
-}
-
-void
-e_cell_leave_edit (ECellView *ecell_view, int model_col, int view_col, int row, void *edit_context)
-{
- E_CELL_CLASS (GTK_OBJECT (ecell_view->ecell)->klass)->leave_edit (
- ecell_view, model_col, view_col, row, edit_context);
-}
diff --git a/widgets/e-cell.h b/widgets/e-cell.h
deleted file mode 100644
index 3c258689e4..0000000000
--- a/widgets/e-cell.h
+++ /dev/null
@@ -1,73 +0,0 @@
-#ifndef _E_CELL_H_
-#define _E_CELL_H_
-
-#include <gdk/gdktypes.h>
-#include "e-table-model.h"
-
-#define E_CELL_TYPE (e_cell_get_type ())
-#define E_CELL(o) (GTK_CHECK_CAST ((o), E_CELL_TYPE, ECell))
-#define E_CELL_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_CELL_TYPE, ECellClass))
-#define E_IS_CELL(o) (GTK_CHECK_TYPE ((o), E_CELL_TYPE))
-#define E_IS_CELL_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_CELL_TYPE))
-
-typedef struct _ECell ECell;
-typedef struct _ECellView ECellView;
-
-struct _ECell {
- GtkObject object;
-};
-
-struct _ECellView {
- ECell *ecell;
- ETableModel *e_table_model;
- void *e_table_item_view;
-
- gint focus_x1, focus_y1, focus_x2, focus_y2;
- gint focus_col, focus_row;
-};
-
-#define E_CELL_IS_FOCUSED(ecell_view) (ecell_view->focus_x1 != -1)
-
-typedef struct {
- GtkObjectClass parent_class;
-
- ECellView *(*new_view) (ECell *ecell, ETableModel *table_model, void *e_table_item_view);
- void (*kill_view) (ECellView *ecell_view);
-
- void (*realize) (ECellView *ecell_view);
- void (*unrealize) (ECellView *ecell_view);
-
- void (*draw) (ECellView *ecell_view, GdkDrawable *drawable,
- int model_col, int view_col, int row,
- gboolean selected, int x1, int y1, int x2, int y2);
- gint (*event) (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row);
- void (*focus) (ECellView *ecell_view, int model_col, int view_col,
- int row, int x1, int y1, int x2, int y2);
- void (*unfocus) (ECellView *ecell_view);
- int (*height) (ECellView *ecell_view, int model_col, int view_col, int row);
-
- void *(*enter_edit)(ECellView *ecell_view, int model_col, int view_col, int row);
- void (*leave_edit)(ECellView *ecell_view, int model_col, int view_col, int row, void *context);
-} ECellClass;
-
-GtkType e_cell_get_type (void);
-ECellView *e_cell_new_view (ECell *ecell, ETableModel *table_model, void *e_table_item_view);
-void e_cell_kill_view (ECellView *ecell_view);
-
-void e_cell_event (ECellView *ecell_view, GdkEvent *event, int model_col, int view_col, int row);
-
-void e_cell_realize (ECellView *ecell_view);
-void e_cell_unrealize (ECellView *ecell_view);
-
-void e_cell_draw (ECellView *ecell_view, GdkDrawable *dr,
- int model_col, int view_col, int row, gboolean selected,
- int x1, int y1, int x2, int y2);
-void e_cell_focus (ECellView *ecell_view, int model_col, int view_col, int row,
- int x1, int y1, int x2, int y2);
-void e_cell_unfocus (ECellView *ecell_view);
-int e_cell_height (ECellView *ecell_view, int model_col, int view_col, int row);
-
-void *e_cell_enter_edit(ECellView *ecell_view, int model_col, int view_col, int row);
-void e_cell_leave_edit(ECellView *ecell_view, int model_col, int view_col, int row, void *edit_context);
-
-#endif /* _E_CELL_H_ */
diff --git a/widgets/e-table-col-dnd.h b/widgets/e-table-col-dnd.h
deleted file mode 100644
index c1c26175c7..0000000000
--- a/widgets/e-table-col-dnd.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _E_TABLE_COL_DND_H_
-#define _E_TABLE_COL_DND_H_
-
-#define TARGET_ETABLE_COL_TYPE "application/x-etable-column-header"
-
-enum {
- TARGET_ETABLE_COL_HEADER
-};
-
-#endif /* _E_TABLE_COL_DND_H_ */
diff --git a/widgets/e-table-col.c b/widgets/e-table-col.c
deleted file mode 100644
index 86392a9419..0000000000
--- a/widgets/e-table-col.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * E-table-col.c: ETableCol implementation
- *
- * Author:
- * Miguel de Icaza (miguel@gnu.org)
- *
- * (C) 1999 Helix Code, Inc
- */
-#include <config.h>
-#include <gtk/gtkobject.h>
-#include <gtk/gtksignal.h>
-#include "e-table-col.h"
-#include "e-util.h"
-
-#define PARENT_TYPE (gtk_object_get_type ())
-
-static GtkObjectClass *parent_class;
-
-static void
-etc_destroy (GtkObject *object)
-{
- ETableCol *etc = E_TABLE_COL (object);
-
- g_free (etc->text);
-
- (*parent_class->destroy)(object);
-}
-
-static void
-e_table_col_class_init (GtkObjectClass *object_class)
-{
- parent_class = gtk_type_class (PARENT_TYPE);
- object_class->destroy = etc_destroy;
-}
-
-E_MAKE_TYPE(e_table_col, "ETableCol", ETableCol, e_table_col_class_init, NULL, PARENT_TYPE);
-
-ETableCol *
-e_table_col_new (int col_idx, const char *text, int width, int min_width,
- ECell *ecell, GCompareFunc compare, gboolean resizable)
-{
- ETableCol *etc;
-
- g_return_val_if_fail (width >= 0, NULL);
- g_return_val_if_fail (min_width >= 0, NULL);
- g_return_val_if_fail (width >= min_width, NULL);
- g_return_val_if_fail (compare != NULL, NULL);
-
- etc = gtk_type_new (E_TABLE_COL_TYPE);
-
- etc->col_idx = col_idx;
- etc->text = g_strdup (text);
- etc->width = width;
- etc->min_width = min_width;
- etc->ecell = ecell;
- etc->compare = compare;
-
- etc->selected = 0;
- etc->resizeable = resizable;
-
- return etc;
-}
-
-
diff --git a/widgets/e-table-col.h b/widgets/e-table-col.h
deleted file mode 100644
index 54f03ae237..0000000000
--- a/widgets/e-table-col.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef _E_TABLE_COL_H_
-#define _E_TABLE_COL_H_
-
-#include "e-cell.h"
-
-#define E_TABLE_COL_TYPE (e_table_col_get_type ())
-#define E_TABLE_COL(o) (GTK_CHECK_CAST ((o), E_TABLE_COL_TYPE, ETableCol))
-#define E_TABLE_COL_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_COL_TYPE, ETableColClass))
-#define E_IS_TABLE_COL(o) (GTK_CHECK_TYPE ((o), E_TABLE_COL_TYPE))
-#define E_IS_TABLE_COL_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_COL_TYPE))
-
-typedef struct _ETableCol ETableCol;
-
-/*
- * Information about a single column
- */
-struct _ETableCol {
- GtkObject base;
- char *text;
- short width;
- short min_width;
- short x;
- GCompareFunc compare;
- unsigned int selected:1;
- unsigned int resizeable:1;
- int col_idx;
-
- ECell *ecell;
-};
-
-typedef struct {
- GtkObjectClass parent_class;
-} ETableColClass;
-
-GtkType e_table_col_get_type (void);
-ETableCol *e_table_col_new (int col_idx, const char *text,
- int width, int min_width,
- ECell *ecell, GCompareFunc compare,
- gboolean resizable);
-void e_table_col_destroy (ETableCol *etc);
-
-
-#endif /* _E_TABLE_COL_H_ */
-
diff --git a/widgets/e-table-column-item.c b/widgets/e-table-column-item.c
deleted file mode 100644
index 0616327a93..0000000000
--- a/widgets/e-table-column-item.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * E-table-column-view.c: A canvas view of the TableColumn.
- *
- * Author:
- * Miguel de Icaza (miguel@gnu.org)
- *
- * Copyright 1999, Helix Code, Inc.
- */
-#include <config.h>
-#include "e-table-column.h"
-#include "e-table-column-view.h"
-
-#define PARENT_OBJECT_TYPE gnome_canvas_item_get_type ()
-
-static GnomeCanvasItemClass *etci_parent_class;
-
-enum {
- ARG_0,
- ARG_TABLE_COLUMN
-};
-
-static void
-etci_destroy (GtkObject *object)
-{
- ETableColumnItem *etcv = E_TABLE_COLUMN_VIEW (object);
-
- gtk_object_unref (GTK_OBJECT (etcv));
-
- if (GTK_OBJECT_CLASS (etcv_parent_class)->destroy)
- (*GTK_OBJECT_CLASS (etcv_parent_class)->destroy) (object);
-}
-
-static void
-etci_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
-{
- if (GNOME_CANVAS_ITEM_CLASS(item_bar_parent_class)->update)
- (*GNOME_CANVAS_ITEM_CLASS(item_bar_parent_class)->update)(item, affine, clip_path, flags);
-
- item->x1 = 0;
- item->y1 = 0;
- item->x2 = INT_MAX;
- item->y2 = INT_MAX;
- gnome_canvas_group_child_bounds (GNOME_CANVAS_GROUP (item->parent), item);
-}
-
-static void
-etci_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
-{
- GnomeCanvasItem *item;
- ETableColumnItem *etci;
- int v;
-
- item = GNOME_CANVAS_ITEM (o);
- etci = E_TABLE_COLUMN_ITEM (o);
-
- switch (arg_id){
- case ARG_TABLE_COLUMN:
- etci->etci = GTK_VALUE_POINTER (*arg);
- break;
- }
- etci_update (item, NULL, NULL, 0);
-}
-
-static void
-etci_realize (GnomeCanvasItem *item)
-{
- ETableColumnItem *etci = E_TABLE_COLUMN_ITEM (item);
- GdkWindow *window;
- GdkColor c;
-
- if (GNOME_CANVAS_ITEM_CLASS (etci_parent_class)-> realize)
- (*GNOME_CANVAS_ITEM_CLASS (etci_parent_class)->realize)(item);
-
- window = GTK_WIDGET (item->canvas)->window;
-
- etci->gc = gdk_gc_new (window);
- gnome_canvas_get_color (item->canvas, "black", &c);
- gdk_gc_set_foreground (etci->gc, &c);
-
- etci->normal_cursor = gdk_cursor_new (GDK_ARROW);
-}
-
-static void
-etci_unrealize (GnomeCanvasItem *item)
-{
- ETableColumnItem *etci = E_TABLE_COLUMN_ITEM (item);
-
- gdk_gc_unref (etci->gc);
- etci->gc = NULL;
-
- gdk_cursor_destroy (etci->change_cursor);
- etci->change_cursor = NULL;
-
- gdk_cursor_destroy (etci->normal_cursor);
- etci->normal_cursor = NULL;
-
- if (GNOME_CANVAS_ITEM_CLASS (etci_parent_class)->unrealize)
- (*GNOME_CANVAS_ITEM_CLASS (etci_parent_class)->unrealize)(item);
-}
-
-static void
-etci_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x1, int y1, int width, int height)
-{
- ETableColumnItem *etci = E_TABLE_COLUMN_ITEM (item);
- GnomeCanvas *canvas = item->canvas;
- GdkGC *gc;
- const int cols = e_table_column_count (etci->etc);
- int x2 = x1 + width;
- int col, total;
-
- total = 0;
- for (col = 0; col < cols; col++){
- ETableCol *col = e_table_column_get_column (etci->etc, col);
- const int col_width = col->width;
-
- if (x1 > total + col_width)
- continue;
-
- if (x2 < total)
- return;
-
- gc = canvas->style->bg_gc [GTK_STATE_ACTIVE];
- gdk_draw_rectangle (drawble, gc, TRUE,
- gtk_draw_shadow (canvas->style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
- x, y, width, height
- }
-}
-
-static double
-etci_point (GnomeCanvasItem *item, double x, double y, int cx, int cy,
- GnomeCanvasItem **actual_item)
-{
- *actual_item = *item;
- return 0.0;
-}
-
-static void
-etci_event (GnomeCanvasItem *item, GdkEvent *e)
-{
- switch (e->type){
- default:
- return FALSE;
- }
- return TRUE;
-}
-
-static void
-etci_class_init (GtkObjectClass *object_class)
-{
- GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class;
-
- object_class->destroy = etci_destroy;
- object_class->set_arg = etci_set_arg;
-
- item_class->update = etci_update;
- item_class->realize = etci_realize;
- item_class->unrealize = etci_unrealize;
- item_class->draw = etci_draw;
- item_class->point = etci_point;
- item_class->event = etci_event;
-
- gtk_object_add_arg_type ("ETableColumnItem::ETableColumn", GTK_TYPE_POINTER,
- GTK_ARG_WRITABLE, ARG_TABLE_COLUMN);
-}
-
-static void
-etci_init (GnomeCanvasItem *item)
-{
- item->x1 = 0;
- item->y1 = 0;
- item->x2 = 0;
- item->y2 = 0;
-}
-
-GtkType
-e_table_column_view_get_type (void)
-{
- static GtkType type = 0;
-
- if (!type){
- GtkTypeInfo info = {
- "ETableColumnItem",
- sizeof (ETableColumnItem),
- sizeof (ETableColumnItemClass),
- (GtkClassInitFunc) etci_class_init,
- (GtkObjectInitFunc) etci_init,
- NULL, /* reserved 1 */
- NULL, /* reserved 2 */
- (GtkClassInitFunc) NULL
- };
-
- type = gtk_type_unique (PARENT_OBJECT_TYPE, &info);
- }
-
- return type;
-}
-
-
-
diff --git a/widgets/e-table-column-item.h b/widgets/e-table-column-item.h
deleted file mode 100644
index fd38681a73..0000000000
--- a/widgets/e-table-column-item.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _E_TABLE_COLUMN_VIEW_H
-#defein _E_TABLE_COLUMN_VIEW_H
-
-#include "e-table-column.h"
-
-typedef struct {
- GnomeCanvasItem parent;
- ETableColumn *etc;
-
- GdkGC *gc;
- GdkCursor *change_cursor, *normal_cursor;
-} ETableColumnView;
-
-typedef struct {
- GnomeCanvasItemClass parent_class;
-} ETableColumnViewClass;
-
-GtkType e_table_column_item_get_type (void);
-
-#endif /* _E_TABLE_COLUMN_VIEW_H */
diff --git a/widgets/e-table-column-model.h b/widgets/e-table-column-model.h
deleted file mode 100644
index 043dd783ca..0000000000
--- a/widgets/e-table-column-model.h
+++ /dev/null
@@ -1,5 +0,0 @@
-
-class ETableColumnModel {
- virtual void add_column (ETableCol *et) = 0;
- virtual ETableCol *get_column (int column);
- virtual
diff --git a/widgets/e-table-column.c b/widgets/e-table-column.c
deleted file mode 100644
index d17a285321..0000000000
--- a/widgets/e-table-column.c
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * e-table-column.c: TableColumn implementation
- *
- * Author:
- * Miguel de Icaza (miguel@gnu.org)
- *
- * (C) 1999 Helix Code, Inc
- */
-#include <config.h>
-#include "e-table-column.h"
-
-enum {
- STRUCTURE_CHANGE,
- DIMENSION_CHANGE,
- LAST_SIGNAL
-};
-
-static guint etc_signals [LAST_SIGNAL] = { 0, };
-
-static GtkObjectClass *e_table_column_parent_class;
-
-static void
-e_table_column_destroy (GtkObject *object)
-{
- ETableColumn *etc = E_TABLE_COLUMN (object);
- const int cols = etc->col_count;
-
- /*
- * Destroy listeners
- */
- for (l = etc->listeners; l; l = l->next)
- g_free (l->data);
- g_slist_free (etc->listeners);
- etc->listeners = NULL;
-
- /*
- * Destroy columns
- */
- for (i = 0; i < cols; i++)
- e_table_column_remove (etc, i);
-
- if (e_table_column_parent_class->destroy)
- e_table_column_parent_class->destroy (object);
-}
-
-static void
-e_table_column_class_init (GtkObjectClass *object_class)
-{
- object_class->destroy = e_table_column_destroy;
-
- e_table_column_parent_class = (gtk_type_class (gtk_object_get_type ()));
-
- etc_signals [STRUCTURE_CHANGE] =
- gtk_signal_new ("structure_change",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (ETableColumn, structure_change),
- gtk_marshal_NONE__NONE,
- GTK_TYPE_NONE, 0);
- etc_signals [DIMENSION_CHANGE] =
- gtk_signal_new ("dimension_change",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (ETableColumn, dimension_change),
- gtk_marshal_NONE__INT,
- GTK_TYPE_NONE, 1, GTK_TYPE_INT);
-
- gtk_object_class_add_signals (object_class, etc_signals, LAST_SIGNAL);
-}
-
-GtkType
-e_table_column_get_type (void)
-{
- static GtkType type = 0;
-
- if (!type){
- GtkTypeInfo info = {
- "ETableColumn",
- sizeof (ETableColumn),
- sizeof (ETableColumnClass),
- (GtkClassInitFunc) e_table_column_class_init,
- (GtkObjectInitFunc) NULL,
- NULL, /* reserved 1 */
- NULL, /* reserved 2 */
- (GtkClassInitFunc) NULL
- };
-
- type = gtk_type_unique (gtk_object_get_type (), &info);
- }
-
- return type;
-}
-
-static void
-etc_do_insert (ETableColumn *etc, int pos, ETableCol *val)
-{
- memcpy (&etc->columns [pos+1], &etc->columns [pos],
- sizeof (ETableCol *) * (etc->col_count - pos));
- etc->columns [pos] = val;
-}
-
-void
-e_table_column_add_column (ETableColumn *etc, ETableCol *tc, int pos)
-{
- ETableCol **new_ptr;
-
- g_return_if_fail (etc != NULL);
- g_return_if_fail (E_IS_TABLE_COLUMN (etc));
- g_return_if_fail (tc != NULL);
- g_return_if_fail (pos >= 0 && pos < etc->col_count);
-
- if (pos == -1)
- pos = etc->col_count;
- etc->columns = g_realloc (etc->columns, sizeof (ETableCol *) * (etc->col_count + 1));
- etc_do_insert (etc, pos, tc);
- etc->col_count++;
-
- gtk_signal_emit (GTK_OBJECT (etc), etc_signals [STRUCTURE_CHANGE]);
-}
-
-ETableCol *
-e_table_column_get_column (ETableColumn *etc, int column)
-{
- g_return_val_if_fail (etc != NULL, NULL);
- g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), NULL);
-
- if (column < 0)
- return NULL;
-
- if (column >= etc->col_count)
- return NULL;
-
- return etc->columns [column];
-}
-
-int
-e_table_column_count (ETableColumn *etc)
-{
- g_return_val_if_fail (etc != NULL, 0);
- g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), 0);
-
- return etc->col_count;
-}
-
-int
-e_table_column_index (ETableColumn *etc, const char *identifier)
-{
- int i;
-
- g_return_val_if_fail (etc != NULL, 0);
- g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), 0);
- g_return_val_if_fail (identifier != NULL, 0);
-
- for (i = 0; i < etc->col_count; i++){
- ETableCol *tc = etc->columns [i];
-
- if (strcmp (i->id, identifier) == 0)
- return i;
- }
-
- return -1;
-}
-
-int
-e_table_column_get_index_at (ETableColumn *etc, int x_offset)
-{
- int i, total;
-
- g_return_val_if_fail (etc != NULL, 0);
- g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), 0);
- g_return_val_if_fail (identifier != NULL, 0);
-
- total = 0;
- for (i = 0; i < etc->col_count; i++){
- total += etc->columns [i]->width;
-
- if (x_offset < total)
- return i;
- }
-
- return -1;
-}
-
-ETableCol **
-e_table_column_get_columns (ETableColumn *etc)
-{
- ETableCol **ret;
- int i;
-
- g_return_val_if_fail (etc != NULL, 0);
- g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), 0);
-
- ret = g_new (ETableCol *, etc->col_count + 1);
- memcpy (ret, etc->columns, sizeof (ETableCol *) * etc->col_count);
- ret [etc->col_count] = NULL;
-
- return ret;
-}
-
-gboolean
-e_table_column_selection_ok (ETableColumn *etc)
-{
- g_return_val_if_fail (etc != NULL, FALSE);
- g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), FALSE);
-
- return etc->selectable;
-}
-
-int
-ve_table_column_get_selected (ETableColumn *etc)
-{
- int i;
- int selected = 0;
-
- g_return_val_if_fail (etc != NULL, 0);
- g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), 0);
-
- for (i = 0; i < etc->col_count; i++){
- if (etc->columns [i]->selected)
- selected++;
- }
-
- return selected;
-}
-
-int
-e_table_column_total_width (ETableColumn *etc)
-{
- int total;
-
- g_return_val_if_fail (etc != NULL, 0);
- g_return_val_if_fail (E_IS_TABLE_COLUMN (etc), 0);
-
- total = 0;
- for (i = 0; i < etc->col_count; i++)
- total += etc->columns [i].width;
-
- return total;
-}
-
-static void
-etc_do_remove (ETableColumn *etc, int idx)
-{
- memcpy (&etc->columns [idx], &etc->columns [idx+1],
- sizeof (ETableCol *) * etc->col_count - idx);
- etc->col_count--;
-}
-
-void
-e_table_column_move (ETableColumn *etc, int source_index, int target_index)
-{
- g_return_if_fail (etc != NULL);
- g_return_if_fail (E_IS_TABLE_COLUMN (etc));
- g_return_if_fail (source_index >= 0);
- g_return_if_fail (target_index >= 0);
- g_return_if_fail (source_index < etc->col_count);
- g_return_if_fail (target_index < etc->col_count);
-
- old = etc->columns [source_index];
- etc_do_remove (etc, source_index);
- etc_do_insert (etc, target_index, old);
- gtk_signal_emit (GTK_OBJECT (etc), etc_signals [STRUCTURE_CHANGE]);
-}
-
-void
-e_table_column_remove (ETableColumn *etc, int idx)
-{
- g_return_if_fail (etc != NULL);
- g_return_if_fail (E_IS_TABLE_COLUMN (etc));
- g_return_if_fail (idx >= 0);
- g_return_if_fail (idx < etc->col_count);
-
- etc_do_remove (etc, idx);
- gtk_signal_emit (GTK_OBJECT (etc), etc_signals [STRUCTURE_CHANGE]);
-}
-
-void
-e_table_column_set_selection (ETableColumn *etc, gboolean allow_selection);
-{
-}
-
-void
-e_table_column_set_size (ETableColumn *etc, int idx, int size)
-{
- g_return_if_fail (etc != NULL);
- g_return_if_fail (E_IS_TABLE_COLUMN (etc));
- g_return_if_fail (idx >= 0);
- g_return_if_fail (idx < etc->col_count);
- g_return_if_fail (size > 0);
-
- etc->columns [idx]->width = size;
- gtk_signal_emit (GTK_OBJECT (etc), etc_signals [SIZE_CHANGE], idx);
-}
diff --git a/widgets/e-table-group.c b/widgets/e-table-group.c
deleted file mode 100644
index 8765c3b83c..0000000000
--- a/widgets/e-table-group.c
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * E-Table-Group.c: Implements the grouping objects for elements on a table
- *
- * Author:
- * Miguel de Icaza (miguel@gnu.org()
- *
- * Copyright 1999, Helix Code, Inc.
- */
-
-#include <config.h>
-#include <gtk/gtksignal.h>
-#include "e-table-group.h"
-#include "e-table-item.h"
-#include <libgnomeui/gnome-canvas-rect-ellipse.h>
-#include "e-util.h"
-
-#define TITLE_HEIGHT 16
-#define GROUP_INDENT 10
-
-#define PARENT_TYPE gnome_canvas_group_get_type ()
-
-static GnomeCanvasGroupClass *etg_parent_class;
-
-enum {
- HEIGHT_CHANGED,
- LAST_SIGNAL
-};
-
-static gint etg_signals [LAST_SIGNAL] = { 0, };
-
-static void
-etg_destroy (GtkObject *object)
-{
- ETableGroup *etg = E_TABLE_GROUP (object);
-
- GTK_OBJECT_CLASS (etg_parent_class)->destroy (object);
-}
-
-static void
-etg_dim (ETableGroup *etg, int *width, int *height)
-{
- GSList *l;
-
- *width = *height = 0;
-
- for (l = etg->children; l; l = l->next){
- GnomeCanvasItem *child = l->data;
-
- *height += child->y2 - child->y1;
- *width += child->x2 - child->x1;
- }
-
- if (!etg->transparent){
- *height += TITLE_HEIGHT;
- *width += GROUP_INDENT;
- }
-}
-
-void
-e_table_group_construct (GnomeCanvasGroup *parent, ETableGroup *etg,
- ETableCol *ecol, gboolean open,
- gboolean transparent)
-{
- gnome_canvas_item_constructv (GNOME_CANVAS_ITEM (etg), parent, 0, NULL);
-
- etg->ecol = ecol;
- etg->open = open;
- etg->transparent = transparent;
-
- etg_dim (etg, &etg->width, &etg->height);
-
- if (!etg->transparent)
- etg->rect = gnome_canvas_item_new (
- GNOME_CANVAS_GROUP (etg),
- gnome_canvas_rect_get_type (),
- "fill_color", "gray",
- "outline_color", "gray20",
- "x1", 0.0,
- "y1", 0.0,
- "x2", (double) etg->width,
- "y2", (double) etg->height,
- NULL);
-
-#if 0
- /*
- * Reparent the child into our space.
- */
- gnome_canvas_item_reparent (child, GNOME_CANVAS_GROUP (etg));
-
- gnome_canvas_item_set (
- child,
- "x", (double) GROUP_INDENT,
- "y", (double) TITLE_HEIGHT,
- NULL);
-
- /*
- * Force dimension computation
- */
- GNOME_CANVAS_ITEM_CLASS (etg_parent_class)->update (
- GNOME_CANVAS_ITEM (etg), NULL, NULL, GNOME_CANVAS_UPDATE_REQUESTED);
-#endif
-}
-
-GnomeCanvasItem *
-e_table_group_new (GnomeCanvasGroup *parent, ETableCol *ecol,
- gboolean open, gboolean transparent)
-{
- ETableGroup *etg;
-
- g_return_val_if_fail (parent != NULL, NULL);
- g_return_val_if_fail (ecol != NULL, NULL);
-
- etg = gtk_type_new (e_table_group_get_type ());
-
- e_table_group_construct (parent, etg, ecol, open, transparent);
-
- return GNOME_CANVAS_ITEM (etg);
-}
-
-static void
-etg_relayout (GnomeCanvasItem *eti, ETableGroup *etg)
-{
- GSList *l;
- int height = etg->transparent ? 0 : GROUP_INDENT;
- gboolean move = FALSE;
-
- printf ("Relaying out\n");
-
- for (l = etg->children; l->next; l = l->next){
- GnomeCanvasItem *child = l->data;
-
- height += child->y2 - child->y1;
-
- if (child == eti)
- move = TRUE;
-
- if (move){
- printf ("Moving item %p\n", child);
- gnome_canvas_item_set (
- child,
- "y", (double) height,
- NULL);
- }
- }
- if (height != etg->height){
- etg->height = height;
- gtk_signal_emit (GTK_OBJECT (etg), etg_signals [HEIGHT_CHANGED]);
- }
-}
-
-void
-e_table_group_add (ETableGroup *etg, GnomeCanvasItem *item)
-{
- double x1, y1, x2, y2;
-
- g_return_if_fail (etg != NULL);
- g_return_if_fail (item != NULL);
- g_return_if_fail (E_IS_TABLE_GROUP (etg));
- g_return_if_fail (GNOME_IS_CANVAS_ITEM (item));
-
- etg->children = g_slist_append (etg->children, item);
-
- GNOME_CANVAS_ITEM_CLASS (GTK_OBJECT (etg)->klass)->bounds (etg, &x1, &y1, &x2, &y2);
-
- if (GTK_OBJECT (etg)->flags & GNOME_CANVAS_ITEM_REALIZED){
- GSList *l;
- int height = etg->transparent ? 0 : TITLE_HEIGHT;
- int x = etg->transparent ? 0 : GROUP_INDENT;
-
- for (l = etg->children; l->next; l = l->next){
- GnomeCanvasItem *child = l->data;
-
- height += child->y2 - child->y1;
- }
-
- printf ("Positioning item %p at %d\n", item, height);
- gnome_canvas_item_set (
- item,
- "y", (double) height,
- "x", (double) x,
- NULL);
-
-
- if (E_IS_TABLE_ITEM (item)){
-
- printf ("Table item! ---------\n");
- gtk_signal_connect (GTK_OBJECT (item), "height_changed",
- GTK_SIGNAL_FUNC (etg_relayout), etg);
- }
- }
-}
-
-static void
-etg_realize (GnomeCanvasItem *item)
-{
- ETableGroup *etg = E_TABLE_GROUP (item);
- GSList *l;
- int height = 0;
-
- GNOME_CANVAS_ITEM_CLASS (etg_parent_class)->realize (item);
-
- for (l = etg->children; l; l = l->next){
- GnomeCanvasItem *child = l->data;
-
- printf ("During realization for child %p -> %d\n", child, height);
- gnome_canvas_item_set (
- child,
- "y", (double) height,
- NULL);
-
- height += child->y2 - child->y1;
- }
-}
-
-static void
-etg_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
-{
- ETableGroup *etg = E_TABLE_GROUP (item);
-
- GNOME_CANVAS_ITEM_CLASS (etg_parent_class)->update (item, affine, clip_path, flags);
-
- if (!etg->transparent){
- int current_width, current_height;
-
- etg_dim (etg, &current_width, &current_height);
-
- if ((current_height != etg->height) || (current_width != etg->width)){
- etg->width = current_width;
- etg->height = current_height;
-
- gnome_canvas_item_set (
- etg->rect,
- "x1", 0.0,
- "y1", 0.0,
- "x2", (double) etg->width,
- "y2", (double) etg->height,
- NULL);
- }
- }
-}
-
-static void
-etg_class_init (GtkObjectClass *object_class)
-{
- GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class;
-
- object_class->destroy = etg_destroy;
-
- item_class->realize = etg_realize;
- item_class->update = etg_update;
-
- etg_parent_class = gtk_type_class (PARENT_TYPE);
-
- etg_signals [HEIGHT_CHANGED] =
- gtk_signal_new ("height_changed",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (ETableGroupClass, height_changed),
- gtk_marshal_NONE__NONE,
- GTK_TYPE_NONE, 0);
-
- gtk_object_class_add_signals (object_class, etg_signals, LAST_SIGNAL);
-
-}
-
-E_MAKE_TYPE (e_table_group, "ETableGroup", ETableGroup, etg_class_init, NULL, PARENT_TYPE);
-
-
-
diff --git a/widgets/e-table-group.h b/widgets/e-table-group.h
deleted file mode 100644
index 468d5dd794..0000000000
--- a/widgets/e-table-group.h
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifndef _E_TABLE_TREE_H_
-#define _E_TABLE_TREE_H_
-
-#include <libgnomeui/gnome-canvas.h>
-#include "e-table-model.h"
-#include "e-table-header.h"
-
-#define E_TABLE_GROUP_TYPE (e_table_group_get_type ())
-#define E_TABLE_GROUP(o) (GTK_CHECK_CAST ((o), E_TABLE_GROUP_TYPE, ETableGroup))
-#define E_TABLE_GROUP_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_GROUP_TYPE, ETableGroupClass))
-#define E_IS_TABLE_GROUP(o) (GTK_CHECK_TYPE ((o), E_TABLE_GROUP_TYPE))
-#define E_IS_TABLE_GROUP_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_GROUP_TYPE))
-
-typedef struct {
- GnomeCanvasGroup group;
-
- /*
- * The ETableCol used to group this set
- */
- ETableCol *ecol;
-
- /*
- * The canvas rectangle that contains the children
- */
- GnomeCanvasItem *rect;
-
- /*
- * Dimensions of the ETableGroup
- */
- int width, height;
-
- /*
- * State: the ETableGroup is open or closed
- */
- guint open:1;
-
- /*
- * Whether we should add indentation and open/close markers,
- * or if we just act as containers of subtables.
- */
- guint transparent:1;
-
- /*
- * List of GnomeCanvasItems we stack
- */
- GSList *children;
-} ETableGroup;
-
-typedef struct {
- GnomeCanvasGroupClass parent_class;
- void (*height_changed) (ETableGroup *etg);
-} ETableGroupClass;
-
-GnomeCanvasItem *e_table_group_new (GnomeCanvasGroup *parent, ETableCol *ecol,
- gboolean open, gboolean transparent);
-void e_table_group_construct (GnomeCanvasGroup *parent, ETableGroup *etg,
- ETableCol *ecol, gboolean open, gboolean transparent);
-
-void e_table_group_add (ETableGroup *etg, GnomeCanvasItem *child);
-
-GtkType e_table_group_get_type (void);
-
-#endif /* _E_TABLE_TREE_H_ */
diff --git a/widgets/e-table-header-item.c b/widgets/e-table-header-item.c
deleted file mode 100644
index 7cea9ae7a0..0000000000
--- a/widgets/e-table-header-item.c
+++ /dev/null
@@ -1,793 +0,0 @@
-/*
- * E-table-column-view.c: A canvas item based view of the ETableColumn.
- *
- * Author:
- * Miguel de Icaza (miguel@gnu.org)
- *
- * Copyright 1999, Helix Code, Inc.
- */
-#include <config.h>
-#include <gtk/gtksignal.h>
-#include <gtk/gtkdnd.h>
-#include <libgnomeui/gnome-canvas.h>
-#include <libgnomeui/gnome-canvas-util.h>
-#include <libgnomeui/gnome-canvas-polygon.h>
-#include <libgnomeui/gnome-canvas-rect-ellipse.h>
-#include "e-table-header.h"
-#include "e-table-header-item.h"
-#include "e-table-col-dnd.h"
-#include "e-cursors.h"
-
-#include "add-col.xpm"
-#include "remove-col.xpm"
-
-/* Padding above and below of the string in the header display */
-#define PADDING 4
-
-/* Defines the tolerance for proximity of the column division to the cursor position */
-#define TOLERANCE 2
-
-#define ETHI_RESIZING(x) ((x)->resize_col != -1)
-
-#define PARENT_OBJECT_TYPE gnome_canvas_item_get_type ()
-
-#define ELEMENTS(x) (sizeof (x) / sizeof (x[0]))
-
-static GnomeCanvasItemClass *ethi_parent_class;
-
-/*
- * DnD icons
- */
-static GdkColormap *dnd_colormap;
-static GdkPixmap *remove_col_pixmap, *remove_col_mask;
-static GdkPixmap *add_col_pixmap, *add_col_mask;
-
-enum {
- ARG_0,
- ARG_TABLE_HEADER,
- ARG_TABLE_X,
- ARG_TABLE_Y,
- ARG_TABLE_FONTSET
-};
-
-static GtkTargetEntry ethi_drag_types [] = {
- { TARGET_ETABLE_COL_TYPE, 0, TARGET_ETABLE_COL_HEADER },
-};
-
-static GtkTargetEntry ethi_drop_types [] = {
- { TARGET_ETABLE_COL_TYPE, 0, TARGET_ETABLE_COL_HEADER },
-};
-
-static void
-ethi_destroy (GtkObject *object)
-{
- ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (object);
-
- gtk_object_unref (GTK_OBJECT (ethi->eth));
-
- if (GTK_OBJECT_CLASS (ethi_parent_class)->destroy)
- (*GTK_OBJECT_CLASS (ethi_parent_class)->destroy) (object);
-}
-
-static void
-ethi_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
-{
- ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item);
-
- if (GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->update)
- (*GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->update)(item, affine, clip_path, flags);
-
- item->x1 = ethi->x1;
- item->y1 = ethi->y1;
- item->x2 = ethi->x1 + ethi->width;
- item->y2 = ethi->y1 + ethi->height;
-
- gnome_canvas_group_child_bounds (GNOME_CANVAS_GROUP (item->parent), item);
-}
-
-static void
-ethi_font_load (ETableHeaderItem *ethi, char *font)
-{
- if (ethi->font)
- gdk_font_unref (ethi->font);
-
- ethi->font = gdk_fontset_load (font);
- if (ethi->font == NULL)
- ethi->font = gdk_font_load ("fixed");
-
- ethi->height = ethi->font->ascent + ethi->font->descent + PADDING;
-}
-
-static void
-ethi_drop_table_header (ETableHeaderItem *ethi)
-{
- GtkObject *header;
-
- if (!ethi->eth)
- return;
-
- header = GTK_OBJECT (ethi->eth);
- gtk_signal_disconnect (header, ethi->structure_change_id);
- gtk_signal_disconnect (header, ethi->dimension_change_id);
-
- gtk_object_unref (header);
- ethi->eth = NULL;
- ethi->width = 0;
-}
-
-static void
-structure_changed (ETableHeader *header, ETableHeaderItem *ethi)
-{
- ethi->width = e_table_header_total_width (header);
-
- ethi_update (GNOME_CANVAS_ITEM (ethi), NULL, NULL, 0);
-}
-
-static void
-dimension_changed (ETableHeader *header, int col, ETableHeaderItem *ethi)
-{
- ethi->width = e_table_header_total_width (header);
-
- ethi_update (GNOME_CANVAS_ITEM (ethi), NULL, NULL, 0);
-}
-
-static void
-ethi_add_table_header (ETableHeaderItem *ethi, ETableHeader *header)
-{
- ethi->eth = header;
- gtk_object_ref (GTK_OBJECT (ethi->eth));
- ethi->width = e_table_header_total_width (header);
-
- ethi->structure_change_id = gtk_signal_connect (
- GTK_OBJECT (header), "structure_change",
- GTK_SIGNAL_FUNC(structure_changed), ethi);
- ethi->dimension_change_id = gtk_signal_connect (
- GTK_OBJECT (header), "dimension_change",
- GTK_SIGNAL_FUNC(dimension_changed), ethi);
-}
-
-static void
-ethi_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
-{
- GnomeCanvasItem *item;
- ETableHeaderItem *ethi;
-
- item = GNOME_CANVAS_ITEM (o);
- ethi = E_TABLE_HEADER_ITEM (o);
-
- switch (arg_id){
- case ARG_TABLE_HEADER:
- ethi_drop_table_header (ethi);
- ethi_add_table_header (ethi, GTK_VALUE_POINTER (*arg));
- break;
-
- case ARG_TABLE_X:
- ethi->x1 = GTK_VALUE_INT (*arg);
- break;
-
- case ARG_TABLE_Y:
- ethi->y1 = GTK_VALUE_INT (*arg);
- break;
-
- case ARG_TABLE_FONTSET:
- ethi_font_load (ethi, GTK_VALUE_STRING (*arg));
- break;
-
- }
- ethi_update (item, NULL, NULL, 0);
-}
-
-static int
-ethi_find_col_by_x (ETableHeaderItem *ethi, int x)
-{
- const int cols = e_table_header_count (ethi->eth);
- int x1 = ethi->x1;
- int col;
-
- if (x < x1)
- return -1;
-
- for (col = 0; col < cols; col++){
- ETableCol *ecol = e_table_header_get_column (ethi->eth, col);
-
- if ((x >= x1) && (x <= x1 + ecol->width))
- return col;
-
- x1 += ecol->width;
- }
- return -1;
-}
-
-static void
-ethi_remove_drop_marker (ETableHeaderItem *ethi)
-{
- if (ethi->drag_mark == -1)
- return;
-
- ethi->drag_mark = -1;
- gtk_object_destroy (GTK_OBJECT (ethi->drag_mark_item));
- ethi->drag_mark_item = NULL;
-}
-
-static void
-ethi_add_drop_marker (ETableHeaderItem *ethi, int col)
-{
- GnomeCanvasPoints *points;
- int x;
-
- if (ethi->drag_mark == col)
- return;
-
- if (ethi->drag_mark_item)
- gtk_object_destroy (GTK_OBJECT (ethi->drag_mark_item));
-
- ethi->drag_mark = col;
-
- ethi->drag_mark_item = gnome_canvas_item_new (
- GNOME_CANVAS_GROUP (GNOME_CANVAS_ITEM (ethi)->canvas->root),
- gnome_canvas_group_get_type (),
- "x", 0,
- "y", 0,
- NULL);
-
- points = gnome_canvas_points_new (3);
-
- x = e_table_header_col_diff (ethi->eth, 0, col);
-
- points->coords [0] = ethi->x1 + x - 5;
- points->coords [1] = ethi->y1;
- points->coords [2] = points->coords [0] + 10;
- points->coords [3] = points->coords [1];
- points->coords [4] = ethi->x1 + x;
- points->coords [5] = ethi->y1 + 5;
-
- gnome_canvas_item_new (
- GNOME_CANVAS_GROUP (ethi->drag_mark_item),
- gnome_canvas_polygon_get_type (),
- "points", points,
- "fill_color", "red",
- NULL);
-
- points->coords [0] --;
- points->coords [1] += ethi->height - 1;
- points->coords [3] = points->coords [1];
- points->coords [5] = points->coords [1] - 6;
-
- gnome_canvas_item_new (
- GNOME_CANVAS_GROUP (ethi->drag_mark_item),
- gnome_canvas_polygon_get_type (),
- "points", points,
- "fill_color", "red",
- NULL);
-
- gnome_canvas_points_unref (points);
-}
-
-#define gray50_width 2
-#define gray50_height 2
-static char gray50_bits [] = {
- 0x02, 0x01, };
-
-static void
-ethi_add_destroy_marker (ETableHeaderItem *ethi)
-{
- double x1;
-
- if (ethi->remove_item)
- gtk_object_destroy (GTK_OBJECT (ethi->remove_item));
-
- if (!ethi->stipple)
- ethi->stipple = gdk_bitmap_create_from_data (NULL, gray50_bits, gray50_width, gray50_height);
-
- x1 = ethi->x1 + (double) e_table_header_col_diff (ethi->eth, 0, ethi->drag_col);
- ethi->remove_item = gnome_canvas_item_new (
- GNOME_CANVAS_GROUP (GNOME_CANVAS_ITEM (ethi)->canvas->root),
- gnome_canvas_rect_get_type (),
- "x1", x1 + 1,
- "y1", (double) ethi->y1 + 1,
- "x2", (double) x1 + e_table_header_col_diff (ethi->eth, ethi->drag_col, ethi->drag_col+1) - 2,
- "y2", (double) ethi->y1 + ethi->height - 2,
- "fill_color", "red",
- "fill_stipple", ethi->stipple,
- NULL);
-}
-
-static void
-ethi_remove_destroy_marker (ETableHeaderItem *ethi)
-{
- if (!ethi->remove_item)
- return;
-
- gtk_object_destroy (GTK_OBJECT (ethi->remove_item));
- ethi->remove_item = NULL;
-}
-
-static gboolean
-ethi_drag_motion (GtkObject *canvas, GdkDragContext *context,
- gint x, gint y, guint time,
- ETableHeaderItem *ethi)
-{
-
- if ((x >= ethi->x1) && (x <= (ethi->x1 + ethi->width)) &&
- (y >= ethi->y1) && (y <= (ethi->y1 + ethi->height))){
- int col;
-
- col = ethi_find_col_by_x (ethi, x);
-
- if (col != -1){
- ethi_remove_destroy_marker (ethi);
- ethi_add_drop_marker (ethi, col);
- } else {
- ethi_remove_drop_marker (ethi);
- ethi_add_destroy_marker (ethi);
- }
- } else {
- ethi_remove_drop_marker (ethi);
- ethi_add_destroy_marker (ethi);
- }
-
- gdk_drag_status (context, context->suggested_action, time);
-
- return TRUE;
-}
-
-static void
-ethi_drag_end (GtkWidget *canvas, GdkDragContext *context, ETableHeaderItem *ethi)
-{
- ethi_remove_drop_marker (ethi);
- ethi_remove_destroy_marker (ethi);
- ethi->drag_col = -1;
-}
-
-static void
-ethi_drag_leave (GtkWidget *widget, GdkDragContext *context, guint time, ETableHeaderItem *ethi)
-{
- ethi_remove_drop_marker (ethi);
- ethi_add_destroy_marker (ethi);
-}
-
-static void
-ethi_realize (GnomeCanvasItem *item)
-{
- ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item);
- GdkWindow *window;
- GdkColor c;
-
- if (GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)-> realize)
- (*GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->realize)(item);
-
- window = GTK_WIDGET (item->canvas)->window;
-
- ethi->gc = gdk_gc_new (window);
- gnome_canvas_get_color (item->canvas, "black", &c);
- gdk_gc_set_foreground (ethi->gc, &c);
-
- ethi->normal_cursor = gdk_cursor_new (GDK_ARROW);
-
- if (!ethi->font)
- ethi_font_load (ethi, "fixed");
-
- /*
- * Now, configure DnD
- */
- gtk_drag_dest_set (GTK_WIDGET (item->canvas), GTK_DEST_DEFAULT_ALL,
- ethi_drop_types, ELEMENTS (ethi_drop_types),
- GDK_ACTION_MOVE);
-
- ethi->drag_motion_id = gtk_signal_connect (
- GTK_OBJECT (item->canvas), "drag_motion",
- GTK_SIGNAL_FUNC (ethi_drag_motion), ethi);
-
- ethi->drag_leave_id = gtk_signal_connect (
- GTK_OBJECT (item->canvas), "drag_leave",
- GTK_SIGNAL_FUNC (ethi_drag_leave), ethi);
-
- ethi->drag_end_id = gtk_signal_connect (
- GTK_OBJECT (item->canvas), "drag_end",
- GTK_SIGNAL_FUNC (ethi_drag_end), ethi);
-}
-
-static void
-ethi_unrealize (GnomeCanvasItem *item)
-{
- ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item);
-
- gdk_gc_unref (ethi->gc);
- ethi->gc = NULL;
-
- gdk_cursor_destroy (ethi->normal_cursor);
- ethi->normal_cursor = NULL;
-
- gtk_signal_disconnect (GTK_OBJECT (item->canvas), ethi->drag_motion_id);
- gtk_signal_disconnect (GTK_OBJECT (item->canvas), ethi->drag_end_id);
- gtk_signal_disconnect (GTK_OBJECT (item->canvas), ethi->drag_leave_id);
-
- if (ethi->stipple){
- gdk_bitmap_unref (ethi->stipple);
- ethi->stipple = NULL;
- }
-
- if (GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->unrealize)
- (*GNOME_CANVAS_ITEM_CLASS (ethi_parent_class)->unrealize)(item);
-}
-
-static void
-draw_button (ETableHeaderItem *ethi, ETableCol *col,
- GdkDrawable *drawable, GdkGC *gc, GtkStyle *style,
- int x, int y, int width, int height)
-{
- GdkRectangle clip;
- int xtra;
-
- gdk_draw_rectangle (
- drawable, gc, TRUE,
- x + 1, y + 1, width - 2, height -2);
-
- gtk_draw_shadow (
- style, drawable,
- GTK_STATE_NORMAL, GTK_SHADOW_OUT,
- x , y, width, height);
-
- clip.x = x + 2;
- clip.y = y + 2;
- clip.width = width - 4;
- clip.height = ethi->height;
-
- gdk_gc_set_clip_rectangle (ethi->gc, &clip);
-
- /* Center the thing */
- xtra = (clip.width - gdk_string_measure (ethi->font, col->text))/2;
-
- if (xtra < 0)
- xtra = 0;
-
- /* Skip over border */
- x += xtra + 2;
-
- gdk_draw_text (
- drawable, ethi->font,
- ethi->gc, x, y + ethi->height - PADDING,
- col->text, strlen (col->text));
-}
-
-static void
-ethi_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height)
-{
- ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item);
- GnomeCanvas *canvas = item->canvas;
- GdkGC *gc;
- const int cols = e_table_header_count (ethi->eth);
- int x1, x2;
- int col;
-
-#if 0
- printf ("My coords are: %g %g %g %g\n",
- item->x1, item->y1, item->x2, item->y2);
-#endif
- x1 = x2 = ethi->x1;
- for (col = 0; col < cols; col++, x1 = x2){
- ETableCol *ecol = e_table_header_get_column (ethi->eth, col);
- int col_width;
-
- if (col == ethi->resize_col)
- col_width = ethi->resize_width;
- else
- col_width = ecol->width;
-
- x2 += col_width;
-
- if (x1 > (x + width))
- break;
-
- if (x2 < x)
- continue;
-
- gc = GTK_WIDGET (canvas)->style->bg_gc [GTK_STATE_ACTIVE];
-
- draw_button (ethi, ecol, drawable, gc,
- GTK_WIDGET (canvas)->style,
- x1 - x, ethi->y1 - y, col_width, ethi->height);
- }
-}
-
-static double
-ethi_point (GnomeCanvasItem *item, double x, double y, int cx, int cy,
- GnomeCanvasItem **actual_item)
-{
- *actual_item = item;
- return 0.0;
-}
-
-/*
- * is_pointer_on_division:
- *
- * Returns whether @pos is a column header division; If @the_total is not NULL,
- * then the actual position is returned here. If @return_ecol is not NULL,
- * then the ETableCol that actually contains this point is returned here
- */
-static gboolean
-is_pointer_on_division (ETableHeaderItem *ethi, int pos, int *the_total, int *return_col)
-{
- const int cols = e_table_header_count (ethi->eth);
- int col, total;
-
- total = 0;
- for (col = 0; col < cols; col++){
- ETableCol *ecol = e_table_header_get_column (ethi->eth, col);
-
- total += ecol->width;
-
- if ((total - TOLERANCE < pos ) && (pos < total + TOLERANCE)){
- if (return_col)
- *return_col = col;
- if (the_total)
- *the_total = total;
-
- return TRUE;
- }
-
- if (total > pos + TOLERANCE)
- return FALSE;
- }
-
- return FALSE;
-}
-
-#define convert(c,sx,sy,x,y) gnome_canvas_w2c (c,sx,sy,x,y)
-
-static void
-set_cursor (ETableHeaderItem *ethi, int pos)
-{
- GtkWidget *canvas = GTK_WIDGET (GNOME_CANVAS_ITEM (ethi)->canvas);
-
- /* We might be invoked before we are realized */
- if (!canvas->window)
- return;
-
- if (is_pointer_on_division (ethi, pos, NULL, NULL))
- e_cursor_set (canvas->window, E_CURSOR_SIZE_X);
- else
- e_cursor_set (canvas->window, E_CURSOR_ARROW);
-}
-
-static void
-ethi_request_redraw (ETableHeaderItem *ethi)
-{
- GnomeCanvas *canvas = GNOME_CANVAS_ITEM (ethi)->canvas;
-
- /*
- * request a redraw
- */
- gnome_canvas_request_redraw (
- canvas, ethi->x1, ethi->y1, ethi->x1 + ethi->width, ethi->x1 + ethi->height);
-}
-
-static void
-ethi_end_resize (ETableHeaderItem *ethi, int new_size)
-{
- e_table_header_set_size (ethi->eth, ethi->resize_col, new_size);
-
- ethi->resize_col = -1;
- ethi_request_redraw (ethi);
-}
-
-static gboolean
-ethi_maybe_start_drag (ETableHeaderItem *ethi, GdkEventMotion *event)
-{
- if (!ethi->maybe_drag)
- return FALSE;
-
- if (MAX (abs (ethi->click_x - event->x),
- abs (ethi->click_y - event->y)) <= 3)
- return FALSE;
-
- return TRUE;
-}
-
-static void
-ethi_start_drag (ETableHeaderItem *ethi, GdkEvent *event)
-{
- GtkWidget *widget = GTK_WIDGET (GNOME_CANVAS_ITEM (ethi)->canvas);
- GtkTargetList *list;
- GdkDragContext *context;
-
- ethi->drag_col = ethi_find_col_by_x (ethi, event->motion.x);
- if (ethi->drag_col == -1)
- return;
-
- list = gtk_target_list_new (ethi_drag_types, ELEMENTS (ethi_drag_types));
- context = gtk_drag_begin (widget, list, GDK_ACTION_MOVE, 1, event);
- ethi->maybe_drag = FALSE;
-}
-
-/*
- * Handles the events on the ETableHeaderItem, particularly it handles resizing
- */
-static int
-ethi_event (GnomeCanvasItem *item, GdkEvent *e)
-{
- ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item);
- GnomeCanvas *canvas = item->canvas;
- const gboolean resizing = ETHI_RESIZING (ethi);
- int x, y, start, col;
-
- switch (e->type){
- case GDK_ENTER_NOTIFY:
- convert (canvas, e->crossing.x, e->crossing.y, &x, &y);
- set_cursor (ethi, x);
- break;
-
- case GDK_LEAVE_NOTIFY:
- e_cursor_set (GTK_WIDGET (canvas)->window, E_CURSOR_ARROW);
- break;
-
- case GDK_MOTION_NOTIFY:
- convert (canvas, e->motion.x, e->motion.y, &x, &y);
- if (resizing){
- int new_width;
-
- if (ethi->resize_guide == NULL){
- /* Quick hack until I actually bind the views */
- ethi->resize_guide = GINT_TO_POINTER (1);
- gnome_canvas_item_grab (item,
- GDK_POINTER_MOTION_MASK |
- GDK_BUTTON_RELEASE_MASK,
- e_cursor_get (E_CURSOR_SIZE_X),
- e->button.time);
- }
-
- new_width = x - ethi->resize_start_pos;
- if (new_width <= 0)
- break;
-
- if (new_width < ethi->resize_min_width)
- break;
-
- ethi_request_redraw (ethi);
-
- ethi->resize_width = new_width;
- e_table_header_set_size (ethi->eth, ethi->resize_col, ethi->resize_width);
-
- ethi_request_redraw (ethi);
- } else if (ethi_maybe_start_drag (ethi, &e->motion)){
- ethi_start_drag (ethi, e);
- } else
- set_cursor (ethi, x);
- break;
-
- case GDK_BUTTON_PRESS:
- convert (canvas, e->button.x, e->button.y, &x, &y);
-
- if (is_pointer_on_division (ethi, x, &start, &col)){
- ETableCol *ecol;
-
- /*
- * Record the important bits.
- *
- * By setting resize_pos to a non -1 value,
- * we know that we are being resized (used in the
- * other event handlers).
- */
- ecol = e_table_header_get_column (ethi->eth, col);
-
- if (!ecol->resizeable)
- break;
- ethi->resize_col = col;
- ethi->resize_width = ecol->width;
- ethi->resize_start_pos = start - ecol->width;
- ethi->resize_min_width = ecol->min_width;
- } else {
- if (e->button.button == 1){
- ethi->click_x = e->button.x;
- ethi->click_y = e->button.y;
- ethi->maybe_drag = TRUE;
- }
- }
- break;
-
- case GDK_2BUTTON_PRESS:
- if (!resizing)
- break;
-
- if (e->button.button != 1)
- break;
- break;
-
- case GDK_BUTTON_RELEASE: {
- gboolean needs_ungrab = FALSE;
-
- if (ethi->resize_col != -1){
- needs_ungrab = (ethi->resize_guide != NULL);
- ethi_end_resize (ethi, ethi->resize_width);
- }
- if (needs_ungrab)
- gnome_canvas_item_ungrab (item, e->button.time);
-
- ethi->maybe_drag = FALSE;
- break;
- }
-
- default:
- return FALSE;
- }
- return TRUE;
-}
-
-static void
-ethi_class_init (GtkObjectClass *object_class)
-{
- GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class;
-
- ethi_parent_class = gtk_type_class (PARENT_OBJECT_TYPE);
-
- object_class->destroy = ethi_destroy;
- object_class->set_arg = ethi_set_arg;
-
- item_class->update = ethi_update;
- item_class->realize = ethi_realize;
- item_class->unrealize = ethi_unrealize;
- item_class->draw = ethi_draw;
- item_class->point = ethi_point;
- item_class->event = ethi_event;
-
- gtk_object_add_arg_type ("ETableHeaderItem::ETableHeader", GTK_TYPE_POINTER,
- GTK_ARG_WRITABLE, ARG_TABLE_HEADER);
- gtk_object_add_arg_type ("ETableHeaderItem::x", GTK_TYPE_INT,
- GTK_ARG_WRITABLE, ARG_TABLE_X);
- gtk_object_add_arg_type ("ETableHeaderItem::y", GTK_TYPE_INT,
- GTK_ARG_WRITABLE, ARG_TABLE_Y);
- gtk_object_add_arg_type ("ETableHeaderItem::fontset", GTK_TYPE_STRING,
- GTK_ARG_WRITABLE, ARG_TABLE_FONTSET);
-
- /*
- * Create our pixmaps for DnD
- */
- dnd_colormap = gtk_widget_get_default_colormap ();
- remove_col_pixmap = gdk_pixmap_colormap_create_from_xpm_d (
- NULL, dnd_colormap,
- &remove_col_mask, NULL, remove_col_xpm);
-
- add_col_pixmap = gdk_pixmap_colormap_create_from_xpm_d (
- NULL, dnd_colormap,
- &add_col_mask, NULL, add_col_xpm);
-}
-
-static void
-ethi_init (GnomeCanvasItem *item)
-{
- ETableHeaderItem *ethi = E_TABLE_HEADER_ITEM (item);
-
- ethi->resize_col = -1;
-
- item->x1 = 0;
- item->y1 = 0;
- item->x2 = 0;
- item->y2 = 0;
-
- ethi->drag_col = -1;
- ethi->drag_mark = -1;
-}
-
-GtkType
-e_table_header_item_get_type (void)
-{
- static GtkType type = 0;
-
- if (!type){
- GtkTypeInfo info = {
- "ETableHeaderItem",
- sizeof (ETableHeaderItem),
- sizeof (ETableHeaderItemClass),
- (GtkClassInitFunc) ethi_class_init,
- (GtkObjectInitFunc) ethi_init,
- NULL, /* reserved 1 */
- NULL, /* reserved 2 */
- (GtkClassInitFunc) NULL
- };
-
- type = gtk_type_unique (PARENT_OBJECT_TYPE, &info);
- }
-
- return type;
-}
-
diff --git a/widgets/e-table-header-item.h b/widgets/e-table-header-item.h
deleted file mode 100644
index 5522d24fae..0000000000
--- a/widgets/e-table-header-item.h
+++ /dev/null
@@ -1,56 +0,0 @@
-#ifndef _E_TABLE_HEADER_ITEM_H_
-#define _E_TABLE_HEADER_ITEM_H_
-
-#include <libgnomeui/gnome-canvas.h>
-#include "e-table-header.h"
-
-#define E_TABLE_HEADER_ITEM_TYPE (e_table_header_item_get_type ())
-#define E_TABLE_HEADER_ITEM(o) (GTK_CHECK_CAST ((o), E_TABLE_HEADER_ITEM_TYPE, ETableHeaderItem))
-#define E_TABLE_HEADER_ITEM_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_HEADER_ITEM_TYPE, ETableHeaderItemClass))
-#define E_IS_TABLE_HEADER_ITEM(o) (GTK_CHECK_TYPE ((o), E_TABLE_HEADER_ITEM_TYPE))
-#define E_IS_TABLE_HEADER_ITEM_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_HEADER_ITEM_TYPE))
-
-typedef struct {
- GnomeCanvasItem parent;
- ETableHeader *eth;
-
- GdkGC *gc;
- GdkCursor *change_cursor, *normal_cursor;
-
- short x1, y1, height, width;
- GdkFont *font;
-
- /*
- * Used during resizing; Could be shorts
- */
- int resize_col;
- int resize_width;
- int resize_start_pos;
- int resize_min_width;
-
- GtkObject *resize_guide;
-
- /*
- * Ids
- */
- int structure_change_id, dimension_change_id;
-
- /*
- * For dragging columns
- */
- guint maybe_drag:1;
- guint dnd_ready:1;
- int click_x, click_y;
- int drag_col, drag_mark;
- guint drag_motion_id, drag_end_id, drag_leave_id;
- GnomeCanvasItem *drag_mark_item, *remove_item;
- GdkBitmap *stipple;
-} ETableHeaderItem;
-
-typedef struct {
- GnomeCanvasItemClass parent_class;
-} ETableHeaderItemClass;
-
-GtkType e_table_header_item_get_type (void);
-
-#endif /* _E_TABLE_HEADER_ITEM_H_ */
diff --git a/widgets/e-table-header.c b/widgets/e-table-header.c
deleted file mode 100644
index 7c54bd936e..0000000000
--- a/widgets/e-table-header.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * E-table-col-head.c: TableColHead implementation
- *
- * Author:
- * Miguel de Icaza (miguel@gnu.org)
- *
- * (C) 1999 Helix Code, Inc
- */
-#include <config.h>
-#include <gtk/gtkobject.h>
-#include <gtk/gtksignal.h>
-#include "e-table-header.h"
-
-enum {
- STRUCTURE_CHANGE,
- DIMENSION_CHANGE,
- LAST_SIGNAL
-};
-
-static guint eth_signals [LAST_SIGNAL] = { 0, };
-
-static GtkObjectClass *e_table_header_parent_class;
-
-static void
-e_table_header_destroy (GtkObject *object)
-{
- ETableHeader *eth = E_TABLE_HEADER (object);
- const int cols = eth->col_count;
- int i;
-
- /*
- * Destroy columns
- */
- for (i = 0; i < cols; i++){
- e_table_header_remove (eth, i);
- }
-
- if (e_table_header_parent_class->destroy)
- e_table_header_parent_class->destroy (object);
-}
-
-static void
-e_table_header_class_init (GtkObjectClass *object_class)
-{
- object_class->destroy = e_table_header_destroy;
-
- e_table_header_parent_class = (gtk_type_class (gtk_object_get_type ()));
-
- eth_signals [STRUCTURE_CHANGE] =
- gtk_signal_new ("structure_change",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (ETableHeaderClass, structure_change),
- gtk_marshal_NONE__NONE,
- GTK_TYPE_NONE, 0);
- eth_signals [DIMENSION_CHANGE] =
- gtk_signal_new ("dimension_change",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (ETableHeaderClass, dimension_change),
- gtk_marshal_NONE__INT,
- GTK_TYPE_NONE, 1, GTK_TYPE_INT);
-
- gtk_object_class_add_signals (object_class, eth_signals, LAST_SIGNAL);
-}
-
-GtkType
-e_table_header_get_type (void)
-{
- static GtkType type = 0;
-
- if (!type){
- GtkTypeInfo info = {
- "ETableHeader",
- sizeof (ETableHeader),
- sizeof (ETableHeaderClass),
- (GtkClassInitFunc) e_table_header_class_init,
- (GtkObjectInitFunc) NULL,
- NULL, /* reserved 1 */
- NULL, /* reserved 2 */
- (GtkClassInitFunc) NULL
- };
-
- type = gtk_type_unique (gtk_object_get_type (), &info);
- }
-
- return type;
-}
-
-ETableHeader *
-e_table_header_new (void)
-{
- ETableHeader *eth;
-
- eth = gtk_type_new (e_table_header_get_type ());
-
- return eth;
-}
-
-static void
-eth_do_insert (ETableHeader *eth, int pos, ETableCol *val)
-{
- memcpy (&eth->columns [pos+1], &eth->columns [pos],
- sizeof (ETableCol *) * (eth->col_count - pos));
- eth->columns [pos] = val;
-}
-
-static void
-eth_update_offsets (ETableHeader *eth)
-{
- int i;
- int x = 0;
-
- for (i = 0; i < eth->col_count; i++){
- ETableCol *etc = eth->columns [i];
-
- etc->x = x;
- x += etc->width;
- }
-}
-
-void
-e_table_header_add_column (ETableHeader *eth, ETableCol *tc, int pos)
-{
- g_return_if_fail (eth != NULL);
- g_return_if_fail (E_IS_TABLE_HEADER (eth));
- g_return_if_fail (tc != NULL);
- g_return_if_fail (E_IS_TABLE_COL (tc));
- g_return_if_fail (pos >= -1 && pos <= eth->col_count);
-
- if (pos == -1)
- pos = eth->col_count;
- eth->columns = g_realloc (eth->columns, sizeof (ETableCol *) * (eth->col_count + 1));
-
- /*
- * We are the primary owners of the column
- */
- gtk_object_ref (GTK_OBJECT (tc));
- gtk_object_sink (GTK_OBJECT (tc));
-
- eth_do_insert (eth, pos, tc);
- eth->col_count++;
- eth_update_offsets (eth);
-
- gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]);
- gtk_signal_emit (GTK_OBJECT (eth), eth_signals [DIMENSION_CHANGE]);
-}
-
-ETableCol *
-e_table_header_get_column (ETableHeader *eth, int column)
-{
- g_return_val_if_fail (eth != NULL, NULL);
- g_return_val_if_fail (E_IS_TABLE_HEADER (eth), NULL);
-
- if (column < 0)
- return NULL;
-
- if (column >= eth->col_count)
- return NULL;
-
- return eth->columns [column];
-}
-
-int
-e_table_header_count (ETableHeader *eth)
-{
- g_return_val_if_fail (eth != NULL, 0);
- g_return_val_if_fail (E_IS_TABLE_HEADER (eth), 0);
-
- return eth->col_count;
-}
-
-int
-e_table_header_index (ETableHeader *eth, int col)
-{
- g_return_val_if_fail (eth != NULL, -1);
- g_return_val_if_fail (E_IS_TABLE_HEADER (eth), -1);
- g_return_val_if_fail (col < eth->col_count, -1);
-
- return eth->columns [col]->col_idx;
-}
-
-int
-e_table_header_get_index_at (ETableHeader *eth, int x_offset)
-{
- int i, total;
-
- g_return_val_if_fail (eth != NULL, 0);
- g_return_val_if_fail (E_IS_TABLE_HEADER (eth), 0);
-
- total = 0;
- for (i = 0; i < eth->col_count; i++){
- total += eth->columns [i]->width;
-
- if (x_offset < total)
- return i;
- }
-
- return -1;
-}
-
-ETableCol **
-e_table_header_get_columns (ETableHeader *eth)
-{
- ETableCol **ret;
-
- g_return_val_if_fail (eth != NULL, 0);
- g_return_val_if_fail (E_IS_TABLE_HEADER (eth), 0);
-
- ret = g_new (ETableCol *, eth->col_count + 1);
- memcpy (ret, eth->columns, sizeof (ETableCol *) * eth->col_count);
- ret [eth->col_count] = NULL;
-
- return ret;
-}
-
-gboolean
-e_table_header_selection_ok (ETableHeader *eth)
-{
- g_return_val_if_fail (eth != NULL, FALSE);
- g_return_val_if_fail (E_IS_TABLE_HEADER (eth), FALSE);
-
- return eth->selectable;
-}
-
-int
-e_table_header_get_selected (ETableHeader *eth)
-{
- int i;
- int selected = 0;
-
- g_return_val_if_fail (eth != NULL, 0);
- g_return_val_if_fail (E_IS_TABLE_HEADER (eth), 0);
-
- for (i = 0; i < eth->col_count; i++){
- if (eth->columns [i]->selected)
- selected++;
- }
-
- return selected;
-}
-
-int
-e_table_header_total_width (ETableHeader *eth)
-{
- int total, i;
-
- g_return_val_if_fail (eth != NULL, 0);
- g_return_val_if_fail (E_IS_TABLE_HEADER (eth), 0);
-
- total = 0;
- for (i = 0; i < eth->col_count; i++)
- total += eth->columns [i]->width;
-
- return total;
-}
-
-static void
-eth_do_remove (ETableHeader *eth, int idx, gboolean do_unref)
-{
- if (do_unref)
- gtk_object_unref (GTK_OBJECT (eth->columns [idx]));
-
- memcpy (&eth->columns [idx], &eth->columns [idx+1],
- sizeof (ETableCol *) * eth->col_count - idx);
- eth->col_count--;
-}
-
-void
-e_table_header_move (ETableHeader *eth, int source_index, int target_index)
-{
- ETableCol *old;
-
- g_return_if_fail (eth != NULL);
- g_return_if_fail (E_IS_TABLE_HEADER (eth));
- g_return_if_fail (source_index >= 0);
- g_return_if_fail (target_index >= 0);
- g_return_if_fail (source_index < eth->col_count);
- g_return_if_fail (target_index < eth->col_count);
-
- old = eth->columns [source_index];
- eth_do_remove (eth, source_index, FALSE);
- eth_do_insert (eth, target_index, old);
- eth_update_offsets (eth);
-
- gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]);
- gtk_signal_emit (GTK_OBJECT (eth), eth_signals [DIMENSION_CHANGE]);
-}
-
-void
-e_table_header_remove (ETableHeader *eth, int idx)
-{
- g_return_if_fail (eth != NULL);
- g_return_if_fail (E_IS_TABLE_HEADER (eth));
- g_return_if_fail (idx >= 0);
- g_return_if_fail (idx < eth->col_count);
-
- eth_do_remove (eth, idx, TRUE);
- gtk_signal_emit (GTK_OBJECT (eth), eth_signals [STRUCTURE_CHANGE]);
- gtk_signal_emit (GTK_OBJECT (eth), eth_signals [DIMENSION_CHANGE]);
-}
-
-void
-e_table_header_set_selection (ETableHeader *eth, gboolean allow_selection)
-{
-}
-
-void
-e_table_header_set_size (ETableHeader *eth, int idx, int size)
-{
- g_return_if_fail (eth != NULL);
- g_return_if_fail (E_IS_TABLE_HEADER (eth));
- g_return_if_fail (idx >= 0);
- g_return_if_fail (idx < eth->col_count);
- g_return_if_fail (size > 0);
-
- eth->columns [idx]->width = size;
- gtk_signal_emit (GTK_OBJECT (eth), eth_signals [DIMENSION_CHANGE], idx);
-}
-
-int
-e_table_header_col_diff (ETableHeader *eth, int start_col, int end_col)
-{
- int total, col;
-
- g_return_val_if_fail (eth != NULL, 0);
- g_return_val_if_fail (E_IS_TABLE_HEADER (eth), 0);
-
- {
- const int max_col = eth->col_count;
-
- total = 0;
- for (col = start_col; col < end_col; col++){
-
- if (col == max_col)
- break;
- total += eth->columns [col]->width;
- }
- }
-
- return total;
-}
diff --git a/widgets/e-table-header.h b/widgets/e-table-header.h
deleted file mode 100644
index 96e65fdc2f..0000000000
--- a/widgets/e-table-header.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef _E_TABLE_COLUMN_H_
-#define _E_TABLE_COLUMN_H_
-
-#include <gtk/gtkobject.h>
-#include <gdk/gdk.h>
-#include "e-table-col.h"
-
-typedef struct _ETableHeader ETableHeader;
-
-#define E_TABLE_HEADER_TYPE (e_table_header_get_type ())
-#define E_TABLE_HEADER(o) (GTK_CHECK_CAST ((o), E_TABLE_HEADER_TYPE, ETableHeader))
-#define E_TABLE_HEADER_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_HEADER_TYPE, ETableHeaderClass))
-#define E_IS_TABLE_HEADER(o) (GTK_CHECK_TYPE ((o), E_TABLE_HEADER_TYPE))
-#define E_IS_TABLE_HEADER_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_HEADER_TYPE))
-
-/*
- * A Columnar header.
- */
-struct _ETableHeader {
- GtkObject base;
-
- int col_count;
- ETableCol **columns;
- gboolean selectable;
-};
-
-typedef struct {
- GtkObjectClass parent_class;
-
- void (*structure_change) (ETableHeader *eth);
- void (*dimension_change) (ETableHeader *eth, int col);
-} ETableHeaderClass;
-
-GtkType e_table_header_get_type (void);
-ETableHeader *e_table_header_new (void);
-
-void e_table_header_add_column (ETableHeader *eth,
- ETableCol *tc, int pos);
-ETableCol * e_table_header_get_column (ETableHeader *eth,
- int column);
-int e_table_header_count (ETableHeader *eth);
-int e_table_header_index (ETableHeader *eth,
- int col);
-int e_table_header_get_index_at (ETableHeader *eth,
- int x_offset);
-ETableCol **e_table_header_get_columns (ETableHeader *eth);
-gboolean e_table_header_selection_ok (ETableHeader *eth);
-int e_table_header_get_selected (ETableHeader *eth);
-int e_table_header_total_width (ETableHeader *eth);
-void e_table_header_move (ETableHeader *eth,
- int source_index,
- int target_index);
-void e_table_header_remove (ETableHeader *eth, int idx);
-void e_table_header_set_size (ETableHeader *eth, int idx, int size);
-void e_table_header_set_selection (ETableHeader *eth,
- gboolean allow_selection);
-
-int e_table_header_col_diff (ETableHeader *eth,
- int start_col, int end_col);
-
-GList *e_table_header_get_selected_indexes(ETableHeader *eth);
-
-
-#endif /* _E_TABLE_HEADER_H_ */
-
diff --git a/widgets/e-table-item.c b/widgets/e-table-item.c
deleted file mode 100644
index 33f0c18616..0000000000
--- a/widgets/e-table-item.c
+++ /dev/null
@@ -1,1316 +0,0 @@
-/*
- * E-table-item.c: A GnomeCanvasItem that is a view of an ETableModel.
- *
- * Author:
- * Miguel de Icaza (miguel@gnu.org)
- *
- * Copyright 1999, Helix Code, Inc.
- *
- * TODO:
- * Add a border to the thing, so that focusing works properly.
- *
- */
-#include <config.h>
-#include <stdio.h>
-#include <gtk/gtksignal.h>
-#include <gdk/gdkkeysyms.h>
-#include <math.h>
-#include "e-table-item.h"
-#include "e-cell.h"
-
-#define PARENT_OBJECT_TYPE gnome_canvas_item_get_type ()
-
-#define FOCUSED_BORDER 2
-
-static GnomeCanvasItemClass *eti_parent_class;
-
-enum {
- ROW_SELECTION,
- HEIGHT_CHANGED,
- LAST_SIGNAL
-};
-
-static gint eti_signals [LAST_SIGNAL] = { 0, };
-
-enum {
- ARG_0,
- ARG_TABLE_HEADER,
- ARG_TABLE_MODEL,
- ARG_TABLE_X,
- ARG_TABLE_Y,
- ARG_TABLE_DRAW_GRID,
- ARG_TABLE_DRAW_FOCUS,
- ARG_MODE_SPREADSHEET,
- ARG_LENGHT_THRESHOLD
-};
-
-static gboolean
-eti_editing (ETableItem *eti)
-{
- if (eti->editing_col == -1)
- return FALSE;
- else
- return TRUE;
-}
-
-/*
- * During realization, we have to invoke the per-ecell realize routine
- * (On our current setup, we have one e-cell per column.
- *
- * We might want to optimize this to only realize the unique e-cells:
- * ie, a strings-only table, uses the same e-cell for every column, and
- * we might want to avoid realizing each e-cell.
- */
-static void
-eti_realize_cell_views (ETableItem *eti)
-{
- int i;
-
- for (i = 0; i < eti->n_cells; i++)
- e_cell_view_realize (eti->cell_views [i], eti);
- eti->cell_views_realized = 1;
-}
-
-static void eti_compute_height (ETableItem *eti);
-
-static void
-eti_attach_cell_views (ETableItem *eti)
-{
- int i;
-
- g_assert (eti->header);
- g_assert (eti->table_model);
-
- /*
- * Now realize the various ECells
- */
- eti->n_cells = eti->cols;
- eti->cell_views = g_new (ECellView *, eti->n_cells);
-
- for (i = 0; i < eti->n_cells; i++){
- ETableCol *col = e_table_header_get_column (eti->header, i);
-
- eti->cell_views [i] = e_cell_new_view (col->ecell, eti->table_model, eti);
- }
-
- eti_compute_height (eti);
-}
-
-/*
- * During unrealization: we invoke every e-cell (one per column in the current
- * setup) to dispose all X resources allocated
- */
-static void
-eti_unrealize_cell_views (ETableItem *eti)
-{
- int i;
-
- if (eti->cell_views_realized == 0)
- return;
-
- for (i = 0; i < eti->n_cells; i++)
- e_cell_unrealize (eti->cell_views [i]);
- eti->cell_views_realized = 0;
-}
-
-static void
-eti_detach_cell_views (ETableItem *eti)
-{
- int i;
-
- for (i = 0; i < eti->n_cells; i++){
- e_cell_kill_view (eti->cell_views [i]);
- eti->cell_views [i] = NULL;
- }
-
- g_free (eti->cell_views);
- eti->cell_views = NULL;
- eti->n_cells = 0;
-}
-
-static void
-eti_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
-{
- double i2c [6];
- ArtPoint c1, c2, i1, i2;
- ETableItem *eti = E_TABLE_ITEM (item);
-
- gnome_canvas_item_i2c_affine (item, i2c);
- i1.x = eti->x1;
- i1.y = eti->y1;
- i2.x = eti->x1 + eti->width;
- i2.y = eti->y1 + eti->height;
- art_affine_point (&c1, &i1, i2c);
- art_affine_point (&c2, &i2, i2c);
-
- item->x1 = c1.x;
- item->y1 = c1.y;
- item->x2 = c2.x;
- item->y2 = c2.y;
-}
-
-
-/*
- * GnomeCanvasItem::update method
- */
-static void
-eti_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
-{
- if (GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->update)
- (*GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->update)(item, affine, clip_path, flags);
-
- eti_bounds (item, &item->x1, &item->y1, &item->x2, &item->y2);
- gnome_canvas_group_child_bounds (GNOME_CANVAS_GROUP (item->parent), item);
-}
-
-/*
- * eti_remove_table_model:
- *
- * Invoked to release the table model associated with this ETableItem
- */
-static void
-eti_remove_table_model (ETableItem *eti)
-{
- if (!eti->table_model)
- return;
-
- gtk_signal_disconnect (GTK_OBJECT (eti->table_model),
- eti->table_model_change_id);
- gtk_signal_disconnect (GTK_OBJECT (eti->table_model),
- eti->table_model_row_change_id);
- gtk_object_unref (GTK_OBJECT (eti->table_model));
-
- eti->table_model_change_id = 0;
- eti->table_model_row_change_id = 0;
- eti->table_model = NULL;
-}
-
-/*
- * eti_remove_header_model:
- *
- * Invoked to release the header model associated with this ETableItem
- */
-static void
-eti_remove_header_model (ETableItem *eti)
-{
- if (!eti->header)
- return;
-
- gtk_signal_disconnect (GTK_OBJECT (eti->header),
- eti->header_structure_change_id);
- gtk_signal_disconnect (GTK_OBJECT (eti->header),
- eti->header_dim_change_id);
-
- if (eti->cell_views){
- eti_unrealize_cell_views (eti);
- eti_detach_cell_views (eti);
- }
- gtk_object_unref (GTK_OBJECT (eti->header));
-
-
- eti->header_structure_change_id = 0;
- eti->header_dim_change_id = 0;
- eti->header = NULL;
-}
-
-/*
- * eti_row_height:
- *
- * Returns the height used by row @row. This does not include the one-pixel
- * used as a separator between rows
- */
-static int
-eti_row_height (ETableItem *eti, int row)
-{
- const int cols = e_table_header_count (eti->header);
- int col;
- int h, max_h;
-
- g_assert (eti->cell_views);
-
- max_h = 0;
-
- for (col = 0; col < cols; col++){
- ETableCol *ecol = e_table_header_get_column (eti->header, col);
-
- h = e_cell_height (eti->cell_views [col], ecol->col_idx, col, row);
-
- if (h > max_h)
- max_h = h;
- }
- return max_h;
-}
-
-/*
- * eti_get_height:
- *
- * Returns the height of the ETableItem.
- *
- * The ETableItem might compute the whole height by asking every row its
- * size. There is a special mode (designed to work when there are too
- * many rows in the table that performing the previous step could take
- * too long) set by the ETableItem->length_threshold that would determine
- * when the height is computed by using the first row as the size for
- * every other row in the ETableItem.
- */
-static int
-eti_get_height (ETableItem *eti)
-{
- const int rows = eti->rows;
- int row;
- int height;
-
- if (rows == 0)
- return 0;
-
- if (eti->length_threshold != -1){
- if (rows > eti->length_threshold){
- height = (eti_row_height (eti, 0) + 1) * rows;
-
- /*
- * 1 pixel at the top
- */
- return height + 1;
- }
- }
-
- height = 1;
- for (row = 0; row < rows; row++)
- height += eti_row_height (eti, row) + 1;
-
- return height;
-}
-
-static void
-eti_compute_height (ETableItem *eti)
-{
- int new_height = eti_get_height (eti);
-
- if (new_height != eti->height){
- double x1, y1, x2, y2;
- printf ("Emitting!\n");
-
- eti->height = new_height;
- eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0);
-
- gtk_signal_emit (GTK_OBJECT (eti), eti_signals [HEIGHT_CHANGED]);
- }
-}
-
-/*
- * Callback routine: invoked when the ETableModel has suffered a change
- */
-static void
-eti_table_model_changed (ETableModel *table_model, ETableItem *eti)
-{
- eti->rows = e_table_model_row_count (eti->table_model);
-
- if (eti->cell_views)
- eti_compute_height (eti);
-
- eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0);
-}
-
-static void
-eti_item_region_redraw (ETableItem *eti, int x0, int y0, int x1, int y1)
-{
- GnomeCanvasItem *item = GNOME_CANVAS_ITEM (eti);
- ArtDRect rect;
- double i2c [6];
-
- rect.x0 = x0;
- rect.y0 = y0;
- rect.x1 = x1;
- rect.y1 = y1;
-
- gnome_canvas_item_i2c_affine (item, i2c);
- art_drect_affine_transform (&rect, &rect, i2c);
-
- gnome_canvas_request_redraw (item->canvas, rect.x0, rect.y0, rect.x1, rect.y1);
-}
-
-/*
- * eti_request_redraw:
- *
- * Queues a canvas redraw for the entire ETableItem.
- */
-static void
-eti_request_redraw (ETableItem *eti)
-{
- eti_item_region_redraw (eti, eti->x1, eti->y1, eti->x1 + eti->width + 1, eti->y1 + eti->height + 1);
-}
-
-/*
- * Computes the distance between @start_row and @end_row in pixels
- */
-static int
-eti_row_diff (ETableItem *eti, int start_row, int end_row)
-{
- int row, total;
-
- total = 0;
-
- for (row = start_row; row < end_row; row++)
- total += eti_row_height (eti, row) + 1;
-
- return total;
-}
-
-/*
- * eti_request_region_redraw:
- *
- * Request a canvas redraw on the range (start_col, start_row) to (end_col, end_row).
- * This is inclusive (ie, you can use: 0,0-0,0 to redraw the first cell).
- *
- * The @border argument is a number of pixels around the region that should also be queued
- * for redraw. This is typically used by the focus routines to queue a redraw for the
- * border as well.
- */
-static void
-eti_request_region_redraw (ETableItem *eti,
- int start_col, int start_row,
- int end_col, int end_row, int border)
-{
- int x1, y1, width, height;
-
- x1 = e_table_header_col_diff (eti->header, 0, start_col);
- y1 = eti_row_diff (eti, 0, start_row);
- width = e_table_header_col_diff (eti->header, start_col, end_col + 1);
- height = eti_row_diff (eti, start_row, end_row + 1);
-
- eti_item_region_redraw (eti, eti->x1 + x1 - border,
- eti->y1 + y1 - border,
- eti->x1 + x1 + width + 1 + border,
- eti->y1 + y1 + height + 1 + border);
-}
-
-static void
-eti_table_model_row_changed (ETableModel *table_model, int row, ETableItem *eti)
-{
- if (eti->renderers_can_change_size){
- eti_table_model_changed (table_model, eti);
- return;
- }
-
- eti_request_region_redraw (eti, 0, row, eti->cols, row, 0);
-}
-
-void
-e_table_item_redraw_range (ETableItem *eti,
- int start_col, int start_row,
- int end_col, int end_row)
-{
- int border;
-
- g_return_if_fail (eti != NULL);
- g_return_if_fail (E_IS_TABLE_ITEM (eti));
-
- if ((start_col == eti->focused_col) ||
- (end_col == eti->focused_col) ||
- (start_row == eti->focused_row) ||
- (end_row == eti->focused_row))
- border = 2;
- else
- border = 0;
-
- eti_request_region_redraw (eti, start_col, start_row, end_col, end_row, border);
-}
-
-static void
-eti_add_table_model (ETableItem *eti, ETableModel *table_model)
-{
- g_assert (eti->table_model == NULL);
-
- eti->table_model = table_model;
- gtk_object_ref (GTK_OBJECT (eti->table_model));
-
- eti->table_model_change_id = gtk_signal_connect (
- GTK_OBJECT (table_model), "model_changed",
- GTK_SIGNAL_FUNC (eti_table_model_changed), eti);
-
- eti->table_model_row_change_id = gtk_signal_connect (
- GTK_OBJECT (table_model), "model_row_changed",
- GTK_SIGNAL_FUNC (eti_table_model_row_changed), eti);
-
- if (eti->header){
- eti_detach_cell_views (eti);
- eti_attach_cell_views (eti);
- }
-
- eti_table_model_changed (table_model, eti);
-}
-
-static void
-eti_header_dim_changed (ETableHeader *eth, int col, ETableItem *eti)
-{
- eti_request_redraw (eti);
-
- eti->width = e_table_header_total_width (eti->header);
- eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0);
-
- eti_request_redraw (eti);
-}
-
-static void
-eti_header_structure_changed (ETableHeader *eth, ETableItem *eti)
-{
- eti_request_redraw (eti);
-
- eti->cols = e_table_header_count (eti->header);
- eti->width = e_table_header_total_width (eti->header);
-
- if (eti->cell_views){
- eti_unrealize_cell_views (eti);
- eti_detach_cell_views (eti);
- eti_attach_cell_views (eti);
- eti_realize_cell_views (eti);
- } else {
- if (eti->table_model){
- eti_detach_cell_views (eti);
- eti_attach_cell_views (eti);
- }
- }
-
- eti_update (GNOME_CANVAS_ITEM (eti), NULL, NULL, 0);
-
- eti_request_redraw (eti);
-}
-
-static void
-eti_add_header_model (ETableItem *eti, ETableHeader *header)
-{
- g_assert (eti->header == NULL);
-
- eti->header = header;
- gtk_object_ref (GTK_OBJECT (header));
-
- eti_header_structure_changed (header, eti);
-
- eti->header_dim_change_id = gtk_signal_connect (
- GTK_OBJECT (header), "dimension_change",
- GTK_SIGNAL_FUNC (eti_header_dim_changed), eti);
-
- eti->header_structure_change_id = gtk_signal_connect (
- GTK_OBJECT (header), "structure_change",
- GTK_SIGNAL_FUNC (eti_header_structure_changed), eti);
-}
-
-/*
- * GtkObject::destroy method
- */
-static void
-eti_destroy (GtkObject *object)
-{
- ETableItem *eti = E_TABLE_ITEM (object);
-
- eti_remove_header_model (eti);
- eti_remove_table_model (eti);
-
- g_slist_free (eti->selection);
-
- if (GTK_OBJECT_CLASS (eti_parent_class)->destroy)
- (*GTK_OBJECT_CLASS (eti_parent_class)->destroy) (object);
-}
-
-static void
-eti_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
-{
- GnomeCanvasItem *item;
- ETableItem *eti;
-
- item = GNOME_CANVAS_ITEM (o);
- eti = E_TABLE_ITEM (o);
-
- switch (arg_id){
- case ARG_TABLE_HEADER:
- eti_remove_header_model (eti);
- eti_add_header_model (eti, GTK_VALUE_POINTER (*arg));
- break;
-
- case ARG_TABLE_MODEL:
- eti_remove_table_model (eti);
- eti_add_table_model (eti, GTK_VALUE_POINTER (*arg));
- break;
-
- case ARG_TABLE_X:
- eti->x1 = GTK_VALUE_DOUBLE (*arg);
- break;
-
- case ARG_TABLE_Y:
- eti->y1 = GTK_VALUE_DOUBLE (*arg);
- break;
-
- case ARG_LENGHT_THRESHOLD:
- eti->length_threshold = GTK_VALUE_INT (*arg);
- break;
-
- case ARG_TABLE_DRAW_GRID:
- eti->draw_grid = GTK_VALUE_BOOL (*arg);
- break;
-
- case ARG_TABLE_DRAW_FOCUS:
- eti->draw_focus = GTK_VALUE_BOOL (*arg);
- break;
-
- case ARG_MODE_SPREADSHEET:
- eti->mode_spreadsheet = GTK_VALUE_BOOL (*arg);
- break;
- }
- eti_update (item, NULL, NULL, 0);
-}
-
-static void
-eti_init (GnomeCanvasItem *item)
-{
- ETableItem *eti = E_TABLE_ITEM (item);
-
- eti->focused_col = -1;
- eti->focused_row = -1;
- eti->editing_col = -1;
- eti->editing_row = -1;
- eti->height = 0;
-
- eti->length_threshold = -1;
- eti->renderers_can_change_size = 0;
-
- eti->selection_mode = GTK_SELECTION_SINGLE;
-}
-
-#define gray50_width 2
-#define gray50_height 2
-static const char gray50_bits[] = {
- 0x02, 0x01, };
-
-static void
-eti_realize (GnomeCanvasItem *item)
-{
- ETableItem *eti = E_TABLE_ITEM (item);
- GtkWidget *canvas_widget = GTK_WIDGET (item->canvas);
- GdkWindow *window;
-
- if (GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->realize)
- (*GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->realize)(item);
-
- /*
- * Gdk Resource allocation
- */
- window = canvas_widget->window;
-
- eti->fill_gc = canvas_widget->style->white_gc;
- gdk_gc_ref (canvas_widget->style->white_gc);
-
- eti->grid_gc = gdk_gc_new (window);
-#if 0
- /* This sets it to gray */
-/* gdk_gc_set_foreground (eti->grid_gc, &canvas_widget->style->bg [GTK_STATE_NORMAL]); */
-#else
- gdk_gc_set_foreground (eti->grid_gc, &canvas_widget->style->black);
-#endif
- eti->focus_gc = gdk_gc_new (window);
- gdk_gc_set_foreground (eti->focus_gc, &canvas_widget->style->bg [GTK_STATE_NORMAL]);
- gdk_gc_set_background (eti->focus_gc, &canvas_widget->style->fg [GTK_STATE_NORMAL]);
- eti->stipple = gdk_bitmap_create_from_data (NULL, gray50_bits, gray50_width, gray50_height);
- gdk_gc_set_ts_origin (eti->focus_gc, 0, 0);
- gdk_gc_set_stipple (eti->focus_gc, eti->stipple);
- gdk_gc_set_fill (eti->focus_gc, GDK_OPAQUE_STIPPLED);
-
- if (eti->cell_views == NULL)
- eti_attach_cell_views (eti);
-
- eti_realize_cell_views (eti);
-
- eti_compute_height (eti);
-
- eti_update (item, NULL, NULL, 0);
-}
-
-static void
-eti_unrealize (GnomeCanvasItem *item)
-{
- ETableItem *eti = E_TABLE_ITEM (item);
-
- gdk_gc_unref (eti->fill_gc);
- eti->fill_gc = NULL;
- gdk_gc_unref (eti->grid_gc);
- eti->grid_gc = NULL;
- gdk_gc_unref (eti->focus_gc);
- eti->focus_gc = NULL;
- gdk_bitmap_unref (eti->stipple);
- eti->stipple = NULL;
-
- eti_unrealize_cell_views (eti);
-
- eti->height = 0;
-
- if (GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->unrealize)
- (*GNOME_CANVAS_ITEM_CLASS (eti_parent_class)->unrealize)(item);
-}
-
-static void
-eti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height)
-{
- ETableItem *eti = E_TABLE_ITEM (item);
- const int rows = eti->rows;
- const int cols = eti->cols;
- int row, col, y1, y2;
- int first_col, last_col, x_offset;
- int first_row, last_row, y_offset, yd;
- int x1, x2;
- int f_x1, f_x2, f_y1, f_y2;
- gboolean f_found;
- double i2c [6];
- ArtPoint eti_base, eti_base_item;
-
- /*
- * Clear the background
- */
-#if 0
- gdk_draw_rectangle (
- drawable, eti->fill_gc, TRUE,
- eti->x1 - x, eti->y1 - y, eti->width, eti->height);
-#endif
-
- /*
- * Find out our real position after grouping
- */
- gnome_canvas_item_i2c_affine (item, i2c);
- eti_base_item.x = eti->x1;
- eti_base_item.y = eti->y1;
- art_affine_point (&eti_base, &eti_base_item, i2c);
-
- /*
- * First column to draw, last column to draw
- */
- first_col = -1;
- last_col = x_offset = 0;
- x1 = x2 = floor (eti_base.x);
- for (col = 0; col < cols; col++, x1 = x2){
- ETableCol *ecol = e_table_header_get_column (eti->header, col);
-
- x2 = x1 + ecol->width;
-
- if (x1 > (x + width))
- break;
- if (x2 < x)
- continue;
- if (first_col == -1){
- x_offset = x1 - x;
- first_col = col;
- }
- }
- last_col = col;
-
- /*
- * Nothing to paint
- */
- if (first_col == -1)
- return;
-
- /*
- * Compute row span.
- */
- first_row = -1;
- y_offset = 0;
- y1 = y2 = floor (eti_base.y) + 1;
- for (row = 0; row < rows; row++, y1 = y2){
-
- y2 += eti_row_height (eti, row) + 1;
-
- if (y1 > y + height)
- break;
-
- if (y2 < y)
- continue;
-
- if (first_row == -1){
- y_offset = y1 - y;
- first_row = row;
- }
- }
- last_row = row;
-
- if (first_row == -1)
- return;
-
- /*
- * Draw cells
- */
- yd = y_offset;
- f_x1 = f_x2 = f_y1 = f_y2 = -1;
- f_found = FALSE;
-
- if (eti->draw_grid && first_row == 0){
- gdk_draw_line (
- drawable, eti->grid_gc,
- eti_base.x - x, yd, eti_base.x + eti->width - x, yd);
- }
- yd++;
-
- for (row = first_row; row < last_row; row++){
- int xd, height;
- gboolean selected;
-
- height = eti_row_height (eti, row);
-
- xd = x_offset;
-/* printf ("paint: %d %d\n", yd, yd + height); */
-
- selected = g_slist_find (eti->selection, GINT_TO_POINTER (row)) != NULL;
-
- for (col = first_col; col < last_col; col++){
- ETableCol *ecol = e_table_header_get_column (eti->header, col);
- ECellView *ecell_view = eti->cell_views [col];
-
- e_cell_draw (ecell_view, drawable, ecol->col_idx, col, row, selected,
- xd, yd, xd + ecol->width, yd + height);
-
- if (col == eti->focused_col && row == eti->focused_row){
- f_x1 = xd;
- f_x2 = xd + ecol->width;
- f_y1 = yd;
- f_y2 = yd + height;
- f_found = TRUE;
- }
-
- xd += ecol->width;
- }
- yd += height;
-
- if (eti->draw_grid)
- gdk_draw_line (
- drawable, eti->grid_gc,
- eti_base.x - x, yd, eti_base.x + eti->width - x, yd);
- yd++;
- }
-
- if (eti->draw_grid){
- int xd = x_offset;
-
- for (col = first_col; col <= last_col; col++){
- ETableCol *ecol = e_table_header_get_column (eti->header, col);
-
- gdk_draw_line (
- drawable, eti->grid_gc,
- xd, y_offset, xd, yd - 1);
-
- /*
- * This looks wierd, but it is to draw the last line
- */
- if (ecol)
- xd += ecol->width;
- }
- }
-
- /*
- * Draw focus
- */
- if (f_found && eti->draw_focus){
-
- if (!eti_editing (eti))
- gdk_draw_rectangle (
- drawable, eti->focus_gc, FALSE,
- f_x1 + 1, f_y1, f_x2 - f_x1 - 2, f_y2 - f_y1 - 1);
- }
-}
-
-static double
-eti_point (GnomeCanvasItem *item, double x, double y, int cx, int cy,
- GnomeCanvasItem **actual_item)
-{
- *actual_item = item;
-
- return 0.0;
-}
-
-static gboolean
-find_cell (ETableItem *eti, double x, double y, int *col_res, int *row_res, double *x1_res, double *y1_res)
-{
- const int cols = eti->cols;
- const int rows = eti->rows;
- gdouble x1, y1, x2, y2;
- int col, row;
-
- /* FIXME: this routine is inneficient, fix later */
-
- x -= eti->x1;
- y -= eti->y1;
-
- x1 = 0;
- for (col = 0; col < cols; col++, x1 = x2){
- ETableCol *ecol = e_table_header_get_column (eti->header, col);
-
- if (x < x1)
- return FALSE;
-
- x2 = x1 + ecol->width;
-
- if (x > x2)
- continue;
-
- *col_res = col;
- if (x1_res)
- *x1_res = x - x1;
- break;
- }
-
- y1 = y2 = 0;
- for (row = 0; row < rows; row++, y1 = y2){
- if (y < y1)
- return FALSE;
-
- y2 += eti_row_height (eti, row) + 1;
-
- if (y > y2)
- continue;
-
- *row_res = row;
- if (y1_res)
- *y1_res = y - y1;
- break;
- }
-
- return TRUE;
-}
-
-static void
-eti_cursor_move_left (ETableItem *eti)
-{
- e_table_item_leave_edit (eti);
- e_table_item_focus (eti, eti->focused_col - 1, eti->focused_row);
-}
-
-static void
-eti_cursor_move_right (ETableItem *eti)
-{
- e_table_item_leave_edit (eti);
- e_table_item_focus (eti, eti->focused_col + 1, eti->focused_row);
-}
-
-static void
-eti_cursor_move_up (ETableItem *eti)
-{
- e_table_item_leave_edit (eti);
- e_table_item_focus (eti, eti->focused_col, eti->focused_row - 1);
-}
-
-static void
-eti_cursor_move_down (ETableItem *eti)
-{
- e_table_item_leave_edit (eti);
- e_table_item_focus (eti, eti->focused_col, eti->focused_row + 1);
-}
-
-static int
-eti_event (GnomeCanvasItem *item, GdkEvent *e)
-{
- ETableItem *eti = E_TABLE_ITEM (item);
- ECellView *ecell_view;
- ETableCol *ecol;
-
- switch (e->type){
- case GDK_BUTTON_PRESS:
- case GDK_BUTTON_RELEASE:
- case GDK_2BUTTON_PRESS: {
- double x1, y1;
- int col, row;
-
- gnome_canvas_item_w2i (item, &e->button.x, &e->button.y);
-
- if (!find_cell (eti, e->button.x, e->button.y, &col, &row, &x1, &y1))
- return TRUE;
-
- if (eti->focused_row == row && eti->focused_col == col){
-
- ecol = e_table_header_get_column (eti->header, col);
- ecell_view = eti->cell_views [col];
-
- /*
- * Adjust the event positions
- */
- e->button.x = x1;
- e->button.y = y1;
-
- e_cell_event (ecell_view, e, ecol->col_idx, col, row);
- } else {
- /*
- * Focus the cell, and select the row
- */
- e_table_item_leave_edit (eti);
- e_table_item_focus (eti, col, row);
- e_table_item_select_row (eti, row);
- }
- break;
- }
-
- case GDK_MOTION_NOTIFY: {
- int col, row;
- double x1, y1;
-
- gnome_canvas_item_w2i (item, &e->button.x, &e->button.y);
-
- if (!find_cell (eti, e->button.x, e->button.y, &col, &row, &x1, &y1))
- return TRUE;
-
- if (eti->focused_row == row && eti->focused_col == col){
- ecol = e_table_header_get_column (eti->header, col);
- ecell_view = eti->cell_views [col];
-
- /*
- * Adjust the event positions
- */
- e->button.x -= (x1 + eti->x1);
- e->button.y -= (y1 + eti->y1);
-
- e_cell_event (ecell_view, e, ecol->col_idx, col, row);
- }
- break;
- }
-
- case GDK_KEY_PRESS:
- if (eti->focused_col == -1)
- return FALSE;
-
- switch (e->key.keyval){
- case GDK_Left:
- if (!eti->mode_spreadsheet && eti_editing (eti))
- break;
-
- if (eti->focused_col > 0)
- eti_cursor_move_left (eti);
-
- return TRUE;
-
- case GDK_Right:
- if (!eti->mode_spreadsheet && eti_editing (eti))
- break;
-
- if ((eti->focused_col + 1) < eti->cols)
- eti_cursor_move_right (eti);
- return TRUE;
-
- case GDK_Up:
- if (eti->focused_row > 0)
- eti_cursor_move_up (eti);
- return TRUE;
-
- case GDK_Down:
- if ((eti->focused_row + 1) < eti->rows)
- eti_cursor_move_down (eti);
-
- return TRUE;
-
- case GDK_Tab:
- if ((e->key.state & GDK_SHIFT_MASK) != 0){
- /* shift tab */
- if (eti->focused_col > 0)
- eti_cursor_move_left (eti);
- else if (eti->focused_row > 0){
- e_table_item_leave_edit (eti);
- e_table_item_focus (eti, eti->cols - 1, eti->focused_row - 1);
- } else {
- /* FIXME: request focus leave backward */
- }
- } else {
- if ((eti->focused_col + 1) < eti->cols)
- eti_cursor_move_right (eti);
- else if ((eti->focused_row + 1) < eti->rows){
- e_table_item_leave_edit (eti);
- e_table_item_focus (eti, 0, eti->rows - 1);
- } else {
- /* FIXME: request focus leave forward */
- }
- }
- break;
-
- default:
- if (!eti_editing (eti)){
- if ((e->key.state & (GDK_MOD1_MASK | GDK_CONTROL_MASK)) != 0)
- return 0;
-
- if (!(e->key.keyval >= 0x20 && e->key.keyval <= 0xff))
- return 0;
- }
- }
-
- ecol = e_table_header_get_column (eti->header, eti->focused_col);
- ecell_view = eti->cell_views [eti->focused_col];
- e_cell_event (ecell_view, e, ecol->col_idx, eti->focused_col, eti->focused_row);
- break;
-
- case GDK_KEY_RELEASE:
- if (eti->focused_col == -1)
- return FALSE;
-
- if (eti_editing (eti)){
- ecell_view = eti->cell_views [eti->editing_col];
- ecol = e_table_header_get_column (eti->header, eti->editing_col);
- e_cell_event (ecell_view, e, ecol->col_idx, eti->editing_col, eti->editing_row);
- }
- break;
-
- default:
- return FALSE;
- }
- return TRUE;
-}
-
-/*
- * ETableItem::row_selection method
- */
-static void
-eti_row_selection (ETableItem *eti, int row, gboolean selected)
-{
- eti_request_region_redraw (eti, 0, row, eti->cols - 1, row, 0);
-
- if (selected)
- eti->selection = g_slist_prepend (eti->selection, GINT_TO_POINTER (row));
- else
- eti->selection = g_slist_remove (eti->selection, GINT_TO_POINTER (row));
-
-}
-
-static void
-eti_class_init (GtkObjectClass *object_class)
-{
- GnomeCanvasItemClass *item_class = (GnomeCanvasItemClass *) object_class;
- ETableItemClass *eti_class = (ETableItemClass *) object_class;
-
- eti_parent_class = gtk_type_class (PARENT_OBJECT_TYPE);
-
- object_class->destroy = eti_destroy;
- object_class->set_arg = eti_set_arg;
-
- item_class->update = eti_update;
- item_class->realize = eti_realize;
- item_class->unrealize = eti_unrealize;
- item_class->draw = eti_draw;
- item_class->point = eti_point;
- item_class->event = eti_event;
- item_class->bounds = eti_bounds;
-
- eti_class->row_selection = eti_row_selection;
-
- gtk_object_add_arg_type ("ETableItem::ETableHeader", GTK_TYPE_POINTER,
- GTK_ARG_WRITABLE, ARG_TABLE_HEADER);
- gtk_object_add_arg_type ("ETableItem::ETableModel", GTK_TYPE_POINTER,
- GTK_ARG_WRITABLE, ARG_TABLE_MODEL);
- gtk_object_add_arg_type ("ETableItem::x", GTK_TYPE_DOUBLE,
- GTK_ARG_WRITABLE, ARG_TABLE_X);
- gtk_object_add_arg_type ("ETableItem::y", GTK_TYPE_DOUBLE,
- GTK_ARG_WRITABLE, ARG_TABLE_Y);
- gtk_object_add_arg_type ("ETableItem::drawgrid", GTK_TYPE_BOOL,
- GTK_ARG_WRITABLE, ARG_TABLE_DRAW_GRID);
- gtk_object_add_arg_type ("ETableItem::drawfocus", GTK_TYPE_BOOL,
- GTK_ARG_WRITABLE, ARG_TABLE_DRAW_FOCUS);
- gtk_object_add_arg_type ("ETableItem::spreadsheet", GTK_TYPE_BOOL,
- GTK_ARG_WRITABLE, ARG_MODE_SPREADSHEET);
-
- eti_signals [ROW_SELECTION] =
- gtk_signal_new ("row_selection",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (ETableItemClass, row_selection),
- gtk_marshal_NONE__INT_INT,
- GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
-
- eti_signals [HEIGHT_CHANGED] =
- gtk_signal_new ("height_changed",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (ETableItemClass, height_changed),
- gtk_marshal_NONE__NONE,
- GTK_TYPE_NONE, 0);
-
- gtk_object_class_add_signals (object_class, eti_signals, LAST_SIGNAL);
-
-}
-
-GtkType
-e_table_item_get_type (void)
-{
- static GtkType type = 0;
-
- if (!type){
- GtkTypeInfo info = {
- "ETableItem",
- sizeof (ETableItem),
- sizeof (ETableItemClass),
- (GtkClassInitFunc) eti_class_init,
- (GtkObjectInitFunc) eti_init,
- NULL, /* reserved 1 */
- NULL, /* reserved 2 */
- (GtkClassInitFunc) NULL
- };
-
- type = gtk_type_unique (PARENT_OBJECT_TYPE, &info);
- }
-
- return type;
-}
-
-void
-e_table_item_focus (ETableItem *eti, int col, int row)
-{
- g_return_if_fail (eti != NULL);
- g_return_if_fail (E_IS_TABLE_ITEM (eti));
-
- if (eti->focused_col != -1)
- e_table_item_unfocus (eti);
-
- eti->focused_col = col;
- eti->focused_row = row;
-
- eti_request_region_redraw (eti, col, row, col, row, FOCUSED_BORDER);
-
- /*
- * make sure we have the Gtk Focus
- */
- gnome_canvas_item_grab_focus (GNOME_CANVAS_ITEM (eti));
-}
-
-void
-e_table_item_unfocus (ETableItem *eti)
-{
- g_return_if_fail (eti != NULL);
- g_return_if_fail (E_IS_TABLE_ITEM (eti));
-
- if (eti->focused_row == -1)
- return;
-
- {
- const int col = eti->focused_col;
- const int row = eti->focused_row;
-
- eti_request_region_redraw (eti, col, row, col, row, FOCUSED_BORDER);
- }
- eti->focused_col = -1;
- eti->focused_row = -1;
-}
-
-const GSList *
-e_table_item_get_selection (ETableItem *eti)
-{
- g_return_val_if_fail (eti != NULL, NULL);
- g_return_val_if_fail (E_IS_TABLE_ITEM (eti), NULL);
-
- return eti->selection;
-}
-
-GtkSelectionMode
-e_table_item_get_selection_mode (ETableItem *eti)
-{
- g_return_val_if_fail (eti != NULL, GTK_SELECTION_SINGLE);
- g_return_val_if_fail (E_IS_TABLE_ITEM (eti), GTK_SELECTION_SINGLE);
-
- return eti->selection_mode;
-}
-
-void
-e_table_item_set_selection_mode (ETableItem *eti, GtkSelectionMode selection_mode)
-{
- g_return_if_fail (eti != NULL);
- g_return_if_fail (E_IS_TABLE_ITEM (eti));
-
- if (selection_mode == GTK_SELECTION_BROWSE ||
- selection_mode == GTK_SELECTION_EXTENDED){
- g_error ("GTK_SELECTION_BROWSE and GTK_SELECTION_EXTENDED are not implemented");
- }
-
- eti->selection_mode = selection_mode;
-}
-
-gboolean
-e_table_item_is_row_selected (ETableItem *eti, int row)
-{
- g_return_val_if_fail (eti != NULL, FALSE);
- g_return_val_if_fail (E_IS_TABLE_ITEM (eti), FALSE);
-
- if (g_slist_find (eti->selection, GINT_TO_POINTER (row)))
- return TRUE;
- else
- return FALSE;
-}
-
-void
-e_table_item_unselect_row (ETableItem *eti, int row)
-{
- g_return_if_fail (eti != NULL);
- g_return_if_fail (E_IS_TABLE_ITEM (eti));
-
- if (e_table_item_is_row_selected (eti, row)){
- gtk_signal_emit (
- GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
- row, 0);
- }
-}
-
-void
-e_table_item_select_row (ETableItem *eti, int row)
-{
- g_return_if_fail (eti != NULL);
- g_return_if_fail (E_IS_TABLE_ITEM (eti));
-
- switch (eti->selection_mode){
- case GTK_SELECTION_SINGLE:
- if (eti->selection){
- gtk_signal_emit (
- GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
- GPOINTER_TO_INT (eti->selection->data), 0);
- }
- g_slist_free (eti->selection);
- eti->selection = NULL;
-
- gtk_signal_emit (
- GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
- GINT_TO_POINTER (row), 1);
- break;
-
- case GTK_SELECTION_MULTIPLE:
- if (g_slist_find (eti->selection, GINT_TO_POINTER (row)))
- return;
- gtk_signal_emit (
- GTK_OBJECT (eti), eti_signals [ROW_SELECTION],
- GINT_TO_POINTER (row), 1);
- break;
-
- default:
-
- }
-}
-
-void
-e_table_item_enter_edit (ETableItem *eti, int col, int row)
-{
- ETableCol *ecol;
-
- g_return_if_fail (eti != NULL);
- g_return_if_fail (E_IS_TABLE_ITEM (eti));
-
- eti->editing_col = col;
- eti->editing_row = row;
-
- ecol = e_table_header_get_column (eti->header, col);
- eti->edit_ctx = e_cell_enter_edit (eti->cell_views [col], ecol->col_idx, col, row);
-}
-
-void
-e_table_item_leave_edit (ETableItem *eti)
-{
- ETableCol *ecol;
-
- g_return_if_fail (eti != NULL);
- g_return_if_fail (E_IS_TABLE_ITEM (eti));
-
- if (!eti_editing (eti))
- return;
-
- ecol = e_table_header_get_column (eti->header, eti->editing_col);
- e_cell_leave_edit (
- eti->cell_views [eti->editing_col],
- ecol->col_idx, eti->editing_col,
- eti->editing_row, eti->edit_ctx);
- eti->editing_col = -1;
- eti->editing_row = -1;
- eti->edit_ctx = NULL;
-}
-
diff --git a/widgets/e-table-item.h b/widgets/e-table-item.h
deleted file mode 100644
index f19819f2fc..0000000000
--- a/widgets/e-table-item.h
+++ /dev/null
@@ -1,106 +0,0 @@
-#ifndef _E_TABLE_ITEM_H_
-#define _E_TABLE_ITEM_H_
-
-#include <libgnomeui/gnome-canvas.h>
-#include "e-table-model.h"
-#include "e-table-header.h"
-
-#define E_TABLE_ITEM_TYPE (e_table_item_get_type ())
-#define E_TABLE_ITEM(o) (GTK_CHECK_CAST ((o), E_TABLE_ITEM_TYPE, ETableItem))
-#define E_TABLE_ITEM_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_ITEM_TYPE, ETableItemClass))
-#define E_IS_TABLE_ITEM(o) (GTK_CHECK_TYPE ((o), E_TABLE_ITEM_TYPE))
-#define E_IS_TABLE_ITEM_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_ITEM_TYPE))
-
-typedef struct {
- GnomeCanvasItem parent;
- ETableModel *table_model;
- ETableHeader *header;
-
- int x1, y1;
- int width, height;
-
- int cols, rows;
-
- /*
- * Ids for the signals we connect to
- */
- int header_dim_change_id;
- int header_structure_change_id;
- int table_model_change_id;
- int table_model_row_change_id;
-
- GdkGC *fill_gc;
- GdkGC *grid_gc;
- GdkGC *focus_gc;
- GdkBitmap *stipple;
-
- unsigned int draw_grid:1;
- unsigned int draw_focus:1;
- unsigned int mode_spreadsheet:1;
- unsigned int renderers_can_change_size:1;
- unsigned int cell_views_realized:1;
-
- int focused_col, focused_row;
-
- /*
- * Realized views, per column
- */
- ECellView **cell_views;
- int n_cells;
-
- /*
- * Lengh Threshold: above this, we stop computing correctly
- * the size
- */
- int length_threshold;
-
- GSList *selection;
- GtkSelectionMode selection_mode;
-
- /*
- * During edition
- */
- int editing_col, editing_row;
- void *edit_ctx;
-} ETableItem;
-
-typedef struct {
- GnomeCanvasItemClass parent_class;
-
- void (*row_selection) (ETableItem *eti, int row, gboolean selected);
- void (*height_changed) (ETableItem *eti);
-} ETableItemClass;
-
-GtkType e_table_item_get_type (void);
-
-/*
- * Focus
- */
-void e_table_item_focus (ETableItem *eti, int col, int row);
-void e_table_item_unfocus (ETableItem *eti);
-
-/*
- * Selection
- */
-void e_table_item_select_row (ETableItem *e_table_Item, int row);
-void e_table_item_unselect_row (ETableItem *e_table_Item, int row);
-
-/*
- * Handling the selection
- */
-const GSList*e_table_item_get_selection (ETableItem *e_table_Item);
-
-GtkSelectionMode e_table_item_get_selection_mode (ETableItem *e_table_Item);
-void e_table_item_set_selection_mode (ETableItem *e_table_Item,
- GtkSelectionMode selection_mode);
-gboolean e_table_item_is_row_selected (ETableItem *e_table_Item,
- int row);
-
-void e_table_item_leave_edit (ETableItem *eti);
-void e_table_item_enter_edit (ETableItem *eti, int col, int row);
-
-void e_table_item_redraw_range (ETableItem *eti,
- int start_col, int start_row,
- int end_col, int end_row);
-
-#endif /* _E_TABLE_ITEM_H_ */
diff --git a/widgets/e-table-model.c b/widgets/e-table-model.c
deleted file mode 100644
index 9e397710ef..0000000000
--- a/widgets/e-table-model.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * e-table-model.c: a Table Model
- *
- * Author:
- * Miguel de Icaza (miguel@gnu.org)
- *
- * (C) 1999 Helix Code, Inc.
- */
-#include <config.h>
-#include <gtk/gtksignal.h>
-#include "e-table-model.h"
-
-#define ETM_CLASS(e) ((ETableModelClass *)((GtkObject *)e)->klass)
-
-static GtkObjectClass *e_table_model_parent_class;
-
-enum {
- MODEL_CHANGED,
- MODEL_ROW_CHANGED,
- MODEL_CELL_CHANGED,
- ROW_SELECTION,
- LAST_SIGNAL
-};
-
-static guint e_table_model_signals [LAST_SIGNAL] = { 0, };
-
-int
-e_table_model_column_count (ETableModel *e_table_model)
-{
- g_return_val_if_fail (e_table_model != NULL, 0);
- g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), 0);
-
- return ETM_CLASS (e_table_model)->column_count (e_table_model);
-}
-
-
-int
-e_table_model_row_count (ETableModel *e_table_model)
-{
- g_return_val_if_fail (e_table_model != NULL, 0);
- g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), 0);
-
- return ETM_CLASS (e_table_model)->row_count (e_table_model);
-}
-
-void *
-e_table_model_value_at (ETableModel *e_table_model, int col, int row)
-{
- g_return_val_if_fail (e_table_model != NULL, NULL);
- g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), NULL);
-
- return ETM_CLASS (e_table_model)->value_at (e_table_model, col, row);
-}
-
-void
-e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, const void *data)
-{
- g_return_if_fail (e_table_model != NULL);
- g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
-
- ETM_CLASS (e_table_model)->set_value_at (e_table_model, col, row, data);
-
- gtk_signal_emit (GTK_OBJECT (e_table_model),
- e_table_model_signals [MODEL_ROW_CHANGED], row);
- gtk_signal_emit (GTK_OBJECT (e_table_model),
- e_table_model_signals [MODEL_CELL_CHANGED], col, row);
-
- /*
- * Notice that "model_changed" is not emitted
- */
-}
-
-gboolean
-e_table_model_is_cell_editable (ETableModel *e_table_model, int col, int row)
-{
- g_return_val_if_fail (e_table_model != NULL, FALSE);
- g_return_val_if_fail (E_IS_TABLE_MODEL (e_table_model), FALSE);
-
- return ETM_CLASS (e_table_model)->is_cell_editable (e_table_model, col, row);
-}
-
-static void
-e_table_model_destroy (GtkObject *object)
-{
- if (e_table_model_parent_class->destroy)
- (*e_table_model_parent_class->destroy)(object);
-}
-
-static void
-e_table_model_class_init (GtkObjectClass *object_class)
-{
- e_table_model_parent_class = gtk_type_class (gtk_object_get_type ());
-
- object_class->destroy = e_table_model_destroy;
-
- e_table_model_signals [MODEL_CHANGED] =
- gtk_signal_new ("model_changed",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (ETableModelClass, model_changed),
- gtk_marshal_NONE__NONE,
- GTK_TYPE_NONE, 0);
-
- e_table_model_signals [MODEL_ROW_CHANGED] =
- gtk_signal_new ("model_row_changed",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (ETableModelClass, model_row_changed),
- gtk_marshal_NONE__INT,
- GTK_TYPE_NONE, 1, GTK_TYPE_INT);
-
- e_table_model_signals [MODEL_CELL_CHANGED] =
- gtk_signal_new ("model_cell_changed",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (ETableModelClass, model_cell_changed),
- gtk_marshal_NONE__INT_INT,
- GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
-
- gtk_object_class_add_signals (object_class, e_table_model_signals, LAST_SIGNAL);
-}
-
-GtkType
-e_table_model_get_type (void)
-{
- static GtkType type = 0;
-
- if (!type){
- GtkTypeInfo info = {
- "ETableModel",
- sizeof (ETableModel),
- sizeof (ETableModelClass),
- (GtkClassInitFunc) e_table_model_class_init,
- (GtkObjectInitFunc) NULL,
- NULL, /* reserved 1 */
- NULL, /* reserved 2 */
- (GtkClassInitFunc) NULL
- };
-
- type = gtk_type_unique (gtk_object_get_type (), &info);
- }
-
- return type;
-}
-
-void
-e_table_model_changed (ETableModel *e_table_model)
-{
- g_return_if_fail (e_table_model != NULL);
- g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
-
- gtk_signal_emit (GTK_OBJECT (e_table_model),
- e_table_model_signals [MODEL_CHANGED]);
-}
-
-void
-e_table_model_row_changed (ETableModel *e_table_model, int row)
-{
- g_return_if_fail (e_table_model != NULL);
- g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
-
- gtk_signal_emit (GTK_OBJECT (e_table_model),
- e_table_model_signals [MODEL_ROW_CHANGED], row);
-}
-
-void
-e_table_model_cell_changed (ETableModel *e_table_model, int col, int row)
-{
- g_return_if_fail (e_table_model != NULL);
- g_return_if_fail (E_IS_TABLE_MODEL (e_table_model));
-
- gtk_signal_emit (GTK_OBJECT (e_table_model),
- e_table_model_signals [MODEL_CELL_CHANGED], col, row);
-}
-
-
diff --git a/widgets/e-table-model.h b/widgets/e-table-model.h
deleted file mode 100644
index 2d08f3744e..0000000000
--- a/widgets/e-table-model.h
+++ /dev/null
@@ -1,58 +0,0 @@
-#ifndef _E_TABLE_MODEL_H_
-#define _E_TABLE_MODEL_H_
-
-#include <gtk/gtkobject.h>
-
-#define E_TABLE_MODEL_TYPE (e_table_model_get_type ())
-#define E_TABLE_MODEL(o) (GTK_CHECK_CAST ((o), E_TABLE_MODEL_TYPE, ETableModel))
-#define E_TABLE_MODEL_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_MODEL_TYPE, ETableModelClass))
-#define E_IS_TABLE_MODEL(o) (GTK_CHECK_TYPE ((o), E_TABLE_MODEL_TYPE))
-#define E_IS_TABLE_MODEL_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_MODEL_TYPE))
-
-typedef struct {
- GtkObject base;
-} ETableModel;
-
-typedef struct {
- GtkObjectClass parent_class;
-
- /*
- * Virtual methods
- */
- int (*column_count) (ETableModel *etm);
- int (*row_count) (ETableModel *etm);
- void *(*value_at) (ETableModel *etm, int col, int row);
- void (*set_value_at) (ETableModel *etm, int col, int row, const void *value);
- gboolean (*is_cell_editable) (ETableModel *etm, int col, int row);
-
- /*
- * Signals
- */
-
- /*
- * Major structural changes: model_changed
- * Changes only in a row: row_changed
- * Only changes in a cell: cell_changed
- */
- void (*model_changed) (ETableModel *etm);
- void (*model_row_changed) (ETableModel *etm, int row);
- void (*model_cell_changed) (ETableModel *etm, int col, int row);
-} ETableModelClass;
-
-GtkType e_table_model_get_type (void);
-
-int e_table_model_column_count (ETableModel *e_table_model);
-const char *e_table_model_column_name (ETableModel *e_table_model, int col);
-int e_table_model_row_count (ETableModel *e_table_model);
-void *e_table_model_value_at (ETableModel *e_table_model, int col, int row);
-void e_table_model_set_value_at (ETableModel *e_table_model, int col, int row, const void *data);
-gboolean e_table_model_is_cell_editable (ETableModel *e_table_model, int col, int row);
-
-/*
- * Routines for emitting signals on the e_table
- */
-void e_table_model_changed (ETableModel *e_table_model);
-void e_table_model_row_changed (ETableModel *e_table_model, int row);
-void e_table_model_cell_changed (ETableModel *e_table_model, int col, int row);
-
-#endif /* _E_TABLE_MODEL_H_ */
diff --git a/widgets/e-table-render.c b/widgets/e-table-render.c
deleted file mode 100644
index 49d742132b..0000000000
--- a/widgets/e-table-render.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * E-table-render.c: Various renderers
- *
- * Author:
- * Miguel de Icaza (miguel@gnu.org)
- *
- * Copyright 1999, Helix Code, Inc.
- */
-#include <config.h>
-#include "e-table-header.h"
-#include "e-table-header-item.h"
-#include "e-table-col.h"
-#include "e-table-render.h"
-
-void
-e_table_render_string (ERenderContext *ctxt)
-{
- printf ("Rendering string: %s\n", ctxt->render_data);
-}
-
diff --git a/widgets/e-table-render.h b/widgets/e-table-render.h
deleted file mode 100644
index ebc65968f0..0000000000
--- a/widgets/e-table-render.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef E_TABLE_RENDER_H
-#define E_TABLE_RENDER_H
-
-#include <libgnomeui/gnome-canvas.h>
-
-struct ERenderContext {
- ETableCol *etc;
- int row;
- int base_x, base_y;
- GnomeCanvasItem *gnome_canvas_item;
- GdkDrawable *drawable;
- int drawable_width;
- int drawable_height;
- void *render_data;
- void *closure;
-};
-
-void e_table_render_string (ERenderContext *ctxt);
-
-
-#endif
diff --git a/widgets/e-table-simple.c b/widgets/e-table-simple.c
deleted file mode 100644
index 943a3291e9..0000000000
--- a/widgets/e-table-simple.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * e-table-model.c: a simple table model implementation that uses function
- * pointers to simplify the creation of new, exotic and colorful tables in
- * no time.
- *
- * Author:
- * Miguel de Icaza (miguel@gnu.org)
- *
- * (C) 1999 Helix Code, Inc.
- */
-
-#include <config.h>
-#include "e-table-simple.h"
-
-#define PARENT_TYPE e_table_model_get_type()
-
-static int
-simple_column_count (ETableModel *etm)
-{
- ETableSimple *simple = (ETableSimple *)etm;
-
- return simple->col_count (etm, simple->data);
-}
-
-static int
-simple_row_count (ETableModel *etm)
-{
- ETableSimple *simple = (ETableSimple *)etm;
-
- return simple->row_count (etm, simple->data);
-}
-
-static void *
-simple_value_at (ETableModel *etm, int col, int row)
-{
- ETableSimple *simple = (ETableSimple *)etm;
-
- return simple->value_at (etm, col, row, simple->data);
-}
-
-static void
-simple_set_value_at (ETableModel *etm, int col, int row, const void *val)
-{
- ETableSimple *simple = (ETableSimple *)etm;
-
- simple->set_value_at (etm, col, row, val, simple->data);
-}
-
-static gboolean
-simple_is_cell_editable (ETableModel *etm, int col, int row)
-{
- ETableSimple *simple = (ETableSimple *)etm;
-
- return simple->is_cell_editable (etm, col, row, simple->data);
-}
-
-static void
-e_table_simple_class_init (GtkObjectClass *object_class)
-{
- ETableModelClass *model_class = (ETableModelClass *) object_class;
-
- model_class->column_count = simple_column_count;
- model_class->row_count = simple_row_count;
- model_class->value_at = simple_value_at;
- model_class->set_value_at = simple_set_value_at;
- model_class->is_cell_editable = simple_is_cell_editable;
-}
-
-GtkType
-e_table_simple_get_type (void)
-{
- static GtkType type = 0;
-
- if (!type){
- GtkTypeInfo info = {
- "ETableSimple",
- sizeof (ETableSimple),
- sizeof (ETableSimpleClass),
- (GtkClassInitFunc) e_table_simple_class_init,
- (GtkObjectInitFunc) NULL,
- NULL, /* reserved 1 */
- NULL, /* reserved 2 */
- (GtkClassInitFunc) NULL
- };
-
- type = gtk_type_unique (PARENT_TYPE, &info);
- }
-
- return type;
-}
-
-ETableModel *
-e_table_simple_new (ETableSimpleColumnCountFn col_count,
- ETableSimpleRowCountFn row_count,
- ETableSimpleValueAtFn value_at,
- ETableSimpleSetValueAtFn set_value_at,
- ETableSimpleIsCellEditableFn is_cell_editable,
- void *data)
-{
- ETableSimple *et;
-
- et = gtk_type_new (e_table_simple_get_type ());
-
- et->col_count = col_count;
- et->row_count = row_count;
- et->value_at = value_at;
- et->set_value_at = set_value_at;
- et->is_cell_editable = is_cell_editable;
-
- return (ETableModel *) et;
-}
diff --git a/widgets/e-table-simple.h b/widgets/e-table-simple.h
deleted file mode 100644
index d890245386..0000000000
--- a/widgets/e-table-simple.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef _E_TABLE_SIMPLE_H_
-#define _E_TABLE_SIMPLE_H_
-
-#include "e-table-model.h"
-
-typedef int (*ETableSimpleColumnCountFn) (ETableModel *etm, void *data);
-typedef int (*ETableSimpleRowCountFn) (ETableModel *etm, void *data);
-typedef void *(*ETableSimpleValueAtFn) (ETableModel *etm, int col, int row, void *data);
-typedef void (*ETableSimpleSetValueAtFn) (ETableModel *etm, int col, int row, const void *val, void *data);
-typedef gboolean (*ETableSimpleIsCellEditableFn) (ETableModel *etm, int col, int row, void *data);
-
-typedef struct {
- ETableModel parent;
-
- ETableSimpleColumnCountFn col_count;
- ETableSimpleRowCountFn row_count;
- ETableSimpleValueAtFn value_at;
- ETableSimpleSetValueAtFn set_value_at;
- ETableSimpleIsCellEditableFn is_cell_editable;
- void *data;
-} ETableSimple;
-
-typedef struct {
- ETableModelClass parent_class;
-} ETableSimpleClass;
-
-GtkType e_table_simple_get_type (void);
-
-ETableModel *e_table_simple_new (ETableSimpleColumnCountFn col_count,
- ETableSimpleRowCountFn row_count,
- ETableSimpleValueAtFn value_at,
- ETableSimpleSetValueAtFn set_value_at,
- ETableSimpleIsCellEditableFn is_cell_editable,
- void *data);
-
-#endif /* _E_TABLE_SIMPLE_H_ */
-
diff --git a/widgets/e-table-sorted.c b/widgets/e-table-sorted.c
deleted file mode 100644
index 6bc55ad9dc..0000000000
--- a/widgets/e-table-sorted.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * E-table-sorted.c: Implements a table that sorts another table
- *
- * Author:
- * Miguel de Icaza (miguel@gnu.org)
- *
- * (C) 1999 Helix Code, Inc.
- */
-#include <config.h>
-#include <stdlib.h>
-#include "e-util.h"
-#include "e-table-sorted.h"
-
-#define PARENT_TYPE E_TABLE_SUBSET_TYPE
-
-static ETableModelClass *ets_parent_class;
-
-static void
-ets_class_init (GtkObjectClass *klass)
-{
- ets_parent_class = gtk_type_class (PARENT_TYPE);
-}
-
-E_MAKE_TYPE(e_table_sorted, "ETableSorted", ETableSorted, ets_class_init, NULL, PARENT_TYPE);
-
-static ETableSorted *sort_ets;
-
-static int
-my_sort (const void *a, const void *b)
-{
- ETableModel *source = E_TABLE_SUBSET (sort_ets)->source;
- const int *ia = (const int *) a;
- const int *ib = (const int *) b;
- void *va, *vb;
-
- va = e_table_model_value_at (source, sort_ets->sort_col, *ia);
- vb = e_table_model_value_at (source, sort_ets->sort_col, *ib);
-
- return (*sort_ets->compare) (va, vb);
-}
-
-static void
-do_sort (ETableSorted *ets)
-{
- ETableSubset *etss = E_TABLE_SUBSET (ets);
- g_assert (sort_ets == NULL);
-
- sort_ets = ets;
- qsort (etss->map_table, etss->n_map, sizeof (unsigned int), my_sort);
- sort_ets = NULL;
-}
-
-ETableModel *
-e_table_sorted_new (ETableModel *source, int col, GCompareFunc compare)
-{
- ETableSorted *ets = gtk_type_new (E_TABLE_SORTED_TYPE);
- ETableSubset *etss = E_TABLE_SUBSET (ets);
- const int nvals = e_table_model_row_count (source);
- int i;
-
- if (e_table_subset_construct (etss, source, nvals) == NULL){
- gtk_object_destroy (GTK_OBJECT (ets));
- return NULL;
- }
-
- ets->compare = compare;
- ets->sort_col = col;
-
- /* Init */
- for (i = 0; i < nvals; i++)
- etss->map_table [i] = i;
-
- do_sort (ets);
-
- return (ETableModel *) ets;
-}
-
-void
-e_table_sorted_resort (ETableSorted *ets, int col, GCompareFunc compare)
-{
- if (col == -1 || compare == NULL)
- do_sort (ets);
- else {
- ets->sort_col = col;
- ets->compare = compare;
- do_sort (ets);
- }
-}
-
diff --git a/widgets/e-table-sorted.h b/widgets/e-table-sorted.h
deleted file mode 100644
index 2ec52df2e7..0000000000
--- a/widgets/e-table-sorted.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef _E_TABLE_SORTED_H_
-#define _E_TABLE_SORTED_H_
-
-#include <gtk/gtkobject.h>
-#include "e-table-model.h"
-#include "e-table-subset.h"
-
-#define E_TABLE_SORTED_TYPE (e_table_sorted_get_type ())
-#define E_TABLE_SORTED(o) (GTK_CHECK_CAST ((o), E_TABLE_SORTED_TYPE, ETableSorted))
-#define E_TABLE_SORTED_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_SORTED_TYPE, ETableSortedClass))
-#define E_IS_TABLE_SORTED(o) (GTK_CHECK_TYPE ((o), E_TABLE_SORTED_TYPE))
-#define E_IS_TABLE_SORTED_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_SORTED_TYPE))
-
-typedef struct {
- ETableSubset base;
-
- short sort_col;
- GCompareFunc compare;
-} ETableSorted;
-
-typedef struct {
- ETableSubset parent_class;
-} ETableSortedClass;
-
-GtkType e_table_sorted_get_type (void);
-ETableModel *e_table_sorted_new (ETableModel *etm, int col, GCompareFunc compare);
-void e_table_sorted_resort (ETableSorted *ets, int col, GCompareFunc compare);
-
-#endif /* _E_TABLE_SORTED_H_ */
diff --git a/widgets/e-table-subset.c b/widgets/e-table-subset.c
deleted file mode 100644
index 88f5c18c85..0000000000
--- a/widgets/e-table-subset.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * E-table-subset.c: Implements a table that contains a subset of another table.
- *
- * Author:
- * Miguel de Icaza (miguel@gnu.org)
- *
- * (C) 1999 Helix Code, Inc.
- */
-#include <config.h>
-#include <stdlib.h>
-#include <gtk/gtksignal.h>
-#include "e-util.h"
-#include "e-table-subset.h"
-
-#define PARENT_TYPE E_TABLE_MODEL_TYPE
-
-static ETableModelClass *etss_parent_class;
-
-static void
-etss_destroy (GtkObject *object)
-{
- ETableSubset *etss = E_TABLE_SUBSET (object);
-
- if (etss->source)
- gtk_object_unref (GTK_OBJECT (etss->source));
-
- if (etss->map_table)
- free (etss->map_table);
-
- GTK_OBJECT_CLASS (etss_parent_class)->destroy (object);
-}
-
-static int
-etss_column_count (ETableModel *etm)
-{
- ETableSubset *etss = (ETableSubset *)etm;
-
- return e_table_model_column_count (etss->source);
-}
-
-static int
-etss_row_count (ETableModel *etm)
-{
- ETableSubset *etss = (ETableSubset *)etm;
-
- return etss->n_map;
-}
-
-static void *
-etss_value_at (ETableModel *etm, int col, int row)
-{
- ETableSubset *etss = (ETableSubset *)etm;
-
- return e_table_model_value_at (etss->source, col, etss->map_table [row]);
-}
-
-static void
-etss_set_value_at (ETableModel *etm, int col, int row, const void *val)
-{
- ETableSubset *etss = (ETableSubset *)etm;
-
- return e_table_model_set_value_at (etss->source, col, etss->map_table [row], val);
-}
-
-static gboolean
-etss_is_cell_editable (ETableModel *etm, int col, int row)
-{
- ETableSubset *etss = (ETableSubset *)etm;
-
- return e_table_model_is_cell_editable (etss->source, col, etss->map_table [row]);
-}
-
-static void
-etss_class_init (GtkObjectClass *klass)
-{
- ETableModelClass *table_class = (ETableModelClass *) klass;
-
- etss_parent_class = gtk_type_class (PARENT_TYPE);
-
- klass->destroy = etss_destroy;
-
- table_class->column_count = etss_column_count;
- table_class->row_count = etss_row_count;
- table_class->value_at = etss_value_at;
- table_class->set_value_at = etss_set_value_at;
- table_class->is_cell_editable = etss_is_cell_editable;
-}
-
-E_MAKE_TYPE(e_table_subset, "ETableSubset", ETableSubset, etss_class_init, NULL, PARENT_TYPE);
-
-static void
-etss_proxy_model_changed (ETableModel *etm, ETableSubset *etss)
-{
- e_table_model_changed (E_TABLE_MODEL (etss));
-}
-
-static void
-etss_proxy_model_row_changed (ETableModel *etm, int row, ETableSubset *etss)
-{
- const int n = etss->n_map;
- const int * const map_table = etss->map_table;
- int i;
-
- for (i = 0; i < n; i++){
- if (map_table [i] == row){
- e_table_model_row_changed (E_TABLE_MODEL (etss), i);
- return;
- }
- }
-}
-
-static void
-etss_proxy_model_cell_changed (ETableModel *etm, int col, int row, ETableSubset *etss)
-{
- const int n = etss->n_map;
- const int * const map_table = etss->map_table;
- int i;
-
- for (i = 0; i < n; i++){
- if (map_table [i] == row){
- e_table_model_cell_changed (E_TABLE_MODEL (etss), col, i);
- return;
- }
- }
-}
-
-ETableModel *
-e_table_subset_construct (ETableSubset *etss, ETableModel *source, int nvals)
-{
- unsigned int *buffer;
- int i;
-
- buffer = (unsigned int *) malloc (sizeof (unsigned int) * nvals);
- if (buffer == NULL)
- return NULL;
- etss->map_table = buffer;
- etss->n_map = nvals;
- etss->source = source;
- gtk_object_ref (GTK_OBJECT (source));
-
- /* Init */
- for (i = 0; i < nvals; i++)
- etss->map_table [i] = i;
-
- gtk_signal_connect (GTK_OBJECT (source), "model_changed",
- GTK_SIGNAL_FUNC (etss_proxy_model_changed), etss);
- gtk_signal_connect (GTK_OBJECT (source), "model_row_changed",
- GTK_SIGNAL_FUNC (etss_proxy_model_row_changed), etss);
- gtk_signal_connect (GTK_OBJECT (source), "model_cell_changed",
- GTK_SIGNAL_FUNC (etss_proxy_model_cell_changed), etss);
-
- return E_TABLE_MODEL (etss);
-}
-
-ETableModel *
-e_table_subset_new (ETableModel *source, const int nvals)
-{
- ETableSubset *etss = gtk_type_new (E_TABLE_SUBSET_TYPE);
-
- if (e_table_subset_construct (etss, source, nvals) == NULL){
- gtk_object_destroy (GTK_OBJECT (etss));
- return NULL;
- }
-
- return (ETableModel *) etss;
-}
-
-ETableModel *
-e_table_subset_get_toplevel (ETableSubset *table)
-{
- g_return_val_if_fail (table != NULL, NULL);
- g_return_val_if_fail (E_IS_TABLE_SUBSET (table), NULL);
-
- if (E_IS_TABLE_SUBSET (table->source))
- return e_table_subset_get_toplevel (E_TABLE_SUBSET (table->source));
- else
- return table->source;
-}
diff --git a/widgets/e-table-subset.h b/widgets/e-table-subset.h
deleted file mode 100644
index 314f28aea6..0000000000
--- a/widgets/e-table-subset.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef _E_TABLE_SUBSET_H_
-#define _E_TABLE_SUBSET_H_
-
-#include <gtk/gtkobject.h>
-#include "e-table-model.h"
-
-#define E_TABLE_SUBSET_TYPE (e_table_subset_get_type ())
-#define E_TABLE_SUBSET(o) (GTK_CHECK_CAST ((o), E_TABLE_SUBSET_TYPE, ETableSubset))
-#define E_TABLE_SUBSET_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_SUBSET_TYPE, ETableSubsetClass))
-#define E_IS_TABLE_SUBSET(o) (GTK_CHECK_TYPE ((o), E_TABLE_SUBSET_TYPE))
-#define E_IS_TABLE_SUBSET_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_SUBSET_TYPE))
-
-typedef struct {
- ETableModel base;
-
- ETableModel *source;
- int n_map;
- int *map_table;
-} ETableSubset;
-
-typedef struct {
- ETableModelClass parent_class;
-} ETableSubsetClass;
-
-GtkType e_table_subset_get_type (void);
-ETableModel *e_table_subset_new (ETableModel *etm, int n_vals);
-ETableModel *e_table_subset_construct (ETableSubset *ets, ETableModel *source, int nvals);
-
-ETableModel *e_table_subset_get_toplevel (ETableSubset *table_model);
-
-#endif /* _E_TABLE_SUBSET_H_ */
-
diff --git a/widgets/e-table-tree.h b/widgets/e-table-tree.h
deleted file mode 100644
index e7e125a6af..0000000000
--- a/widgets/e-table-tree.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _E_TABLE_TREE_H_
-#define _E_TABLE_TREE_H_
-
-typedef struct {
- char *title;
-
- union {
- ETableModel *table;
- GList *children;
- } u;
-
- guint expanded :1;
- guint is_leaf :1;
-} ETableGroup;
-
-ETableGroup *e_table_group_new (const char *title, ETableModel *table);
-ETableGroup *e_table_group_new_leaf (const char *title);
-
-#endif /* _E_TABLE_TREE_H_ */
diff --git a/widgets/e-table.c b/widgets/e-table.c
deleted file mode 100644
index 01389135bf..0000000000
--- a/widgets/e-table.c
+++ /dev/null
@@ -1,558 +0,0 @@
-/*
- * E-table-view.c: A graphical view of a Table.
- *
- * Author:
- * Miguel de Icaza (miguel@gnu.org)
- *
- * Copyright 1999, Helix Code, Inc
- */
-#include <config.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <alloca.h>
-#include <stdio.h>
-#include <libgnomeui/gnome-canvas.h>
-#include <gtk/gtksignal.h>
-#include "e-table.h"
-#include "e-util.h"
-#include "e-table-header-item.h"
-#include "e-table-subset.h"
-#include "e-table-item.h"
-#include "e-table-group.h"
-
-#define COLUMN_HEADER_HEIGHT 16
-#define TITLE_HEIGHT 16
-#define GROUP_INDENT 10
-
-#define PARENT_TYPE gtk_table_get_type ()
-
-static GtkObjectClass *e_table_parent_class;
-
-static void
-et_destroy (GtkObject *object)
-{
- ETable *et = E_TABLE (object);
-
- gtk_object_unref (GTK_OBJECT (et->model));
- gtk_object_unref (GTK_OBJECT (et->full_header));
- gtk_object_unref (GTK_OBJECT (et->header));
-
- g_free (et->group_spec);
-
- (*e_table_parent_class->destroy)(object);
-}
-
-static void
-e_table_init (GtkObject *object)
-{
- ETable *e_table = E_TABLE (object);
-
- e_table->draw_grid = 1;
- e_table->draw_focus = 1;
- e_table->spreadsheet = 1;
-}
-
-static ETableHeader *
-e_table_make_header (ETable *e_table, ETableHeader *full_header, const char *cols)
-{
- ETableHeader *nh;
- char *copy = alloca (strlen (cols) + 1);
- char *p, *state;
- const int max_cols = e_table_header_count (full_header);
-
- nh = e_table_header_new ();
- strcpy (copy, cols);
- while ((p = strtok_r (copy, ",", &state)) != NULL){
- int col = atoi (p);
-
- copy = NULL;
- if (col >= max_cols)
- continue;
-
- e_table_header_add_column (nh, e_table_header_get_column (full_header, col), -1);
- }
-
- return nh;
-}
-
-static void
-header_canvas_size_alocate (GtkWidget *widget, GtkAllocation *alloc, ETable *e_table)
-{
- gnome_canvas_set_scroll_region (
- GNOME_CANVAS (e_table->header_canvas),
- 0, 0, alloc->width, COLUMN_HEADER_HEIGHT);
-}
-
-static void
-e_table_setup_header (ETable *e_table)
-{
- e_table->header_canvas = GNOME_CANVAS (gnome_canvas_new ());
-
- gtk_widget_show (GTK_WIDGET (e_table->header_canvas));
-
- e_table->header_item = gnome_canvas_item_new (
- gnome_canvas_root (e_table->header_canvas),
- e_table_header_item_get_type (),
- "ETableHeader", e_table->header,
- "x", 0,
- "y", 0,
- NULL);
-
- gtk_signal_connect (
- GTK_OBJECT (e_table->header_canvas), "size_allocate",
- GTK_SIGNAL_FUNC (header_canvas_size_alocate), e_table);
-
- gtk_widget_set_usize (GTK_WIDGET (e_table->header_canvas), -1, COLUMN_HEADER_HEIGHT);
-
- gtk_table_attach (
- GTK_TABLE (e_table), GTK_WIDGET (e_table->header_canvas),
- 0, 1, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 0);
-
-}
-
-typedef struct {
- void *value;
- GArray *array;
-} group_key_t;
-
-static GArray *
-e_table_create_groups (ETableModel *etm, int key_col, GCompareFunc comp)
-{
- GArray *groups;
- const int rows = e_table_model_row_count (etm);
- int row, i;
-
- groups = g_array_new (FALSE, FALSE, sizeof (group_key_t));
-
- for (row = 0; row < rows; row++){
- void *val = e_table_model_value_at (etm, key_col, row);
- const int n_groups = groups->len;
-
- /*
- * Should replace this with a bsearch later
- */
- for (i = 0; i < n_groups; i++){
- group_key_t *g = &g_array_index (groups, group_key_t, i);
-
- if ((*comp) (g->value, val)){
- g_array_append_val (g->array, row);
- break;
- }
- }
- if (i != n_groups)
- continue;
-
- /*
- * We need to create a new group
- */
- {
- group_key_t gk;
-
- gk.value = val;
- gk.array = g_array_new (FALSE, FALSE, sizeof (int));
-
- g_array_append_val (gk.array, row);
- g_array_append_val (groups, gk);
- }
- }
-
- return groups;
-}
-
-static void
-e_table_destroy_groups (GArray *groups)
-{
- const int n = groups->len;
- int i;
-
- for (i = 0; i < n; i++){
- group_key_t *g = &g_array_index (groups, group_key_t, i);
-
- g_array_free (g->array, TRUE);
- }
- g_array_free (groups, TRUE);
-}
-
-static ETableModel **
-e_table_make_subtables (ETableModel *model, GArray *groups)
-{
- const int n_groups = groups->len;
- ETableModel **tables;
- int i;
-
- tables = g_new (ETableModel *, n_groups+1);
-
- for (i = 0; i < n_groups; i++){
- group_key_t *g = &g_array_index (groups, group_key_t, i);
- const int sub_size = g->array->len;
- ETableSubset *ss;
- int j;
-
- tables [i] = e_table_subset_new (model, sub_size);
- ss = E_TABLE_SUBSET (tables [i]);
-
- for (j = 0; j < sub_size; j++)
- ss->map_table [j] = g_array_index (g->array, int, j);
- }
- tables [i] = NULL;
-
- return (ETableModel **) tables;
-}
-
-typedef struct _Node Node;
-
-struct _Node {
- Node *parent;
- GnomeCanvasItem *item;
- ETableModel *table_model;
- GSList *children;
-
- guint is_leaf:1;
-};
-
-static Node *
-leaf_new (GnomeCanvasItem *table_item, ETableModel *table_model, Node *parent)
-{
- Node *node = g_new (Node, 1);
-
- g_assert (table_item != NULL);
- g_assert (table_model != NULL);
- g_assert (parent != NULL);
-
- node->item = table_item;
- node->parent = parent;
- node->table_model = table_model;
- node->is_leaf = 1;
-
- g_assert (!parent->is_leaf);
-
- parent->children = g_slist_append (parent->children, node);
-
- e_table_group_add (E_TABLE_GROUP (parent->item), table_item);
-
- return node;
-}
-
-static Node *
-node_new (GnomeCanvasItem *group_item, ETableModel *table_model, Node *parent)
-{
- Node *node = g_new (Node, 1);
-
- g_assert (table_model != NULL);
-
- node->children = NULL;
- node->item = group_item;
- node->parent = parent;
- node->table_model = table_model;
- node->is_leaf = 0;
-
- if (parent){
- parent->children = g_slist_append (parent->children, node);
-
- e_table_group_add (E_TABLE_GROUP (parent->item), group_item);
- }
-
- return node;
-}
-
-static Node *
-e_table_create_leaf (ETable *e_table, ETableModel *etm, Node *parent)
-{
- GnomeCanvasItem *table_item;
- static double last_y;
- Node *leaf;
-
- table_item = gnome_canvas_item_new (
- GNOME_CANVAS_GROUP (parent->item),
- e_table_item_get_type (),
- "ETableHeader", e_table->header,
- "ETableModel", etm,
- "drawgrid", e_table->draw_grid,
- "drawfocus", e_table->draw_focus,
- "spreadsheet", e_table->spreadsheet,
- NULL);
-
- leaf = leaf_new (table_item, etm, parent);
-
- return leaf;
-}
-
-static int
-leaf_height (Node *leaf)
-{
- const GnomeCanvasItem *item = leaf->item;
-
- return item->y2 - item->y1;
-}
-
-static int
-leaf_event (GnomeCanvasItem *item, GdkEvent *event)
-{
- static int last_x = -1;
- static int last_y = -1;
-
- if (event->type == GDK_BUTTON_PRESS){
- last_x = event->button.x;
- last_y = event->button.y;
- } else if (event->type == GDK_BUTTON_RELEASE){
- last_x = -1;
- last_y = -1;
- } else if (event->type == GDK_MOTION_NOTIFY){
- if (last_x == -1)
- return FALSE;
-
- gnome_canvas_item_move (item, event->motion.x - last_x, event->motion.y - last_y);
- last_x = event->motion.x;
- last_y = event->motion.y;
- } else
- return FALSE;
- return TRUE;
-}
-
-static Node *
-e_table_create_nodes (ETable *e_table, ETableModel *model, ETableHeader *header,
- GnomeCanvasGroup *root, Node *parent, int *groups_list)
-{
- GArray *groups;
- ETableModel **tables;
- ETableCol *ecol;
- int key_col, i;
- GnomeCanvasItem *group_item;
- Node *group;
-
- key_col = *groups_list;
- g_assert (key_col != -1);
-
- /*
- * Create groups
- */
- ecol = e_table_header_get_column (header, key_col);
-
- g_assert (ecol != NULL);
-
- groups = e_table_create_groups (model, key_col, ecol->compare);
- tables = e_table_make_subtables (e_table->model, groups);
- e_table_destroy_groups (groups);
-
- group_item = e_table_group_new (root, ecol, TRUE, parent == NULL);
- group = node_new (group_item, model, parent);
-
- for (i = 0; tables [i] != NULL; i++){
- Node *node;
-
- /*
- * Leafs
- */
- if (groups_list [1] == -1){
- GnomeCanvasItem *item_leaf_header;
- Node *leaf_header;
-
- item_leaf_header = e_table_group_new (
- GNOME_CANVAS_GROUP (group_item), ecol, TRUE, FALSE);
- leaf_header = node_new (item_leaf_header, tables [i], group);
-
- e_table_create_leaf (e_table, tables [i], leaf_header);
- } else {
- e_table_create_nodes (
- e_table, tables [i], header, GNOME_CANVAS_GROUP (group_item),
- group, &groups_list [1]);
- }
- }
-
- return group;
-}
-
-static int *
-group_spec_to_desc (const char *group_spec)
-{
- int a_size = 10;
- int *elements;
- char *p, *copy, *follow;
- int n_elements = 0;
-
- if (group_spec == NULL)
- return NULL;
-
- elements = g_new (int, a_size);
- copy = alloca (strlen (group_spec) + 1);
- strcpy (copy, group_spec);
-
- while ((p = strtok_r (copy, ",", &follow)) != NULL){
- elements [n_elements] = atoi (p);
- ++n_elements;
- if (n_elements+1 == a_size){
- int *new_e;
-
- n_elements += 10;
- new_e = g_renew (int, elements, n_elements);
- if (new_e == NULL){
- g_free (elements);
- return NULL;
- }
- elements = new_e;
- }
- copy = NULL;
- }
-
- /* Tag end */
- elements [n_elements] = -1;
-
- return elements;
-}
-
-/*
- * The ETableCanvas object is just used to enable us to
- * hook up to the realize/unrealize phases of the canvas
- * initialization (as laying out the subtables requires us to
- * know the actual size of the subtables we are inserting
- */
-
-#define E_TABLE_CANVAS_PARENT_TYPE gnome_canvas_get_type ()
-
-typedef struct {
- GnomeCanvas base;
-
- ETable *e_table;
-} ETableCanvas;
-
-typedef struct {
- GnomeCanvasClass base_class;
-} ETableCanvasClass;
-
-static GnomeCanvasClass *e_table_canvas_parent_class;
-
-static void
-e_table_canvas_realize (GtkWidget *widget)
-{
- ETableCanvas *e_table_canvas = (ETableCanvas *) widget;
- ETable *e_table = e_table_canvas->e_table;
- int *groups;
- Node *leaf;
-
- GTK_WIDGET_CLASS (e_table_canvas_parent_class)->realize (widget);
-
- groups = group_spec_to_desc (e_table->group_spec);
-
- e_table->root = gnome_canvas_item_new (
- GNOME_CANVAS_GROUP (e_table->table_canvas->root),
- gnome_canvas_group_get_type (),
- "x", 0.0,
- "y", 0.0,
- NULL);
-
- leaf = e_table_create_nodes (
- e_table, e_table->model,
- e_table->header, GNOME_CANVAS_GROUP (e_table->root), 0, groups);
-
- gnome_canvas_set_scroll_region (
- GNOME_CANVAS (e_table_canvas),
- 0, 0,
- e_table_header_total_width (e_table->header) + 200,
- leaf_height (leaf));
-
- if (groups)
- g_free (groups);
-}
-
-static void
-e_table_canvas_unrealize (GtkWidget *widget)
-{
- ETableCanvas *e_table_canvas = (ETableCanvas *) widget;
- ETable *e_table = e_table_canvas->e_table;
-
- gtk_object_destroy (GTK_OBJECT (e_table->root));
- e_table->root = NULL;
-
- GTK_WIDGET_CLASS (e_table_canvas_parent_class)->unrealize (widget);
-}
-
-static void
-e_table_canvas_class_init (GtkObjectClass *object_class)
-{
- GtkWidgetClass *widget_class = (GtkWidgetClass *) object_class;
-
- widget_class->realize = e_table_canvas_realize;
- widget_class->unrealize = e_table_canvas_unrealize;
-
- e_table_canvas_parent_class = gtk_type_class (E_TABLE_CANVAS_PARENT_TYPE);
-}
-
-static void
-e_table_canvas_init (GtkObject *canvas)
-{
- GTK_WIDGET_SET_FLAGS (canvas, GTK_CAN_FOCUS);
-}
-
-GtkType e_table_canvas_get_type (void);
-
-E_MAKE_TYPE (e_table_canvas, "ETableCanvas", ETableCanvas, e_table_canvas_class_init,
- e_table_canvas_init, E_TABLE_CANVAS_PARENT_TYPE);
-
-static GnomeCanvas *
-e_table_canvas_new (ETable *e_table)
-{
- ETableCanvas *e_table_canvas;
-
- e_table_canvas = gtk_type_new (e_table_canvas_get_type ());
- e_table_canvas->e_table = e_table;
-
- return GNOME_CANVAS (e_table_canvas);
-}
-
-static void
-e_table_setup_table (ETable *e_table)
-{
- e_table->table_canvas = e_table_canvas_new (e_table);
-
- gtk_widget_show (GTK_WIDGET (e_table->table_canvas));
- gtk_table_attach (
- GTK_TABLE (e_table), GTK_WIDGET (e_table->table_canvas),
- 0, 1, 1, 2, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0);
-}
-
-void
-e_table_construct (ETable *e_table, ETableHeader *full_header, ETableModel *etm,
- const char *cols_spec, const char *group_spec)
-{
- GTK_TABLE (e_table)->homogeneous = FALSE;
-
- gtk_table_resize (GTK_TABLE (e_table), 1, 2);
-
- e_table->full_header = full_header;
- gtk_object_ref (GTK_OBJECT (full_header));
-
- e_table->model = etm;
- gtk_object_ref (GTK_OBJECT (etm));
-
- e_table->header = e_table_make_header (e_table, full_header, cols_spec);
-
- e_table_setup_header (e_table);
- e_table_setup_table (e_table);
-
- e_table->group_spec = g_strdup (group_spec);
-
-}
-
-GtkWidget *
-e_table_new (ETableHeader *full_header, ETableModel *etm, const char *cols_spec, const char *group_spec)
-{
- ETable *e_table;
-
- e_table = gtk_type_new (e_table_get_type ());
-
- e_table_construct (e_table, full_header, etm, cols_spec, group_spec);
-
- return (GtkWidget *) e_table;
-}
-
-static void
-e_table_class_init (GtkObjectClass *object_class)
-{
- e_table_parent_class = gtk_type_class (PARENT_TYPE);
-
- object_class->destroy = et_destroy;
-}
-
-E_MAKE_TYPE(e_table, "ETable", ETable, e_table_class_init, e_table_init, PARENT_TYPE);
-
diff --git a/widgets/e-table.h b/widgets/e-table.h
deleted file mode 100644
index 63c131324f..0000000000
--- a/widgets/e-table.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#ifndef _E_TABLE_H_
-#define _E_TABLE_H_
-
-#include <libgnomeui/gnome-canvas.h>
-#include <gtk/gtktable.h>
-#include "e-table-model.h"
-#include "e-table-header.h"
-
-BEGIN_GNOME_DECLS
-
-#define E_TABLE_TYPE (e_table_get_type ())
-#define E_TABLE(o) (GTK_CHECK_CAST ((o), E_TABLE_TYPE, ETable))
-#define E_TABLE_CLASS(k) (GTK_CHECK_CLASS_CAST((k), E_TABLE_TYPE, ETableClass))
-#define E_IS_TABLE(o) (GTK_CHECK_TYPE ((o), E_TABLE_TYPE))
-#define E_IS_TABLE_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_TABLE_TYPE))
-
-typedef struct {
- GtkTable parent;
-
- ETableModel *model;
-
- ETableHeader *full_header, *header;
-
- GnomeCanvas *header_canvas, *table_canvas;
-
- GnomeCanvasItem *header_item, *root;
-
- guint draw_grid:1;
- guint draw_focus:1;
- guint spreadsheet:1;
-
- char *group_spec;
-} ETable;
-
-typedef struct {
- GtkTableClass parent_class;
-} ETableClass;
-
-GtkType e_table_get_type (void);
-void e_table_construct (ETable *e_table, ETableHeader *full_header, ETableModel *etm,
- const char *cols_spec, const char *group_spec);
-GtkWidget *e_table_new (ETableHeader *full_header, ETableModel *etm,
- const char *cols_spec, const char *group_spec);
-
-
-END_GNOME_DECLS
-
- #endif /* _E_TABLE_H_ */
diff --git a/widgets/e-table/Makefile.am b/widgets/e-table/Makefile.am
index 73bd54ee2c..8f81a8076c 100644
--- a/widgets/e-table/Makefile.am
+++ b/widgets/e-table/Makefile.am
@@ -1,16 +1,11 @@
-
-SUBDIRS =
- meeting-time-sel
-
INCLUDES = \
- -I$(top_srcdir)/camel \
- -I$(top_builddir)/camel \
- $(GNOME_INCLUDEDIR)
+ $(GNOME_INCLUDEDIR) \
+ -I$(top_srcdir)/e-util
noinst_LIBRARIES = \
- libevolutionwidgets.a
+ libetable.a
-libevolutionwidgets_a_SOURCES = \
+libetable_a_SOURCES = \
e-cell.c \
e-cell.h \
e-cell-checkbox.c \
@@ -19,8 +14,6 @@ libevolutionwidgets_a_SOURCES = \
e-cell-text.h \
e-cell-toggle.c \
e-cell-toggle.h \
- e-cursors.c \
- e-cursors.h \
e-table.c \
e-table.h \
e-table-col.c \
@@ -51,9 +44,10 @@ table_test_SOURCES = \
test-cols.c \
table-test.c
-table_test_LDADD = \
- $(EXTRA_GNOME_LIBS) \
- libevolutionwidgets.a
+table_test_LDADD = \
+ $(EXTRA_GNOME_LIBS) \
+ libetable.a \
+ $(top_builddir)/e-util/libeutil.a
table_test_LDFLAGS = `gnome-config --libs gdk_pixbuf`
diff --git a/widgets/e-table/e-cell-checkbox.c b/widgets/e-table/e-cell-checkbox.c
index 6e4b597abf..d77e1fa4cd 100644
--- a/widgets/e-table/e-cell-checkbox.c
+++ b/widgets/e-table/e-cell-checkbox.c
@@ -14,7 +14,7 @@
#include <gdk/gdkkeysyms.h>
#include <libgnomeui/gnome-canvas.h>
#include "e-cell-checkbox.h"
-#include "e-util.h"
+#include <e-util/e-util.h>
#include "e-table-item.h"
#include "check-empty.xpm"
diff --git a/widgets/e-table/e-cell-text.c b/widgets/e-table/e-cell-text.c
index 1b2205ba51..9ce8190a14 100644
--- a/widgets/e-table/e-cell-text.c
+++ b/widgets/e-table/e-cell-text.c
@@ -15,7 +15,7 @@
#include <libgnomeui/gnome-canvas.h>
#include <stdio.h>
#include "e-cell-text.h"
-#include "e-util.h"
+#include <e-util/e-util.h>
#include "e-table-item.h"
#define PARENT_TYPE e_cell_get_type()
diff --git a/widgets/e-table/e-cell-toggle.c b/widgets/e-table/e-cell-toggle.c
index 6ea181ea40..a933a62c49 100644
--- a/widgets/e-table/e-cell-toggle.c
+++ b/widgets/e-table/e-cell-toggle.c
@@ -14,7 +14,7 @@
#include <gdk/gdkkeysyms.h>
#include <libgnomeui/gnome-canvas.h>
#include "e-cell-toggle.h"
-#include "e-util.h"
+#include <e-util/e-util.h>
#include "e-table-item.h"
#define PARENT_TYPE e_cell_get_type()
diff --git a/widgets/e-table/e-cell.c b/widgets/e-table/e-cell.c
index 0f9297ecba..b5cbc0e850 100644
--- a/widgets/e-table/e-cell.c
+++ b/widgets/e-table/e-cell.c
@@ -8,7 +8,7 @@
*/
#include <config.h>
#include "e-cell.h"
-#include "e-util.h"
+#include <e-util/e-util.h>
#define PARENT_TYPE gtk_object_get_type()
diff --git a/widgets/e-table/e-table-col.c b/widgets/e-table/e-table-col.c
index 86392a9419..62a451ca4f 100644
--- a/widgets/e-table/e-table-col.c
+++ b/widgets/e-table/e-table-col.c
@@ -10,7 +10,7 @@
#include <gtk/gtkobject.h>
#include <gtk/gtksignal.h>
#include "e-table-col.h"
-#include "e-util.h"
+#include <e-util/e-util.h>
#define PARENT_TYPE (gtk_object_get_type ())
diff --git a/widgets/e-table/e-table-group.c b/widgets/e-table/e-table-group.c
index 8765c3b83c..14c7a33f79 100644
--- a/widgets/e-table/e-table-group.c
+++ b/widgets/e-table/e-table-group.c
@@ -12,7 +12,7 @@
#include "e-table-group.h"
#include "e-table-item.h"
#include <libgnomeui/gnome-canvas-rect-ellipse.h>
-#include "e-util.h"
+#include <e-util/e-util.h>
#define TITLE_HEIGHT 16
#define GROUP_INDENT 10
diff --git a/widgets/e-table/e-table-sorted.c b/widgets/e-table/e-table-sorted.c
index 6bc55ad9dc..b559b3d87f 100644
--- a/widgets/e-table/e-table-sorted.c
+++ b/widgets/e-table/e-table-sorted.c
@@ -8,7 +8,7 @@
*/
#include <config.h>
#include <stdlib.h>
-#include "e-util.h"
+#include <e-util/e-util.h>
#include "e-table-sorted.h"
#define PARENT_TYPE E_TABLE_SUBSET_TYPE
diff --git a/widgets/e-table/e-table-subset.c b/widgets/e-table/e-table-subset.c
index 88f5c18c85..be4c7ab732 100644
--- a/widgets/e-table/e-table-subset.c
+++ b/widgets/e-table/e-table-subset.c
@@ -9,7 +9,7 @@
#include <config.h>
#include <stdlib.h>
#include <gtk/gtksignal.h>
-#include "e-util.h"
+#include <e-util/e-util.h>
#include "e-table-subset.h"
#define PARENT_TYPE E_TABLE_MODEL_TYPE
diff --git a/widgets/e-table/e-table.c b/widgets/e-table/e-table.c
index 01389135bf..730306b374 100644
--- a/widgets/e-table/e-table.c
+++ b/widgets/e-table/e-table.c
@@ -14,8 +14,8 @@
#include <stdio.h>
#include <libgnomeui/gnome-canvas.h>
#include <gtk/gtksignal.h>
+#include <e-util/e-util.h>
#include "e-table.h"
-#include "e-util.h"
#include "e-table-header-item.h"
#include "e-table-subset.h"
#include "e-table-item.h"
diff --git a/widgets/e-util.h b/widgets/e-util.h
deleted file mode 100644
index ad4d754770..0000000000
--- a/widgets/e-util.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef _E_UTIL_H_
-#define _E_UTIL_H_
-
-#define E_MAKE_TYPE(l,str,t,ci,i,parent) \
-GtkType l##_get_type(void)\
-{\
- static GtkType type = 0;\
- if (!type){\
- GtkTypeInfo info = {\
- str,\
- sizeof (t),\
- sizeof (t##Class),\
- (GtkClassInitFunc) ci,\
- (GtkObjectInitFunc) i,\
- NULL, /* reserved 1 */\
- NULL, /* reserved 2 */\
- (GtkClassInitFunc) NULL\
- };\
- type = gtk_type_unique (parent, &info);\
- }\
- return type;\
-}\
-
-#endif /* _E_UTIL_H_ */
diff --git a/widgets/image1.png b/widgets/image1.png
deleted file mode 100644
index 8326ac241f..0000000000
--- a/widgets/image1.png
+++ /dev/null
Binary files differ
diff --git a/widgets/image2.png b/widgets/image2.png
deleted file mode 100644
index e6a4c75dbe..0000000000
--- a/widgets/image2.png
+++ /dev/null
Binary files differ
diff --git a/widgets/image3.png b/widgets/image3.png
deleted file mode 100644
index 50e16e8620..0000000000
--- a/widgets/image3.png
+++ /dev/null
Binary files differ
diff --git a/widgets/remove-col.xpm b/widgets/remove-col.xpm
deleted file mode 100644
index ff1024f0c9..0000000000
--- a/widgets/remove-col.xpm
+++ /dev/null
@@ -1,22 +0,0 @@
-/* XPM */
-static char * remove_col_xpm[] = {
-"16 16 3 1",
-" c None",
-". c #000000",
-"+ c #FF0000",
-"... ...",
-".++. .++.",
-".+++. .+++.",
-" .+++. .+++. ",
-" .+++. .+++. ",
-" .+++..+++. ",
-" .++++++. ",
-" .++++. ",
-" .++++. ",
-" .++++++. ",
-" .+++..+++. ",
-" .+++. .+++. ",
-" .+++. .+++. ",
-".+++. .+++.",
-".++. .++.",
-"... ..."};
diff --git a/widgets/sample.table b/widgets/sample.table
deleted file mode 100644
index 45c8ff0691..0000000000
--- a/widgets/sample.table
+++ /dev/null
@@ -1,11 +0,0 @@
-Col1 Col2 Address Title Dorks
-c1.a c2.a a.a tit-1 DorkA
-c1.b c2.b a.b tit-2 DDork
-c1.c c2.c a.c tit-1 DorkB
-c1.d c2.d a.d tit-2 ADork
-c1.e c2.e a.e tit-1 DorkC
-c1.f c2.f a.f tit-2 UDork
-c1.g c2.g a.g tit-3 Dork---
-j k k tit-1 DorkA
-
-
diff --git a/widgets/shortcut-bar/Makefile.am b/widgets/shortcut-bar/Makefile.am
new file mode 100644
index 0000000000..c60c57e872
--- /dev/null
+++ b/widgets/shortcut-bar/Makefile.am
@@ -0,0 +1,30 @@
+
+noinst_LIBRARIES = libshortcut-bar.a
+noinst_PROGRAMS = test-shortcut-bar
+
+INCLUDES = \
+ -DEVOLUTION_VERSION=\""$(VERSION)"\" \
+ $(EXTRA_GNOME_CFLAGS)
+
+libshortcut_bar_a_SOURCES = \
+ e-clipped-label.c \
+ e-clipped-label.h \
+ e-group-bar.c \
+ e-group-bar.h \
+ e-icon-bar-bg-item.c \
+ e-icon-bar-bg-item.h \
+ e-icon-bar-text-item.c \
+ e-icon-bar-text-item.h \
+ e-icon-bar.c \
+ e-icon-bar.h \
+ e-shortcut-bar.c \
+ e-shortcut-bar.h \
+ e-vscrolled-bar.c \
+ e-vscrolled-bar.h
+
+test_shortcut_bar_SOURCES = \
+ test-shortcut-bar.c
+
+test_shortcut_bar_LDADD = \
+ ./libshortcut-bar.a \
+ $(EXTRA_GNOME_LIBS) \
diff --git a/widgets/shortcut-bar/e-clipped-label.c b/widgets/shortcut-bar/e-clipped-label.c
new file mode 100644
index 0000000000..0b595f6063
--- /dev/null
+++ b/widgets/shortcut-bar/e-clipped-label.c
@@ -0,0 +1,361 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Author :
+ * Damon Chaplin <damon@gtk.org>
+ *
+ * Copyright 1999, Helix Code, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ * This is similar to GtkLabel but clips itself and displays '...' if it
+ * can't fit inside its allocated area. The intended use is for inside buttons
+ * that are a fixed size. The GtkLabel would normally display only the middle
+ * part of the text, which doesn't look very good. This only supports one line
+ * of text (so no wrapping/justification), without underlined characters.
+ */
+
+#include <math.h>
+
+#include <gdk/gdki18n.h>
+#include <libgnome/gnome-defs.h>
+#include <libgnome/gnome-i18n.h>
+
+#include "e-clipped-label.h"
+
+
+static void e_clipped_label_class_init (EClippedLabelClass *class);
+static void e_clipped_label_init (EClippedLabel *label);
+static void e_clipped_label_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void e_clipped_label_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static gint e_clipped_label_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static void e_clipped_label_recalc_chars_displayed (EClippedLabel *label);
+
+
+static GtkMiscClass *parent_class;
+
+/* This is the string to draw when the label is clipped, e.g. '...'. */
+static gchar *e_clipped_label_ellipsis;
+
+/* Flags used in chars_displayed field. Must be negative. */
+#define E_CLIPPED_LABEL_NEED_RECALC -1
+#define E_CLIPPED_LABEL_SHOW_ENTIRE_LABEL -2
+
+
+GtkType
+e_clipped_label_get_type (void)
+{
+ static GtkType e_clipped_label_type = 0;
+
+ if (!e_clipped_label_type){
+ GtkTypeInfo e_clipped_label_info = {
+ "EClippedLabel",
+ sizeof (EClippedLabel),
+ sizeof (EClippedLabelClass),
+ (GtkClassInitFunc) e_clipped_label_class_init,
+ (GtkObjectInitFunc) e_clipped_label_init,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ parent_class = gtk_type_class (GTK_TYPE_MISC);
+ e_clipped_label_type = gtk_type_unique (GTK_TYPE_MISC,
+ &e_clipped_label_info);
+ }
+
+ return e_clipped_label_type;
+}
+
+
+static void
+e_clipped_label_class_init (EClippedLabelClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = (GtkObjectClass *) class;
+ widget_class = (GtkWidgetClass *) class;
+
+ /* Method override */
+ widget_class->size_request = e_clipped_label_size_request;
+ widget_class->size_allocate = e_clipped_label_size_allocate;
+ widget_class->expose_event = e_clipped_label_expose;
+
+ e_clipped_label_ellipsis = _("...");
+}
+
+
+static void
+e_clipped_label_init (EClippedLabel *label)
+{
+ GTK_WIDGET_SET_FLAGS (label, GTK_NO_WINDOW);
+
+ label->label = NULL;
+ label->label_wc = NULL;
+ label->chars_displayed = E_CLIPPED_LABEL_NEED_RECALC;
+}
+
+
+/**
+ * e_clipped_label_new:
+ *
+ * @text: The label text.
+ * @Returns: A new #EClippedLabel.
+ *
+ * Creates a new #EClippedLabel with the given text.
+ **/
+GtkWidget *
+e_clipped_label_new (const gchar *text)
+{
+ GtkWidget *label;
+
+ label = GTK_WIDGET (gtk_type_new (e_clipped_label_get_type ()));
+
+ if (text && *text)
+ e_clipped_label_set_text (E_CLIPPED_LABEL (label), text);
+
+ return label;
+}
+
+
+static void
+e_clipped_label_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ EClippedLabel *label;
+ GdkFont *font;
+
+ g_return_if_fail (E_IS_CLIPPED_LABEL (widget));
+ g_return_if_fail (requisition != NULL);
+
+ label = E_CLIPPED_LABEL (widget);
+ font = widget->style->font;
+
+ requisition->width = 0;
+ requisition->height = font->ascent + font->descent
+ + 2 * GTK_MISC (widget)->ypad;
+}
+
+
+static void
+e_clipped_label_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ EClippedLabel *label;
+
+ label = E_CLIPPED_LABEL (widget);
+
+ widget->allocation = *allocation;
+
+ /* Flag that we need to recalculate how many characters to display. */
+ label->chars_displayed = E_CLIPPED_LABEL_NEED_RECALC;
+}
+
+
+static gint
+e_clipped_label_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ EClippedLabel *label;
+ GtkMisc *misc;
+ gint x, y;
+ GdkFont *font;
+ gchar *tmp_str, tmp_ch;
+
+ g_return_val_if_fail (E_IS_CLIPPED_LABEL (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ label = E_CLIPPED_LABEL (widget);
+ misc = GTK_MISC (widget);
+ font = widget->style->font;
+
+ /* If the label isn't visible or has no text, just return. */
+ if (!GTK_WIDGET_VISIBLE (widget) || !GTK_WIDGET_MAPPED (widget)
+ || !label->label || (*label->label == '\0'))
+ return TRUE;
+
+ /* Recalculate the number of characters displayed, if necessary. */
+ if (label->chars_displayed == E_CLIPPED_LABEL_NEED_RECALC)
+ e_clipped_label_recalc_chars_displayed (label);
+
+ /*
+ * GC Clipping
+ */
+ gdk_gc_set_clip_rectangle (widget->style->white_gc,
+ &event->area);
+ gdk_gc_set_clip_rectangle (widget->style->fg_gc[widget->state],
+ &event->area);
+
+ y = floor (widget->allocation.y + (gint)misc->ypad
+ + (((gint)widget->allocation.height - 2 * (gint)misc->ypad
+ - (gint)font->ascent - font->descent)
+ * misc->yalign) + 0.5) + font->ascent;
+
+ if (label->chars_displayed == E_CLIPPED_LABEL_SHOW_ENTIRE_LABEL) {
+ x = floor (widget->allocation.x + (gint)misc->xpad
+ + (((gint)widget->allocation.width -
+ (gint)label->label_width - 2 * (gint)misc->xpad)
+ * misc->xalign) + 0.5);
+
+ gtk_paint_string (widget->style, widget->window, widget->state,
+ &event->area, widget, "label",
+ x, y, label->label);
+ } else {
+ x = widget->allocation.x + (gint)misc->xpad;
+
+ tmp_ch = label->label_wc[label->chars_displayed];
+ label->label_wc[label->chars_displayed] = '\0';
+ tmp_str = gdk_wcstombs (label->label_wc);
+ if (tmp_str) {
+ gtk_paint_string (widget->style, widget->window,
+ widget->state, &event->area,
+ widget, "label",
+ x, y, tmp_str);
+ g_free (tmp_str);
+ }
+ label->label_wc[label->chars_displayed] = tmp_ch;
+
+ x = widget->allocation.x + (gint)misc->xpad
+ + label->ellipsis_x;
+ gtk_paint_string (widget->style, widget->window, widget->state,
+ &event->area, widget, "label",
+ x, y, e_clipped_label_ellipsis);
+ }
+
+ gdk_gc_set_clip_mask (widget->style->white_gc, NULL);
+ gdk_gc_set_clip_mask (widget->style->fg_gc[widget->state], NULL);
+
+ return TRUE;
+}
+
+
+/**
+ * e_clipped_label_get_text:
+ *
+ * @label: An #EClippedLabel.
+ * @Return: The label text.
+ *
+ * Returns the label text, or NULL.
+ **/
+gchar*
+e_clipped_label_get_text (EClippedLabel *label)
+{
+ g_return_val_if_fail (E_IS_CLIPPED_LABEL (label), NULL);
+
+ return label->label;
+}
+
+
+/**
+ * e_clipped_label_set_text:
+ *
+ * @label: An #EClippedLabel.
+ * @text: The new label text.
+ *
+ * Sets the label text.
+ **/
+void
+e_clipped_label_set_text (EClippedLabel *label,
+ const gchar *text)
+{
+ gint len;
+
+ g_return_if_fail (E_IS_CLIPPED_LABEL (label));
+
+ if (label->label != text || !label->label || !text
+ || strcmp (label->label, text)) {
+ g_free (label->label);
+ g_free (label->label_wc);
+ label->label = NULL;
+ label->label_wc = NULL;
+
+ if (text) {
+ label->label = g_strdup (text);
+ len = strlen (text);
+ label->label_wc = g_new (GdkWChar, len + 1);
+ label->wc_len = gdk_mbstowcs (label->label_wc,
+ label->label, len + 1);
+ label->label_wc[label->wc_len] = '\0';
+ }
+
+ /* Reset the number of characters displayed, so it is
+ recalculated when needed. */
+ label->chars_displayed = E_CLIPPED_LABEL_NEED_RECALC;
+
+ /* We don't queue a resize, since the label should not affect
+ the widget size, but we queue a draw. */
+ gtk_widget_queue_draw (GTK_WIDGET (label));
+ }
+}
+
+
+static void
+e_clipped_label_recalc_chars_displayed (EClippedLabel *label)
+{
+ GdkFont *font;
+ gint max_width, width, ch, last_width;
+
+ font = GTK_WIDGET (label)->style->font;
+
+ max_width = GTK_WIDGET (label)->allocation.width
+ - 2 * GTK_MISC (label)->xpad;
+
+ if (!label->label) {
+ label->chars_displayed = 0;
+ return;
+ }
+
+ /* See if the entire label fits in the allocated width. */
+ label->label_width = gdk_string_width (font, label->label);
+ if (label->label_width <= max_width) {
+ label->chars_displayed = E_CLIPPED_LABEL_SHOW_ENTIRE_LABEL;
+ return;
+ }
+
+ /* Calculate the width of the ellipsis string. */
+ max_width -= gdk_string_measure (font, e_clipped_label_ellipsis);
+
+ if (max_width <= 0) {
+ label->chars_displayed = 0;
+ label->ellipsis_x = 0;
+ return;
+ }
+
+ /* Step through the wide-char label, adding on the widths of the
+ characters, until we can't fit any more in. */
+ width = last_width = 0;
+ for (ch = 0; ch < label->wc_len; ch++) {
+ width += gdk_char_width_wc (font, label->label_wc[ch]);
+
+ if (width > max_width) {
+ label->chars_displayed = ch;
+ label->ellipsis_x = last_width;
+ return;
+ }
+
+ last_width = width;
+ }
+
+ g_warning ("Clipped label width not exceeded as expected");
+ label->chars_displayed = E_CLIPPED_LABEL_SHOW_ENTIRE_LABEL;
+}
+
diff --git a/widgets/shortcut-bar/e-clipped-label.h b/widgets/shortcut-bar/e-clipped-label.h
new file mode 100644
index 0000000000..b94d261c11
--- /dev/null
+++ b/widgets/shortcut-bar/e-clipped-label.h
@@ -0,0 +1,90 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Author :
+ * Damon Chaplin <damon@gtk.org>
+ *
+ * Copyright 1999, Helix Code, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ * This is similar to GtkLabel but clips itself and displays '...' if it
+ * can't fit inside its allocated area. The intended use is for inside buttons
+ * that are a fixed size. The GtkLabel would normally display only the middle
+ * part of the text, which doesn't look very good. This only supports one line
+ * of text (so no wrapping/justification), without underlined characters.
+ */
+#ifndef _E_CLIPPED_LABEL_H_
+#define _E_CLIPPED_LABEL_H_
+
+#include <gtk/gtkmisc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define E_CLIPPED_LABEL(obj) GTK_CHECK_CAST (obj, e_clipped_label_get_type (), EClippedLabel)
+#define E_CLIPPED_LABEL_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, e_clipped_label_get_type (), EClippedLabelClass)
+#define E_IS_CLIPPED_LABEL(obj) GTK_CHECK_TYPE (obj, e_clipped_label_get_type ())
+
+
+typedef struct _EClippedLabel EClippedLabel;
+typedef struct _EClippedLabelClass EClippedLabelClass;
+
+struct _EClippedLabel
+{
+ GtkMisc misc;
+
+ gchar *label;
+ GdkWChar *label_wc;
+
+ /* This is the number of wide characters in the label. */
+ gint wc_len;
+
+ /* This is the width of the entire label string, in pixels. */
+ gint label_width;
+
+ /* This is the number of characters we can fit in, or
+ E_CLIPPED_LABEL_NEED_RECALC if it needs to be recalculated, or
+ E_CLIPPED_LABEL_SHOW_ENTIRE_LABEL to show the entire label. */
+ gint chars_displayed;
+
+ /* This is the x position to display the ellipsis string, e.g. '...',
+ relative to the start of the label. */
+ gint ellipsis_x;
+};
+
+struct _EClippedLabelClass
+{
+ GtkMiscClass parent_class;
+};
+
+
+GtkType e_clipped_label_get_type (void);
+GtkWidget* e_clipped_label_new (const gchar *text);
+
+gchar* e_clipped_label_get_text (EClippedLabel *label);
+void e_clipped_label_set_text (EClippedLabel *label,
+ const gchar *text);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _E_CLIPPED_LABEL_H_ */
diff --git a/widgets/shortcut-bar/e-group-bar.c b/widgets/shortcut-bar/e-group-bar.c
new file mode 100644
index 0000000000..603aa6f78f
--- /dev/null
+++ b/widgets/shortcut-bar/e-group-bar.c
@@ -0,0 +1,1498 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Author :
+ * Damon Chaplin <damon@gtk.org>
+ *
+ * Copyright 1999, Helix Code, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ * ShortcutBar displays a vertical bar with a number of Groups, each of which
+ * contains any number of icons. It is used on the left of the main application
+ * window so users can easily access items such as folders and files.
+ */
+
+#include <math.h>
+
+#include <gnome.h>
+
+#include "e-group-bar.h"
+
+#define E_GROUP_BAR_SCROLL_TIMEOUT 10
+#define E_GROUP_BAR_MIN_STEP_SIZE 4
+
+#define E_GROUP_BAR_AUTO_SHOW_TIMEOUT 300
+
+
+static void e_group_bar_class_init (EGroupBarClass *class);
+static void e_group_bar_init (EGroupBar *group_bar);
+static void e_group_bar_destroy (GtkObject *object);
+static void e_group_bar_realize (GtkWidget *widget);
+static void e_group_bar_unrealize (GtkWidget *widget);
+static void e_group_bar_map (GtkWidget *widget);
+static void e_group_bar_unmap (GtkWidget *widget);
+static void e_group_bar_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void e_group_bar_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static gint e_group_bar_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static void e_group_bar_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static void e_group_bar_add (GtkContainer *container,
+ GtkWidget *widget);
+static void e_group_bar_remove (GtkContainer *container,
+ GtkWidget *widget);
+static void e_group_bar_forall (GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data);
+
+static void e_group_bar_create_group_button_window (EGroupBar *group_bar,
+ gint group_num);
+static void e_group_bar_create_group_child_window (EGroupBar *group_bar,
+ gint group_num);
+static gint e_group_bar_get_group_button_position (EGroupBar *group_bar,
+ gint group_num);
+static gint e_group_bar_sum_button_heights (EGroupBar *group_bar,
+ gint first,
+ gint last);
+static gint e_group_bar_get_child_height (EGroupBar *group_bar);
+static gint e_group_bar_get_group_child_position (EGroupBar *group_bar,
+ gint group_num);
+
+static void e_group_bar_on_button_clicked (GtkWidget *group_button,
+ EGroupBar *group_bar);
+static gint e_group_bar_find_button (EGroupBar *group_bar,
+ GtkWidget *group_button);
+static void e_group_bar_start_animation (EGroupBar *group_bar,
+ gint group_num);
+static gboolean e_group_bar_timeout_handler (gpointer data);
+static gint e_group_bar_get_increment (EGroupBar *group_bar,
+ gint window_y,
+ gint window_target_y);
+static gboolean e_group_bar_on_button_drag_motion (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time,
+ EGroupBar *group_bar);
+static void e_group_bar_on_button_drag_leave (GtkWidget *widget,
+ GdkDragContext *context,
+ guint time,
+ EGroupBar *group_bar);
+static gboolean e_group_bar_auto_show (gpointer data);
+static void e_group_bar_stop_all_animation (EGroupBar *group_bar);
+
+
+static GtkContainerClass *parent_class;
+
+
+GtkType
+e_group_bar_get_type (void)
+{
+ static GtkType e_group_bar_type = 0;
+
+ if (!e_group_bar_type){
+ GtkTypeInfo e_group_bar_info = {
+ "EGroupBar",
+ sizeof (EGroupBar),
+ sizeof (EGroupBarClass),
+ (GtkClassInitFunc) e_group_bar_class_init,
+ (GtkObjectInitFunc) e_group_bar_init,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
+ e_group_bar_type = gtk_type_unique (GTK_TYPE_CONTAINER,
+ &e_group_bar_info);
+ }
+
+ return e_group_bar_type;
+}
+
+
+static void
+e_group_bar_class_init (EGroupBarClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+
+ object_class = (GtkObjectClass *) class;
+ widget_class = (GtkWidgetClass *) class;
+ container_class = (GtkContainerClass *) class;
+
+ /* Method override */
+ object_class->destroy = e_group_bar_destroy;
+
+ widget_class->realize = e_group_bar_realize;
+ widget_class->unrealize = e_group_bar_unrealize;
+ widget_class->map = e_group_bar_map;
+ widget_class->unmap = e_group_bar_unmap;
+ widget_class->size_request = e_group_bar_size_request;
+ widget_class->size_allocate = e_group_bar_size_allocate;
+ widget_class->expose_event = e_group_bar_expose;
+ widget_class->draw = e_group_bar_draw;
+
+ container_class->add = e_group_bar_add;
+ container_class->remove = e_group_bar_remove;
+ container_class->forall = e_group_bar_forall;
+}
+
+
+static void
+e_group_bar_init (EGroupBar *group_bar)
+{
+
+ GTK_WIDGET_UNSET_FLAGS (group_bar, GTK_NO_WINDOW);
+
+ /* We don't want child resizes to propagate up to the parent. */
+ gtk_container_set_resize_mode (GTK_CONTAINER (group_bar),
+ GTK_RESIZE_QUEUE);
+
+ group_bar->children = g_array_new (FALSE, FALSE,
+ sizeof (EGroupBarChild));
+
+ group_bar->current_group_num = -1;
+ group_bar->buttons_homogeneous = TRUE;
+ group_bar->max_button_height = 0;
+ group_bar->animation_timeout_id = 0;
+}
+
+
+/**
+ * e_group_bar_new:
+ * @Returns: a new #EGroupBar.
+ *
+ * Creates a new #EGroupBar.
+ **/
+GtkWidget *
+e_group_bar_new (void)
+{
+ GtkWidget *group_bar;
+
+ group_bar = GTK_WIDGET (gtk_type_new (e_group_bar_get_type ()));
+
+ return group_bar;
+}
+
+
+static void
+e_group_bar_destroy (GtkObject *object)
+{
+ EGroupBar *group_bar;
+
+ group_bar = E_GROUP_BAR (object);
+
+ e_group_bar_stop_all_animation (group_bar);
+
+ /* The parent GtkContainer class will automatically destroy all the
+ child widgets, but it calls gtk_container_foreach() so we must not
+ destroy our children array until after. */
+ GTK_OBJECT_CLASS (parent_class)->destroy (object);
+
+ g_array_free (group_bar->children, TRUE);
+}
+
+
+static void
+e_group_bar_realize (GtkWidget *widget)
+{
+ EGroupBar *group_bar;
+ EGroupBarChild *group;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+ gint border_width, group_num;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (E_IS_GROUP_BAR (widget));
+
+ group_bar = E_GROUP_BAR (widget);
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+ border_width = GTK_CONTAINER (group_bar)->border_width;
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = widget->allocation.x + border_width;
+ attributes.y = widget->allocation.y + border_width;
+ attributes.width = widget->allocation.width - 2 * border_width;
+ attributes.height = widget->allocation.height - 2 * border_width;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= (GDK_EXPOSURE_MASK);
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y
+ | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
+ &attributes, attributes_mask);
+ gdk_window_set_user_data (widget->window, widget);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+ gtk_style_set_background (widget->style, widget->window,
+ GTK_STATE_NORMAL);
+
+ gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
+
+ /* Create windows for all the buttons & group canvases. */
+ for (group_num = 0;
+ group_num < group_bar->children->len;
+ group_num++) {
+ group = &g_array_index (group_bar->children,
+ EGroupBarChild, group_num);
+ e_group_bar_create_group_button_window (group_bar, group_num);
+ e_group_bar_create_group_child_window (group_bar, group_num);
+ }
+}
+
+
+static void
+e_group_bar_unrealize (GtkWidget *widget)
+{
+ EGroupBar *group_bar;
+ EGroupBarChild *group;
+ gint group_num;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (E_IS_GROUP_BAR (widget));
+
+ group_bar = E_GROUP_BAR (widget);
+
+ /* Destroy the windows for all the buttons & group canvases. */
+ for (group_num = 0;
+ group_num < group_bar->children->len;
+ group_num++) {
+ group = &g_array_index (group_bar->children,
+ EGroupBarChild, group_num);
+
+ if (group->button_window) {
+ gdk_window_set_user_data (group->button_window, NULL);
+ gdk_window_destroy (group->button_window);
+ group->button_window = NULL;
+ }
+ if (group->child_window) {
+ gdk_window_set_user_data (group->child_window, NULL);
+ gdk_window_destroy (group->child_window);
+ group->child_window = NULL;
+ }
+ }
+
+ if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+ (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+}
+
+
+static void
+e_group_bar_map (GtkWidget *widget)
+{
+ EGroupBar *group_bar;
+ EGroupBarChild *group;
+ gint group_num;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (E_IS_GROUP_BAR (widget));
+
+ group_bar = E_GROUP_BAR (widget);
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
+
+ /* We do this in reverse order, and lower all the child windows, so
+ the stacking order ends up correct. */
+ for (group_num = group_bar->children->len - 1;
+ group_num >= 0;
+ group_num--) {
+ group = &g_array_index (group_bar->children,
+ EGroupBarChild, group_num);
+
+ if (group->button_window) {
+ gdk_window_show (group->button_window);
+ }
+
+ if (group->button
+ && GTK_WIDGET_VISIBLE (group->button)
+ && !GTK_WIDGET_MAPPED (group->button)) {
+ gtk_widget_map (group->button);
+ }
+
+ if (group->child_window) {
+ gdk_window_show (group->child_window);
+ gdk_window_lower (group->child_window);
+ }
+
+ if (group->child
+ && GTK_WIDGET_VISIBLE (group->child)
+ && !GTK_WIDGET_MAPPED (group->child))
+ gtk_widget_map (group->child);
+ }
+
+ gdk_window_show (widget->window);
+}
+
+
+static void
+e_group_bar_unmap (GtkWidget *widget)
+{
+ EGroupBar *group_bar;
+ EGroupBarChild *group;
+ gint group_num;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (E_IS_GROUP_BAR (widget));
+
+ group_bar = E_GROUP_BAR (widget);
+
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+
+ for (group_num = 0;
+ group_num < group_bar->children->len;
+ group_num++) {
+ group = &g_array_index (group_bar->children,
+ EGroupBarChild, group_num);
+
+ if (group->button_window) {
+ gdk_window_hide (group->button_window);
+ }
+
+ if (group->button
+ && GTK_WIDGET_MAPPED (group->button))
+ gtk_widget_unmap (group->button);
+
+ if (group->child_window) {
+ gdk_window_hide (group->child_window);
+ }
+
+ if (group->child
+ && GTK_WIDGET_MAPPED (group->child))
+ gtk_widget_unmap (group->child);
+ }
+
+ gdk_window_hide (widget->window);
+}
+
+
+static void
+e_group_bar_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ EGroupBar *group_bar;
+ EGroupBarChild *group;
+ gint group_num, max_child_height;
+ GtkRequisition child_requisition;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (E_IS_GROUP_BAR (widget));
+ g_return_if_fail (requisition != NULL);
+
+ group_bar = E_GROUP_BAR (widget);
+
+ /* We set the requisition width to the largest requested width of the
+ child widgets. The requisition height is set to the sum of all the
+ button heights plus the height of the largest child. */
+ requisition->width = 0;
+ requisition->height = 0;
+
+ /* We have to call size_request on all children, even though we don't
+ use the results, since some widgets like GtkLabel depend on it. */
+ group_bar->max_button_height = 0;
+ max_child_height = 0;
+ for (group_num = 0;
+ group_num < group_bar->children->len;
+ group_num++) {
+ group = &g_array_index (group_bar->children,
+ EGroupBarChild, group_num);
+
+ if (group->button) {
+ gtk_widget_size_request (group->button,
+ &child_requisition);
+ group->button_height = child_requisition.height;
+ } else {
+ group->button_height = 0;
+ }
+
+ group_bar->max_button_height = MAX (group_bar->max_button_height, group->button_height);
+ requisition->height += child_requisition.height;
+
+ if (group->child) {
+ gtk_widget_size_request (group->child,
+ &child_requisition);
+ max_child_height = MAX (max_child_height,
+ child_requisition.height);
+ requisition->width = MAX (requisition->width,
+ child_requisition.width);
+ }
+ }
+
+ requisition->height += max_child_height;
+
+ /* Add on the standard container border widths. */
+ requisition->width += GTK_CONTAINER (widget)->border_width * 2;
+ requisition->height += GTK_CONTAINER (widget)->border_width * 2;
+}
+
+
+static void
+e_group_bar_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
+{
+ EGroupBar *group_bar;
+ EGroupBarChild *group;
+ gint group_num, border_width, width, height, child_height, y;
+ GtkAllocation button_allocation, child_allocation;
+
+ group_bar = E_GROUP_BAR (widget);
+
+ /* All child & button windows and widgets use the same width as the
+ group bar minus the border width. */
+ border_width = GTK_CONTAINER (widget)->border_width;
+ width = allocation->width - border_width * 2;
+ height = allocation->height - border_width * 2;
+
+ widget->allocation = *allocation;
+ if (GTK_WIDGET_REALIZED (widget))
+ gdk_window_move_resize (widget->window,
+ allocation->x + border_width,
+ allocation->y + border_width,
+ width, height);
+
+ /* All the child widgets use the same height. */
+ child_height = e_group_bar_get_child_height (group_bar);
+
+ /* The buttons are always in the top-left of the button windows, and
+ all have the same width. The height is calculated for each group. */
+ button_allocation.x = 0;
+ button_allocation.y = 0;
+ button_allocation.width = width;
+
+ /* The child widgets are always in the top-left of the child windows,
+ and all have the same width and height. */
+ child_allocation.x = 0;
+ child_allocation.y = 0;
+ child_allocation.width = width;
+ child_allocation.height = child_height;
+
+ /* Step through the groups, placing the windows as necessary, and
+ allocating the areas for the child widgets. Note that if a button
+ or child window is in the middle of an animation, we just resize it
+ and update the target position, and let the animation continue. */
+ for (group_num = 0;
+ group_num < group_bar->children->len;
+ group_num++) {
+ group = &g_array_index (group_bar->children,
+ EGroupBarChild, group_num);
+
+ /* Calculate the y position of the button, which depends on
+ the currently selected group and the button heights. */
+ y = e_group_bar_get_group_button_position (group_bar, group_num);
+ button_allocation.height = group_bar->buttons_homogeneous ? group_bar->max_button_height : group->button_height;
+
+ if (GTK_WIDGET_REALIZED (group->button)) {
+ if (group->button_window_in_animation) {
+ gdk_window_resize (group->button_window,
+ width, button_allocation.height);
+ group->button_window_target_y = y;
+ } else {
+ gdk_window_move_resize (group->button_window,
+ 0, y, width, button_allocation.height);
+ }
+ }
+ gtk_widget_size_allocate (group->button, &button_allocation);
+
+ if (GTK_WIDGET_REALIZED (group->child)) {
+ if (group->child_window_in_animation) {
+ gdk_window_resize (group->child_window,
+ width, child_height);
+ group->child_window_target_y = y + button_allocation.height;
+ } else {
+ gdk_window_move_resize (group->child_window,
+ 0, y + button_allocation.height,
+ width, child_height);
+ }
+ }
+ gtk_widget_size_allocate (group->child, &child_allocation);
+ }
+}
+
+
+static gint
+e_group_bar_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ EGroupBar *group_bar;
+ EGroupBarChild *group;
+ GdkEventExpose child_event;
+ gint group_num;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (E_IS_GROUP_BAR (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget)) {
+ group_bar = E_GROUP_BAR (widget);
+
+ child_event = *event;
+
+ for (group_num = 0;
+ group_num < group_bar->children->len;
+ group_num++) {
+ group = &g_array_index (group_bar->children,
+ EGroupBarChild, group_num);
+
+ if (event->window == group->button_window
+ && GTK_WIDGET_DRAWABLE (group->button)
+ && GTK_WIDGET_NO_WINDOW (group->button)
+ && gtk_widget_intersect (group->button, &event->area, &child_event.area))
+ gtk_widget_event (group->button, (GdkEvent*) &child_event);
+
+ if (event->window == group->child_window
+ && GTK_WIDGET_DRAWABLE (group->child)
+ && GTK_WIDGET_NO_WINDOW (group->child)
+ && gtk_widget_intersect (group->child, &event->area, &child_event.area))
+ gtk_widget_event (group->child, (GdkEvent*) &child_event);
+ }
+ }
+
+ return FALSE;
+}
+
+
+static void
+e_group_bar_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ EGroupBar *group_bar;
+ EGroupBarChild *group;
+ gint group_num;
+#if 0
+ GdkRectangle child_area;
+#endif
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (E_IS_GROUP_BAR (widget));
+
+ g_print ("In e_group_bar_draw %i,%i %ix%i\n", area->x, area->y,
+ area->width, area->height);
+
+ if (GTK_WIDGET_DRAWABLE (widget)) {
+ group_bar = E_GROUP_BAR (widget);
+
+ for (group_num = 0;
+ group_num < group_bar->children->len;
+ group_num++) {
+ group = &g_array_index (group_bar->children,
+ EGroupBarChild, group_num);
+ /* FIXME */
+#if 0
+ if (GTK_WIDGET_DRAWABLE (child->widget) &&
+ gtk_widget_intersect (child->widget, area, &child_area))
+ gtk_widget_draw (child->widget, &child_area);
+#endif
+ }
+ }
+}
+
+
+static void
+e_group_bar_add (GtkContainer *container,
+ GtkWidget *widget)
+{
+ EGroupBar *group_bar;
+ GtkWidget *button;
+ gchar buffer[32];
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (E_IS_GROUP_BAR (container));
+ g_return_if_fail (widget != NULL);
+
+ g_snprintf (buffer, sizeof (buffer), _("Group %i"),
+ group_bar->children->len + 1);
+ button = gtk_button_new_with_label (buffer);
+ gtk_widget_show (button);
+
+ e_group_bar_add_group (group_bar, widget, button, -1);
+}
+
+
+static void
+e_group_bar_remove (GtkContainer *container,
+ GtkWidget *widget)
+{
+ EGroupBar *group_bar;
+ gint group_num;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (E_IS_GROUP_BAR (container));
+ g_return_if_fail (widget != NULL);
+
+ group_bar = E_GROUP_BAR (container);
+
+ group_num = e_group_bar_get_group_num (group_bar, widget);
+ e_group_bar_remove_group (group_bar, group_num);
+}
+
+
+static void
+e_group_bar_forall (GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ EGroupBar *group_bar;
+ EGroupBarChild *group;
+ gint group_num;
+ GList *tmp_list;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (E_IS_GROUP_BAR (container));
+ g_return_if_fail (callback != NULL);
+
+ group_bar = E_GROUP_BAR (container);
+
+ /* Note that drag-and-drop does not check the Z-order of widgets, so
+ we have to iterate through them from top to bottom, or it will
+ not work properly. We also have to use temporary lists so widgets
+ can be safely destroyed while iterating. */
+
+ if (include_internals) {
+ tmp_list = NULL;
+ for (group_num = group_bar->children->len - 1;
+ group_num >= 0;
+ group_num--) {
+ group = &g_array_index (group_bar->children,
+ EGroupBarChild, group_num);
+
+ if (group->button)
+ tmp_list = g_list_prepend (tmp_list,
+ group->button);
+ }
+
+ g_list_foreach (tmp_list, (GFunc) callback, callback_data);
+ g_list_free (tmp_list);
+ }
+
+ tmp_list = NULL;
+ for (group_num = 0;
+ group_num < group_bar->children->len;
+ group_num++) {
+ group = &g_array_index (group_bar->children,
+ EGroupBarChild, group_num);
+
+ if (group->child)
+ tmp_list = g_list_prepend (tmp_list, group->child);
+ }
+ g_list_foreach (tmp_list, (GFunc) callback, callback_data);
+ g_list_free (tmp_list);
+}
+
+
+static void
+e_group_bar_create_group_button_window (EGroupBar *group_bar,
+ gint group_num)
+{
+ EGroupBarChild *group;
+ GtkWidget *widget;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+ gint y, height, border_width;
+
+ widget = GTK_WIDGET (group_bar);
+
+ group = &g_array_index (group_bar->children,
+ EGroupBarChild, group_num);
+ y = e_group_bar_get_group_button_position (group_bar, group_num);
+ height = group_bar->buttons_homogeneous ? group_bar->max_button_height
+ : group->button_height;
+ border_width = GTK_CONTAINER (group_bar)->border_width;
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = 0;
+ attributes.y = y;
+ attributes.width = widget->allocation.width - 2 * border_width;
+ attributes.height = height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= (GDK_EXPOSURE_MASK);
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y
+ | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ group->button_window = gdk_window_new (widget->window, &attributes,
+ attributes_mask);
+ gdk_window_set_user_data (group->button_window, widget);
+
+ gtk_widget_set_parent_window (group->button,
+ group->button_window);
+ gdk_window_set_back_pixmap (group->button_window, NULL, TRUE);
+}
+
+
+static void
+e_group_bar_create_group_child_window (EGroupBar *group_bar,
+ gint group_num)
+{
+ EGroupBarChild *group;
+ GtkWidget *widget;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+ gint y, height, border_width;
+
+ widget = GTK_WIDGET (group_bar);
+
+ group = &g_array_index (group_bar->children,
+ EGroupBarChild, group_num);
+ y = e_group_bar_get_group_button_position (group_bar, group_num);
+ y += group_bar->buttons_homogeneous ? group_bar->max_button_height
+ : group->button_height;
+ height = e_group_bar_get_child_height (group_bar);
+ border_width = GTK_CONTAINER (group_bar)->border_width;
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = 0;
+ attributes.y = y;
+ attributes.width = widget->allocation.width - 2 * border_width;
+ attributes.height = height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= (GDK_EXPOSURE_MASK);
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y
+ | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ group->child_window = gdk_window_new (widget->window, &attributes,
+ attributes_mask);
+ gdk_window_set_user_data (group->child_window, widget);
+
+ gtk_widget_set_parent_window (GTK_WIDGET (group->child),
+ group->child_window);
+ gdk_window_set_back_pixmap (group->child_window, NULL, TRUE);
+}
+
+
+/* This returns the y position of a group's button within the EGroupBar window.
+ */
+static gint
+e_group_bar_get_group_button_position (EGroupBar *group_bar,
+ gint group_num)
+{
+ gint border_width, window_height, y;
+
+ border_width = GTK_CONTAINER (group_bar)->border_width;
+ window_height = GTK_WIDGET (group_bar)->allocation.height - 2 * border_width;
+
+ if (group_num <= group_bar->current_group_num)
+ y = e_group_bar_sum_button_heights (group_bar, 0, group_num - 1);
+ else
+ y = window_height - e_group_bar_sum_button_heights (group_bar, group_num, group_bar->children->len - 1);
+
+ return y;
+}
+
+
+/* This returns the sum of all the buttons from first to last inclusive. */
+static gint
+e_group_bar_sum_button_heights (EGroupBar *group_bar, gint first, gint last)
+{
+ EGroupBarChild *group;
+ gint height, group_num;
+
+ height = 0;
+
+ if (group_bar->buttons_homogeneous)
+ return (last - first + 1) * group_bar->max_button_height;
+
+ for (group_num = first; group_num <= last; group_num++) {
+ group = &g_array_index (group_bar->children,
+ EGroupBarChild, group_num);
+ height += group->button_height;
+ }
+
+ return height;
+}
+
+
+static gint
+e_group_bar_get_group_child_position (EGroupBar *group_bar,
+ gint group_num)
+{
+ EGroupBarChild *group;
+ gint y;
+
+ y = e_group_bar_get_group_button_position (group_bar, group_num);
+ group = &g_array_index (group_bar->children,
+ EGroupBarChild, group_num);
+ y += group_bar->buttons_homogeneous ? group_bar->max_button_height
+ : group->button_height;
+
+ return y;
+}
+
+
+static gint
+e_group_bar_get_child_height (EGroupBar *group_bar)
+{
+ EGroupBarChild *group;
+ gint group_num;
+
+ /* Start with the allocated height of the EGroupBar, less the border.*/
+ group_bar->child_height = GTK_WIDGET (group_bar)->allocation.height;
+ group_bar->child_height -= 2 * GTK_CONTAINER (group_bar)->border_width;
+
+ /* Now subtract the heights of all the buttons. */
+ if (group_bar->buttons_homogeneous) {
+ group_bar->child_height -= group_bar->children->len * group_bar->max_button_height;
+ } else {
+ for (group_num = 0;
+ group_num < group_bar->children->len;
+ group_num++) {
+ group = &g_array_index (group_bar->children,
+ EGroupBarChild, group_num);
+ group_bar->child_height -= group->button_height;
+ }
+ }
+
+ return group_bar->child_height;
+}
+
+
+/*
+ * Insertion, reordering and deletion of items.
+ */
+
+/**
+ * e_group_bar_add_group:
+ * @group_bar: an #EGroupBar.
+ * @child: the child widget to add.
+ * @button: the button used to show the child widget.
+ * @position: the new group's position, or -1 to place it last.
+ * @Returns: the position of the new group.
+ *
+ * Adds a new group to a #EGroupBar at the given position.
+ **/
+gint
+e_group_bar_add_group (EGroupBar *group_bar,
+ GtkWidget *child,
+ GtkWidget *button,
+ gint position)
+{
+ EGroupBarChild *group, empty_group, *tmp_group;
+ gint group_num, tmp_group_num;
+
+ g_return_val_if_fail (group_bar != NULL, -1);
+ g_return_val_if_fail (E_IS_GROUP_BAR (group_bar), -1);
+ g_return_val_if_fail (child != NULL, -1);
+ g_return_val_if_fail (button != NULL, -1);
+ g_return_val_if_fail (GTK_IS_BUTTON (button), -1);
+
+ /* Append an empty group to the children array and get a pointer to
+ it, so we can use it like a normal group. */
+ group_num = group_bar->children->len;
+ g_array_append_val (group_bar->children, empty_group);
+ group = &g_array_index (group_bar->children,
+ EGroupBarChild, group_num);
+
+ /* Initialize the group. */
+ group->button = button;
+ group->button_window = NULL;
+ group->child = child;
+ group->child_window = NULL;
+ group->button_window_in_animation = FALSE;
+ group->child_window_in_animation = FALSE;
+ group->button_window_target_y = 0;
+ group->child_window_target_y = 0;
+
+ /* If we don't have a current group, set it to the first one. */
+ if (group_bar->current_group_num == -1)
+ group_bar->current_group_num = 0;
+
+ /* If the EGroupBar widget is realize, we need to create the child
+ windows to put the button & child in. */
+ if (GTK_WIDGET_REALIZED (group_bar)) {
+ e_group_bar_create_group_button_window (group_bar, group_num);
+ e_group_bar_create_group_child_window (group_bar, group_num);
+
+ /* We need to lower all the child windows of the previous
+ groups, in reverse order, to keep the stacking order
+ correct. */
+ for (tmp_group_num = group_num - 1;
+ tmp_group_num >= 0;
+ tmp_group_num--) {
+ tmp_group = &g_array_index (group_bar->children,
+ EGroupBarChild,
+ tmp_group_num);
+ gdk_window_lower (group->child_window);
+ }
+ }
+
+ gtk_widget_set_parent (group->button, GTK_WIDGET (group_bar));
+ gtk_widget_set_parent (group->child, GTK_WIDGET (group_bar));
+
+ if (GTK_WIDGET_REALIZED (group_bar)) {
+ gtk_widget_realize (group->button);
+ gtk_widget_realize (group->child);
+ }
+
+ if (GTK_WIDGET_VISIBLE (group_bar)
+ && GTK_WIDGET_MAPPED (group_bar)) {
+ if (group->button
+ && GTK_WIDGET_VISIBLE (group->button)
+ && !GTK_WIDGET_MAPPED (group->button)) {
+ gtk_widget_map (group->button);
+ gtk_widget_queue_resize (group->button);
+ }
+ if (group->child
+ && GTK_WIDGET_VISIBLE (group->child)
+ && !GTK_WIDGET_MAPPED (group->child)) {
+ gtk_widget_map (group->child);
+ gtk_widget_queue_resize (group->child);
+ }
+ }
+
+ gtk_signal_connect (GTK_OBJECT (group->button), "clicked",
+ GTK_SIGNAL_FUNC (e_group_bar_on_button_clicked),
+ group_bar);
+
+ gtk_signal_connect (GTK_OBJECT (group->button), "drag_motion",
+ GTK_SIGNAL_FUNC (e_group_bar_on_button_drag_motion),
+ group_bar);
+ gtk_signal_connect (GTK_OBJECT (group->button), "drag_leave",
+ GTK_SIGNAL_FUNC (e_group_bar_on_button_drag_leave),
+ group_bar);
+
+ return group_num;
+}
+
+
+/**
+ * e_group_bar_reorder_group:
+ * @group_bar: an #EGroupBar.
+ * @group_num: the index of the group to move.
+ * @new_position: the new position of the group.
+ *
+ * Moves a group to a new position within the #EGroupBar.
+ **/
+void
+e_group_bar_reorder_group (EGroupBar *group_bar,
+ gint group_num,
+ gint new_position)
+{
+ g_return_if_fail (E_IS_GROUP_BAR (group_bar));
+
+}
+
+
+/**
+ * e_group_bar_remove_group:
+ * @group_bar: an #EGroupBar.
+ * @group_num: the index of the group to remove.
+ *
+ * Removes a group from an #EGroupBar.
+ **/
+void
+e_group_bar_remove_group (EGroupBar *group_bar,
+ gint group_num)
+{
+ EGroupBarChild *group;
+
+ g_return_if_fail (E_IS_GROUP_BAR (group_bar));
+ g_return_if_fail (group_num >= 0);
+ g_return_if_fail (group_num < group_bar->children->len);
+
+ group = &g_array_index (group_bar->children,
+ EGroupBarChild, group_num);
+
+ /* Stop any animation. */
+ e_group_bar_stop_all_animation (group_bar);
+
+ gtk_widget_unparent (group->child);
+ if (group->button)
+ gtk_widget_unparent (group->button);
+
+ if (group->button_window) {
+ gdk_window_set_user_data (group->button_window, NULL);
+ gdk_window_destroy (group->button_window);
+ }
+ if (group->child_window) {
+ gdk_window_set_user_data (group->child_window, NULL);
+ gdk_window_destroy (group->child_window);
+ }
+
+ g_array_remove_index (group_bar->children, group_num);
+
+ /* Make sure the current group is valid. */
+ if (group_bar->current_group_num >= group_bar->children->len)
+ group_bar->current_group_num = group_bar->children->len - 1;
+
+ gtk_widget_queue_resize (GTK_WIDGET (group_bar));
+}
+
+
+/*
+ * Getting & setting the current group.
+ */
+
+/**
+ * e_group_bar_get_current_group_num:
+ * @group_bar: an #EGroupBar.
+ * @Returns: the index of the group currently displayed.
+ *
+ * Returns the index of the group currently displayed.
+ **/
+gint
+e_group_bar_get_current_group_num (EGroupBar *group_bar)
+{
+ g_return_val_if_fail (E_IS_GROUP_BAR (group_bar), -1);
+
+ return group_bar->current_group_num;
+}
+
+
+/**
+ * e_group_bar_set_current_group_num:
+ * @group_bar: an #EGroupBar.
+ * @Returns: the index of the group to display.
+ *
+ * Sets the group to display.
+ **/
+/* FIXME: animate option? May want to set group without animation. */
+void
+e_group_bar_set_current_group_num (EGroupBar *group_bar,
+ gint group_num)
+{
+ g_return_if_fail (E_IS_GROUP_BAR (group_bar));
+
+ /* If that already is the current group, just return. */
+ if (group_bar->current_group_num == group_num)
+ return;
+
+ /* FIXME: Set the target positions of the old current group and the
+ new current group, map the new group's child window, and create the
+ animation timeout, if we haven't already got one. */
+
+ group_bar->current_group_num = group_num;
+
+}
+
+
+/*
+ * Getting groups and group numbers.
+ */
+
+/**
+ * e_group_bar_get_nth_group:
+ * @group_bar: an #EGroupBar.
+ * @group_num: the index of the group to get.
+ * @Returns: the child widget at the given index.
+ *
+ * Returns the child widget at the given index.
+ **/
+GtkWidget*
+e_group_bar_get_nth_group (EGroupBar *group_bar,
+ gint group_num)
+{
+ EGroupBarChild *group;
+
+ g_return_val_if_fail (E_IS_GROUP_BAR (group_bar), NULL);
+ g_return_val_if_fail (group_num >= 0, NULL);
+ g_return_val_if_fail (group_num < group_bar->children->len, NULL);
+
+ group = &g_array_index (group_bar->children,
+ EGroupBarChild, group_num);
+ return group->child;
+}
+
+
+/**
+ * e_group_bar_get_group_num:
+ * @group_bar: an #EGroupBar.
+ * @child: the child widget to find.
+ * @Returns: the index of the group containing the given widget.
+ *
+ * Returns the index of the group containing the given child widget.
+ **/
+gint
+e_group_bar_get_group_num (EGroupBar *group_bar,
+ GtkWidget *child)
+{
+ EGroupBarChild *group;
+ gint group_num;
+
+ g_return_val_if_fail (E_IS_GROUP_BAR (group_bar), -1);
+ g_return_val_if_fail (child != NULL, -1);
+
+ for (group_num = 0;
+ group_num < group_bar->children->len;
+ group_num++) {
+ group = &g_array_index (group_bar->children,
+ EGroupBarChild, group_num);
+
+ if (group->child == child)
+ return group_num;
+ }
+
+ return -1;
+}
+
+
+/**
+ * e_group_bar_set_group_button_label:
+ * @group_bar: an #EGroupBar.
+ * @group_num: the index of the group.
+ * @label: the label widget to place in the group's button.
+ *
+ * Sets the label widget for the given group's button, replacing any existing
+ * widget in the button.
+ **/
+void
+e_group_bar_set_group_button_label (EGroupBar *group_bar,
+ gint group_num,
+ GtkWidget *label)
+{
+ EGroupBarChild *group;
+ GtkWidget *button_child;
+
+ g_return_if_fail (E_IS_GROUP_BAR (group_bar));
+ g_return_if_fail (group_num >= 0);
+ g_return_if_fail (group_num < group_bar->children->len);
+
+ group = &g_array_index (group_bar->children,
+ EGroupBarChild, group_num);
+
+ button_child = GTK_BIN (group->button)->child;
+ if (button_child) {
+ gtk_container_remove (GTK_CONTAINER (group->button),
+ button_child);
+ }
+
+ if (label)
+ gtk_container_add (GTK_CONTAINER (group->button), label);
+}
+
+
+/*
+ * Getting & setting the EGroupBar options.
+ */
+
+/**
+ * e_group_bar_get_buttons_homogeneous:
+ * @group_bar: an #EGroupBar.
+ * @Returns: TRUE if the buttons are homoegeneous.
+ *
+ * Returns TRUE if the buttons are homogeneous (i.e. all have the same height).
+ **/
+gboolean
+e_group_bar_get_buttons_homogeneous (EGroupBar *group_bar)
+{
+ g_return_val_if_fail (E_IS_GROUP_BAR (group_bar), TRUE);
+
+ return group_bar->buttons_homogeneous;
+}
+
+
+/**
+ * e_group_bar_set_buttons_homogeneous:
+ * @group_bar: an #EGroupBar.
+ * @homogeneous: TRUE if the buttons should be homoegeneous.
+ *
+ * Specifies whether the buttons should be homogeneous. When set to TRUE all
+ * the group buttons will be set to the same height (equal to the largest
+ * requested height). When set to FALSE the buttons will use their own
+ * individual requested heights.
+ **/
+void
+e_group_bar_set_buttons_homogeneous (EGroupBar *group_bar,
+ gboolean homogeneous)
+{
+ g_return_if_fail (E_IS_GROUP_BAR (group_bar));
+
+ /* Just return if the setting hasn't changed. */
+ if (group_bar->buttons_homogeneous == homogeneous)
+ return;
+
+ group_bar->buttons_homogeneous = homogeneous;
+
+ /* Update the position & sizes of the buttons. */
+ gtk_widget_queue_resize (GTK_WIDGET (group_bar));
+}
+
+
+static void
+e_group_bar_on_button_clicked (GtkWidget *group_button,
+ EGroupBar *group_bar)
+{
+ gint group_num;
+
+ /* Determine which group button was clicked. */
+ group_num = e_group_bar_find_button (group_bar, group_button);
+
+ if (group_num != -1)
+ e_group_bar_start_animation (group_bar, group_num);
+}
+
+
+/* This returns the group containing the given button, or -1 if not found. */
+static gint
+e_group_bar_find_button (EGroupBar *group_bar,
+ GtkWidget *group_button)
+{
+ EGroupBarChild *group;
+ gint group_num;
+
+ /* Determine which group button was clicked. */
+ for (group_num = 0;
+ group_num < group_bar->children->len;
+ group_num++) {
+ group = &g_array_index (group_bar->children,
+ EGroupBarChild, group_num);
+ if (group->button == group_button)
+ return group_num;
+ }
+
+ return -1;
+}
+
+
+static void
+e_group_bar_start_animation (EGroupBar *group_bar,
+ gint group_num)
+{
+ EGroupBarChild *group, *old_group;
+ gint old_group_num, step;
+
+ old_group_num = group_bar->current_group_num;
+
+ /* Return if it is already the current group. */
+ if (old_group_num == group_num)
+ return;
+
+ group_bar->current_group_num = group_num;
+
+ /* Calculate the target y position of the new current group button
+ and child, and map the child. */
+ group = &g_array_index (group_bar->children,
+ EGroupBarChild, group_num);
+ group->button_window_target_y = e_group_bar_get_group_button_position (group_bar, group_num);
+ group->button_window_in_animation = TRUE;
+
+ group->child_window_target_y = e_group_bar_get_group_child_position (group_bar, group_num);
+ group->child_window_in_animation = TRUE;
+
+ /* Calculate the target y position of the current group button and
+ child. */
+ old_group = &g_array_index (group_bar->children,
+ EGroupBarChild, old_group_num);
+ old_group->button_window_target_y = e_group_bar_get_group_button_position (group_bar, old_group_num);
+ old_group->button_window_in_animation = TRUE;
+
+ old_group->child_window_target_y = e_group_bar_get_group_child_position (group_bar, old_group_num);
+ old_group->child_window_in_animation = TRUE;
+
+ /* We also need to animate the buttons in between the old group and the
+ new group. */
+ step = (old_group_num < group_num) ? 1 : -1;
+ old_group_num += step;
+ while (old_group_num != group_num) {
+ old_group = &g_array_index (group_bar->children,
+ EGroupBarChild, old_group_num);
+ old_group->button_window_target_y = e_group_bar_get_group_button_position (group_bar, old_group_num);
+ old_group->button_window_in_animation = TRUE;
+
+ old_group->child_window_target_y = e_group_bar_get_group_child_position (group_bar, old_group_num);
+ old_group->child_window_in_animation = TRUE;
+
+ old_group_num += step;
+ }
+
+ /* Add a timeout handler if we haven't already got one. */
+ if (group_bar->animation_timeout_id == 0) {
+ group_bar->animation_timeout_id = g_timeout_add (E_GROUP_BAR_SCROLL_TIMEOUT, e_group_bar_timeout_handler, group_bar);
+ }
+}
+
+
+static gboolean
+e_group_bar_timeout_handler (gpointer data)
+{
+ EGroupBar *group_bar;
+ EGroupBarChild *group;
+ gint group_num, button_window_y, child_window_y;
+ gboolean finished = TRUE;
+
+ g_return_val_if_fail (E_IS_GROUP_BAR (data), FALSE);
+
+ group_bar = E_GROUP_BAR (data);
+
+ GDK_THREADS_ENTER ();
+
+ for (group_num = 0;
+ group_num < group_bar->children->len;
+ group_num++) {
+ group = &g_array_index (group_bar->children,
+ EGroupBarChild, group_num);
+
+ if (group->button_window_in_animation) {
+ gdk_window_get_position (group->button_window, NULL,
+ &button_window_y);
+ button_window_y += e_group_bar_get_increment (group_bar, button_window_y, group->button_window_target_y);
+ if (button_window_y == group->button_window_target_y)
+ group->button_window_in_animation = FALSE;
+ else
+ finished = FALSE;
+ gdk_window_move (group->button_window,
+ 0, button_window_y);
+ }
+ if (group->child_window_in_animation) {
+ gdk_window_get_position (group->child_window, NULL,
+ &child_window_y);
+ child_window_y += e_group_bar_get_increment (group_bar, child_window_y, group->child_window_target_y);
+ if (child_window_y == group->child_window_target_y)
+ group->child_window_in_animation = FALSE;
+ else
+ finished = FALSE;
+ gdk_window_move (group->child_window,
+ 0, child_window_y);
+ }
+
+ }
+
+ if (finished)
+ group_bar->animation_timeout_id = 0;
+
+ GDK_THREADS_LEAVE ();
+
+ return !finished;
+}
+
+
+static gint
+e_group_bar_get_increment (EGroupBar *group_bar,
+ gint window_y,
+ gint window_target_y)
+{
+ gdouble percentage;
+ gint distance, total_distance, step;
+
+ total_distance = group_bar->child_height;
+ distance = MIN (abs (window_target_y - window_y), total_distance);
+
+ /* Convert the distance into an angle between -PI/2 and PI/2, so we can
+ then do a cosine of it. */
+ percentage = cos (M_PI * ((gdouble)distance / (gdouble)total_distance) - M_PI / 2);
+
+ /* Now multiply by our maximum step size to get the step size. */
+ step = percentage * total_distance / 6;
+
+ /* Add it to the minimum step size, but don't go too far. */
+ step = step + E_GROUP_BAR_MIN_STEP_SIZE;
+ step = MIN (step, distance);
+
+ if (window_target_y > window_y)
+ return step;
+ else
+ return -step;
+}
+
+
+static gboolean
+e_group_bar_on_button_drag_motion (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time,
+ EGroupBar *group_bar)
+{
+ gint group_num;
+
+ if (!group_bar->auto_show_timeout_id) {
+ group_num = e_group_bar_find_button (group_bar, widget);
+ if (group_num != -1) {
+ group_bar->auto_show_timeout_id = gtk_timeout_add (E_GROUP_BAR_AUTO_SHOW_TIMEOUT, e_group_bar_auto_show, group_bar);
+ group_bar->auto_show_group_num = group_num;
+ }
+ }
+ return TRUE;
+}
+
+
+static void
+e_group_bar_on_button_drag_leave (GtkWidget *widget,
+ GdkDragContext *context,
+ guint time,
+ EGroupBar *group_bar)
+{
+ if (group_bar->auto_show_timeout_id) {
+ gtk_timeout_remove (group_bar->auto_show_timeout_id);
+ group_bar->auto_show_timeout_id = 0;
+ }
+}
+
+
+static gboolean
+e_group_bar_auto_show (gpointer data)
+{
+ EGroupBar *group_bar;
+
+ g_return_val_if_fail (E_IS_GROUP_BAR (data), FALSE);
+
+ group_bar = E_GROUP_BAR (data);
+
+ GDK_THREADS_ENTER ();
+
+ e_group_bar_start_animation (group_bar,
+ group_bar->auto_show_group_num);
+
+ group_bar->auto_show_timeout_id = 0;
+
+ GDK_THREADS_LEAVE ();
+
+ return FALSE;
+}
+
+
+/* This removes all timeouts and sets all 'in_animation' flags to FALSE. */
+static void
+e_group_bar_stop_all_animation (EGroupBar *group_bar)
+{
+ EGroupBarChild *group;
+ gint group_num;
+
+ if (group_bar->animation_timeout_id) {
+ g_source_remove (group_bar->animation_timeout_id);
+ group_bar->animation_timeout_id = 0;
+ }
+ if (group_bar->auto_show_timeout_id) {
+ g_source_remove (group_bar->auto_show_timeout_id);
+ group_bar->auto_show_timeout_id = 0;
+ }
+
+ for (group_num = 0;
+ group_num < group_bar->children->len;
+ group_num++) {
+ group = &g_array_index (group_bar->children,
+ EGroupBarChild, group_num);
+ group->button_window_in_animation = FALSE;
+ group->child_window_in_animation = FALSE;
+ }
+}
+
diff --git a/widgets/shortcut-bar/e-group-bar.h b/widgets/shortcut-bar/e-group-bar.h
new file mode 100644
index 0000000000..9a6f83b461
--- /dev/null
+++ b/widgets/shortcut-bar/e-group-bar.h
@@ -0,0 +1,171 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Author :
+ * Damon Chaplin <damon@gtk.org>
+ *
+ * Copyright 1999, Helix Code, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+#ifndef _E_GROUP_BAR_H_
+#define _E_GROUP_BAR_H_
+
+#include <gtk/gtkcontainer.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * EGroupBar displays a vertical bar with a number of Groups, which are viewed
+ * one at a time by selecting the Group's button. When a different Group is
+ * selected, it slides into view, and the old Group slides out.
+ * It is typically used on the left of the main application window so users
+ * can easily access particular features.
+ *
+ * It is implemented like GtkNotebook, i.e. the main widgets are the children
+ * of the EGroupBar and the button widgets are treated specially like the
+ * GtkNotebook tab labels.
+ */
+
+/* This contains information on one item. */
+typedef struct _EGroupBarChild EGroupBarChild;
+struct _EGroupBarChild
+{
+ /* This is the button used to select the group, and the window we use
+ to move it around easily. */
+ GtkWidget *button;
+ GdkWindow *button_window;
+ gint button_height;
+
+ /* This is the child widget, which can be any widget added by the
+ application, and the window we use to move it around easily. */
+ GtkWidget *child;
+ GdkWindow *child_window;
+
+ /* These are TRUE if we are currently animating the windows. */
+ gboolean button_window_in_animation;
+ gboolean child_window_in_animation;
+
+ /* These are the target y positions that the windows should eventually
+ move to, used for animation. If we get a size_allocate we just
+ update these and the animation can continue as normal.
+ When a child window reaches its target position, it is unmapped if
+ if it is not the current group (i.e. it has slid off screen). */
+ gint button_window_target_y;
+ gint child_window_target_y;
+};
+
+
+#define E_GROUP_BAR(obj) GTK_CHECK_CAST (obj, e_group_bar_get_type (), EGroupBar)
+#define E_GROUP_BAR_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, e_group_bar_get_type (), EGroupBarClass)
+#define E_IS_GROUP_BAR(obj) GTK_CHECK_TYPE (obj, e_group_bar_get_type ())
+
+
+typedef struct _EGroupBar EGroupBar;
+typedef struct _EGroupBarClass EGroupBarClass;
+
+struct _EGroupBar
+{
+ GtkContainer container;
+
+ /* This is an array of EGroupBarChild elements. */
+ GArray *children;
+
+ /* This is the group currently shown. */
+ gint current_group_num;
+
+ /* This is TRUE if all the buttons are allocated the same height. */
+ gboolean buttons_homogeneous;
+
+ /* This is the biggest requested height of all the buttons, which we
+ use for all buttons when buttons_homogeneous is set. */
+ gint max_button_height;
+
+ /* This is the height of all the child windows & widgets. */
+ gint child_height;
+
+ /* The id of the source function for animation timeouts. If this is
+ not 0 then we are in the middle of an animation. */
+ guint animation_timeout_id;
+
+ /* The id of the source function for automatically showing groups when
+ the user drags over the group button, and the group to show. */
+ guint auto_show_timeout_id;
+ gint auto_show_group_num;
+};
+
+struct _EGroupBarClass
+{
+ GtkContainerClass parent_class;
+};
+
+
+GtkType e_group_bar_get_type (void);
+GtkWidget* e_group_bar_new (void);
+
+/*
+ * Insertion, reordering and deletion of items.
+ */
+
+/* Adds a new group at the given position. If position is -1 it adds it as
+ the last group. It returns the group number. */
+gint e_group_bar_add_group (EGroupBar *group_bar,
+ GtkWidget *child,
+ GtkWidget *button,
+ gint position);
+void e_group_bar_reorder_group (EGroupBar *group_bar,
+ gint group_num,
+ gint new_position);
+void e_group_bar_remove_group (EGroupBar *group_bar,
+ gint group_num);
+
+/*
+ * Getting & setting the current group.
+ */
+gint e_group_bar_get_current_group_num (EGroupBar *group_bar);
+void e_group_bar_set_current_group_num (EGroupBar *group_bar,
+ gint group_num);
+
+/*
+ * Getting groups and group numbers.
+ */
+GtkWidget* e_group_bar_get_nth_group (EGroupBar *group_bar,
+ gint group_num);
+gint e_group_bar_get_group_num (EGroupBar *group_bar,
+ GtkWidget *child);
+
+/*
+ * Setting the group button label.
+ */
+void e_group_bar_set_group_button_label (EGroupBar *group_bar,
+ gint group_num,
+ GtkWidget *label);
+
+/*
+ * Getting & setting the EGroupBar options.
+ */
+gboolean e_group_bar_get_buttons_homogeneous (EGroupBar *group_bar);
+void e_group_bar_set_buttons_homogeneous (EGroupBar *group_bar,
+ gboolean homogeneous);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _E_GROUP_BAR_H_ */
diff --git a/widgets/shortcut-bar/e-icon-bar-bg-item.c b/widgets/shortcut-bar/e-icon-bar-bg-item.c
new file mode 100644
index 0000000000..1bdb7a308d
--- /dev/null
+++ b/widgets/shortcut-bar/e-icon-bar-bg-item.c
@@ -0,0 +1,361 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Author :
+ * Damon Chaplin <damon@gtk.org>
+ *
+ * Copyright 1999, Helix Code, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ * EIconBarBgItem - A GnomeCanvasItem which covers the entire EIconBar.
+ * It paints the rectangles around items when the mouse moves over them, and
+ * the lines between items when dragging.
+ */
+
+#include "e-icon-bar-bg-item.h"
+#include "e-icon-bar.h"
+
+/* This is the size of the border around the icons, for the shadow. */
+#define E_ICON_BAR_LARGE_ICON_SHADOW_BORDER 2
+#define E_ICON_BAR_SMALL_ICON_SHADOW_BORDER 2
+
+/* These are for the horzontal bar when dragging. */
+#define E_ICON_BAR_BG_ITEM_BAR_HEIGHT 1
+#define E_ICON_BAR_BG_ITEM_BAR_OFFSET 2
+#define E_ICON_BAR_BG_ITEM_LARGE_ARROW_HEIGHT 8
+#define E_ICON_BAR_BG_ITEM_SMALL_ARROW_HEIGHT 4
+
+static void e_icon_bar_bg_item_class_init (EIconBarBgItemClass *class);
+static void e_icon_bar_bg_item_init (EIconBarBgItem *ibitem);
+
+static void e_icon_bar_bg_item_set_arg (GtkObject *o, GtkArg *arg,
+ guint arg_id);
+static void e_icon_bar_bg_item_update (GnomeCanvasItem *item,
+ double *affine,
+ ArtSVP *clip_path, int flags);
+static void e_icon_bar_bg_item_draw (GnomeCanvasItem *item,
+ GdkDrawable *drawable,
+ int x, int y,
+ int width, int height);
+static double e_icon_bar_bg_item_point (GnomeCanvasItem *item,
+ double x, double y,
+ int cx, int cy,
+ GnomeCanvasItem **actual_item);
+static gint e_icon_bar_bg_item_event (GnomeCanvasItem *item,
+ GdkEvent *event);
+static gint e_icon_bar_bg_item_button_press (EIconBarBgItem *ibitem,
+ GdkEvent *event);
+static gint e_icon_bar_bg_item_button_release (EIconBarBgItem *ibitem,
+ GdkEvent *event);
+static gint e_icon_bar_bg_item_motion_notify (EIconBarBgItem *ibitem,
+ GdkEvent *event);
+
+static GnomeCanvasItemClass *parent_class;
+
+/* The arguments we take */
+enum {
+ ARG_0,
+ ARG_ICON_BAR
+};
+
+
+GtkType
+e_icon_bar_bg_item_get_type (void)
+{
+ static GtkType e_icon_bar_bg_item_type = 0;
+
+ if (!e_icon_bar_bg_item_type) {
+ GtkTypeInfo e_icon_bar_bg_item_info = {
+ "EIconBarBgItem",
+ sizeof (EIconBarBgItem),
+ sizeof (EIconBarBgItemClass),
+ (GtkClassInitFunc) e_icon_bar_bg_item_class_init,
+ (GtkObjectInitFunc) e_icon_bar_bg_item_init,
+ NULL, /* reserved_1 */
+ NULL, /* reserved_2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ e_icon_bar_bg_item_type = gtk_type_unique (gnome_canvas_item_get_type (), &e_icon_bar_bg_item_info);
+ }
+
+ return e_icon_bar_bg_item_type;
+}
+
+
+static void
+e_icon_bar_bg_item_class_init (EIconBarBgItemClass *class)
+{
+ GtkObjectClass *object_class;
+ GnomeCanvasItemClass *item_class;
+
+ parent_class = gtk_type_class (gnome_canvas_item_get_type());
+
+ object_class = (GtkObjectClass *) class;
+ item_class = (GnomeCanvasItemClass *) class;
+
+ gtk_object_add_arg_type ("EIconBarBgItem::icon_bar",
+ GTK_TYPE_POINTER, GTK_ARG_WRITABLE,
+ ARG_ICON_BAR);
+
+ object_class->set_arg = e_icon_bar_bg_item_set_arg;
+
+ /* GnomeCanvasItem method overrides */
+ item_class->update = e_icon_bar_bg_item_update;
+ item_class->draw = e_icon_bar_bg_item_draw;
+ item_class->point = e_icon_bar_bg_item_point;
+ item_class->event = e_icon_bar_bg_item_event;
+}
+
+
+static void
+e_icon_bar_bg_item_init (EIconBarBgItem *ibitem)
+{
+ GnomeCanvasItem *item = GNOME_CANVAS_ITEM (ibitem);
+
+ ibitem->icon_bar = NULL;
+
+ item->x1 = 0;
+ item->y1 = 0;
+ item->x2 = 0;
+ item->y2 = 0;
+}
+
+
+static void
+e_icon_bar_bg_item_set_arg (GtkObject *o, GtkArg *arg, guint arg_id)
+{
+ GnomeCanvasItem *item;
+ EIconBarBgItem *ibitem;
+
+ item = GNOME_CANVAS_ITEM (o);
+ ibitem = E_ICON_BAR_BG_ITEM (o);
+
+ switch (arg_id){
+ case ARG_ICON_BAR:
+ ibitem->icon_bar = GTK_VALUE_POINTER (*arg);
+ break;
+ }
+}
+
+
+static void
+e_icon_bar_bg_item_update (GnomeCanvasItem *item,
+ double *affine,
+ ArtSVP *clip_path,
+ int flags)
+{
+ if (GNOME_CANVAS_ITEM_CLASS (parent_class)->update)
+ (* GNOME_CANVAS_ITEM_CLASS (parent_class)->update) (item, affine, clip_path, flags);
+
+ /* The grid covers the entire canvas area. */
+ item->x1 = 0;
+ item->y1 = 0;
+ item->x2 = INT_MAX;
+ item->y2 = INT_MAX;
+}
+
+
+/*
+ * DRAWING ROUTINES - functions to paint the canvas item.
+ */
+
+static void
+e_icon_bar_bg_item_draw (GnomeCanvasItem *canvas_item, GdkDrawable *drawable,
+ int x, int y, int width, int height)
+{
+ EIconBar *icon_bar;
+ EIconBarItem *item;
+ EIconBarBgItem *ibitem;
+ GtkStyle *style;
+ GdkGC *gc;
+ GtkShadowType shadow;
+ gint item_num, border, bar_x, bar_y, bar_w, i, arrow_height;
+
+ ibitem = E_ICON_BAR_BG_ITEM (canvas_item);
+ icon_bar = ibitem->icon_bar;
+ g_return_if_fail (icon_bar != NULL);
+ style = GTK_WIDGET (icon_bar)->style;
+
+ /* Draw the highlight around the current highlight item. */
+ item_num = -1;
+ if (icon_bar->editing_item_num == -1) {
+ if (icon_bar->pressed_item_num != -1) {
+ item_num = icon_bar->pressed_item_num;
+ if (icon_bar->pressed_item_num == icon_bar->mouse_over_item_num)
+ shadow = GTK_SHADOW_IN;
+ else
+ shadow = GTK_SHADOW_OUT;
+ } else if (icon_bar->mouse_over_item_num != -1) {
+ item_num = icon_bar->mouse_over_item_num;
+ shadow = GTK_SHADOW_OUT;
+ }
+ }
+
+ if (item_num != -1) {
+ item = &g_array_index (icon_bar->items, EIconBarItem,
+ item_num);
+
+ if (icon_bar->view_type == E_ICON_BAR_LARGE_ICONS)
+ border = E_ICON_BAR_LARGE_ICON_SHADOW_BORDER;
+ else
+ border = E_ICON_BAR_SMALL_ICON_SHADOW_BORDER;
+
+ gtk_draw_shadow (style, drawable, GTK_STATE_NORMAL, shadow,
+ icon_bar->icon_x - border - x,
+ item->icon_y - border - y,
+ icon_bar->icon_w + border * 2 - 1,
+ icon_bar->icon_h + border * 2 - 1);
+ }
+
+ /* Draw the bar between items when dragging, if needed. */
+ if (icon_bar->in_drag && icon_bar->dragging_before_item_num != -1) {
+ if (icon_bar->dragging_before_item_num < icon_bar->items->len) {
+ item = &g_array_index (icon_bar->items, EIconBarItem,
+ icon_bar->dragging_before_item_num);
+ bar_y = 0;
+ } else {
+ /* We need to draw the bar after the last item. */
+ item = &g_array_index (icon_bar->items, EIconBarItem,
+ icon_bar->items->len - 1);
+ bar_y = item->item_height + icon_bar->spacing;
+ }
+
+ if (icon_bar->view_type == E_ICON_BAR_LARGE_ICONS) {
+ bar_y += item->icon_y;
+ } else {
+ bar_y += MIN (item->icon_y, item->text_y);
+ }
+ bar_y -= y + icon_bar->spacing / 2;
+
+ bar_x = E_ICON_BAR_BG_ITEM_BAR_OFFSET - x;
+ bar_w = GTK_WIDGET (icon_bar)->allocation.width - 2 * E_ICON_BAR_BG_ITEM_BAR_OFFSET - 1;
+
+ gc = GTK_WIDGET (icon_bar)->style->fg_gc[GTK_STATE_NORMAL];
+
+ /* Draw the horizontal bar. */
+ gdk_draw_rectangle (drawable, gc, TRUE,
+ bar_x, bar_y,
+ bar_w, E_ICON_BAR_BG_ITEM_BAR_HEIGHT);
+
+ if (icon_bar->view_type == E_ICON_BAR_LARGE_ICONS)
+ arrow_height = E_ICON_BAR_BG_ITEM_LARGE_ARROW_HEIGHT / 2;
+ else
+ arrow_height = E_ICON_BAR_BG_ITEM_SMALL_ARROW_HEIGHT / 2;
+
+ /* Draw the arrows at the end of the lines. We use
+ gdk_draw_line() to draw a series of vertical lines, since
+ gdk_draw_polygon() produces odd results. */
+ i = 0;
+ while (arrow_height > 0) {
+ gdk_draw_line (drawable, gc,
+ bar_x + i,
+ bar_y - arrow_height,
+ bar_x + i,
+ bar_y + arrow_height);
+ gdk_draw_line (drawable, gc,
+ bar_x + bar_w - i - 1,
+ bar_y - arrow_height,
+ bar_x + bar_w - i - 1,
+ bar_y + arrow_height);
+ arrow_height--;
+ i++;
+ }
+ }
+}
+
+
+/* This is supposed to return the nearest item the the point and the distance.
+ Since we are the only item we just return ourself and 0 for the distance.
+ This is needed so that we get button/motion events. */
+static double
+e_icon_bar_bg_item_point (GnomeCanvasItem *item, double x, double y,
+ int cx, int cy,
+ GnomeCanvasItem **actual_item)
+{
+ *actual_item = item;
+ return 0.0;
+}
+
+
+static gint
+e_icon_bar_bg_item_event (GnomeCanvasItem *item, GdkEvent *event)
+{
+ EIconBarBgItem *ibitem;
+
+ ibitem = E_ICON_BAR_BG_ITEM (item);
+
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ return e_icon_bar_bg_item_button_press (ibitem, event);
+ case GDK_BUTTON_RELEASE:
+ return e_icon_bar_bg_item_button_release (ibitem, event);
+ case GDK_MOTION_NOTIFY:
+ return e_icon_bar_bg_item_motion_notify (ibitem, event);
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+
+static gint
+e_icon_bar_bg_item_button_press (EIconBarBgItem *ibitem,
+ GdkEvent *event)
+{
+ gint item_num;
+
+ item_num = e_icon_bar_find_item_at_position (ibitem->icon_bar,
+ event->button.x,
+ event->button.y,
+ NULL);
+ e_icon_bar_item_pressed (ibitem->icon_bar, item_num, event);
+ return TRUE;
+}
+
+
+static gint
+e_icon_bar_bg_item_button_release (EIconBarBgItem *ibitem,
+ GdkEvent *event)
+{
+ gint item_num;
+
+ item_num = e_icon_bar_find_item_at_position (ibitem->icon_bar,
+ event->button.x,
+ event->button.y,
+ NULL);
+ e_icon_bar_item_released (ibitem->icon_bar, item_num, event);
+ return TRUE;
+}
+
+
+static gint
+e_icon_bar_bg_item_motion_notify (EIconBarBgItem *ibitem,
+ GdkEvent *event)
+{
+ gint item_num;
+
+ item_num = e_icon_bar_find_item_at_position (ibitem->icon_bar,
+ event->motion.x,
+ event->motion.y,
+ NULL);
+ e_icon_bar_item_motion (ibitem->icon_bar, item_num, event);
+ return TRUE;
+}
diff --git a/widgets/shortcut-bar/e-icon-bar-bg-item.h b/widgets/shortcut-bar/e-icon-bar-bg-item.h
new file mode 100644
index 0000000000..ae25e987d7
--- /dev/null
+++ b/widgets/shortcut-bar/e-icon-bar-bg-item.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Author :
+ * Damon Chaplin <damon@gtk.org>
+ *
+ * Copyright 1999, Helix Code, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ * EIconBarBgItem - A GnomeCanvasItem which covers the entire EIconBar.
+ * It paints the rectangles around items when the mouse moves over them, and
+ * the lines between items when dragging.
+ */
+
+#ifndef _E_ICON_BAR_BG_ITEM_H_
+#define _E_ICON_BAR_BG_ITEM_H_
+
+#include <libgnomeui/gnome-canvas.h>
+
+#include "e-icon-bar.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define E_ICON_BAR_BG_ITEM(obj) (GTK_CHECK_CAST((obj), e_icon_bar_bg_item_get_type (), EIconBarBgItem))
+#define E_ICON_BAR_BG_ITEM_CLASS(k) (GTK_CHECK_CLASS_CAST ((k), e_icon_bar_bg_item_get_type (), EIconBarBgItemClass))
+#define E_IS_ICON_BAR_BG_ITEM(o) (GTK_CHECK_TYPE((o), e_icon_bar_bg_item_get_type ()))
+
+
+typedef struct _EIconBarBgItem EIconBarBgItem;
+typedef struct _EIconBarBgItemClass EIconBarBgItemClass;
+
+struct _EIconBarBgItem
+{
+ GnomeCanvasItem canvas_item;
+
+ /* The parent EIconBar widget. */
+ EIconBar *icon_bar;
+};
+
+
+struct _EIconBarBgItemClass
+{
+ GnomeCanvasItemClass parent_class;
+};
+
+GtkType e_icon_bar_bg_item_get_type (void);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _E_ICON_BAR_BG_ITEM_H_ */
diff --git a/widgets/shortcut-bar/e-icon-bar-text-item.c b/widgets/shortcut-bar/e-icon-bar-text-item.c
new file mode 100644
index 0000000000..5548c630b3
--- /dev/null
+++ b/widgets/shortcut-bar/e-icon-bar-text-item.c
@@ -0,0 +1,1696 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Author :
+ * Damon Chaplin <damon@gtk.org>
+ *
+ * Copyright 1999, Helix Code, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ * Based on gnome-icon-text-item: an editable text block with word wrapping
+ * for the GNOME canvas.
+ *
+ * Copyright (C) 1998, 1999 The Free Software Foundation
+ *
+ * Authors: Miguel de Icaza <miguel@gnu.org>
+ * Federico Mena <federico@gimp.org>
+ */
+
+/*
+ * EIconBarTextItem - An editable canvas text item for the EIconBar.
+ */
+
+#include <math.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtkmain.h>
+#include <gtk/gtksignal.h>
+#include <gtk/gtkwindow.h>
+#include <libgnome/gnome-defs.h>
+#include <libgnome/gnome-i18n.h>
+
+#include "e-icon-bar-text-item.h"
+
+
+/* Margins used to display the information */
+#define MARGIN_X 2
+#define MARGIN_Y 2
+
+/* Default fontset to be used if the user specified fontset is not found */
+#define DEFAULT_FONT_NAME "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*," \
+ "-*-*-medium-r-normal--10-*-*-*-*-*-*-*,*"
+
+/* Separators for text layout */
+#define DEFAULT_SEPARATORS " \t-.[]#"
+
+/* This is the string to draw when the text is clipped, e.g. '...'. */
+static gchar *e_icon_bar_text_item_ellipsis;
+
+/* Aliases to minimize screen use in my laptop */
+#define ITI(x) E_ICON_BAR_TEXT_ITEM (x)
+#define ITI_CLASS(x) E_ICON_BAR_TEXT_ITEM_CLASS (x)
+#define IS_ITI(x) E_IS_ICON_BAR_TEXT_ITEM (x)
+
+
+typedef EIconBarTextItem Iti;
+
+/* Private part of the EIconBarTextItem structure */
+typedef struct {
+ /* Font */
+ GdkFont *font;
+
+ /* Hack: create an offscreen window and place an entry inside it */
+ GtkEntry *entry;
+ GtkWidget *entry_top;
+
+ /* Whether the user pressed the mouse while the item was unselected */
+ guint unselected_click : 1;
+
+ /* Whether we need to update the position */
+ guint need_pos_update : 1;
+
+ /* Whether we need to update the font */
+ guint need_font_update : 1;
+
+ /* Whether we need to update the text */
+ guint need_text_update : 1;
+
+ /* Whether we need to update because the editing/selected state changed */
+ guint need_state_update : 1;
+} ItiPrivate;
+
+typedef struct _EIconBarTextItemInfoRow EIconBarTextItemInfoRow;
+
+struct _EIconBarTextItemInfoRow {
+ gchar *text;
+ gint width;
+ GdkWChar *text_wc; /* text in wide characters */
+ gint text_length; /* number of characters */
+};
+
+struct _EIconBarTextItemInfo {
+ GList *rows;
+ GdkFont *font;
+ gint width;
+ gint height;
+ gint baseline_skip;
+};
+
+static GnomeCanvasItemClass *parent_class;
+
+enum {
+ ARG_0,
+ ARG_XALIGN,
+ ARG_JUSTIFY,
+ ARG_MAX_LINES,
+ ARG_SHOW_ELLIPSIS
+};
+
+enum {
+ TEXT_CHANGED,
+ HEIGHT_CHANGED,
+ WIDTH_CHANGED,
+ EDITING_STARTED,
+ EDITING_STOPPED,
+ SELECTION_STARTED,
+ SELECTION_STOPPED,
+ LAST_SIGNAL
+};
+
+static guint iti_signals [LAST_SIGNAL] = { 0 };
+
+static GdkFont *default_font;
+
+static void e_icon_bar_text_item_free_info (EIconBarTextItemInfo *ti);
+static EIconBarTextItemInfo *e_icon_bar_text_item_layout_text (EIconBarTextItem *iti, GdkFont *font, const gchar *text, const gchar *separators, gint max_width, gboolean confine);
+static void e_icon_bar_text_item_paint_text (EIconBarTextItem *iti,
+ EIconBarTextItemInfo *ti,
+ GdkDrawable *drawable,
+ GdkGC *gc,
+ gint x,
+ gint y,
+ GtkJustification just);
+
+
+/* Stops the editing state of an icon text item */
+static void
+iti_stop_editing (Iti *iti)
+{
+ ItiPrivate *priv;
+
+ priv = iti->priv;
+
+ iti->editing = FALSE;
+
+ gtk_widget_destroy (priv->entry_top);
+ priv->entry = NULL;
+ priv->entry_top = NULL;
+
+ priv->need_state_update = TRUE;
+ gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (iti));
+
+ gtk_signal_emit (GTK_OBJECT (iti), iti_signals[EDITING_STOPPED]);
+}
+
+/* Lays out the text in an icon item */
+static void
+layout_text (Iti *iti)
+{
+ ItiPrivate *priv;
+ char *text;
+ int old_width, old_height;
+ int width, height;
+
+ priv = iti->priv;
+
+ /* Save old size */
+
+ if (iti->ti) {
+ old_width = iti->ti->width + 2 * MARGIN_X;
+ old_height = iti->ti->height + 2 * MARGIN_Y;
+
+ e_icon_bar_text_item_free_info (iti->ti);
+ } else {
+ old_width = 2 * MARGIN_X;
+ old_height = 2 * MARGIN_Y;
+ }
+
+ /* Change the text layout */
+
+ if (iti->editing)
+ text = gtk_entry_get_text (priv->entry);
+ else
+ text = iti->text;
+
+ iti->ti = e_icon_bar_text_item_layout_text (iti, priv->font,
+ text,
+ DEFAULT_SEPARATORS,
+ iti->width - 2 * MARGIN_X,
+ TRUE);
+
+ /* Check the sizes and see if we need to emit any signals */
+
+ width = iti->ti->width + 2 * MARGIN_X;
+ height = iti->ti->height + 2 * MARGIN_Y;
+
+ if (width != old_width)
+ gtk_signal_emit (GTK_OBJECT (iti), iti_signals[WIDTH_CHANGED]);
+
+ if (height != old_height)
+ gtk_signal_emit (GTK_OBJECT (iti), iti_signals[HEIGHT_CHANGED]);
+}
+
+/* Accepts the text in the off-screen entry of an icon text item */
+static void
+iti_edition_accept (Iti *iti)
+{
+ ItiPrivate *priv;
+ gboolean accept;
+
+ priv = iti->priv;
+ accept = TRUE;
+
+ gtk_signal_emit (GTK_OBJECT (iti), iti_signals [TEXT_CHANGED], &accept);
+
+ if (iti->editing){
+ if (accept) {
+ if (iti->is_text_allocated)
+ g_free (iti->text);
+
+ iti->text = g_strdup (gtk_entry_get_text (priv->entry));
+ iti->is_text_allocated = 1;
+ }
+
+ iti_stop_editing (iti);
+ }
+
+ priv->need_text_update = TRUE;
+ gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (iti));
+}
+
+/* Callback used when the off-screen entry of an icon text item is activated.
+ * When this happens, we have to accept edition.
+ */
+static void
+iti_entry_activate (GtkWidget *entry, Iti *iti)
+{
+ iti_edition_accept (iti);
+}
+
+/* Starts the editing state of an icon text item */
+static void
+iti_start_editing (Iti *iti)
+{
+ ItiPrivate *priv;
+
+ priv = iti->priv;
+
+ if (iti->editing)
+ return;
+
+ /* Trick: The actual edition of the entry takes place in a GtkEntry
+ * which is placed offscreen. That way we get all of the advantages
+ * from GtkEntry without duplicating code. Yes, this is a hack.
+ */
+ priv->entry = (GtkEntry *) gtk_entry_new ();
+ gtk_entry_set_text (priv->entry, iti->text);
+ gtk_signal_connect (GTK_OBJECT (priv->entry), "activate",
+ GTK_SIGNAL_FUNC (iti_entry_activate), iti);
+
+ priv->entry_top = gtk_window_new (GTK_WINDOW_POPUP);
+ gtk_container_add (GTK_CONTAINER (priv->entry_top), GTK_WIDGET (priv->entry));
+ gtk_widget_set_uposition (priv->entry_top, 20000, 20000);
+ gtk_widget_show_all (priv->entry_top);
+
+ gtk_editable_select_region (GTK_EDITABLE (priv->entry), 0, -1);
+
+ iti->editing = TRUE;
+
+ priv->need_text_update = TRUE;
+ priv->need_state_update = TRUE;
+ gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (iti));
+
+ gtk_signal_emit (GTK_OBJECT (iti), iti_signals[EDITING_STARTED]);
+}
+
+/* Destroy method handler for the icon text item */
+static void
+iti_destroy (GtkObject *object)
+{
+ Iti *iti;
+ ItiPrivate *priv;
+ GnomeCanvasItem *item;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (IS_ITI (object));
+
+ iti = ITI (object);
+ priv = iti->priv;
+ item = GNOME_CANVAS_ITEM (object);
+
+ /* FIXME: stop selection and editing */
+
+ /* Queue redraw of bounding box */
+
+ gnome_canvas_request_redraw (item->canvas, item->x1, item->y1, item->x2, item->y2);
+
+ /* Free everything */
+
+ if (iti->fontname)
+ g_free (iti->fontname);
+
+ if (iti->text && iti->is_text_allocated)
+ g_free (iti->text);
+
+ if (iti->ti)
+ e_icon_bar_text_item_free_info (iti->ti);
+
+ if (priv->font)
+ gdk_font_unref (priv->font);
+
+ if (priv->entry_top)
+ gtk_widget_destroy (priv->entry_top);
+
+ g_free (priv);
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+/* set_arg handler for the icon text item */
+static void
+iti_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
+{
+ Iti *iti;
+ GnomeCanvasItem *item;
+ ItiPrivate *priv;
+ gfloat xalign;
+ gint max_lines;
+ gboolean show_ellipsis;
+ GtkJustification justification;
+
+ iti = ITI (object);
+ item = GNOME_CANVAS_ITEM (object);
+ priv = iti->priv;
+
+ switch (arg_id) {
+ case ARG_XALIGN:
+ xalign = GTK_VALUE_FLOAT (*arg);
+ if (iti->xalign != xalign) {
+ iti->xalign = xalign;
+ priv->need_pos_update = TRUE;
+ gnome_canvas_item_request_update (item);
+ }
+ break;
+ case ARG_JUSTIFY:
+ justification = GTK_VALUE_ENUM (*arg);
+ if (iti->justification != justification) {
+ iti->justification = justification;
+ priv->need_text_update = TRUE;
+ gnome_canvas_item_request_update (item);
+ }
+ break;
+ case ARG_MAX_LINES:
+ max_lines = GTK_VALUE_INT (*arg);
+ if (iti->max_lines != max_lines) {
+ iti->max_lines = max_lines;
+ priv->need_text_update = TRUE;
+ gnome_canvas_item_request_update (item);
+ }
+ break;
+ case ARG_SHOW_ELLIPSIS:
+ show_ellipsis = GTK_VALUE_BOOL (*arg);
+ if (iti->show_ellipsis != show_ellipsis) {
+ iti->show_ellipsis = show_ellipsis;
+ priv->need_text_update = TRUE;
+ gnome_canvas_item_request_update (item);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+iti_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
+{
+ Iti *iti;
+ ItiPrivate *priv;
+
+ iti = ITI (object);
+ priv = iti->priv;
+
+ switch (arg_id) {
+ case ARG_XALIGN:
+ GTK_VALUE_FLOAT (*arg) = iti->xalign;
+ break;
+ case ARG_JUSTIFY:
+ GTK_VALUE_ENUM (*arg) = iti->justification;
+ break;
+ case ARG_MAX_LINES:
+ GTK_VALUE_INT (*arg) = iti->max_lines;
+ break;
+ case ARG_SHOW_ELLIPSIS:
+ GTK_VALUE_BOOL (*arg) = iti->show_ellipsis;
+ break;
+ default:
+ arg->type = GTK_TYPE_INVALID;
+ break;
+ }
+}
+
+/* Loads the default font for icon text items if necessary */
+static GdkFont *
+get_default_font (void)
+{
+ if (!default_font) {
+ /* FIXME: this is never unref-ed */
+ default_font = gdk_fontset_load (DEFAULT_FONT_NAME);
+ g_assert (default_font != NULL);
+ }
+
+ return gdk_font_ref (default_font);
+}
+
+/* Recomputes the bounding box of an icon text item */
+static void
+recompute_bounding_box (Iti *iti)
+{
+ GnomeCanvasItem *item;
+ double affine[6];
+ ArtPoint p, q;
+ int x1, y1, x2, y2;
+ int width, height;
+
+ item = GNOME_CANVAS_ITEM (iti);
+
+ /* Compute width, height, position */
+
+ width = iti->ti->width + 2 * MARGIN_X;
+ height = iti->ti->height + 2 * MARGIN_Y;
+
+ x1 = iti->x + (iti->width - width) * iti->xalign;
+ y1 = iti->y;
+ x2 = x1 + width;
+ y2 = y1 + height;
+
+ /* Translate to world coordinates */
+
+ gnome_canvas_item_i2w_affine (item, affine);
+
+ p.x = x1;
+ p.y = y1;
+ art_affine_point (&q, &p, affine);
+ item->x1 = q.x;
+ item->y1 = q.y;
+
+ p.x = x2;
+ p.y = y2;
+ art_affine_point (&q, &p, affine);
+ item->x2 = q.x;
+ item->y2 = q.y;
+}
+
+/* Update method for the icon text item */
+static void
+iti_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
+{
+ Iti *iti;
+ ItiPrivate *priv;
+
+ iti = ITI (item);
+ priv = iti->priv;
+
+ if (parent_class->update)
+ (* parent_class->update) (item, affine, clip_path, flags);
+
+ /* If necessary, queue a redraw of the old bounding box */
+
+ if ((flags & GNOME_CANVAS_UPDATE_VISIBILITY)
+ || (flags & GNOME_CANVAS_UPDATE_AFFINE)
+ || priv->need_pos_update
+ || priv->need_font_update
+ || priv->need_text_update)
+ gnome_canvas_request_redraw (item->canvas, item->x1, item->y1, item->x2, item->y2);
+
+ if (priv->need_text_update)
+ layout_text (iti);
+
+ /* Compute new bounds */
+
+ if (priv->need_pos_update
+ || priv->need_font_update
+ || priv->need_text_update)
+ recompute_bounding_box (iti);
+
+ /* Queue redraw */
+
+ gnome_canvas_request_redraw (item->canvas, item->x1, item->y1, item->x2, item->y2);
+
+ priv->need_pos_update = FALSE;
+ priv->need_font_update = FALSE;
+ priv->need_text_update = FALSE;
+ priv->need_state_update = FALSE;
+}
+
+/* Draw the icon text item's text when it is being edited */
+static void
+iti_paint_text (Iti *iti, GdkDrawable *drawable, int x, int y)
+{
+ ItiPrivate *priv;
+ EIconBarTextItemInfoRow *row;
+ EIconBarTextItemInfo *ti;
+ GtkStyle *style;
+ GdkGC *fg_gc, *bg_gc;
+ GdkGC *gc, *bgc, *sgc, *bsgc;
+ GList *item;
+ int xpos, len;
+
+ priv = iti->priv;
+ style = GTK_WIDGET (GNOME_CANVAS_ITEM (iti)->canvas)->style;
+
+ ti = iti->ti;
+ len = 0;
+ y += ti->font->ascent;
+
+ /*
+ * Pointers to all of the GCs we use
+ */
+ gc = style->black_gc;
+ bgc = style->white_gc;
+ sgc = style->fg_gc [GTK_STATE_SELECTED];
+ bsgc = style->bg_gc [GTK_STATE_SELECTED];
+
+ for (item = ti->rows; item; item = item->next, len += (row ? row->text_length : 0)) {
+ GdkWChar *text_wc;
+ int text_length;
+ int cursor, offset, i;
+ int sel_start, sel_end;
+
+ row = item->data;
+
+ if (!row) {
+ y += ti->baseline_skip;
+ continue;
+ }
+
+ text_wc = row->text_wc;
+ text_length = row->text_length;
+
+ switch (iti->justification) {
+ case GTK_JUSTIFY_LEFT:
+ xpos = 0;
+ break;
+
+ case GTK_JUSTIFY_RIGHT:
+ xpos = ti->width - row->width;
+ break;
+
+ case GTK_JUSTIFY_CENTER:
+ xpos = (ti->width - row->width) / 2;
+ break;
+
+ default:
+ /* Anyone care to implement GTK_JUSTIFY_FILL? */
+ g_warning ("Justification type %d not supported. Using left-justification.",
+ (int) iti->justification);
+ xpos = 0;
+ }
+
+ sel_start = GTK_EDITABLE (priv->entry)->selection_start_pos - len;
+ sel_end = GTK_EDITABLE (priv->entry)->selection_end_pos - len;
+ offset = 0;
+ cursor = GTK_EDITABLE (priv->entry)->current_pos - len;
+
+ for (i = 0; *text_wc; text_wc++, i++) {
+ int size, px;
+
+ size = gdk_text_width_wc (ti->font, text_wc, 1);
+
+ if (i >= sel_start && i < sel_end) {
+ fg_gc = sgc;
+ bg_gc = bsgc;
+ } else {
+ fg_gc = gc;
+ bg_gc = bgc;
+ }
+
+ px = x + xpos + offset;
+ gdk_draw_rectangle (drawable,
+ bg_gc,
+ TRUE,
+ px,
+ y - ti->font->ascent,
+ size, ti->baseline_skip);
+
+ gdk_draw_text_wc (drawable,
+ ti->font,
+ fg_gc,
+ px, y,
+ text_wc, 1);
+
+ if (cursor == i)
+ gdk_draw_line (drawable,
+ gc,
+ px - 1,
+ y - ti->font->ascent,
+ px - 1,
+ y + ti->font->descent - 1);
+
+ offset += size;
+ }
+
+ if (cursor == i) {
+ int px = x + xpos + offset;
+
+ gdk_draw_line (drawable,
+ gc,
+ px - 1,
+ y - ti->font->ascent,
+ px - 1,
+ y + ti->font->descent - 1);
+ }
+
+ y += ti->baseline_skip;
+ }
+}
+
+/* Draw method handler for the icon text item */
+static void
+iti_draw (GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height)
+{
+ Iti *iti;
+ GtkStyle *style;
+ int w, h;
+ int xofs, yofs;
+
+ iti = ITI (item);
+
+ if (iti->ti) {
+ w = iti->ti->width + 2 * MARGIN_X;
+ h = iti->ti->height + 2 * MARGIN_Y;
+ } else {
+ w = 2 * MARGIN_X;
+ h = 2 * MARGIN_Y;
+ }
+
+ xofs = item->x1 - x;
+ yofs = item->y1 - y;
+
+ style = GTK_WIDGET (item->canvas)->style;
+
+ if (iti->selected && !iti->editing)
+ gdk_draw_rectangle (drawable,
+ style->bg_gc[GTK_STATE_SELECTED],
+ TRUE,
+ xofs, yofs,
+ w, h);
+
+ if (iti->editing) {
+ gdk_draw_rectangle (drawable,
+ style->white_gc,
+ TRUE,
+ xofs + 1, yofs + 1,
+ w - 2, h - 2);
+ gdk_draw_rectangle (drawable,
+ style->black_gc,
+ FALSE,
+ xofs, yofs,
+ w - 1, h - 1);
+
+ iti_paint_text (iti, drawable, xofs + MARGIN_X, yofs + MARGIN_Y);
+ } else
+ e_icon_bar_text_item_paint_text (iti, iti->ti,
+ drawable,
+ style->fg_gc[(iti->selected
+ ? GTK_STATE_SELECTED
+ : GTK_STATE_NORMAL)],
+ xofs + MARGIN_X,
+ yofs + MARGIN_Y,
+ iti->justification);
+}
+
+/* Point method handler for the icon text item */
+static double
+iti_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item)
+{
+ double dx, dy;
+
+ *actual_item = item;
+
+ if (cx < item->x1)
+ dx = item->x1 - cx;
+ else if (cx > item->x2)
+ dx = cx - item->x2;
+ else
+ dx = 0.0;
+
+ if (cy < item->y1)
+ dy = item->y1 - cy;
+ else if (cy > item->y2)
+ dy = cy - item->y2;
+ else
+ dy = 0.0;
+
+ return sqrt (dx * dx + dy * dy);
+}
+
+/* Given X, Y, a mouse position, return a valid index inside the edited text */
+static int
+iti_idx_from_x_y (Iti *iti, int x, int y)
+{
+ ItiPrivate *priv;
+ EIconBarTextItemInfoRow *row;
+ int lines;
+ int line, col, i, idx;
+ GList *l;
+
+ priv = iti->priv;
+
+ if (iti->ti->rows == NULL)
+ return 0;
+
+ lines = g_list_length (iti->ti->rows);
+ line = y / iti->ti->baseline_skip;
+
+ if (line < 0)
+ line = 0;
+ else if (lines < line + 1)
+ line = lines - 1;
+
+ /* Compute the base index for this line */
+ for (l = iti->ti->rows, idx = i = 0; i < line; l = l->next, i++) {
+ row = l->data;
+ idx += row->text_length;
+ }
+
+ row = g_list_nth (iti->ti->rows, line)->data;
+ col = 0;
+ if (row != NULL) {
+ int first_char;
+ int last_char;
+
+ first_char = (iti->ti->width - row->width) / 2;
+ last_char = first_char + row->width;
+
+ if (x < first_char) {
+ /* nothing */
+ } else if (x > last_char) {
+ col = row->text_length;
+ } else {
+ GdkWChar *s = row->text_wc;
+ int pos = first_char;
+
+ while (pos < last_char) {
+ pos += gdk_text_width_wc (iti->ti->font, s, 1);
+ if (pos > x)
+ break;
+ col++;
+ s++;
+ }
+ }
+ }
+
+ idx += col;
+
+ g_assert (idx <= priv->entry->text_size);
+
+ return idx;
+}
+
+/* Starts the selection state in the icon text item */
+static void
+iti_start_selecting (Iti *iti, int idx, guint32 event_time)
+{
+ ItiPrivate *priv;
+ GtkEditable *e;
+ GdkCursor *ibeam;
+
+ priv = iti->priv;
+ e = GTK_EDITABLE (priv->entry);
+
+ gtk_editable_select_region (e, idx, idx);
+ gtk_editable_set_position (e, idx);
+ ibeam = gdk_cursor_new (GDK_XTERM);
+ gnome_canvas_item_grab (GNOME_CANVAS_ITEM (iti),
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_POINTER_MOTION_MASK,
+ ibeam, event_time);
+ gdk_cursor_destroy (ibeam);
+
+ gtk_editable_select_region (e, idx, idx);
+ e->current_pos = e->selection_start_pos;
+ e->has_selection = TRUE;
+ iti->selecting = TRUE;
+
+ priv->need_state_update = TRUE;
+ gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (iti));
+
+ gtk_signal_emit (GTK_OBJECT (iti), iti_signals[SELECTION_STARTED]);
+}
+
+/* Stops the selection state in the icon text item */
+static void
+iti_stop_selecting (Iti *iti, guint32 event_time)
+{
+ ItiPrivate *priv;
+ GnomeCanvasItem *item;
+ GtkEditable *e;
+
+ priv = iti->priv;
+ item = GNOME_CANVAS_ITEM (iti);
+ e = GTK_EDITABLE (priv->entry);
+
+ gnome_canvas_item_ungrab (item, event_time);
+ e->has_selection = FALSE;
+ iti->selecting = FALSE;
+
+ priv->need_state_update = TRUE;
+ gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (iti));
+ gtk_signal_emit (GTK_OBJECT (iti), iti_signals[SELECTION_STOPPED]);
+}
+
+/* Handles selection range changes on the icon text item */
+static void
+iti_selection_motion (Iti *iti, int idx)
+{
+ ItiPrivate *priv;
+ GtkEditable *e;
+
+ priv = iti->priv;
+ e = GTK_EDITABLE (priv->entry);
+
+ if (idx < e->current_pos) {
+ e->selection_start_pos = idx;
+ e->selection_end_pos = e->current_pos;
+ } else {
+ e->selection_start_pos = e->current_pos;
+ e->selection_end_pos = idx;
+ }
+
+ priv->need_state_update = TRUE;
+ gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (iti));
+}
+
+/* Event handler for icon text items */
+static gint
+iti_event (GnomeCanvasItem *item, GdkEvent *event)
+{
+ Iti *iti;
+ ItiPrivate *priv;
+ int idx;
+ double x, y;
+
+ iti = ITI (item);
+ priv = iti->priv;
+
+ switch (event->type) {
+ case GDK_KEY_PRESS:
+ if (!iti->editing)
+ break;
+
+ if (event->key.keyval == GDK_Escape)
+ iti_stop_editing (iti);
+ else
+ gtk_widget_event (GTK_WIDGET (priv->entry), event);
+
+ priv->need_text_update = TRUE;
+ gnome_canvas_item_request_update (item);
+ return TRUE;
+
+ case GDK_BUTTON_PRESS:
+ if (!iti->editing)
+ break;
+
+ if (iti->editing && event->button.button == 1) {
+ x = event->button.x - (item->x1 + MARGIN_X);
+ y = event->button.y - (item->y1 + MARGIN_Y);
+ idx = iti_idx_from_x_y (iti, x, y);
+
+ iti_start_selecting (iti, idx, event->button.time);
+ }
+
+ return TRUE;
+
+ case GDK_MOTION_NOTIFY:
+ if (!iti->selecting)
+ break;
+
+ x = event->motion.x - (item->x1 + MARGIN_X);
+ y = event->motion.y - (item->y1 + MARGIN_Y);
+ idx = iti_idx_from_x_y (iti, x, y);
+ iti_selection_motion (iti, idx);
+ return TRUE;
+
+ case GDK_BUTTON_RELEASE:
+ if (iti->selecting && event->button.button == 1)
+ iti_stop_selecting (iti, event->button.time);
+ else
+ break;
+
+ return TRUE;
+
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+/* Bounds method handler for the icon text item */
+static void
+iti_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
+{
+ Iti *iti;
+ ItiPrivate *priv;
+ int width, height;
+
+ iti = ITI (item);
+ priv = iti->priv;
+
+ if (priv->need_text_update) {
+ layout_text (iti);
+ priv->need_text_update = FALSE;
+ }
+
+ if (iti->ti) {
+ width = iti->ti->width + 2 * MARGIN_X;
+ height = iti->ti->height + 2 * MARGIN_Y;
+ } else {
+ width = 2 * MARGIN_X;
+ height = 2 * MARGIN_Y;
+ }
+
+ *x1 = iti->x + (iti->width - width) * iti->xalign;
+ *y1 = iti->y;
+ *x2 = *x1 + width;
+ *y2 = *y1 + height;
+}
+
+/* Class initialization function for the icon text item */
+static void
+iti_class_init (EIconBarTextItemClass *text_item_class)
+{
+ GtkObjectClass *object_class;
+ GnomeCanvasItemClass *item_class;
+
+ object_class = (GtkObjectClass *) text_item_class;
+ item_class = (GnomeCanvasItemClass *) text_item_class;
+
+ parent_class = gtk_type_class (gnome_canvas_item_get_type ());
+
+ gtk_object_add_arg_type ("EIconBarTextItem::xalign", GTK_TYPE_FLOAT, GTK_ARG_READWRITE, ARG_XALIGN);
+ gtk_object_add_arg_type ("EIconBarTextItem::justify", GTK_TYPE_JUSTIFICATION, GTK_ARG_READWRITE, ARG_JUSTIFY);
+ gtk_object_add_arg_type ("EIconBarTextItem::max_lines", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_MAX_LINES);
+ gtk_object_add_arg_type ("EIconBarTextItem::show_ellipsis", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SHOW_ELLIPSIS);
+
+ iti_signals [TEXT_CHANGED] =
+ gtk_signal_new (
+ "text_changed",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EIconBarTextItemClass, text_changed),
+ gtk_marshal_BOOL__NONE,
+ GTK_TYPE_BOOL, 0);
+
+ iti_signals [HEIGHT_CHANGED] =
+ gtk_signal_new (
+ "height_changed",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EIconBarTextItemClass, height_changed),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ iti_signals [WIDTH_CHANGED] =
+ gtk_signal_new (
+ "width_changed",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EIconBarTextItemClass, width_changed),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ iti_signals[EDITING_STARTED] =
+ gtk_signal_new (
+ "editing_started",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EIconBarTextItemClass, editing_started),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ iti_signals[EDITING_STOPPED] =
+ gtk_signal_new (
+ "editing_stopped",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EIconBarTextItemClass, editing_stopped),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ iti_signals[SELECTION_STARTED] =
+ gtk_signal_new (
+ "selection_started",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EIconBarTextItemClass, selection_started),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ iti_signals[SELECTION_STOPPED] =
+ gtk_signal_new (
+ "selection_stopped",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EIconBarTextItemClass, selection_stopped),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (object_class, iti_signals, LAST_SIGNAL);
+
+ object_class->destroy = iti_destroy;
+ object_class->get_arg = iti_get_arg;
+ object_class->set_arg = iti_set_arg;
+
+ item_class->update = iti_update;
+ item_class->draw = iti_draw;
+ item_class->point = iti_point;
+ item_class->bounds = iti_bounds;
+ item_class->event = iti_event;
+
+ e_icon_bar_text_item_ellipsis = _("...");
+}
+
+/* Object initialization function for the icon text item */
+static void
+iti_init (EIconBarTextItem *iti)
+{
+ ItiPrivate *priv;
+
+ priv = g_new0 (ItiPrivate, 1);
+ iti->priv = priv;
+
+ iti->xalign = 0.5;
+ iti->justification = GTK_JUSTIFY_CENTER;
+ iti->max_lines = -1;
+ iti->show_ellipsis = TRUE;
+}
+
+/**
+ * e_icon_bar_text_item_configure:
+ * @iti: An #EIconBarTextItem.
+ * @x: X position in which to place the item.
+ * @y: Y position in which to place the item.
+ * @width: Maximum width allowed for this item, to be used for word wrapping.
+ * @fontname: Name of the fontset that should be used to display the text.
+ * @text: Text that is going to be displayed.
+ * @is_static: Whether @text points to a static string or not.
+ *
+ * This routine is used to configure an #EIconBarTextItem.
+ *
+ * @x and @y specify the coordinates where the item is placed in the canvas.
+ * The @x coordinate should be the leftmost position that the item can
+ * assume at any one time, that is, the left margin of the column in which the
+ * icon is to be placed. The @y coordinate specifies the top of the item.
+ *
+ * @width is the maximum width allowed for this icon text item. The coordinates
+ * define the upper-left corner of an item with maximum width; this may
+ * actually be outside the bounding box of the item if the text is narrower
+ * than the maximum width.
+ *
+ * If @is_static is true, it means that there is no need for the item to
+ * allocate memory for the string (it is a guarantee that the text is allocated
+ * by the caller and it will not be deallocated during the lifetime of this
+ * item). This is an optimization to reduce memory usage for large icon sets.
+ */
+void
+e_icon_bar_text_item_configure (EIconBarTextItem *iti, int x, int y,
+ int width, const char *fontname,
+ const char *text,
+ gboolean is_static)
+{
+ ItiPrivate *priv;
+
+ g_return_if_fail (iti != NULL);
+ g_return_if_fail (IS_ITI (iti));
+ g_return_if_fail (width > 2 * MARGIN_X);
+ g_return_if_fail (text != NULL);
+
+ priv = iti->priv;
+
+ iti->x = x;
+ iti->y = y;
+ iti->width = width;
+
+ if (iti->text && iti->is_text_allocated)
+ g_free (iti->text);
+
+ iti->is_text_allocated = !is_static;
+
+ /* This cast is to shut up the compiler */
+ if (is_static)
+ iti->text = (char *) text;
+ else
+ iti->text = g_strdup (text);
+
+ if (iti->fontname)
+ g_free (iti->fontname);
+
+ iti->fontname = g_strdup (fontname ? fontname : DEFAULT_FONT_NAME);
+
+ if (priv->font)
+ gdk_font_unref (priv->font);
+
+ priv->font = NULL;
+ if (fontname)
+ priv->font = gdk_fontset_load (iti->fontname);
+ if (!priv->font)
+ priv->font = get_default_font ();
+
+ /* Request update */
+
+ priv->need_pos_update = TRUE;
+ priv->need_font_update = TRUE;
+ priv->need_text_update = TRUE;
+ gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (iti));
+}
+
+/**
+ * e_icon_bar_text_item_set_width:
+ * @iti: An #EIconBarTextItem.
+ * @width: Maximum width allowed for this item, to be used for word wrapping.
+ *
+ * This routine is used to set the maximum width of an #EIconBarTextItem.
+ */
+void
+e_icon_bar_text_item_set_width (EIconBarTextItem *iti, int width)
+{
+ ItiPrivate *priv;
+
+ g_return_if_fail (iti != NULL);
+ g_return_if_fail (IS_ITI (iti));
+ g_return_if_fail (width > 2 * MARGIN_X);
+
+ priv = iti->priv;
+
+ if (iti->width == width)
+ return;
+
+ iti->width = width;
+
+ /* Request update */
+ priv->need_text_update = TRUE;
+ gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (iti));
+}
+
+/**
+ * e_icon_bar_text_item_setxy:
+ * @iti: An #EIconBarTextItem.
+ * @x: X position.
+ * @y: Y position.
+ *
+ * Sets the coordinates at which the #EIconBarTextItem should be placed.
+ *
+ * See also: e_icon_bar_text_item_configure().
+ */
+void
+e_icon_bar_text_item_setxy (EIconBarTextItem *iti, int x, int y)
+{
+ ItiPrivate *priv;
+
+ g_return_if_fail (iti != NULL);
+ g_return_if_fail (IS_ITI (iti));
+
+ priv = iti->priv;
+
+ iti->x = x;
+ iti->y = y;
+
+ priv->need_pos_update = TRUE;
+ gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (iti));
+}
+
+/**
+ * e_icon_bar_text_item_select:
+ * @iti: An #EIconBarTextItem.
+ * @sel: Whether the item should be displayed as selected.
+ *
+ * This function is used to control whether an icon text item is displayed as
+ * selected or not. Mouse events are ignored by the item when it is unselected;
+ * when the user clicks on a selected icon text item, it will start the text
+ * editing process.
+ */
+void
+e_icon_bar_text_item_select (EIconBarTextItem *iti, int sel)
+{
+ ItiPrivate *priv;
+
+ g_return_if_fail (iti != NULL);
+ g_return_if_fail (IS_ITI (iti));
+
+ priv = iti->priv;
+
+ if (!iti->selected == !sel)
+ return;
+
+ iti->selected = sel ? TRUE : FALSE;
+
+ if (!iti->selected && iti->editing)
+ iti_edition_accept (iti);
+
+ priv->need_state_update = TRUE;
+ gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (iti));
+}
+
+/**
+ * e_icon_bar_text_item_get_text:
+ * @iti: An #EIconBarTextItem.
+ *
+ * Returns the current text. The client should not free this string, as it is
+ * internal to the #EIconBarTextItem.
+ */
+char *
+e_icon_bar_text_item_get_text (EIconBarTextItem *iti)
+{
+ ItiPrivate *priv;
+
+ g_return_val_if_fail (iti != NULL, NULL);
+ g_return_val_if_fail (IS_ITI (iti), NULL);
+
+ priv = iti->priv;
+
+ if (iti->editing)
+ return gtk_entry_get_text (priv->entry);
+ else
+ return iti->text;
+}
+
+
+/**
+ * e_icon_bar_text_item_set_text:
+ * @iti: An #EIconBarTextItem.
+ * @text: Text that is going to be displayed.
+ * @is_static: Whether @text points to a static string or not.
+ *
+ * If @is_static is true, it means that there is no need for the item to
+ * allocate memory for the string (it is a guarantee that the text is allocated
+ * by the caller and it will not be deallocated during the lifetime of this
+ * item). This is an optimization to reduce memory usage for large icon sets.
+ */
+void
+e_icon_bar_text_item_set_text (EIconBarTextItem *iti, const char *text,
+ gboolean is_static)
+{
+ ItiPrivate *priv;
+
+ g_return_if_fail (iti != NULL);
+ g_return_if_fail (IS_ITI (iti));
+ g_return_if_fail (text != NULL);
+
+ priv = iti->priv;
+
+ if (iti->text && iti->is_text_allocated)
+ g_free (iti->text);
+
+ iti->is_text_allocated = !is_static;
+
+ /* This cast is to shut up the compiler */
+ if (is_static)
+ iti->text = (char *) text;
+ else
+ iti->text = g_strdup (text);
+
+ /* Request update */
+
+ priv->need_text_update = TRUE;
+ gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (iti));
+}
+
+
+/**
+ * e_icon_bar_text_item_start_editing:
+ * @iti: An #EIconBarTextItem.
+ *
+ * Starts the editing state of an #EIconBarTextItem.
+ **/
+void
+e_icon_bar_text_item_start_editing (EIconBarTextItem *iti)
+{
+ g_return_if_fail (iti != NULL);
+ g_return_if_fail (IS_ITI (iti));
+
+ if (iti->editing)
+ return;
+
+ iti->selected = TRUE; /* Ensure that we are selected */
+ gnome_canvas_item_grab_focus (GNOME_CANVAS_ITEM (iti));
+ iti_start_editing (iti);
+}
+
+/**
+ * e_icon_bar_text_item_stop_editing:
+ * @iti: An #EIconBarTextItem.
+ * @accept: Whether to accept the current text or to discard it.
+ *
+ * Terminates the editing state of an icon text item. The @accept argument
+ * controls whether the item's current text should be accepted or discarded.
+ * If it is discarded, then the icon's original text will be restored.
+ **/
+void
+e_icon_bar_text_item_stop_editing (EIconBarTextItem *iti,
+ gboolean accept)
+{
+ g_return_if_fail (iti != NULL);
+ g_return_if_fail (IS_ITI (iti));
+
+ if (!iti->editing)
+ return;
+
+ if (accept)
+ iti_edition_accept (iti);
+ else
+ iti_stop_editing (iti);
+}
+
+
+/**
+ * e_icon_bar_text_item_get_type:
+ *
+ * Registers the &EIconBarTextItem class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: the type ID of the #EIconBarTextItem class.
+ **/
+GtkType
+e_icon_bar_text_item_get_type (void)
+{
+ static GtkType iti_type = 0;
+
+ if (!iti_type) {
+ static const GtkTypeInfo iti_info = {
+ "EIconBarTextItem",
+ sizeof (EIconBarTextItem),
+ sizeof (EIconBarTextItemClass),
+ (GtkClassInitFunc) iti_class_init,
+ (GtkObjectInitFunc) iti_init,
+ NULL, /* reserved_1 */
+ NULL, /* reserved_2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ iti_type = gtk_type_unique (gnome_canvas_item_get_type (), &iti_info);
+ }
+
+ return iti_type;
+}
+
+
+static void
+free_row (gpointer data, gpointer user_data)
+{
+ EIconBarTextItemInfoRow *row;
+
+ if (data) {
+ row = data;
+ g_free (row->text);
+ g_free (row->text_wc);
+ g_free (row);
+ }
+}
+
+/*
+ * e_icon_bar_text_item_free_info:
+ * @ti: An icon text info structure.
+ *
+ * Frees a &EIconBarTextItemInfo structure. You should call this instead of
+ * freeing the structure yourself.
+ */
+static void
+e_icon_bar_text_item_free_info (EIconBarTextItemInfo *ti)
+{
+ g_list_foreach (ti->rows, free_row, NULL);
+ g_list_free (ti->rows);
+ g_free (ti);
+}
+
+/*
+ * e_icon_bar_text_item_layout_text:
+ * @font: Name of the font that will be used to render the text.
+ * @text: Text to be formatted.
+ * @separators: Separators used for word wrapping, can be NULL.
+ * @max_width: Width in pixels to be used for word wrapping.
+ * @confine: Whether it is mandatory to wrap at @max_width.
+ *
+ * Creates a new &EIconBarTextItemInfo structure by wrapping the specified
+ * text. If non-NULL, the @separators argument defines a set of characters
+ * to be used as word delimiters for performing word wrapping. If it is
+ * NULL, then only spaces will be used as word delimiters.
+ *
+ * The @max_width argument is used to specify the width at which word
+ * wrapping will be performed. If there is a very long word that does not
+ * fit in a single line, the @confine argument can be used to specify
+ * whether the word should be unconditionally split to fit or whether
+ * the maximum width should be increased as necessary.
+ *
+ * Return value: A newly-created &EIconBarTextItemInfo structure.
+ */
+static EIconBarTextItemInfo *
+e_icon_bar_text_item_layout_text (EIconBarTextItem *iti, GdkFont *font,
+ const gchar *text, const gchar *separators,
+ gint max_width, gboolean confine)
+{
+ EIconBarTextItemInfo *ti;
+ EIconBarTextItemInfoRow *row;
+ GdkWChar *row_end;
+ GdkWChar *s, *word_start, *word_end, *old_word_end;
+ GdkWChar *sub_text;
+ int i, w_len, w;
+ GdkWChar *text_wc, *text_iter, *separators_wc;
+ int text_len_wc, separators_len_wc;
+ gboolean restrict_lines;
+ int lines;
+
+ g_return_val_if_fail (font != NULL, NULL);
+ g_return_val_if_fail (text != NULL, NULL);
+
+ if (!separators)
+ separators = " ";
+
+ text_wc = g_new (GdkWChar, strlen (text) + 1);
+ text_len_wc = gdk_mbstowcs (text_wc, text, strlen (text));
+ if (text_len_wc < 0) text_len_wc = 0;
+ text_wc[text_len_wc] = 0;
+
+ separators_wc = g_new (GdkWChar, strlen (separators) + 1);
+ separators_len_wc = gdk_mbstowcs (separators_wc, separators, strlen (separators));
+ if (separators_len_wc < 0) separators_len_wc = 0;
+ separators_wc[separators_len_wc] = 0;
+
+ ti = g_new (EIconBarTextItemInfo, 1);
+
+ ti->rows = NULL;
+ ti->font = font;
+ ti->width = 0;
+ ti->height = 0;
+ ti->baseline_skip = font->ascent + font->descent;
+
+ word_end = NULL;
+
+ if (!iti->editing && iti->max_lines != -1)
+ restrict_lines = TRUE;
+ else
+ restrict_lines = FALSE;
+
+ text_iter = text_wc;
+ lines = 0;
+ while (*text_iter) {
+ /* If we are restricting the height, and this is the last line,
+ and we are displaying the ellipsis, then subtract the width
+ of the ellipsis from our max_width. */
+ if (restrict_lines && lines == iti->max_lines - 1
+ && iti->show_ellipsis) {
+ max_width -= gdk_string_measure (font, e_icon_bar_text_item_ellipsis);
+ }
+
+ for (row_end = text_iter; *row_end != 0 && *row_end != '\n'; row_end++);
+
+ /* Accumulate words from this row until they don't fit in the max_width */
+
+ s = text_iter;
+
+ while (s < row_end) {
+ word_start = s;
+ old_word_end = word_end;
+ for (word_end = word_start; *word_end; word_end++) {
+ GdkWChar *p;
+ for (p = separators_wc; *p; p++) {
+ if (*word_end == *p)
+ goto found;
+ }
+ }
+ found:
+ if (word_end < row_end)
+ word_end++;
+
+ if (gdk_text_width_wc (font, text_iter, word_end - text_iter) > max_width) {
+ if (word_start == text_iter
+ || (restrict_lines
+ && lines == iti->max_lines - 1)) {
+ if (confine) {
+ /* We must force-split the word. Look for a proper
+ * place to do it.
+ */
+
+ w_len = word_end - text_iter;
+
+ for (i = 1; i < w_len; i++) {
+ w = gdk_text_width_wc (font, text_iter, i);
+ if (w > max_width) {
+ if (i == 1)
+ /* Shit, not even a single character fits */
+ max_width = w;
+ else
+ break;
+ }
+ }
+
+ /* Create sub-row with the chars that fit */
+
+ sub_text = g_new (GdkWChar, i);
+ memcpy (sub_text, text_iter, (i - 1) * sizeof (GdkWChar));
+ sub_text[i - 1] = 0;
+
+ row = g_new (EIconBarTextItemInfoRow, 1);
+ row->text_wc = sub_text;
+ row->text_length = i - 1;
+ row->width = gdk_text_width_wc (font, sub_text, i - 1);
+ row->text = gdk_wcstombs(sub_text);
+ if (row->text == NULL)
+ row->text = g_strdup("");
+
+ ti->rows = g_list_append (ti->rows, row);
+
+ if (row->width > ti->width)
+ ti->width = row->width;
+
+ ti->height += ti->baseline_skip;
+
+ /* Bump the text pointer */
+
+ text_iter += i - 1;
+ s = text_iter;
+
+ lines++;
+ if (restrict_lines
+ && lines >= iti->max_lines)
+ break;
+
+ continue;
+ } else
+ max_width = gdk_text_width_wc (font, word_start, word_end - word_start);
+
+ continue; /* Retry split */
+ } else {
+ word_end = old_word_end; /* Restore to region that does fit */
+ break; /* Stop the loop because we found something that doesn't fit */
+ }
+ }
+
+ s = word_end;
+ }
+
+ if (restrict_lines && lines >= iti->max_lines)
+ break;
+
+ /* Append row */
+
+ if (text_iter == row_end) {
+ /* We are on a newline, so append an empty row */
+
+ ti->rows = g_list_append (ti->rows, NULL);
+ ti->height += ti->baseline_skip;
+
+ /* Next! */
+
+ text_iter = row_end + 1;
+
+ lines++;
+ if (restrict_lines && lines >= iti->max_lines)
+ break;
+
+ } else {
+ /* Create subrow and append it to the list */
+
+ int sub_len;
+ sub_len = word_end - text_iter;
+
+ sub_text = g_new (GdkWChar, sub_len + 1);
+ memcpy (sub_text, text_iter, sub_len * sizeof (GdkWChar));
+ sub_text[sub_len] = 0;
+
+ row = g_new (EIconBarTextItemInfoRow, 1);
+ row->text_wc = sub_text;
+ row->text_length = sub_len;
+ row->width = gdk_text_width_wc (font, sub_text, sub_len);
+ row->text = gdk_wcstombs(sub_text);
+ if (row->text == NULL)
+ row->text = g_strdup("");
+
+ ti->rows = g_list_append (ti->rows, row);
+
+ if (row->width > ti->width)
+ ti->width = row->width;
+
+ ti->height += ti->baseline_skip;
+
+ /* Next! */
+
+ text_iter = word_end;
+
+ lines++;
+ if (restrict_lines && lines >= iti->max_lines)
+ break;
+ }
+ }
+
+ /* Check if we've had to clip the text. */
+ iti->is_clipped = *text_iter ? TRUE : FALSE;
+
+ g_free (text_wc);
+ g_free (separators_wc);
+ return ti;
+}
+
+/*
+ * e_icon_bar_text_item_paint_text:
+ * @ti: An icon text info structure.
+ * @drawable: Target drawable.
+ * @gc: GC used to render the string.
+ * @x: Left coordinate for text.
+ * @y: Upper coordinate for text.
+ * @just: Justification for text.
+ *
+ * Paints the formatted text in the icon text info structure onto a drawable.
+ * This is just a sample implementation; applications can choose to use other
+ * rendering functions.
+ */
+static void
+e_icon_bar_text_item_paint_text (EIconBarTextItem *iti,
+ EIconBarTextItemInfo *ti,
+ GdkDrawable *drawable, GdkGC *gc,
+ gint x, gint y, GtkJustification just)
+{
+ GList *item;
+ EIconBarTextItemInfoRow *row;
+ int xpos, line, width;
+ gboolean show_ellipsis;
+
+ g_return_if_fail (ti != NULL);
+ g_return_if_fail (drawable != NULL);
+ g_return_if_fail (gc != NULL);
+
+ y += ti->font->ascent;
+
+ for (item = ti->rows, line = 1; item; item = item->next, line++) {
+
+ if (item->data) {
+ row = item->data;
+ width = row->width;
+ }
+
+ /* If this is the last line, and the text has been clipped,
+ and show_ellipsis is TRUE, display '...' */
+ if (line == iti->max_lines && iti->is_clipped) {
+ show_ellipsis = TRUE;
+ width += gdk_string_measure (ti->font, e_icon_bar_text_item_ellipsis);
+ } else {
+ show_ellipsis = FALSE;
+ }
+
+ switch (just) {
+ case GTK_JUSTIFY_LEFT:
+ xpos = 0;
+ break;
+
+ case GTK_JUSTIFY_RIGHT:
+ xpos = ti->width - width;
+ break;
+
+ case GTK_JUSTIFY_CENTER:
+ xpos = (ti->width - width) / 2;
+ break;
+
+ default:
+ /* Anyone care to implement GTK_JUSTIFY_FILL? */
+ g_warning ("Justification type %d not supported. Using left-justification.",
+ (int) just);
+ xpos = 0;
+ }
+
+ if (item->data)
+ gdk_draw_text_wc (drawable, ti->font, gc, x + xpos, y, row->text_wc, row->text_length);
+
+ if (show_ellipsis)
+ gdk_draw_string (drawable, ti->font, gc,
+ x + xpos + row->width, y,
+ e_icon_bar_text_item_ellipsis);
+
+ y += ti->baseline_skip;
+ }
+}
diff --git a/widgets/shortcut-bar/e-icon-bar-text-item.h b/widgets/shortcut-bar/e-icon-bar-text-item.h
new file mode 100644
index 0000000000..7c0380c87b
--- /dev/null
+++ b/widgets/shortcut-bar/e-icon-bar-text-item.h
@@ -0,0 +1,158 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Author :
+ * Damon Chaplin <damon@gtk.org>
+ *
+ * Copyright 1999, Helix Code, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ * Based on gnome-icon-text-item: an editable text block with word wrapping
+ * for the GNOME canvas.
+ *
+ * Copyright (C) 1998, 1999 The Free Software Foundation
+ *
+ * Authors: Miguel de Icaza <miguel@gnu.org>
+ * Federico Mena <federico@gimp.org>
+ */
+
+/*
+ * EIconBarTextItem - An editable canvas text item for the EIconBar.
+ */
+
+#ifndef _E_ICON_BAR_TEXT_ITEM_H_
+#define _E_ICON_BAR_TEXT_ITEM_H_
+
+#include <gtk/gtkentry.h>
+#include <libgnomeui/gnome-canvas.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define E_ICON_BAR_TEXT_ITEM(obj) (GTK_CHECK_CAST((obj), \
+ e_icon_bar_text_item_get_type (), EIconBarTextItem))
+#define E_ICON_BAR_TEXT_ITEM_CLASS(k) (GTK_CHECK_CLASS_CAST ((k),\
+ e_icon_bar_text_item_get_type ()))
+#define E_IS_ICON_BAR_TEXT_ITEM(o) (GTK_CHECK_TYPE((o), \
+ e_icon_bar_text_item_get_type ()))
+
+typedef struct _EIconBarTextItemInfo EIconBarTextItemInfo;
+
+typedef struct {
+ GnomeCanvasItem canvas_item;
+
+ /* Size and maximum allowed width */
+ int x, y;
+ int width;
+
+ /* Font name */
+ char *fontname;
+
+ /* Private data */
+ gpointer priv; /* was GtkEntry *entry */
+
+ /* Actual text */
+ char *text;
+
+ /* Text layout information */
+ EIconBarTextItemInfo *ti;
+
+ /* Whether the text is being edited */
+ unsigned int editing : 1;
+
+ /* Whether the text item is selected */
+ unsigned int selected : 1;
+
+ /* Whether the user is select-dragging a block of text */
+ unsigned int selecting : 1;
+
+ /* Whether the text is editable */
+ unsigned int is_editable : 1;
+
+ /* Whether the text is allocated by us (FALSE if allocated by the client) */
+ unsigned int is_text_allocated : 1;
+
+
+ /* The horizontal alignment of the text (default 0.5). */
+ gfloat xalign;
+
+ /* The justification of the text (default is centered). */
+ GtkJustification justification;
+
+ /* The max number of lines of text shown, or -1 for all (default). */
+ gint max_lines;
+
+ /* If '...' is displayed if the text doesn't all fit (default TRUE). */
+ gboolean show_ellipsis;
+
+ /* This is TRUE if we couldn't fit all the text in. */
+ gboolean is_clipped;
+} EIconBarTextItem;
+
+typedef struct {
+ GnomeCanvasItemClass parent_class;
+
+ /* Signals we emit */
+ int (* text_changed) (EIconBarTextItem *iti);
+ void (* height_changed) (EIconBarTextItem *iti);
+ void (* width_changed) (EIconBarTextItem *iti);
+ void (* editing_started) (EIconBarTextItem *iti);
+ void (* editing_stopped) (EIconBarTextItem *iti);
+ void (* selection_started) (EIconBarTextItem *iti);
+ void (* selection_stopped) (EIconBarTextItem *iti);
+} EIconBarTextItemClass;
+
+GtkType e_icon_bar_text_item_get_type (void);
+
+void e_icon_bar_text_item_configure (EIconBarTextItem *iti,
+ int x,
+ int y,
+ int width,
+ const char *fontname,
+ const char *text,
+ gboolean is_static);
+
+void e_icon_bar_text_item_set_width (EIconBarTextItem *iti,
+ int width);
+
+void e_icon_bar_text_item_setxy (EIconBarTextItem *iti,
+ int x,
+ int y);
+
+void e_icon_bar_text_item_select (EIconBarTextItem *iti,
+ int sel);
+
+char* e_icon_bar_text_item_get_text (EIconBarTextItem *iti);
+void e_icon_bar_text_item_set_text (EIconBarTextItem *iti,
+ const char *text,
+ gboolean is_static);
+
+void e_icon_bar_text_item_start_editing (EIconBarTextItem *iti);
+void e_icon_bar_text_item_stop_editing (EIconBarTextItem *iti,
+ gboolean accept);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _E_ICON_BAR_TEXT_ITEM_H_ */
+
diff --git a/widgets/shortcut-bar/e-icon-bar.c b/widgets/shortcut-bar/e-icon-bar.c
new file mode 100644
index 0000000000..6bb32ed2a2
--- /dev/null
+++ b/widgets/shortcut-bar/e-icon-bar.c
@@ -0,0 +1,1450 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Author :
+ * Damon Chaplin <damon@gtk.org>
+ *
+ * Copyright 1999, Helix Code, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ * EIconBar is a subclass of GnomeCanvas for displaying a vertical column of
+ * icons and descriptions. It provides 2 views - large icons and small icons.
+ */
+
+#include <gtk/gtkmain.h>
+#include <gtk/gtksignal.h>
+#include <libgnomeui/gnome-canvas-image.h>
+
+#include "e-icon-bar.h"
+#include "e-icon-bar-bg-item.h"
+#include "e-icon-bar-text-item.h"
+
+/* These are the offsets of the icons & text in both views. Note that the
+ shadow around icons is drawn in the space between items (as is the
+ horizontal bar when dragging). */
+#define E_ICON_BAR_LARGE_ICON_SPACING 8 /* Spacing between items. */
+#define E_ICON_BAR_LARGE_ICON_WIDTH 48
+#define E_ICON_BAR_LARGE_ICON_HEIGHT 48
+#define E_ICON_BAR_LARGE_ICON_TEXT_X 4
+#define E_ICON_BAR_LARGE_ICON_TEXT_Y (E_ICON_BAR_LARGE_ICON_HEIGHT + 4)
+
+#define E_ICON_BAR_SMALL_ICON_SPACING 4 /* Spacing between items. */
+#define E_ICON_BAR_SMALL_ICON_WIDTH 24
+#define E_ICON_BAR_SMALL_ICON_HEIGHT 24
+#define E_ICON_BAR_SMALL_ICON_X 4
+#define E_ICON_BAR_SMALL_ICON_TEXT_X (E_ICON_BAR_SMALL_ICON_WIDTH + 4)
+
+/* The space we leave at the top or bottom of the bar when position an item
+ while it is being edited. This is used since the EIconBar may be in a
+ EScrolledBar which may show buttons at the top or bottom. */
+#define E_ICON_BAR_V_SPACE 22
+
+/* The number of pixels the mouse has to be moved with the button down before
+ we start a drag. */
+#define E_ICON_BAR_DRAG_START_OFFSET 4
+
+/* This is the area at the top & bottom of the bar where we auto-scroll if the
+ mouse goes into during a drag-and-drop operation. */
+#define E_ICON_BAR_DRAG_AUTO_SCROLL_OFFSET 16
+
+/* This is the time between each auto-scroll, when dragging. */
+#define E_ICON_BAR_SCROLL_TIMEOUT 30
+
+/* This is the number of timeouts we skip before we start scrolling. */
+#define E_ICON_BAR_SCROLL_DELAY 12
+
+
+static void e_icon_bar_class_init (EIconBarClass *class);
+static void e_icon_bar_init (EIconBar *icon_bar);
+static void e_icon_bar_destroy (GtkObject *object);
+static void e_icon_bar_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static gint e_icon_bar_leave_notify_event (GtkWidget *widget,
+ GdkEventCrossing *event);
+static gint e_icon_bar_focus_in (GtkWidget *widget,
+ GdkEventFocus *event);
+static gint e_icon_bar_focus_out (GtkWidget *widget,
+ GdkEventFocus *event);
+static gint e_icon_bar_key_event (GtkWidget *widget, GdkEventKey *event);
+
+static gint e_icon_bar_drag_motion (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time);
+static void e_icon_bar_drag_leave (GtkWidget *widget,
+ GdkDragContext *context,
+ guint time);
+static void e_icon_bar_set_dragging_before_item (EIconBar *icon_bar,
+ gint before_item);
+static gboolean e_icon_bar_timeout_handler (gpointer data);
+
+static void e_icon_bar_recalc_common_positions (EIconBar *icon_bar);
+static gint e_icon_bar_recalc_item_positions (EIconBar *icon_bar);
+static void e_icon_bar_on_text_height_changed (GnomeCanvasItem *text_item,
+ EIconBar *icon_bar);
+static gint e_icon_bar_find_item (EIconBar *icon_bar,
+ GnomeCanvasItem *text_item);
+static gboolean e_icon_bar_on_item_event (GnomeCanvasItem *item,
+ GdkEvent *event,
+ EIconBar *icon_bar);
+
+static gboolean e_icon_bar_large_icons_intersects (EIconBar *icon_bar,
+ EIconBarItem *item,
+ gint x,
+ gint y);
+static gboolean e_icon_bar_large_icons_is_before (EIconBar *icon_bar,
+ EIconBarItem *item,
+ gint x,
+ gint y);
+static gboolean e_icon_bar_small_icons_intersects (EIconBar *icon_bar,
+ EIconBarItem *item,
+ gint x,
+ gint y);
+static gboolean e_icon_bar_small_icons_is_before (EIconBar *icon_bar,
+ EIconBarItem *item,
+ gint x,
+ gint y);
+static void e_icon_bar_on_text_item_editing_started (EIconBarTextItem *text_item,
+ EIconBar *icon_bar);
+static void e_icon_bar_on_text_item_editing_stopped (EIconBarTextItem *text_item,
+ EIconBar *icon_bar);
+static void e_icon_bar_ensure_edited_item_visible (EIconBar *icon_bar);
+static void e_icon_bar_update_highlight (EIconBar *icon_bar);
+
+enum
+{
+ ITEM_SELECTED,
+ ITEM_DRAGGED,
+ LAST_SIGNAL
+};
+
+static guint e_icon_bar_signals[LAST_SIGNAL] = {0};
+
+static GnomeCanvasClass *parent_class;
+
+
+GtkType
+e_icon_bar_get_type (void)
+{
+ static GtkType e_icon_bar_type = 0;
+
+ if (!e_icon_bar_type){
+ GtkTypeInfo e_icon_bar_info = {
+ "EIconBar",
+ sizeof (EIconBar),
+ sizeof (EIconBarClass),
+ (GtkClassInitFunc) e_icon_bar_class_init,
+ (GtkObjectInitFunc) e_icon_bar_init,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ parent_class = gtk_type_class (gnome_canvas_get_type ());
+ e_icon_bar_type = gtk_type_unique (gnome_canvas_get_type (),
+ &e_icon_bar_info);
+ }
+
+ return e_icon_bar_type;
+}
+
+
+static void
+e_icon_bar_class_init (EIconBarClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = (GtkObjectClass *) class;
+ widget_class = (GtkWidgetClass *) class;
+
+ e_icon_bar_signals[ITEM_SELECTED] =
+ gtk_signal_new ("item_selected",
+ GTK_RUN_LAST | GTK_RUN_ACTION,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EIconBarClass,
+ selected_item),
+ gtk_marshal_NONE__POINTER_INT,
+ GTK_TYPE_NONE, 2, GTK_TYPE_GDK_EVENT,
+ GTK_TYPE_INT);
+ e_icon_bar_signals[ITEM_DRAGGED] =
+ gtk_signal_new ("item_dragged",
+ GTK_RUN_LAST | GTK_RUN_ACTION,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EIconBarClass,
+ dragged_item),
+ gtk_marshal_NONE__POINTER_INT,
+ GTK_TYPE_NONE, 2, GTK_TYPE_GDK_EVENT,
+ GTK_TYPE_INT);
+
+ gtk_object_class_add_signals (object_class, e_icon_bar_signals,
+ LAST_SIGNAL);
+
+ /* Method override */
+ object_class->destroy = e_icon_bar_destroy;
+
+ widget_class->size_allocate = e_icon_bar_size_allocate;
+ widget_class->leave_notify_event = e_icon_bar_leave_notify_event;
+ widget_class->focus_in_event = e_icon_bar_focus_in;
+ widget_class->focus_out_event = e_icon_bar_focus_out;
+ widget_class->key_press_event = e_icon_bar_key_event;
+ widget_class->key_release_event = e_icon_bar_key_event;
+ widget_class->drag_motion = e_icon_bar_drag_motion;
+ widget_class->drag_leave = e_icon_bar_drag_leave;
+
+ class->selected_item = NULL;
+}
+
+
+static void
+e_icon_bar_init (EIconBar *icon_bar)
+{
+ icon_bar->view_type = E_ICON_BAR_LARGE_ICONS;
+ icon_bar->items = g_array_new (FALSE, FALSE, sizeof (EIconBarItem));
+ icon_bar->pressed_item_num = -1;
+ icon_bar->mouse_over_item_num = -1;
+ icon_bar->editing_item_num = -1;
+ icon_bar->in_drag = FALSE;
+ icon_bar->dragging_before_item_num = -1;
+ icon_bar->icon_x = 0;
+ icon_bar->icon_w = 0;
+ icon_bar->icon_h = 0;
+ icon_bar->text_x = 0;
+ icon_bar->text_w = 5;
+ icon_bar->auto_scroll_timeout_id = 0;
+
+ /* Create the background item in the canvas, which handles selections
+ and drag-and-drop. */
+ gnome_canvas_item_new (GNOME_CANVAS_GROUP (GNOME_CANVAS (icon_bar)->root),
+ e_icon_bar_bg_item_get_type (),
+ "EIconBarBgItem::icon_bar", icon_bar,
+ NULL);
+}
+
+
+/**
+ * e_icon_bar_new:
+ * @Returns: A new #EIconBar.
+ *
+ * Creates a new #EIconBar.
+ **/
+GtkWidget *
+e_icon_bar_new (void)
+{
+ GtkWidget *icon_bar;
+
+ icon_bar = GTK_WIDGET (gtk_type_new (e_icon_bar_get_type ()));
+
+ return icon_bar;
+}
+
+
+static void
+e_icon_bar_destroy (GtkObject *object)
+{
+ EIconBar *icon_bar;
+
+ icon_bar = E_ICON_BAR (object);
+
+ GTK_OBJECT_CLASS (parent_class)->destroy (object);
+
+ g_array_free (icon_bar->items, TRUE);
+
+ if (icon_bar->auto_scroll_timeout_id != 0) {
+ gtk_timeout_remove (icon_bar->auto_scroll_timeout_id);
+ icon_bar->auto_scroll_timeout_id = 0;
+ }
+}
+
+
+static void
+e_icon_bar_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
+{
+ EIconBar *icon_bar;
+ gint canvas_width, canvas_height, height;
+
+ icon_bar = E_ICON_BAR (widget);
+
+ GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
+
+ canvas_width = GTK_WIDGET (icon_bar)->allocation.width;
+ canvas_height = GTK_WIDGET (icon_bar)->allocation.height;
+
+ /* Reset the y position and widths of all the items to the width of
+ the canvas, and reset the button labels, so they fit. */
+ e_icon_bar_recalc_common_positions (icon_bar);
+ height = e_icon_bar_recalc_item_positions (icon_bar);
+
+ gnome_canvas_set_scroll_region (GNOME_CANVAS (widget),
+ 0, 0, canvas_width,
+ MAX (height, canvas_height - 1));
+
+ /* If we are editing an item, make sure it is visible. */
+ e_icon_bar_ensure_edited_item_visible (icon_bar);
+
+ GTK_LAYOUT (widget)->vadjustment->step_increment = 16;
+
+ e_icon_bar_update_highlight (icon_bar);
+}
+
+
+/* This sets all the item positions which are the same for all items in the
+ group. */
+static void
+e_icon_bar_recalc_common_positions (EIconBar *icon_bar)
+{
+ gint canvas_width;
+
+ canvas_width = GTK_WIDGET (icon_bar)->allocation.width;
+
+ if (icon_bar->view_type == E_ICON_BAR_LARGE_ICONS) {
+ icon_bar->icon_x = (canvas_width - E_ICON_BAR_LARGE_ICON_WIDTH) / 2;
+ icon_bar->icon_w = E_ICON_BAR_LARGE_ICON_WIDTH;
+ icon_bar->icon_h = E_ICON_BAR_LARGE_ICON_HEIGHT;
+
+ icon_bar->text_x = E_ICON_BAR_LARGE_ICON_TEXT_X;
+ icon_bar->text_w = MAX (canvas_width - (E_ICON_BAR_LARGE_ICON_TEXT_X * 2), 5);
+
+ icon_bar->spacing = E_ICON_BAR_LARGE_ICON_SPACING;
+ } else {
+ icon_bar->icon_x = E_ICON_BAR_SMALL_ICON_X;
+ icon_bar->icon_w = E_ICON_BAR_SMALL_ICON_WIDTH;
+ icon_bar->icon_h = E_ICON_BAR_SMALL_ICON_HEIGHT;
+
+ icon_bar->text_x = E_ICON_BAR_SMALL_ICON_TEXT_X;
+ icon_bar->text_w = MAX (canvas_width - E_ICON_BAR_SMALL_ICON_TEXT_X, 5);
+
+ icon_bar->spacing = E_ICON_BAR_SMALL_ICON_SPACING;
+ }
+}
+
+
+/* This recalculates the positions of all the items, according to the current
+ view type and the height of the text items. */
+static gint
+e_icon_bar_recalc_item_positions (EIconBar *icon_bar)
+{
+ EIconBarItem *item;
+ gint y, item_num;
+ gdouble x1, y1, x2, y2, xalign;
+ GtkJustification justify;
+ gint max_lines;
+
+ if (icon_bar->view_type == E_ICON_BAR_LARGE_ICONS) {
+ xalign = 0.5;
+ justify = GTK_JUSTIFY_CENTER;
+ max_lines = 2;
+ } else {
+ xalign = 0.0;
+ justify = GTK_JUSTIFY_LEFT;
+ max_lines = 1;
+ }
+
+ /* Now step through the items, setting the y positions. */
+ y = icon_bar->spacing;
+ for (item_num = 0; item_num < icon_bar->items->len; item_num++) {
+ item = &g_array_index (icon_bar->items,
+ EIconBarItem, item_num);
+
+ e_icon_bar_text_item_set_width (E_ICON_BAR_TEXT_ITEM (item->text),
+ icon_bar->text_w);
+
+ /* Get the text item's height. */
+ gnome_canvas_item_get_bounds (item->text, &x1, &y1, &x2, &y2);
+ item->text_width = x2 - x1;
+ item->text_height = y2 - y1;
+
+ if (icon_bar->view_type == E_ICON_BAR_LARGE_ICONS) {
+ item->icon_y = y;
+ item->text_y = y + E_ICON_BAR_LARGE_ICON_TEXT_Y;
+
+ item->item_height = E_ICON_BAR_LARGE_ICON_TEXT_Y
+ + item->text_height;
+ } else {
+ item->item_height = MAX (item->text_height, E_ICON_BAR_SMALL_ICON_HEIGHT);
+ item->icon_y = y + (item->item_height - E_ICON_BAR_SMALL_ICON_HEIGHT) / 2;
+ item->text_y = y + (item->item_height - item->text_height) / 2;
+ }
+
+ e_icon_bar_text_item_setxy (E_ICON_BAR_TEXT_ITEM (item->text),
+ icon_bar->text_x, item->text_y);
+
+ /* We need to get the bounds again, in case it has moved. */
+ gnome_canvas_item_get_bounds (item->text, &x1, &y1, &x2, &y2);
+ item->text_x = x1;
+
+ gnome_canvas_item_set (item->text,
+ "EIconBarTextItem::xalign", xalign,
+ "EIconBarTextItem::justify", justify,
+ "EIconBarTextItem::max_lines", max_lines,
+ NULL);
+
+ gnome_canvas_item_set (item->image,
+ "GnomeCanvasImage::x", (gdouble)icon_bar->icon_x,
+ "GnomeCanvasImage::y", (gdouble)item->icon_y,
+ "GnomeCanvasImage::width", (gdouble)icon_bar->icon_w,
+ "GnomeCanvasImage::height", (gdouble)icon_bar->icon_h,
+ NULL);
+
+ y += item->item_height + icon_bar->spacing;
+ }
+
+ return y;
+}
+
+
+static gint
+e_icon_bar_leave_notify_event (GtkWidget *widget, GdkEventCrossing *event)
+{
+ EIconBar *icon_bar;
+
+ icon_bar = E_ICON_BAR (widget);
+
+ GTK_WIDGET_CLASS (parent_class)->leave_notify_event (widget, event);
+
+ /* Make sure no items are highlighted. */
+ e_icon_bar_item_motion (icon_bar, -1, NULL);
+
+ return FALSE;
+}
+
+
+static gint
+e_icon_bar_focus_in (GtkWidget *widget,
+ GdkEventFocus *event)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (E_IS_ICON_BAR (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ GTK_WIDGET_CLASS (parent_class)->focus_in_event (widget, event);
+ GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
+ return FALSE;
+}
+
+
+static gint
+e_icon_bar_focus_out (GtkWidget *widget,
+ GdkEventFocus *event)
+{
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (E_IS_ICON_BAR (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ GTK_WIDGET_CLASS (parent_class)->focus_out_event (widget, event);
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
+ return FALSE;
+}
+
+
+/* Key event handler for the canvas.
+ FIXME: GnomeCanvas bug workaround - I needed to override this to stop the
+ canvas ignoring key events from other windows. */
+static gint
+e_icon_bar_key_event (GtkWidget *widget, GdkEventKey *event)
+{
+ GnomeCanvas *canvas;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (E_IS_ICON_BAR (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ canvas = GNOME_CANVAS (widget);
+
+ if (event->window != canvas->layout.bin_window) {
+ /* We change the window in the event struct so the canvas
+ doesn't ignore the event. Note that windows are ref-counted
+ in the event struct. */
+ if (event->window)
+ gdk_window_unref (event->window);
+ event->window = canvas->layout.bin_window;
+ gdk_window_ref (event->window);
+ }
+
+ /* These both call the same function at present, but we'll do it
+ properly just in case that changes. */
+ if (event->type == GDK_KEY_PRESS)
+ return (*GTK_WIDGET_CLASS (parent_class)->key_press_event)(widget, event);
+ else
+ return (*GTK_WIDGET_CLASS (parent_class)->key_release_event)(widget, event);
+}
+
+
+/**
+ * e_icon_bar_set_view_type:
+ * @icon_bar: An #EIconBar.
+ * @view_type: The new view type, %E_ICON_BAR_LARGE_ICONS or
+ * %E_ICON_BAR_SMALL_ICONS.
+ *
+ * Sets the view type of the #EIconBar.
+ **/
+void
+e_icon_bar_set_view_type (EIconBar *icon_bar,
+ EIconBarViewType view_type)
+{
+ g_return_if_fail (E_IS_ICON_BAR (icon_bar));
+
+ if (icon_bar->view_type == view_type)
+ return;
+
+ icon_bar->view_type = view_type;
+
+ /* Queue a resize of the canvas, so everything is put in the right
+ positions based on the new view type. */
+ gtk_widget_queue_resize (GTK_WIDGET (icon_bar));
+}
+
+
+/**
+ * e_icon_bar_add_item:
+ * @icon_bar: An #EIconBar.
+ * @image: the new item's icon.
+ * @text: the new item's text.
+ * @position: the position to place the new item, or -1 to place it last.
+ *
+ * Adds an item to the #EIconBar at the given position.
+ **/
+gint
+e_icon_bar_add_item (EIconBar *icon_bar,
+ GdkImlibImage *image,
+ gchar *text,
+ gint position)
+{
+ EIconBarItem item;
+ gfloat xalign;
+ GtkJustification justify;
+ gint max_lines, retval;
+
+ g_return_val_if_fail (E_IS_ICON_BAR (icon_bar), -1);
+ g_return_val_if_fail (text != NULL, -1);
+ g_return_val_if_fail (position >= -1, -1);
+ g_return_val_if_fail (position <= (gint)icon_bar->items->len, -1);
+
+ if (icon_bar->view_type == E_ICON_BAR_LARGE_ICONS) {
+ xalign = 0.5;
+ justify = GTK_JUSTIFY_CENTER;
+ max_lines = 2;
+ } else {
+ xalign = 0.0;
+ justify = GTK_JUSTIFY_LEFT;
+ max_lines = 1;
+ }
+
+ item.text = gnome_canvas_item_new (GNOME_CANVAS_GROUP (GNOME_CANVAS (icon_bar)->root),
+ e_icon_bar_text_item_get_type (),
+ "EIconBarTextItem::xalign", xalign,
+ "EIconBarTextItem::justify", justify,
+ "EIconBarTextItem::max_lines", max_lines,
+ NULL);
+ e_icon_bar_text_item_configure (E_ICON_BAR_TEXT_ITEM (item.text),
+ icon_bar->text_x, 0,
+ icon_bar->text_w, NULL,
+ text, FALSE);
+ gtk_signal_connect (GTK_OBJECT (item.text), "height_changed",
+ GTK_SIGNAL_FUNC (e_icon_bar_on_text_height_changed), icon_bar);
+ gtk_signal_connect (GTK_OBJECT (item.text), "event",
+ GTK_SIGNAL_FUNC (e_icon_bar_on_item_event),
+ icon_bar);
+ gtk_signal_connect (GTK_OBJECT (item.text), "editing_started",
+ GTK_SIGNAL_FUNC (e_icon_bar_on_text_item_editing_started),
+ icon_bar);
+ gtk_signal_connect (GTK_OBJECT (item.text), "editing_stopped",
+ GTK_SIGNAL_FUNC (e_icon_bar_on_text_item_editing_stopped),
+ icon_bar);
+
+ item.image = gnome_canvas_item_new (GNOME_CANVAS_GROUP (GNOME_CANVAS (icon_bar)->root),
+ gnome_canvas_image_get_type (),
+ "GnomeCanvasImage::image", image,
+ "GnomeCanvasImage::anchor", GTK_ANCHOR_NORTH_WEST,
+ "GnomeCanvasImage::width", (gdouble) icon_bar->icon_w,
+ "GnomeCanvasImage::height", (gdouble) icon_bar->icon_h,
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (item.image), "event",
+ GTK_SIGNAL_FUNC (e_icon_bar_on_item_event),
+ icon_bar);
+
+ item.data = NULL;
+ item.destroy = NULL;
+
+ if (position == -1) {
+ g_array_append_val (icon_bar->items, item);
+ retval = icon_bar->items->len - 1;
+ } else {
+ g_array_insert_val (icon_bar->items, position, item);
+ retval = position;
+
+ /* FIXME: Should possibly update other indices. */
+ if (icon_bar->dragged_item_num >= position)
+ icon_bar->dragged_item_num++;
+ }
+
+ gtk_widget_queue_resize (GTK_WIDGET (icon_bar));
+
+ return retval;
+}
+
+
+/**
+ * e_icon_bar_reorder_item:
+ * @icon_bar: An #EIconBar.
+ * @item_num: The index of the item to move.
+ * @new_position: The new position of the item, which is used after the item
+ * has been removed from its current position. If @new_position is -1, the item
+ * is placed last.
+ *
+ * Moves an item to a new position within the #EIconBar.
+ **/
+void
+e_icon_bar_reorder_item (EIconBar *icon_bar,
+ gint item_num,
+ gint new_position)
+{
+ EIconBarItem tmp_item;
+
+ g_return_if_fail (E_IS_ICON_BAR (icon_bar));
+ g_return_if_fail (item_num >= 0);
+ g_return_if_fail (item_num < icon_bar->items->len);
+ g_return_if_fail (new_position >= -1);
+ g_return_if_fail (new_position < icon_bar->items->len);
+
+ tmp_item = g_array_index (icon_bar->items, EIconBarItem, item_num);
+ g_array_remove_index (icon_bar->items, item_num);
+
+ if (new_position == -1)
+ g_array_append_val (icon_bar->items, tmp_item);
+ else
+ g_array_insert_val (icon_bar->items, new_position, tmp_item);
+
+ gtk_widget_queue_resize (GTK_WIDGET (icon_bar));
+}
+
+
+/**
+ * e_icon_bar_remove_item:
+ * @icon_bar: An #EIconBar.
+ * @item_num: The index of the item to remove.
+ *
+ * Removes an item from the #EIconBar.
+ **/
+void
+e_icon_bar_remove_item (EIconBar *icon_bar,
+ gint item_num)
+{
+ EIconBarItem *item;
+
+ g_return_if_fail (E_IS_ICON_BAR (icon_bar));
+ g_return_if_fail (item_num >= 0);
+ g_return_if_fail (item_num < icon_bar->items->len);
+
+ item = &g_array_index (icon_bar->items, EIconBarItem, item_num);
+
+ if (item->destroy)
+ item->destroy (item->data);
+
+ gtk_object_destroy (GTK_OBJECT (item->text));
+ gtk_object_destroy (GTK_OBJECT (item->image));
+
+ g_array_remove_index (icon_bar->items, item_num);
+
+ gtk_widget_queue_resize (GTK_WIDGET (icon_bar));
+}
+
+
+/**
+ * e_icon_bar_get_item_image:
+ * @icon_bar: An #EIconBar.
+ * @item_num: The index of the item.
+ * @Returns: The icon of the given item.
+ *
+ * Returns the icon used for the given item.
+ **/
+GdkImlibImage*
+e_icon_bar_get_item_image (EIconBar *icon_bar,
+ gint item_num)
+{
+ EIconBarItem *item;
+ GdkImlibImage *image;
+
+ g_return_val_if_fail (E_IS_ICON_BAR (icon_bar), NULL);
+ g_return_val_if_fail (item_num >= 0, NULL);
+ g_return_val_if_fail (item_num < icon_bar->items->len, NULL);
+
+ item = &g_array_index (icon_bar->items, EIconBarItem, item_num);
+ gtk_object_get (GTK_OBJECT (item->image),
+ "GnomeCanvasImage::image", image,
+ NULL);
+ return image;
+}
+
+
+/**
+ * e_icon_bar_set_item_image:
+ * @icon_bar: An #EIconBar.
+ * @item_num: The index of the item.
+ * @image: The new icon to use for the given item.
+ *
+ * Sets the icon to use for the given item.
+ **/
+void
+e_icon_bar_set_item_image (EIconBar *icon_bar,
+ gint item_num,
+ GdkImlibImage *image)
+{
+ EIconBarItem *item;
+
+ g_return_if_fail (E_IS_ICON_BAR (icon_bar));
+ g_return_if_fail (item_num >= 0);
+ g_return_if_fail (item_num < icon_bar->items->len);
+
+ item = &g_array_index (icon_bar->items, EIconBarItem, item_num);
+ gnome_canvas_item_set (item->image,
+ "GnomeCanvasImage::image", image,
+ NULL);
+}
+
+
+/**
+ * e_icon_bar_get_item_text:
+ * @icon_bar: An #EIconBar.
+ * @item_num: The index of the item.
+ * @Returns: The text of the given item.
+ *
+ * Returns the text of the given item.
+ **/
+gchar*
+e_icon_bar_get_item_text (EIconBar *icon_bar,
+ gint item_num)
+{
+ EIconBarItem *item;
+
+ g_return_val_if_fail (E_IS_ICON_BAR (icon_bar), NULL);
+ g_return_val_if_fail (item_num >= 0, NULL);
+ g_return_val_if_fail (item_num < icon_bar->items->len, NULL);
+
+ item = &g_array_index (icon_bar->items, EIconBarItem, item_num);
+ return e_icon_bar_text_item_get_text (E_ICON_BAR_TEXT_ITEM (item->text));
+}
+
+
+/**
+ * e_icon_bar_set_item_text:
+ * @icon_bar: An #EIconBar.
+ * @item_num: The index of the item.
+ * @text: The new text for the given item.
+ *
+ * Sets the text of the given item.
+ **/
+void
+e_icon_bar_set_item_text (EIconBar *icon_bar,
+ gint item_num,
+ gchar *text)
+{
+ EIconBarItem *item;
+
+ g_return_if_fail (E_IS_ICON_BAR (icon_bar));
+ g_return_if_fail (item_num >= 0);
+ g_return_if_fail (item_num < icon_bar->items->len);
+
+ item = &g_array_index (icon_bar->items, EIconBarItem, item_num);
+ e_icon_bar_text_item_set_text (E_ICON_BAR_TEXT_ITEM (item->text),
+ text, FALSE);
+}
+
+
+/**
+ * e_icon_bar_get_item_data:
+ * @icon_bar: An #EIconBar.
+ * @item_num: The index of the item.
+ * @Returns: The user data associated with the given item.
+ *
+ * Returns the user data associated with the given item.
+ **/
+gpointer
+e_icon_bar_get_item_data (EIconBar *icon_bar,
+ gint item_num)
+{
+ EIconBarItem *item;
+
+ g_return_val_if_fail (E_IS_ICON_BAR (icon_bar), NULL);
+ g_return_val_if_fail (item_num >= 0, NULL);
+ g_return_val_if_fail (item_num < icon_bar->items->len, NULL);
+
+ item = &g_array_index (icon_bar->items, EIconBarItem, item_num);
+ return item->data;
+}
+
+
+/**
+ * e_icon_bar_set_item_data:
+ * @icon_bar: An #EIconBar.
+ * @item_num: The index of the item.
+ * @data: The user data to set for the given item.
+ *
+ * Sets the user data of the given item.
+ **/
+void
+e_icon_bar_set_item_data (EIconBar *icon_bar,
+ gint item_num,
+ gpointer data)
+{
+ e_icon_bar_set_item_data_full (icon_bar, item_num, data, NULL);
+}
+
+
+/**
+ * e_icon_bar_set_item_data_full:
+ * @icon_bar: An #EIconBar.
+ * @item_num: The index of the item.
+ * @data: The user data to set for the given item.
+ * @destroy: The function to free @data when the item is destroyed.
+ *
+ * Sets the user data of the given item, and the function to free the data
+ * when the item is destroyed.
+ **/
+void
+e_icon_bar_set_item_data_full (EIconBar *icon_bar,
+ gint item_num,
+ gpointer data,
+ GtkDestroyNotify destroy)
+{
+ EIconBarItem *item;
+
+ g_return_if_fail (E_IS_ICON_BAR (icon_bar));
+ g_return_if_fail (item_num >= 0);
+ g_return_if_fail (item_num < icon_bar->items->len);
+
+ item = &g_array_index (icon_bar->items, EIconBarItem, item_num);
+
+ if (item->destroy)
+ item->destroy (item->data);
+
+ item->data = data;
+ item->destroy = destroy;
+}
+
+
+static void
+e_icon_bar_on_text_height_changed (GnomeCanvasItem *text_item,
+ EIconBar *icon_bar)
+{
+ gtk_widget_queue_resize (GTK_WIDGET (icon_bar));
+}
+
+
+/* This returns the index of the given item, or -1 if it isn't found. */
+static gint
+e_icon_bar_find_item (EIconBar *icon_bar,
+ GnomeCanvasItem *canvas_item)
+{
+ EIconBarItem *item;
+ gint item_num;
+
+ for (item_num = 0; item_num < icon_bar->items->len; item_num++) {
+ item = &g_array_index (icon_bar->items,
+ EIconBarItem, item_num);
+
+ if (item->text == canvas_item || item->image == canvas_item) {
+ return item_num;
+ }
+ }
+
+ return -1;
+}
+
+
+/* When an item has a grab, it will get all events, so we need to use the
+ position to find the real item. */
+static gboolean
+e_icon_bar_on_item_event (GnomeCanvasItem *item,
+ GdkEvent *event,
+ EIconBar *icon_bar)
+{
+ gint item_num;
+
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ item_num = e_icon_bar_find_item_at_position (icon_bar,
+ event->button.x,
+ event->button.y,
+ NULL);
+ e_icon_bar_item_pressed (icon_bar, item_num, event);
+ return TRUE;
+ case GDK_BUTTON_RELEASE:
+ item_num = e_icon_bar_find_item_at_position (icon_bar,
+ event->button.x,
+ event->button.y,
+ NULL);
+ e_icon_bar_item_released (icon_bar, item_num, event);
+ return TRUE;
+ case GDK_MOTION_NOTIFY:
+ item_num = e_icon_bar_find_item_at_position (icon_bar,
+ event->motion.x,
+ event->motion.y,
+ NULL);
+ e_icon_bar_item_motion (icon_bar, item_num, event);
+ return TRUE;
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+
+void
+e_icon_bar_item_pressed (EIconBar *icon_bar,
+ gint item_num,
+ GdkEvent *event)
+{
+ EIconBarItem *item;
+ gint button;
+
+ /* If we are editing an item, and a different item (or anywhere outside
+ an item) is clicked, stop the edit. If the item being edited is
+ clicked we just return, since the user may be selecting text. */
+ if (icon_bar->editing_item_num != -1) {
+ if (icon_bar->editing_item_num == item_num) {
+ item = &g_array_index (icon_bar->items, EIconBarItem,
+ icon_bar->editing_item_num);
+ if (!GTK_WIDGET_HAS_FOCUS (item->text->canvas)
+ || item->text->canvas->focused_item != item->text)
+ gnome_canvas_item_grab_focus (item->text);
+ } else {
+ e_icon_bar_stop_editing_item (icon_bar, TRUE);
+ }
+
+ return;
+ }
+
+ button = event->button.button;
+
+ if (button == 1 && item_num != -1) {
+ icon_bar->pressed_item_num = item_num;
+ icon_bar->pressed_x = event->button.x;
+ icon_bar->pressed_y = event->button.y;
+ gtk_widget_queue_draw (GTK_WIDGET (icon_bar));
+ } else if (button == 3) {
+ gtk_signal_emit (GTK_OBJECT (icon_bar),
+ e_icon_bar_signals[ITEM_SELECTED],
+ event, item_num);
+ }
+}
+
+
+void
+e_icon_bar_item_released (EIconBar *icon_bar,
+ gint item_num,
+ GdkEvent *event)
+{
+ gint button;
+
+ /* If we are editing an item, just return. */
+ if (icon_bar->editing_item_num != -1)
+ return;
+
+ button = event->button.button;
+
+ if (button == 1) {
+ if (icon_bar->pressed_item_num == icon_bar->mouse_over_item_num) {
+ gtk_signal_emit (GTK_OBJECT (icon_bar),
+ e_icon_bar_signals[ITEM_SELECTED],
+ event, item_num);
+ }
+
+ icon_bar->pressed_item_num = -1;
+ gtk_widget_queue_draw (GTK_WIDGET (icon_bar));
+ }
+}
+
+
+void
+e_icon_bar_item_motion (EIconBar *icon_bar,
+ gint item_num,
+ GdkEvent *event)
+{
+ gboolean need_redraw = TRUE;
+
+ if (event && event->motion.state & GDK_BUTTON1_MASK
+ && icon_bar->pressed_item_num != -1) {
+ if (abs (event->motion.x - icon_bar->pressed_x) > E_ICON_BAR_DRAG_START_OFFSET
+ || abs (event->motion.y - icon_bar->pressed_y) > E_ICON_BAR_DRAG_START_OFFSET) {
+ icon_bar->dragged_item_num = icon_bar->pressed_item_num;
+ gtk_signal_emit (GTK_OBJECT (icon_bar),
+ e_icon_bar_signals[ITEM_DRAGGED],
+ event, icon_bar->dragged_item_num);
+
+ /* Don't show the button as pressed while dragging. */
+ icon_bar->pressed_item_num = -1;
+ gtk_widget_queue_draw (GTK_WIDGET (icon_bar));
+ }
+
+ return;
+ }
+
+ if (icon_bar->mouse_over_item_num == item_num)
+ return;
+
+ /* If we are editing an item, items aren't highlighted so we don't
+ need a redraw. Also if an item is pressed, we only need a redraw if
+ item_num or the old mouse_over_item_num is the pressed item. */
+ if (icon_bar->editing_item_num != -1) {
+ need_redraw = FALSE;
+ } else if (icon_bar->pressed_item_num != -1) {
+ if (icon_bar->pressed_item_num != item_num
+ && icon_bar->pressed_item_num != icon_bar->mouse_over_item_num)
+ need_redraw = FALSE;
+ }
+
+ icon_bar->mouse_over_item_num = item_num;
+
+ if (need_redraw)
+ gtk_widget_queue_draw (GTK_WIDGET (icon_bar));
+}
+
+
+/* This returns the index of the item at the given position on the EIconBar,
+ or -1 if no item is found. If before_item is not NULL, it returns the
+ item which the mouse is before, or -1 (for dragging). */
+gint
+e_icon_bar_find_item_at_position (EIconBar *icon_bar,
+ gint x,
+ gint y,
+ gint *before_item)
+{
+ EIconBarItem *item;
+ gint item_num;
+
+ if (before_item)
+ *before_item = -1;
+
+ for (item_num = 0; item_num < icon_bar->items->len; item_num++) {
+ item = &g_array_index (icon_bar->items,
+ EIconBarItem, item_num);
+
+ if (icon_bar->view_type == E_ICON_BAR_LARGE_ICONS) {
+ if (e_icon_bar_large_icons_intersects (icon_bar, item,
+ x, y))
+ return item_num;
+
+ if (before_item
+ && e_icon_bar_large_icons_is_before (icon_bar,
+ item, x, y)) {
+ *before_item = item_num;
+ return -1;
+ }
+ } else {
+ if (e_icon_bar_small_icons_intersects (icon_bar, item,
+ x, y))
+ return item_num;
+
+ if (before_item
+ && e_icon_bar_small_icons_is_before (icon_bar,
+ item, x, y)) {
+ *before_item = item_num;
+ return -1;
+ }
+
+ }
+
+ }
+
+ /* If the mouse is below all the items, but inside the items' width,
+ and before_item is not NULL, we set it to the number of items, so
+ the dropped item would be added at the end. Note that this assumes
+ that the item variable points to the last item in the EIconBar. */
+ if (before_item) {
+ if (icon_bar->view_type == E_ICON_BAR_LARGE_ICONS) {
+ if (x < icon_bar->text_x
+ || x >= icon_bar->text_x + icon_bar->text_w)
+ return -1;
+
+ if (item == NULL
+ || y > item->icon_y + item->item_height)
+ *before_item = icon_bar->items->len;
+ } else {
+ if (x < icon_bar->icon_x
+ || x >= icon_bar->text_x + icon_bar->text_w)
+ return -1;
+
+ if (item == NULL) {
+ *before_item = icon_bar->items->len;
+ } else {
+ gint max_y;
+ max_y = MAX (item->icon_y + icon_bar->icon_h,
+ item->text_y + item->text_height);
+ if (y > max_y)
+ *before_item = icon_bar->items->len;
+ }
+ }
+ }
+
+ return -1;
+}
+
+
+static gboolean
+e_icon_bar_large_icons_intersects (EIconBar *icon_bar,
+ EIconBarItem *item,
+ gint x,
+ gint y)
+{
+ if (y < item->icon_y || y >= item->text_y + item->text_height)
+ return FALSE;
+
+ if (y < item->icon_y + icon_bar->icon_h) {
+ if (x < icon_bar->icon_x
+ || x >= icon_bar->icon_x + icon_bar->icon_w)
+ return FALSE;
+ } else {
+ if (x < item->text_x
+ || x >= item->text_x + item->text_width)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+static gboolean
+e_icon_bar_large_icons_is_before (EIconBar *icon_bar,
+ EIconBarItem *item,
+ gint x,
+ gint y)
+{
+ if (y < item->icon_y - icon_bar->spacing
+ || y >= item->icon_y)
+ return FALSE;
+
+ if (x < icon_bar->text_x || x >= icon_bar->text_x + icon_bar->text_w)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+static gboolean
+e_icon_bar_small_icons_intersects (EIconBar *icon_bar,
+ EIconBarItem *item,
+ gint x,
+ gint y)
+{
+ gint min_y, max_y;
+
+ min_y = MIN (item->icon_y, item->text_y);
+ max_y = MAX (item->icon_y + icon_bar->icon_h,
+ item->text_y + item->text_height);
+
+ if (y < min_y || y >= max_y)
+ return FALSE;
+
+ if (x < icon_bar->icon_x || x >= item->text_x + item->text_width)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+static gboolean
+e_icon_bar_small_icons_is_before (EIconBar *icon_bar,
+ EIconBarItem *item,
+ gint x,
+ gint y)
+{
+ gint min_y, max_y;
+
+ max_y = MIN (item->icon_y, item->text_y);
+ min_y = max_y - icon_bar->spacing;
+
+ if (y < min_y || y >= max_y)
+ return FALSE;
+
+ if (x < icon_bar->icon_x || x >= icon_bar->text_x + icon_bar->text_w)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/**
+ * e_icon_bar_start_editing_item:
+ * @icon_bar: An #EIconBar.
+ * @item_num: The index of the item.
+ *
+ * Turns the item into an editable text field so the user can rename it.
+ * Editing is stopped automatically when the user hits 'Return' or clicks
+ * outside the item. It can also be stopped explicitly by calling
+ * e_icon_bar_stop_editing_item().
+ **/
+void
+e_icon_bar_start_editing_item (EIconBar *icon_bar,
+ gint item_num)
+{
+ EIconBarItem *item;
+
+ g_return_if_fail (E_IS_ICON_BAR (icon_bar));
+ g_return_if_fail (item_num >= 0);
+ g_return_if_fail (item_num < icon_bar->items->len);
+
+ item = &g_array_index (icon_bar->items,
+ EIconBarItem, item_num);
+
+ e_icon_bar_text_item_start_editing (E_ICON_BAR_TEXT_ITEM (item->text));
+}
+
+
+/**
+ * e_icon_bar_stop_editing_item:
+ * @icon_bar: An #EIconBar.
+ * @accept: TRUE if the changes should be accepted, FALSE if the text should be
+ * changed back to its state before the editing started.
+ *
+ * Stops the editing of the items, if any were being edited.
+ **/
+void
+e_icon_bar_stop_editing_item (EIconBar *icon_bar,
+ gboolean accept)
+{
+ EIconBarItem *item;
+
+ g_return_if_fail (E_IS_ICON_BAR (icon_bar));
+
+ if (icon_bar->editing_item_num != -1) {
+ item = &g_array_index (icon_bar->items, EIconBarItem,
+ icon_bar->editing_item_num);
+ e_icon_bar_text_item_stop_editing (E_ICON_BAR_TEXT_ITEM (item->text), accept);
+ }
+}
+
+
+static void
+e_icon_bar_on_text_item_editing_started (EIconBarTextItem *text_item,
+ EIconBar *icon_bar)
+{
+ gint item_num;
+
+ item_num = e_icon_bar_find_item (icon_bar,
+ GNOME_CANVAS_ITEM (text_item));
+ g_return_if_fail (item_num != -1);
+
+ /* Turn off any highlighted item. */
+ e_icon_bar_item_motion (icon_bar, -1, NULL);
+
+ icon_bar->editing_item_num = item_num;
+
+ e_icon_bar_ensure_edited_item_visible (icon_bar);
+}
+
+
+static void
+e_icon_bar_on_text_item_editing_stopped (EIconBarTextItem *text_item,
+ EIconBar *icon_bar)
+{
+ gint item_num;
+
+ item_num = e_icon_bar_find_item (icon_bar,
+ GNOME_CANVAS_ITEM (text_item));
+ g_return_if_fail (item_num != -1);
+
+ e_icon_bar_text_item_select (text_item, FALSE);
+
+ icon_bar->editing_item_num = -1;
+
+ e_icon_bar_update_highlight (icon_bar);
+}
+
+
+static void
+e_icon_bar_ensure_edited_item_visible (EIconBar *icon_bar)
+{
+ EIconBarItem *item;
+ gint scroll_x, scroll_y, min_scroll_y, max_scroll_y, new_scroll_y;
+
+ if (icon_bar->editing_item_num == -1)
+ return;
+
+ item = &g_array_index (icon_bar->items,
+ EIconBarItem, icon_bar->editing_item_num);
+ gnome_canvas_get_scroll_offsets (GNOME_CANVAS (icon_bar),
+ &scroll_x, &scroll_y);
+
+ /* The minimum scroll y position is with the text right on the bottom
+ of the display. */
+ min_scroll_y = item->text_y + item->text_height + E_ICON_BAR_V_SPACE
+ - GTK_WIDGET (icon_bar)->allocation.height;
+ /* The maximum scroll y position is with the text at the top. */
+ max_scroll_y = item->text_y - E_ICON_BAR_V_SPACE;
+
+ new_scroll_y = MAX (scroll_y, min_scroll_y);
+ new_scroll_y = MIN (new_scroll_y, max_scroll_y);
+
+ if (new_scroll_y != scroll_y)
+ gnome_canvas_scroll_to (GNOME_CANVAS (icon_bar),
+ scroll_x, new_scroll_y);
+}
+
+
+/* This gets the mouse position and updates the highlight if necessary.
+ It is called after items are added/deleted/scrolled/edited. */
+static void
+e_icon_bar_update_highlight (EIconBar *icon_bar)
+{
+ GtkWidget *widget;
+ gint x, y, item_num;
+
+ widget = GTK_WIDGET (icon_bar);
+
+ if (!widget->window)
+ return;
+
+ gdk_window_get_pointer (widget->window, &x, &y, NULL);
+
+ if (x < 0 || y < 0
+ || x > widget->allocation.width || y > widget->allocation.height)
+ return;
+
+ item_num = e_icon_bar_find_item_at_position (icon_bar, x, y, NULL);
+ e_icon_bar_item_motion (icon_bar, item_num, NULL);
+}
+
+
+static gint
+e_icon_bar_drag_motion (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time)
+{
+ EIconBar *icon_bar;
+ gint item_num, before_item, scroll_x, scroll_y;
+
+ g_return_val_if_fail (E_IS_ICON_BAR (widget), FALSE);
+
+ icon_bar = E_ICON_BAR (widget);
+
+ icon_bar->in_drag = TRUE;
+
+ /* Check if the mouse is over or between items, and if so highlight. */
+ gnome_canvas_get_scroll_offsets (GNOME_CANVAS (icon_bar),
+ &scroll_x, &scroll_y);
+ item_num = e_icon_bar_find_item_at_position (icon_bar,
+ x + scroll_x,
+ y + scroll_y,
+ &before_item);
+ e_icon_bar_item_motion (icon_bar, item_num, NULL);
+ e_icon_bar_set_dragging_before_item (icon_bar, before_item);
+
+ /* Check if the mouse is at the top or bottom of the bar, and if it is
+ scroll up/down. */
+ if (y < E_ICON_BAR_DRAG_AUTO_SCROLL_OFFSET)
+ icon_bar->scrolling_up = TRUE;
+ else if (y >= widget->allocation.height - E_ICON_BAR_DRAG_AUTO_SCROLL_OFFSET)
+ icon_bar->scrolling_up = FALSE;
+ else {
+ if (icon_bar->auto_scroll_timeout_id != 0) {
+ gtk_timeout_remove (icon_bar->auto_scroll_timeout_id);
+ icon_bar->auto_scroll_timeout_id = 0;
+ }
+ return FALSE;
+ }
+
+ if (icon_bar->auto_scroll_timeout_id == 0) {
+ icon_bar->auto_scroll_timeout_id = g_timeout_add (E_ICON_BAR_SCROLL_TIMEOUT, e_icon_bar_timeout_handler, icon_bar);
+ icon_bar->auto_scroll_delay = E_ICON_BAR_SCROLL_DELAY;
+ }
+
+ return FALSE;
+}
+
+
+static void
+e_icon_bar_drag_leave (GtkWidget *widget,
+ GdkDragContext *context,
+ guint time)
+{
+ EIconBar *icon_bar;
+
+ g_return_if_fail (E_IS_ICON_BAR (widget));
+
+ icon_bar = E_ICON_BAR (widget);
+
+ icon_bar->in_drag = FALSE;
+
+ if (icon_bar->auto_scroll_timeout_id != 0) {
+ gtk_timeout_remove (icon_bar->auto_scroll_timeout_id);
+ icon_bar->auto_scroll_timeout_id = 0;
+ }
+
+ if (icon_bar->mouse_over_item_num != -1) {
+ icon_bar->mouse_over_item_num = -1;
+ gtk_widget_queue_draw (GTK_WIDGET (icon_bar));
+ }
+}
+
+
+static void
+e_icon_bar_set_dragging_before_item (EIconBar *icon_bar,
+ gint before_item)
+{
+ if (icon_bar->dragging_before_item_num == before_item)
+ return;
+
+ icon_bar->dragging_before_item_num = before_item;
+
+ gtk_widget_queue_draw (GTK_WIDGET (icon_bar));
+}
+
+
+static gboolean
+e_icon_bar_timeout_handler (gpointer data)
+{
+ EIconBar *icon_bar;
+ gint scroll_x, scroll_y, new_scroll_y;
+ GtkAdjustment *adj;
+
+ g_return_val_if_fail (E_IS_ICON_BAR (data), FALSE);
+
+ icon_bar = E_ICON_BAR (data);
+
+ GDK_THREADS_ENTER ();
+
+ if (icon_bar->auto_scroll_delay > 0) {
+ icon_bar->auto_scroll_delay--;
+ GDK_THREADS_LEAVE ();
+ return TRUE;
+ }
+
+ gnome_canvas_get_scroll_offsets (GNOME_CANVAS (icon_bar),
+ &scroll_x, &scroll_y);
+
+ adj = GTK_LAYOUT (icon_bar)->vadjustment;
+
+ if (icon_bar->scrolling_up)
+ new_scroll_y = MAX (scroll_y - adj->step_increment, 0);
+ else
+ new_scroll_y = MIN (scroll_y + adj->step_increment,
+ adj->upper - adj->page_size);
+
+ if (new_scroll_y != scroll_y)
+ gnome_canvas_scroll_to (GNOME_CANVAS (icon_bar),
+ scroll_x, new_scroll_y);
+
+ GDK_THREADS_LEAVE ();
+ return TRUE;
+}
diff --git a/widgets/shortcut-bar/e-icon-bar.h b/widgets/shortcut-bar/e-icon-bar.h
new file mode 100644
index 0000000000..74b7507384
--- /dev/null
+++ b/widgets/shortcut-bar/e-icon-bar.h
@@ -0,0 +1,221 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Author :
+ * Damon Chaplin <damon@gtk.org>
+ *
+ * Copyright 1999, Helix Code, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+#ifndef _E_ICON_BAR_H_
+#define _E_ICON_BAR_H_
+
+#include <gdk_imlib.h>
+#include <libgnomeui/gnome-canvas.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * EIconBar is a subclass of GnomeCanvas for displaying a vertical column of
+ * icons and descriptions. It provides 2 views - large icons and small icons.
+ */
+
+
+/* This contains information on one item. */
+typedef struct _EIconBarItem EIconBarItem;
+struct _EIconBarItem
+{
+ GnomeCanvasItem *text;
+ GnomeCanvasItem *image;
+
+ /* This is user data attached to the item, e.g. a URL. */
+ gpointer data;
+ GtkDestroyNotify destroy;
+
+ /* This is the height of the item. */
+ gint item_height;
+
+ /* This is the actual x, width and height of the text, rather than
+ the maximum allowed area. */
+ gint text_x;
+ gint text_width;
+ gint text_height;
+
+ gint icon_y, text_y;
+};
+
+
+/* These are the view types. Defaults to LARGE_ICONS. */
+typedef enum
+{
+ E_ICON_BAR_LARGE_ICONS,
+ E_ICON_BAR_SMALL_ICONS
+} EIconBarViewType;
+
+
+#define E_ICON_BAR(obj) GTK_CHECK_CAST (obj, e_icon_bar_get_type (), EIconBar)
+#define E_ICON_BAR_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, e_icon_bar_get_type (), EIconBarClass)
+#define E_IS_ICON_BAR(obj) GTK_CHECK_TYPE (obj, e_icon_bar_get_type ())
+
+
+typedef struct _EIconBar EIconBar;
+typedef struct _EIconBarClass EIconBarClass;
+
+struct _EIconBar
+{
+ GnomeCanvas canvas;
+
+ /* This specifies if we are using large icons or small icons. */
+ EIconBarViewType view_type;
+
+ /* This is an array of EIconBarItem elements. */
+ GArray *items;
+
+ /* This is the index of the item which has been pressed, or -1.
+ It will be shown as pressed in while the mouse is over it. */
+ gint pressed_item_num;
+
+ /* This is the coordinates of where the button was pressed. If the
+ mouse moves a certain distance with the button still pressed, we
+ start a drag. */
+ gint pressed_x;
+ gint pressed_y;
+
+ /* This is the index of the item the mouse is currently over, or -1.
+ It will be highlighted unless one of the items is pressed. */
+ gint mouse_over_item_num;
+
+ /* This is the item that we are currently editing, or -1. */
+ gint editing_item_num;
+
+ /* This is the index of the item which is being dragged, or -1.
+ If the drag results in a move it will be deleted. */
+ gint dragged_item_num;
+
+ /* This is TRUE if we are dragging over this EIconBar. */
+ gboolean in_drag;
+
+ /* This is used in drag-and-drop to indicate the item which the mouse
+ is currently before, e.g. if it is 1 then a dropped item would be
+ inserted between items 0 and 1. It ranges from 0 to the number of
+ items, or is -1 when the mouse is not dragging between items. */
+ gint dragging_before_item_num;
+
+ /* These are the common positions of all the items in the EIconBar. */
+ gint icon_x, icon_w, icon_h, text_x, text_w, spacing;
+
+ /* This is the source id of our auto-scroll timeout handler, used when
+ in the middle of drag-and-drop operations. */
+ gint auto_scroll_timeout_id;
+ gint auto_scroll_delay;
+ gboolean scrolling_up;
+};
+
+struct _EIconBarClass
+{
+ GnomeCanvasClass parent_class;
+
+ void (*selected_item) (EIconBar *icon_bar,
+ GdkEvent *event,
+ gint item_num);
+ void (*dragged_item) (EIconBar *icon_bar,
+ GdkEvent *event,
+ gint item_num);
+};
+
+
+GtkType e_icon_bar_get_type (void);
+GtkWidget* e_icon_bar_new (void);
+
+/* Sets the view type. */
+void e_icon_bar_set_view_type (EIconBar *icon_bar,
+ EIconBarViewType view_type);
+
+/* Adds a new item to a group at the given position. If position is -1 it is
+ added at the end. It returns the index of the item. */
+gint e_icon_bar_add_item (EIconBar *icon_bar,
+ GdkImlibImage *image,
+ gchar *text,
+ gint position);
+
+/* Reorders an item. Note that position refers to the new position to add the
+ item after removing it from its current position. If position is -1 it is
+ moved to the end of the bar. */
+void e_icon_bar_reorder_item (EIconBar *icon_bar,
+ gint item_num,
+ gint new_position);
+void e_icon_bar_remove_item (EIconBar *icon_bar,
+ gint item_num);
+
+GdkImlibImage* e_icon_bar_get_item_image (EIconBar *icon_bar,
+ gint item_num);
+void e_icon_bar_set_item_image (EIconBar *icon_bar,
+ gint item_num,
+ GdkImlibImage *image);
+
+gchar* e_icon_bar_get_item_text (EIconBar *icon_bar,
+ gint item_num);
+void e_icon_bar_set_item_text (EIconBar *icon_bar,
+ gint item_num,
+ gchar *text);
+
+gpointer e_icon_bar_get_item_data (EIconBar *icon_bar,
+ gint item_num);
+void e_icon_bar_set_item_data (EIconBar *icon_bar,
+ gint item_num,
+ gpointer data);
+void e_icon_bar_set_item_data_full (EIconBar *icon_bar,
+ gint item_num,
+ gpointer data,
+ GtkDestroyNotify destroy);
+
+void e_icon_bar_start_editing_item (EIconBar *icon_bar,
+ gint item_num);
+void e_icon_bar_stop_editing_item (EIconBar *icon_bar,
+ gboolean accept);
+
+
+
+/*
+ * INTERNAL FUNCTIONS - for use by EIconBarBgItem.
+ */
+
+/* This returns the index of the item at the given position on the EIconBar,
+ or -1 if no item is found. If before_item is not NULL, it returns the
+ item which the mouse is before, or -1 (this is used for dragging). */
+gint e_icon_bar_find_item_at_position (EIconBar *icon_bar,
+ gint x,
+ gint y,
+ gint *before_item);
+
+void e_icon_bar_item_pressed (EIconBar *icon_bar,
+ gint item_num,
+ GdkEvent *event);
+void e_icon_bar_item_released (EIconBar *icon_bar,
+ gint item_num,
+ GdkEvent *event);
+void e_icon_bar_item_motion (EIconBar *icon_bar,
+ gint item_num,
+ GdkEvent *event);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _E_ICON_BAR_H_ */
diff --git a/widgets/shortcut-bar/e-shortcut-bar.c b/widgets/shortcut-bar/e-shortcut-bar.c
new file mode 100644
index 0000000000..7ad00feb78
--- /dev/null
+++ b/widgets/shortcut-bar/e-shortcut-bar.c
@@ -0,0 +1,563 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Author :
+ * Damon Chaplin <damon@gtk.org>
+ *
+ * Copyright 1999, Helix Code, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ * ShortcutBar displays a vertical bar with a number of Groups, each of which
+ * contains any number of icons. It is used on the left of the main application
+ * window so users can easily access items such as folders and files.
+ */
+
+#include <string.h>
+#include <gnome.h>
+
+#include "e-shortcut-bar.h"
+#include "e-clipped-label.h"
+#include "e-vscrolled-bar.h"
+
+/* Drag and Drop stuff. */
+enum {
+ TARGET_SHORTCUT
+};
+static GtkTargetEntry target_table[] = {
+ { "E-SHORTCUT", 0, TARGET_SHORTCUT }
+};
+static guint n_targets = sizeof(target_table) / sizeof(target_table[0]);
+
+typedef struct _EShortcutBarBuiltinType EShortcutBarBuiltinType;
+struct _EShortcutBarBuiltinType {
+ gchar *name;
+ gchar *filename;
+ GdkImlibImage *image;
+};
+
+EShortcutBarBuiltinType e_shortcut_bar_builtin_types[] = {
+ { "folder:", "gnome-word.png", NULL },
+ { "calendar:", "gnome-calendar.png", NULL },
+ { "todo:", "gnome-cromagnon.png", NULL },
+ { "contacts:", "gnome-ccthemes.png", NULL }
+};
+static gint e_shortcut_bar_num_builtin_types = sizeof (e_shortcut_bar_builtin_types) / sizeof (EShortcutBarBuiltinType);
+
+gboolean e_shortcut_bar_default_type_image_loaded = FALSE;
+GdkImlibImage *e_shortcut_bar_default_type_image = NULL;
+gchar *e_shortcut_bar_default_type_filename = "gnome-balsa2.png";
+
+static void e_shortcut_bar_class_init (EShortcutBarClass *class);
+static void e_shortcut_bar_init (EShortcutBar *shortcut_bar);
+static void e_shortcut_bar_destroy (GtkObject *object);
+static void e_shortcut_bar_set_canvas_style (EShortcutBar *shortcut_bar,
+ GtkWidget *canvas);
+static void e_shortcut_bar_item_selected (EIconBar *icon_bar,
+ GdkEvent *event,
+ gint item_num,
+ EShortcutBar *shortcut_bar);
+static void e_shortcut_bar_item_dragged (EIconBar *icon_bar,
+ GdkEvent *event,
+ gint item_num,
+ EShortcutBar *shortcut_bar);
+static void e_shortcut_bar_on_drag_data_get (GtkWidget *widget,
+ GdkDragContext *context,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time,
+ EShortcutBar *shortcut_bar);
+static void e_shortcut_bar_on_drag_data_received (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *data,
+ guint info,
+ guint time,
+ EShortcutBar *shortcut_bar);
+static void e_shortcut_bar_on_drag_data_delete (GtkWidget *widget,
+ GdkDragContext *context,
+ EShortcutBar *shortcut_bar);
+static void e_shortcut_bar_stop_editing (GtkWidget *button,
+ EShortcutBar *shortcut_bar);
+static GdkImlibImage* e_shortcut_bar_get_image_from_url (EShortcutBar *shortcut_bar,
+ gchar *item_url);
+static GdkImlibImage* e_shortcut_bar_load_image (gchar *filename);
+
+
+enum
+{
+ ITEM_SELECTED,
+ LAST_SIGNAL
+};
+
+static guint e_shortcut_bar_signals[LAST_SIGNAL] = {0};
+
+static EGroupBarClass *parent_class;
+
+
+GtkType
+e_shortcut_bar_get_type (void)
+{
+ static GtkType e_shortcut_bar_type = 0;
+
+ if (!e_shortcut_bar_type){
+ GtkTypeInfo e_shortcut_bar_info = {
+ "EShortcutBar",
+ sizeof (EShortcutBar),
+ sizeof (EShortcutBarClass),
+ (GtkClassInitFunc) e_shortcut_bar_class_init,
+ (GtkObjectInitFunc) e_shortcut_bar_init,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ parent_class = gtk_type_class (e_group_bar_get_type ());
+ e_shortcut_bar_type = gtk_type_unique (e_group_bar_get_type (),
+ &e_shortcut_bar_info);
+ }
+
+ return e_shortcut_bar_type;
+}
+
+
+static void
+e_shortcut_bar_class_init (EShortcutBarClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = (GtkObjectClass *) class;
+ widget_class = (GtkWidgetClass *) class;
+
+ e_shortcut_bar_signals[ITEM_SELECTED] =
+ gtk_signal_new ("item_selected",
+ GTK_RUN_LAST | GTK_RUN_ACTION,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EShortcutBarClass,
+ selected_item),
+ gtk_marshal_NONE__POINTER_INT_INT,
+ GTK_TYPE_NONE, 3, GTK_TYPE_GDK_EVENT,
+ GTK_TYPE_INT, GTK_TYPE_INT);
+
+ gtk_object_class_add_signals (object_class, e_shortcut_bar_signals,
+ LAST_SIGNAL);
+
+ /* Method override */
+ object_class->destroy = e_shortcut_bar_destroy;
+}
+
+
+static void
+e_shortcut_bar_init (EShortcutBar *shortcut_bar)
+{
+ shortcut_bar->groups = g_array_new (FALSE, FALSE,
+ sizeof (EShortcutBarGroup));
+}
+
+
+GtkWidget *
+e_shortcut_bar_new (void)
+{
+ GtkWidget *shortcut_bar;
+
+ shortcut_bar = GTK_WIDGET (gtk_type_new (e_shortcut_bar_get_type ()));
+
+ return shortcut_bar;
+}
+
+
+static void
+e_shortcut_bar_destroy (GtkObject *object)
+{
+ EShortcutBar *shortcut_bar;
+
+ shortcut_bar = E_SHORTCUT_BAR (object);
+
+ GTK_OBJECT_CLASS (parent_class)->destroy (object);
+
+ g_array_free (shortcut_bar->groups, TRUE);
+}
+
+
+gint
+e_shortcut_bar_add_group (EShortcutBar *shortcut_bar, gchar *group_name)
+{
+ EShortcutBarGroup *group, tmp_group;
+ gint group_num;
+ GtkWidget *button, *label;
+
+ g_return_val_if_fail (E_IS_SHORTCUT_BAR (shortcut_bar), -1);
+ g_return_val_if_fail (group_name != NULL, -1);
+
+ group_num = shortcut_bar->groups->len;
+ g_array_append_val (shortcut_bar->groups, tmp_group);
+
+ group = &g_array_index (shortcut_bar->groups,
+ EShortcutBarGroup, group_num);
+
+ group->vscrolled_bar = e_vscrolled_bar_new (NULL);
+ gtk_widget_show (group->vscrolled_bar);
+ gtk_signal_connect (GTK_OBJECT (E_VSCROLLED_BAR (group->vscrolled_bar)->up_button), "pressed", GTK_SIGNAL_FUNC (e_shortcut_bar_stop_editing), shortcut_bar);
+ gtk_signal_connect (GTK_OBJECT (E_VSCROLLED_BAR (group->vscrolled_bar)->down_button), "pressed", GTK_SIGNAL_FUNC (e_shortcut_bar_stop_editing), shortcut_bar);
+
+ group->icon_bar = e_icon_bar_new ();
+ gtk_widget_show (group->icon_bar);
+ gtk_container_add (GTK_CONTAINER (group->vscrolled_bar),
+ group->icon_bar);
+ gtk_signal_connect (GTK_OBJECT (group->icon_bar), "item_selected",
+ GTK_SIGNAL_FUNC (e_shortcut_bar_item_selected),
+ shortcut_bar);
+ gtk_signal_connect (GTK_OBJECT (group->icon_bar), "item_dragged",
+ GTK_SIGNAL_FUNC (e_shortcut_bar_item_dragged),
+ shortcut_bar);
+ gtk_signal_connect (GTK_OBJECT (group->icon_bar), "drag_data_get",
+ GTK_SIGNAL_FUNC (e_shortcut_bar_on_drag_data_get),
+ shortcut_bar);
+ gtk_signal_connect (GTK_OBJECT (group->icon_bar), "drag_data_received",
+ GTK_SIGNAL_FUNC (e_shortcut_bar_on_drag_data_received),
+ shortcut_bar);
+ gtk_signal_connect (GTK_OBJECT (group->icon_bar), "drag_data_delete",
+ GTK_SIGNAL_FUNC (e_shortcut_bar_on_drag_data_delete),
+ shortcut_bar);
+
+ e_shortcut_bar_set_canvas_style (shortcut_bar, group->icon_bar);
+
+ button = gtk_button_new ();
+ label = e_clipped_label_new (group_name);
+ gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5);
+ gtk_widget_show (label);
+ gtk_container_add (GTK_CONTAINER (button), label);
+ gtk_widget_show (button);
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (e_shortcut_bar_stop_editing),
+ shortcut_bar);
+
+ gtk_drag_dest_set (GTK_WIDGET (group->icon_bar),
+ GTK_DEST_DEFAULT_ALL,
+ target_table, n_targets,
+ GDK_ACTION_COPY | GDK_ACTION_MOVE);
+ gtk_drag_dest_set (GTK_WIDGET (button),
+ GTK_DEST_DEFAULT_ALL,
+ target_table, n_targets,
+ GDK_ACTION_COPY | GDK_ACTION_MOVE);
+
+ e_group_bar_add_group (E_GROUP_BAR (shortcut_bar),
+ group->vscrolled_bar, button, -1);
+
+
+ return group_num;
+}
+
+
+void
+e_shortcut_bar_remove_group (EShortcutBar *shortcut_bar,
+ gint group_num)
+{
+ e_group_bar_remove_group (E_GROUP_BAR (shortcut_bar), group_num);
+ g_array_remove_index (shortcut_bar->groups, group_num);
+}
+
+
+gint
+e_shortcut_bar_add_item (EShortcutBar *shortcut_bar, gint group_num,
+ gchar *item_url, gchar *item_name)
+{
+ EShortcutBarGroup *group;
+ GdkImlibImage *image;
+ gint item_num;
+
+ g_return_val_if_fail (E_IS_SHORTCUT_BAR (shortcut_bar), -1);
+ g_return_val_if_fail (group_num >= 0, -1);
+ g_return_val_if_fail (group_num < shortcut_bar->groups->len, -1);
+ g_return_val_if_fail (item_url != NULL, -1);
+ g_return_val_if_fail (item_name != NULL, -1);
+
+ image = e_shortcut_bar_get_image_from_url (shortcut_bar, item_url);
+
+ group = &g_array_index (shortcut_bar->groups,
+ EShortcutBarGroup, group_num);
+
+ item_num = e_icon_bar_add_item (E_ICON_BAR (group->icon_bar),
+ image, item_name, -1);
+ e_icon_bar_set_item_data_full (E_ICON_BAR (group->icon_bar), item_num,
+ g_strdup (item_url), g_free);
+ return item_num;
+}
+
+
+void
+e_shortcut_bar_remove_item (EShortcutBar *shortcut_bar,
+ gint group_num,
+ gint item_num)
+{
+ EShortcutBarGroup *group;
+
+ g_return_if_fail (E_IS_SHORTCUT_BAR (shortcut_bar));
+ g_return_if_fail (group_num >= 0);
+ g_return_if_fail (group_num < shortcut_bar->groups->len);
+
+ group = &g_array_index (shortcut_bar->groups,
+ EShortcutBarGroup, group_num);
+
+ e_icon_bar_remove_item (E_ICON_BAR (group->icon_bar), item_num);
+}
+
+
+static void
+e_shortcut_bar_set_canvas_style (EShortcutBar *shortcut_bar,
+ GtkWidget *canvas)
+{
+ GtkRcStyle *rc_style;
+
+ rc_style = gtk_rc_style_new ();
+
+ rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG | GTK_RC_BG;
+ rc_style->fg[GTK_STATE_NORMAL].red = 65535;
+ rc_style->fg[GTK_STATE_NORMAL].green = 65535;
+ rc_style->fg[GTK_STATE_NORMAL].blue = 65535;
+
+ rc_style->bg[GTK_STATE_NORMAL].red = 32512;
+ rc_style->bg[GTK_STATE_NORMAL].green = 32512;
+ rc_style->bg[GTK_STATE_NORMAL].blue = 32512;
+
+ gtk_widget_modify_style (GTK_WIDGET (canvas), rc_style);
+ gtk_rc_style_unref (rc_style);
+}
+
+
+void
+e_shortcut_bar_set_view_type (EShortcutBar *shortcut_bar,
+ gint group_num,
+ EIconBarViewType view_type)
+{
+ EShortcutBarGroup *group;
+
+ g_return_if_fail (E_IS_SHORTCUT_BAR (shortcut_bar));
+ g_return_if_fail (group_num >= 0);
+ g_return_if_fail (group_num < shortcut_bar->groups->len);
+
+ group = &g_array_index (shortcut_bar->groups,
+ EShortcutBarGroup, group_num);
+
+ e_icon_bar_set_view_type (E_ICON_BAR (group->icon_bar), view_type);
+}
+
+
+static void
+e_shortcut_bar_item_selected (EIconBar *icon_bar,
+ GdkEvent *event,
+ gint item_num,
+ EShortcutBar *shortcut_bar)
+{
+ gint group_num;
+
+ group_num = e_group_bar_get_group_num (E_GROUP_BAR (shortcut_bar),
+ GTK_WIDGET (icon_bar)->parent);
+
+ gtk_signal_emit (GTK_OBJECT (shortcut_bar),
+ e_shortcut_bar_signals[ITEM_SELECTED],
+ event, group_num, item_num);
+}
+
+
+static void
+e_shortcut_bar_item_dragged (EIconBar *icon_bar,
+ GdkEvent *event,
+ gint item_num,
+ EShortcutBar *shortcut_bar)
+{
+ GtkTargetList *target_list;
+ gint group_num;
+
+ group_num = e_group_bar_get_group_num (E_GROUP_BAR (shortcut_bar),
+ GTK_WIDGET (icon_bar)->parent);
+
+ /* FIXME: free somewhere - drag_end? */
+ shortcut_bar->dragged_url = g_strdup (e_icon_bar_get_item_data (icon_bar, item_num));
+ shortcut_bar->dragged_name = g_strdup (e_icon_bar_get_item_text (icon_bar, item_num));
+
+ target_list = gtk_target_list_new (target_table, n_targets);
+ gtk_drag_begin (GTK_WIDGET (icon_bar), target_list,
+ GDK_ACTION_COPY | GDK_ACTION_MOVE,
+ 1, event);
+ gtk_target_list_unref (target_list);
+}
+
+
+static void
+e_shortcut_bar_on_drag_data_get (GtkWidget *widget,
+ GdkDragContext *context,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time,
+ EShortcutBar *shortcut_bar)
+{
+ gchar *data;
+
+ if (info == TARGET_SHORTCUT) {
+ data = g_strdup_printf ("%s%c%s", shortcut_bar->dragged_name,
+ '\0', shortcut_bar->dragged_url);
+ gtk_selection_data_set (selection_data, selection_data->target,
+ 8, data,
+ strlen (shortcut_bar->dragged_name)
+ + strlen (shortcut_bar->dragged_url)
+ + 2);
+ g_free (data);
+ }
+}
+
+
+static void
+e_shortcut_bar_on_drag_data_received (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *data,
+ guint info,
+ guint time,
+ EShortcutBar *shortcut_bar)
+{
+ EShortcutBarGroup *group;
+ gchar *item_name, *item_url;
+ EIconBar *icon_bar;
+ GdkImlibImage *image;
+ gint group_num, item_num;
+
+ icon_bar = E_ICON_BAR (widget);
+
+ if ((data->length >= 0) && (data->format == 8)
+ && icon_bar->dragging_before_item_num != -1) {
+ item_name = data->data;
+ item_url = item_name + strlen (item_name) + 1;
+
+ image = e_shortcut_bar_get_image_from_url (shortcut_bar,
+ item_url);
+
+ group_num = e_group_bar_get_group_num (E_GROUP_BAR (shortcut_bar),
+ GTK_WIDGET (icon_bar)->parent);
+ group = &g_array_index (shortcut_bar->groups,
+ EShortcutBarGroup, group_num);
+
+ item_num = e_icon_bar_add_item (E_ICON_BAR (group->icon_bar), image, item_name, icon_bar->dragging_before_item_num);
+ e_icon_bar_set_item_data_full (E_ICON_BAR (group->icon_bar),
+ item_num, g_strdup (item_url),
+ g_free);
+
+ gtk_drag_finish (context, TRUE, TRUE, time);
+ return;
+ }
+
+ gtk_drag_finish (context, FALSE, FALSE, time);
+}
+
+
+static void
+e_shortcut_bar_on_drag_data_delete (GtkWidget *widget,
+ GdkDragContext *context,
+ EShortcutBar *shortcut_bar)
+{
+ EIconBar *icon_bar;
+
+ icon_bar = E_ICON_BAR (widget);
+
+ e_icon_bar_remove_item (icon_bar, icon_bar->dragged_item_num);
+}
+
+
+void
+e_shortcut_bar_start_editing_item (EShortcutBar *shortcut_bar,
+ gint group_num,
+ gint item_num)
+{
+ EShortcutBarGroup *group;
+
+ g_return_if_fail (E_IS_SHORTCUT_BAR (shortcut_bar));
+ g_return_if_fail (group_num >= 0);
+ g_return_if_fail (group_num < shortcut_bar->groups->len);
+
+ group = &g_array_index (shortcut_bar->groups,
+ EShortcutBarGroup, group_num);
+
+ e_icon_bar_start_editing_item (E_ICON_BAR (group->icon_bar), item_num);
+}
+
+
+/* We stop editing any item when a scroll button is pressed. */
+static void
+e_shortcut_bar_stop_editing (GtkWidget *button,
+ EShortcutBar *shortcut_bar)
+{
+ EShortcutBarGroup *group;
+ gint group_num;
+
+ for (group_num = 0;
+ group_num < shortcut_bar->groups->len;
+ group_num++) {
+ group = &g_array_index (shortcut_bar->groups,
+ EShortcutBarGroup, group_num);
+ e_icon_bar_stop_editing_item (E_ICON_BAR (group->icon_bar),
+ TRUE);
+ }
+}
+
+
+static GdkImlibImage*
+e_shortcut_bar_get_image_from_url (EShortcutBar *shortcut_bar,
+ gchar *item_url)
+{
+ gchar *method_terminator;
+ gint method_len, i;
+
+ method_terminator = strchr (item_url, ':');
+ if (method_terminator) {
+ method_len = method_terminator - item_url + 1;
+
+ /* Check if it is a builtin type. */
+ for (i = 0; i < e_shortcut_bar_num_builtin_types; i++) {
+ if (!strncmp (item_url, e_shortcut_bar_builtin_types[i].name, method_len)) {
+ if (!e_shortcut_bar_builtin_types[i].image)
+ e_shortcut_bar_builtin_types[i].image = e_shortcut_bar_load_image (e_shortcut_bar_builtin_types[i].filename);
+ return e_shortcut_bar_builtin_types[i].image;
+ }
+ }
+ }
+
+ if (!e_shortcut_bar_default_type_image_loaded) {
+ e_shortcut_bar_default_type_image_loaded = TRUE;
+ e_shortcut_bar_default_type_image = e_shortcut_bar_load_image (e_shortcut_bar_default_type_filename);
+ }
+ return e_shortcut_bar_default_type_image;
+}
+
+
+static GdkImlibImage*
+e_shortcut_bar_load_image (gchar *filename)
+{
+ gchar *pathname;
+ GdkImlibImage *image = NULL;
+
+ pathname = gnome_pixmap_file (filename);
+ if (pathname)
+ image = gdk_imlib_load_image (pathname);
+ else
+ g_warning ("Couldn't find pixmap: %s", filename);
+
+ return image;
+}
diff --git a/widgets/shortcut-bar/e-shortcut-bar.h b/widgets/shortcut-bar/e-shortcut-bar.h
new file mode 100644
index 0000000000..1bbdfb6754
--- /dev/null
+++ b/widgets/shortcut-bar/e-shortcut-bar.h
@@ -0,0 +1,114 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Author :
+ * Damon Chaplin <damon@gtk.org>
+ *
+ * Copyright 1999, Helix Code, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+#ifndef _E_SHORTCUT_BAR_H_
+#define _E_SHORTCUT_BAR_H_
+
+#include "e-group-bar.h"
+#include "e-icon-bar.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * EShortcutBar displays a vertical bar with a number of Groups, each of which
+ * contains any number of icons. It is used on the left of the main application
+ * window so users can easily access items such as folders and files.
+ */
+
+
+/* This contains information on one group. */
+typedef struct _EShortcutBarGroup EShortcutBarGroup;
+struct _EShortcutBarGroup
+{
+ /* This is the EVScrolledBar which scrolls the group. */
+ GtkWidget *vscrolled_bar;
+
+ /* This is the icon bar containing the child items. */
+ GtkWidget *icon_bar;
+};
+
+
+#define E_SHORTCUT_BAR(obj) GTK_CHECK_CAST (obj, e_shortcut_bar_get_type (), EShortcutBar)
+#define E_SHORTCUT_BAR_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, e_shortcut_bar_get_type (), EShortcutBarClass)
+#define E_IS_SHORTCUT_BAR(obj) GTK_CHECK_TYPE (obj, e_shortcut_bar_get_type ())
+
+
+typedef struct _EShortcutBar EShortcutBar;
+typedef struct _EShortcutBarClass EShortcutBarClass;
+
+struct _EShortcutBar
+{
+ EGroupBar group_bar;
+
+ /* This is an array of EShortcutBarGroup elements. */
+ GArray *groups;
+
+ gchar *dragged_url;
+ gchar *dragged_name;
+};
+
+struct _EShortcutBarClass
+{
+ EGroupBarClass parent_class;
+
+ void (*selected_item) (EShortcutBar *shortcut_bar,
+ GdkEvent *event,
+ gint group_num,
+ gint item_num);
+};
+
+
+GtkType e_shortcut_bar_get_type (void);
+GtkWidget* e_shortcut_bar_new (void);
+
+/* Adds a new group, returning the index. */
+gint e_shortcut_bar_add_group (EShortcutBar *shortcut_bar,
+ gchar *group_name);
+void e_shortcut_bar_remove_group (EShortcutBar *shortcut_bar,
+ gint group_num);
+
+/* Sets the view type for the group. */
+void e_shortcut_bar_set_view_type (EShortcutBar *shortcut_bar,
+ gint group_num,
+ EIconBarViewType view_type);
+
+/* Adds a new item to a group, returning the index within the group. */
+gint e_shortcut_bar_add_item (EShortcutBar *shortcut_bar,
+ gint group_num,
+ gchar *item_url,
+ gchar *item_name);
+
+void e_shortcut_bar_start_editing_item (EShortcutBar *shortcut_bar,
+ gint group_num,
+ gint item_num);
+void e_shortcut_bar_remove_item (EShortcutBar *shortcut_bar,
+ gint group_num,
+ gint item_num);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _E_SHORTCUT_BAR_H_ */
diff --git a/widgets/shortcut-bar/e-vscrolled-bar.c b/widgets/shortcut-bar/e-vscrolled-bar.c
new file mode 100644
index 0000000000..5d5f0ab2e2
--- /dev/null
+++ b/widgets/shortcut-bar/e-vscrolled-bar.c
@@ -0,0 +1,652 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Author :
+ * Damon Chaplin <damon@gtk.org>
+ *
+ * Copyright 1999, Helix Code, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ * EVScrolledBar is like GtkScrolledWindow but only scrolls the child widget
+ * vertically. It is intended for scrolling narrow vertical bars.
+ */
+
+#include <gtk/gtkarrow.h>
+#include <gtk/gtkbutton.h>
+#include <gtk/gtksignal.h>
+
+#include "e-vscrolled-bar.h"
+
+/* These are the offsets of the up & down buttons from the right and top/bottom
+ of the widget. */
+#define E_VSCROLLED_BAR_BUTTON_X_OFFSET 2
+#define E_VSCROLLED_BAR_BUTTON_Y_OFFSET 2
+
+/* This is the time between scrolls. */
+#define E_VSCROLLED_BAR_SCROLL_TIMEOUT 20
+
+static void e_vscrolled_bar_class_init (EVScrolledBarClass *class);
+static void e_vscrolled_bar_init (EVScrolledBar *vscrolled_bar);
+static void e_vscrolled_bar_destroy (GtkObject *object);
+static void e_vscrolled_bar_finalize (GtkObject *object);
+static void e_vscrolled_bar_map (GtkWidget *widget);
+static void e_vscrolled_bar_unmap (GtkWidget *widget);
+static void e_vscrolled_bar_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void e_vscrolled_bar_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void e_vscrolled_bar_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static void e_vscrolled_bar_add (GtkContainer *container,
+ GtkWidget *child);
+static void e_vscrolled_bar_remove (GtkContainer *container,
+ GtkWidget *child);
+static void e_vscrolled_bar_forall (GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data);
+static void e_vscrolled_bar_adjustment_changed (GtkAdjustment *adjustment,
+ gpointer data);
+static void e_vscrolled_bar_button_pressed (GtkWidget *button,
+ EVScrolledBar *vscrolled_bar);
+static void e_vscrolled_bar_button_released (GtkWidget *button,
+ EVScrolledBar *vscrolled_bar);
+static void e_vscrolled_bar_button_clicked (GtkWidget *button,
+ EVScrolledBar *vscrolled_bar);
+static gboolean e_vscrolled_bar_timeout_handler (gpointer data);
+
+
+static GtkBinClass *parent_class;
+
+
+GtkType
+e_vscrolled_bar_get_type (void)
+{
+ static GtkType e_vscrolled_bar_type = 0;
+
+ if (!e_vscrolled_bar_type) {
+ GtkTypeInfo e_vscrolled_bar_info = {
+ "EVScrolledBar",
+ sizeof (EVScrolledBar),
+ sizeof (EVScrolledBarClass),
+ (GtkClassInitFunc) e_vscrolled_bar_class_init,
+ (GtkObjectInitFunc) e_vscrolled_bar_init,
+ NULL, /* reserved 1 */
+ NULL, /* reserved 2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ parent_class = gtk_type_class (GTK_TYPE_BIN);
+ e_vscrolled_bar_type = gtk_type_unique (GTK_TYPE_BIN,
+ &e_vscrolled_bar_info);
+ }
+
+ return e_vscrolled_bar_type;
+}
+
+
+static void
+e_vscrolled_bar_class_init (EVScrolledBarClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+
+ object_class = (GtkObjectClass *) class;
+ widget_class = (GtkWidgetClass *) class;
+ container_class = (GtkContainerClass *) class;
+
+ /* Method override */
+ object_class->destroy = e_vscrolled_bar_destroy;
+ object_class->finalize = e_vscrolled_bar_finalize;
+
+ widget_class->map = e_vscrolled_bar_map;
+ widget_class->unmap = e_vscrolled_bar_unmap;
+ widget_class->size_request = e_vscrolled_bar_size_request;
+ widget_class->size_allocate = e_vscrolled_bar_size_allocate;
+ widget_class->draw = e_vscrolled_bar_draw;
+
+ container_class->add = e_vscrolled_bar_add;
+ container_class->remove = e_vscrolled_bar_remove;
+ container_class->forall = e_vscrolled_bar_forall;
+}
+
+
+static void
+e_vscrolled_bar_init (EVScrolledBar *vscrolled_bar)
+{
+ GtkWidget *arrow;
+
+ GTK_WIDGET_SET_FLAGS (vscrolled_bar, GTK_NO_WINDOW);
+
+ gtk_container_set_resize_mode (GTK_CONTAINER (vscrolled_bar),
+ GTK_RESIZE_QUEUE);
+
+ gtk_widget_push_composite_child ();
+
+ vscrolled_bar->up_button = gtk_button_new ();
+ gtk_widget_set_composite_name (vscrolled_bar->up_button,
+ "up_button");
+ gtk_widget_set_parent (vscrolled_bar->up_button,
+ GTK_WIDGET (vscrolled_bar));
+ arrow = gtk_arrow_new (GTK_ARROW_UP, GTK_SHADOW_OUT);
+ gtk_misc_set_padding (GTK_MISC (arrow), 1, 1);
+ gtk_widget_show (arrow);
+ gtk_container_add (GTK_CONTAINER (vscrolled_bar->up_button), arrow);
+ gtk_signal_connect_after (GTK_OBJECT (vscrolled_bar->up_button), "pressed", GTK_SIGNAL_FUNC (e_vscrolled_bar_button_pressed), vscrolled_bar);
+ gtk_signal_connect_after (GTK_OBJECT (vscrolled_bar->up_button), "released", GTK_SIGNAL_FUNC (e_vscrolled_bar_button_released), vscrolled_bar);
+ gtk_signal_connect (GTK_OBJECT (vscrolled_bar->up_button), "clicked", GTK_SIGNAL_FUNC (e_vscrolled_bar_button_clicked), vscrolled_bar);
+
+ vscrolled_bar->down_button = gtk_button_new ();
+ gtk_widget_set_composite_name (vscrolled_bar->up_button,
+ "down_button");
+ gtk_widget_set_parent (vscrolled_bar->down_button,
+ GTK_WIDGET (vscrolled_bar));
+ arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
+ gtk_misc_set_padding (GTK_MISC (arrow), 1, 1);
+ gtk_widget_show (arrow);
+ gtk_container_add (GTK_CONTAINER (vscrolled_bar->down_button), arrow);
+ gtk_signal_connect_after (GTK_OBJECT (vscrolled_bar->down_button), "pressed", GTK_SIGNAL_FUNC (e_vscrolled_bar_button_pressed), vscrolled_bar);
+ gtk_signal_connect_after (GTK_OBJECT (vscrolled_bar->down_button), "released", GTK_SIGNAL_FUNC (e_vscrolled_bar_button_released), vscrolled_bar);
+ gtk_signal_connect (GTK_OBJECT (vscrolled_bar->down_button), "clicked", GTK_SIGNAL_FUNC (e_vscrolled_bar_button_clicked), vscrolled_bar);
+
+ gtk_widget_pop_composite_child ();
+
+ vscrolled_bar->adjustment = NULL;
+ vscrolled_bar->timeout_id = 0;
+ vscrolled_bar->scrolling_up = FALSE;
+ vscrolled_bar->min_distance = -1.0;
+ vscrolled_bar->button_pressed = FALSE;
+}
+
+
+/**
+ * e_vscrolled_bar_new:
+ *
+ * @adjustment: The #GtkAdjustment to use for scrolling, or NULL.
+ * @Return: A new #EVScrolledBar.
+ *
+ * Creates a new #EVScrolledBar with the given adjustment.
+ **/
+GtkWidget *
+e_vscrolled_bar_new (GtkAdjustment *adjustment)
+{
+ GtkWidget *vscrolled_bar;
+
+ vscrolled_bar = GTK_WIDGET (gtk_type_new (e_vscrolled_bar_get_type ()));
+ e_vscrolled_bar_set_adjustment (E_VSCROLLED_BAR (vscrolled_bar),
+ adjustment);
+
+ return vscrolled_bar;
+}
+
+
+static void
+e_vscrolled_bar_destroy (GtkObject *object)
+{
+ EVScrolledBar *vscrolled_bar;
+
+ vscrolled_bar = E_VSCROLLED_BAR (object);
+
+ if (vscrolled_bar->timeout_id) {
+ g_source_remove (vscrolled_bar->timeout_id);
+ vscrolled_bar->timeout_id = 0;
+ }
+
+ gtk_widget_unparent (vscrolled_bar->up_button);
+ gtk_widget_unparent (vscrolled_bar->down_button);
+
+ GTK_OBJECT_CLASS (parent_class)->destroy (object);
+}
+
+
+static void
+e_vscrolled_bar_finalize (GtkObject *object)
+{
+ EVScrolledBar *vscrolled_bar;
+
+ vscrolled_bar = E_VSCROLLED_BAR (object);
+
+ gtk_object_unref (GTK_OBJECT (vscrolled_bar->adjustment));
+
+ GTK_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+static void
+e_vscrolled_bar_map (GtkWidget *widget)
+{
+ EVScrolledBar *vscrolled_bar;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (E_IS_VSCROLLED_BAR (widget));
+
+ vscrolled_bar = E_VSCROLLED_BAR (widget);
+
+ /* chain parent class handler to map self and child */
+ GTK_WIDGET_CLASS (parent_class)->map (widget);
+
+ if (GTK_WIDGET_VISIBLE (vscrolled_bar->up_button) &&
+ !GTK_WIDGET_MAPPED (vscrolled_bar->up_button))
+ gtk_widget_map (vscrolled_bar->up_button);
+
+ if (GTK_WIDGET_VISIBLE (vscrolled_bar->down_button) &&
+ !GTK_WIDGET_MAPPED (vscrolled_bar->down_button))
+ gtk_widget_map (vscrolled_bar->down_button);
+}
+
+
+static void
+e_vscrolled_bar_unmap (GtkWidget *widget)
+{
+ EVScrolledBar *vscrolled_bar;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (E_IS_VSCROLLED_BAR (widget));
+
+ vscrolled_bar = E_VSCROLLED_BAR (widget);
+
+ /* chain parent class handler to unmap self and child */
+ GTK_WIDGET_CLASS (parent_class)->unmap (widget);
+
+ if (GTK_WIDGET_MAPPED (vscrolled_bar->up_button))
+ gtk_widget_unmap (vscrolled_bar->up_button);
+
+ if (GTK_WIDGET_MAPPED (vscrolled_bar->down_button))
+ gtk_widget_unmap (vscrolled_bar->down_button);
+}
+
+
+static void
+e_vscrolled_bar_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ EVScrolledBar *vscrolled_bar;
+ GtkBin *bin;
+ GtkRequisition child_requisition;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (E_IS_VSCROLLED_BAR (widget));
+ g_return_if_fail (requisition != NULL);
+
+ vscrolled_bar = E_VSCROLLED_BAR (widget);
+ bin = GTK_BIN (widget);
+
+ requisition->width = 0;
+ requisition->height = 0;
+
+ /* We just return the requisition of the child widget, plus the
+ border width. */
+ if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) {
+ gtk_widget_size_request (bin->child, &child_requisition);
+ *requisition = child_requisition;
+ }
+
+ /* We remember the requested heights of the up & down buttons. */
+ gtk_widget_size_request (vscrolled_bar->up_button,
+ &child_requisition);
+ vscrolled_bar->up_button_width = child_requisition.width;
+ vscrolled_bar->up_button_height = child_requisition.height;
+
+ gtk_widget_size_request (vscrolled_bar->down_button,
+ &child_requisition);
+ vscrolled_bar->down_button_width = child_requisition.width;
+ vscrolled_bar->down_button_height = child_requisition.height;
+
+ /* Add on the standard container border widths. */
+ requisition->width += GTK_CONTAINER (widget)->border_width * 2;
+ requisition->height += GTK_CONTAINER (widget)->border_width * 2;
+}
+
+
+static void
+e_vscrolled_bar_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ EVScrolledBar *vscrolled_bar;
+ GtkBin *bin;
+ GtkAllocation button_allocation, child_allocation;
+ gint border_width;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (E_IS_VSCROLLED_BAR (widget));
+ g_return_if_fail (allocation != NULL);
+
+ vscrolled_bar = E_VSCROLLED_BAR (widget);
+ bin = GTK_BIN (widget);
+
+ widget->allocation = *allocation;
+
+ border_width = GTK_CONTAINER (widget)->border_width;
+
+ child_allocation.x = border_width;
+ child_allocation.y = border_width;
+ child_allocation.width = allocation->width - 2 * border_width;
+ child_allocation.height = allocation->height - 2 * border_width;
+ gtk_widget_size_allocate (bin->child, &child_allocation);
+
+ button_allocation.x = allocation->width - border_width
+ - vscrolled_bar->up_button_width
+ - E_VSCROLLED_BAR_BUTTON_X_OFFSET;
+ button_allocation.y = border_width + E_VSCROLLED_BAR_BUTTON_Y_OFFSET;
+ button_allocation.width = vscrolled_bar->up_button_width;
+ button_allocation.height = vscrolled_bar->up_button_height;
+ gtk_widget_size_allocate (vscrolled_bar->up_button,
+ &button_allocation);
+
+ button_allocation.x = allocation->width - border_width
+ - vscrolled_bar->down_button_width
+ - E_VSCROLLED_BAR_BUTTON_X_OFFSET;
+ button_allocation.y = allocation->height - border_width
+ - vscrolled_bar->down_button_height
+ - E_VSCROLLED_BAR_BUTTON_Y_OFFSET;
+ button_allocation.width = vscrolled_bar->down_button_width;
+ button_allocation.height = vscrolled_bar->down_button_height;
+ gtk_widget_size_allocate (vscrolled_bar->down_button,
+ &button_allocation);
+}
+
+
+static void
+e_vscrolled_bar_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ EVScrolledBar *vscrolled_bar;
+ GtkBin *bin;
+ GdkRectangle child_area;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (E_IS_VSCROLLED_BAR (widget));
+ g_return_if_fail (area != NULL);
+
+ vscrolled_bar = E_VSCROLLED_BAR (widget);
+ bin = GTK_BIN (widget);
+
+ if (bin->child && GTK_WIDGET_VISIBLE (bin->child) &&
+ gtk_widget_intersect (bin->child, area, &child_area))
+ gtk_widget_draw (bin->child, &child_area);
+
+ if (GTK_WIDGET_VISIBLE (vscrolled_bar->up_button) &&
+ gtk_widget_intersect (vscrolled_bar->up_button, area, &child_area))
+ gtk_widget_draw (vscrolled_bar->up_button, &child_area);
+
+ if (GTK_WIDGET_VISIBLE (vscrolled_bar->down_button) &&
+ gtk_widget_intersect (vscrolled_bar->down_button, area, &child_area))
+ gtk_widget_draw (vscrolled_bar->down_button, &child_area);
+}
+
+
+static void
+e_vscrolled_bar_add (GtkContainer *container,
+ GtkWidget *child)
+{
+ EVScrolledBar *vscrolled_bar;
+ GtkBin *bin;
+
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (E_IS_VSCROLLED_BAR (container));
+
+ vscrolled_bar = E_VSCROLLED_BAR (container);
+ bin = GTK_BIN (container);
+
+ g_return_if_fail (bin->child == NULL);
+
+ bin->child = child;
+ gtk_widget_set_parent (child, GTK_WIDGET (bin));
+
+ gtk_widget_set_scroll_adjustments (child, NULL,
+ vscrolled_bar->adjustment);
+
+ if (GTK_WIDGET_REALIZED (child->parent))
+ gtk_widget_realize (child);
+
+ if (GTK_WIDGET_VISIBLE (child->parent) && GTK_WIDGET_VISIBLE (child)) {
+ if (GTK_WIDGET_MAPPED (child->parent))
+ gtk_widget_map (child);
+
+ gtk_widget_queue_resize (child);
+ }
+}
+
+
+static void
+e_vscrolled_bar_remove (GtkContainer *container,
+ GtkWidget *child)
+{
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (E_IS_VSCROLLED_BAR (container));
+ g_return_if_fail (child != NULL);
+ g_return_if_fail (GTK_BIN (container)->child == child);
+
+ gtk_widget_set_scroll_adjustments (child, NULL, NULL);
+
+ /* chain parent class handler to remove child */
+ GTK_CONTAINER_CLASS (parent_class)->remove (container, child);
+}
+
+
+static void
+e_vscrolled_bar_forall (GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (E_IS_VSCROLLED_BAR (container));
+ g_return_if_fail (callback != NULL);
+
+ GTK_CONTAINER_CLASS (parent_class)->forall (container,
+ include_internals,
+ callback,
+ callback_data);
+ if (include_internals) {
+ EVScrolledBar *vscrolled_bar;
+
+ vscrolled_bar = E_VSCROLLED_BAR (container);
+
+ if (vscrolled_bar->up_button)
+ callback (vscrolled_bar->up_button, callback_data);
+ if (vscrolled_bar->down_button)
+ callback (vscrolled_bar->down_button, callback_data);
+ }
+}
+
+
+/**
+ * e_vscrolled_bar_get_adjustment:
+ *
+ * @vscrolled_bar: An #EVScrolledBar.
+ * @Return: The #GtkAdjustment used for scrolling @vscrolled_bar.
+ *
+ * Returns the #GtkAdjustment used for scrolling the #EVscrolledBar.
+ **/
+GtkAdjustment*
+e_vscrolled_bar_get_adjustment (EVScrolledBar *vscrolled_bar)
+{
+ g_return_val_if_fail (vscrolled_bar != NULL, NULL);
+ g_return_val_if_fail (E_IS_VSCROLLED_BAR (vscrolled_bar), NULL);
+
+ return vscrolled_bar->adjustment;
+}
+
+
+/**
+ * e_vscrolled_bar_set_adjustment:
+ *
+ * @vscrolled_bar: An #EVScrolledBar.
+ * @adjustment: The #GtkAdjustment to use for scrolling @vscrolled_bar.
+ *
+ * Sets the #GtkAdjustment to use for scrolling the #EVscrolledBar.
+ **/
+void
+e_vscrolled_bar_set_adjustment (EVScrolledBar *vscrolled_bar,
+ GtkAdjustment *adjustment)
+{
+ g_return_if_fail (vscrolled_bar != NULL);
+ g_return_if_fail (E_IS_VSCROLLED_BAR (vscrolled_bar));
+
+ if (adjustment)
+ g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
+ else
+ adjustment = (GtkAdjustment*) gtk_object_new (GTK_TYPE_ADJUSTMENT, NULL);
+
+ if (vscrolled_bar->adjustment == adjustment)
+ return;
+
+ if (vscrolled_bar->adjustment) {
+ gtk_signal_disconnect_by_func (GTK_OBJECT (vscrolled_bar->adjustment),
+ GTK_SIGNAL_FUNC (e_vscrolled_bar_adjustment_changed),
+ vscrolled_bar);
+ gtk_object_unref (GTK_OBJECT (vscrolled_bar->adjustment));
+ }
+
+ vscrolled_bar->adjustment = adjustment;
+ gtk_object_ref (GTK_OBJECT (vscrolled_bar->adjustment));
+ gtk_object_sink (GTK_OBJECT (vscrolled_bar->adjustment));
+
+ /* I've used connect_after here to avoid a problem when using a
+ GnomeCanvas as the child widget. When just using connect it would
+ leave a blank space when one of the buttons is hidden. We want
+ the GtkLayout to handle the scrolling before we hide any buttons. */
+ gtk_signal_connect_after (GTK_OBJECT (adjustment), "changed",
+ GTK_SIGNAL_FUNC (e_vscrolled_bar_adjustment_changed),
+ vscrolled_bar);
+ gtk_signal_connect_after (GTK_OBJECT (adjustment), "value_changed",
+ GTK_SIGNAL_FUNC (e_vscrolled_bar_adjustment_changed),
+ vscrolled_bar);
+
+ e_vscrolled_bar_adjustment_changed (adjustment, vscrolled_bar);
+
+ if (GTK_BIN (vscrolled_bar)->child)
+ gtk_widget_set_scroll_adjustments (GTK_BIN (vscrolled_bar)->child, NULL, adjustment);
+}
+
+
+static void
+e_vscrolled_bar_adjustment_changed (GtkAdjustment *adjustment,
+ gpointer data)
+{
+ EVScrolledBar *vscrolled_bar;
+
+ g_return_if_fail (adjustment != NULL);
+ g_return_if_fail (data != NULL);
+
+ vscrolled_bar = E_VSCROLLED_BAR (data);
+
+ /* If the adjustment value is not 0, show the up button. */
+ if (adjustment->value != 0)
+ gtk_widget_show (vscrolled_bar->up_button);
+ else
+ gtk_widget_hide (vscrolled_bar->up_button);
+
+ /* If the adjustment value is less than the maximum value, show the
+ down button. */
+ if (adjustment->value < adjustment->upper - adjustment->page_size)
+ gtk_widget_show (vscrolled_bar->down_button);
+ else
+ gtk_widget_hide (vscrolled_bar->down_button);
+}
+
+
+static void
+e_vscrolled_bar_button_pressed (GtkWidget *button,
+ EVScrolledBar *vscrolled_bar)
+{
+ if (vscrolled_bar->timeout_id != 0)
+ g_source_remove (vscrolled_bar->timeout_id);
+
+ vscrolled_bar->timeout_id = g_timeout_add (E_VSCROLLED_BAR_SCROLL_TIMEOUT, e_vscrolled_bar_timeout_handler, vscrolled_bar);
+ vscrolled_bar->scrolling_up = (button == vscrolled_bar->up_button) ? TRUE : FALSE;
+ vscrolled_bar->min_distance = vscrolled_bar->adjustment->page_size / 4;
+ vscrolled_bar->button_pressed = TRUE;
+
+ e_vscrolled_bar_timeout_handler (vscrolled_bar);
+}
+
+
+static void
+e_vscrolled_bar_button_released (GtkWidget *button,
+ EVScrolledBar *vscrolled_bar)
+{
+ vscrolled_bar->button_pressed = FALSE;
+}
+
+
+/* This will be called when the user hits the space key to activate the button.
+ It will also be called just before button_released() is called, but since
+ we already handle that we simply return if the button is pressed. */
+static void
+e_vscrolled_bar_button_clicked (GtkWidget *button,
+ EVScrolledBar *vscrolled_bar)
+{
+ if (vscrolled_bar->button_pressed)
+ return;
+
+ /* We act as if the button is pressed and released immediately. */
+ e_vscrolled_bar_button_pressed (button, vscrolled_bar);
+ vscrolled_bar->button_pressed = FALSE;
+}
+
+
+static gboolean
+e_vscrolled_bar_timeout_handler (gpointer data)
+{
+ EVScrolledBar *vscrolled_bar;
+ GtkAdjustment *adjustment;
+ gfloat new_value;
+ gboolean retval = TRUE;
+
+ vscrolled_bar = E_VSCROLLED_BAR (data);
+ adjustment = vscrolled_bar->adjustment;
+
+ GDK_THREADS_ENTER ();
+
+ /* Check if the user has released the button and we have already
+ scrolled the minimum distance. */
+ if (vscrolled_bar->button_pressed == FALSE
+ && vscrolled_bar->min_distance <= 0) {
+ GDK_THREADS_LEAVE ();
+ return FALSE;
+ }
+
+ vscrolled_bar->min_distance -= adjustment->step_increment;
+
+ if (vscrolled_bar->scrolling_up) {
+ new_value = adjustment->value - adjustment->step_increment;
+ if (new_value <= adjustment->lower) {
+ new_value = adjustment->lower;
+ retval = FALSE;
+ }
+ } else {
+ new_value = adjustment->value + adjustment->step_increment;
+ if (new_value >= adjustment->upper - adjustment->page_size) {
+ new_value = adjustment->upper - adjustment->page_size;
+ retval = FALSE;
+ }
+ }
+
+ if (adjustment->value != new_value) {
+ adjustment->value = new_value;
+ gtk_signal_emit_by_name (GTK_OBJECT (adjustment),
+ "value_changed");
+ }
+
+ GDK_THREADS_LEAVE ();
+ return retval;
+}
diff --git a/widgets/shortcut-bar/e-vscrolled-bar.h b/widgets/shortcut-bar/e-vscrolled-bar.h
new file mode 100644
index 0000000000..d3273e6685
--- /dev/null
+++ b/widgets/shortcut-bar/e-vscrolled-bar.h
@@ -0,0 +1,97 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Author :
+ * Damon Chaplin <damon@gtk.org>
+ *
+ * Copyright 1999, Helix Code, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+#ifndef _E_VSCROLLED_BAR_H_
+#define _E_VSCROLLED_BAR_H_
+
+#include <gtk/gtkbin.h>
+#include <gtk/gtkadjustment.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * EVScrolledBar is like GtkScrolledWindow but only scrolls the child widget
+ * vertically. It is intended for scrolling narrow vertical bars.
+ */
+
+
+#define E_VSCROLLED_BAR(obj) GTK_CHECK_CAST (obj, e_vscrolled_bar_get_type (), EVScrolledBar)
+#define E_VSCROLLED_BAR_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, e_vscrolled_bar_get_type (), EVScrolledBarClass)
+#define E_IS_VSCROLLED_BAR(obj) GTK_CHECK_TYPE (obj, e_vscrolled_bar_get_type ())
+
+
+typedef struct _EVScrolledBar EVScrolledBar;
+typedef struct _EVScrolledBarClass EVScrolledBarClass;
+
+struct _EVScrolledBar
+{
+ GtkBin bin;
+
+ GtkWidget *up_button;
+ GtkWidget *down_button;
+
+ GtkAdjustment *adjustment;
+
+ gint up_button_width;
+ gint up_button_height;
+ gint down_button_width;
+ gint down_button_height;
+
+ /* The GTK+ event source ID of our timeout handler. */
+ gint timeout_id;
+
+ /* TRUE if we are scrolling up, FALSE if scrolling down. */
+ gboolean scrolling_up;
+
+ /* The minimum distance left to scroll. If the user just clicks a
+ button we scroll a minimum amount. This is reduced after each
+ scroll. */
+ gfloat min_distance;
+
+ /* TRUE if the button is still pressed. When the up/down button is
+ released, this gets set to FALSE, and we scroll until the minimum
+ distance falls below 0. */
+ gboolean button_pressed;
+};
+
+struct _EVScrolledBarClass
+{
+ GtkBinClass parent_class;
+};
+
+
+GtkType e_vscrolled_bar_get_type (void);
+GtkWidget* e_vscrolled_bar_new (GtkAdjustment *adjustment);
+
+GtkAdjustment* e_vscrolled_bar_get_adjustment (EVScrolledBar *vscrolled_bar);
+void e_vscrolled_bar_set_adjustment (EVScrolledBar *vscrolled_bar,
+ GtkAdjustment *adjustment);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _E_VSCROLLED_BAR_H_ */
diff --git a/widgets/shortcut-bar/test-shortcut-bar.c b/widgets/shortcut-bar/test-shortcut-bar.c
new file mode 100644
index 0000000000..186bf3ed8a
--- /dev/null
+++ b/widgets/shortcut-bar/test-shortcut-bar.c
@@ -0,0 +1,445 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * Author :
+ * Damon Chaplin <damon@gtk.org>
+ *
+ * Copyright 1999, Helix Code, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+/*
+ * This tests the ShortcutBar widget.
+ */
+
+#include <gnome.h>
+
+#include "e-shortcut-bar.h"
+
+#define NUM_SHORTCUT_TYPES 5
+gchar *shortcut_types[] = {
+ "folder:", "file:", "calendar:", "todo:", "contacts:"
+};
+
+GtkWidget *main_label;
+
+static void quit (GtkWidget *window, GdkEvent *event, gpointer data);
+static void add_test_groups (EShortcutBar *shortcut_bar);
+static void add_test_group (EShortcutBar *shortcut_bar, gint i,
+ gchar *group_name);
+static gint get_random_int (gint max);
+
+static void on_shortcut_bar_item_selected (EShortcutBar *shortcut_bar,
+ GdkEvent *event,
+ gint group_num,
+ gint item_num);
+static void show_standard_popup (EShortcutBar *shortcut_bar,
+ GdkEvent *event,
+ gint group_num);
+static void show_context_popup (EShortcutBar *shortcut_bar,
+ GdkEvent *event,
+ gint group_num,
+ gint item_num);
+
+static void set_large_icons (GtkWidget *menuitem,
+ EShortcutBar *shortcut_bar);
+static void set_small_icons (GtkWidget *menuitem,
+ EShortcutBar *shortcut_bar);
+static void remove_group (GtkWidget *menuitem,
+ EShortcutBar *shortcut_bar);
+
+static void rename_item (GtkWidget *menuitem,
+ EShortcutBar *shortcut_bar);
+static void remove_item (GtkWidget *menuitem,
+ EShortcutBar *shortcut_bar);
+
+int
+main (int argc, char *argv[])
+{
+ GtkWidget *window, *hpaned, *shortcut_bar;
+
+ gnome_init ("test-shortcut-bar", "0.1", argc, argv);
+
+ gtk_widget_push_visual (gdk_imlib_get_visual ());
+ gtk_widget_push_colormap (gdk_imlib_get_colormap ());
+
+ window = gnome_app_new ("TestShortcutBar", "TestShortCutBar");
+ gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
+ gtk_window_set_policy (GTK_WINDOW (window), FALSE, TRUE, FALSE);
+
+ gtk_signal_connect (GTK_OBJECT (window), "delete-event",
+ GTK_SIGNAL_FUNC (quit), NULL);
+
+ hpaned = gtk_hpaned_new ();
+ gnome_app_set_contents (GNOME_APP (window), hpaned);
+ gtk_widget_show (hpaned);
+
+ shortcut_bar = e_shortcut_bar_new ();
+ gtk_paned_pack1 (GTK_PANED (hpaned), shortcut_bar, FALSE, TRUE);
+ gtk_widget_show (shortcut_bar);
+
+#if 0
+ gtk_container_set_border_width (GTK_CONTAINER (shortcut_bar), 4);
+#endif
+
+ gtk_paned_set_position (GTK_PANED (hpaned), 100);
+ /*gtk_paned_set_gutter_size (GTK_PANED (hpaned), 12);*/
+
+ main_label = gtk_label_new ("Main Application Window Goes Here");
+ gtk_paned_pack2 (GTK_PANED (hpaned), main_label, TRUE, TRUE);
+ gtk_widget_show (main_label);
+
+
+ gtk_widget_pop_visual ();
+ gtk_widget_pop_colormap ();
+
+ add_test_groups (E_SHORTCUT_BAR (shortcut_bar));
+
+ gtk_signal_connect (GTK_OBJECT (shortcut_bar), "item_selected",
+ GTK_SIGNAL_FUNC (on_shortcut_bar_item_selected),
+ NULL);
+
+ gtk_widget_show (window);
+ gtk_main ();
+ return 0;
+}
+
+
+static void
+quit (GtkWidget *window, GdkEvent *event, gpointer data)
+{
+ gtk_widget_destroy (window);
+ gtk_exit (0);
+}
+
+
+static void
+add_test_groups (EShortcutBar *shortcut_bar)
+{
+ add_test_group (shortcut_bar, 1, "Shortcuts");
+ add_test_group (shortcut_bar, 2, "My Shortcuts");
+ add_test_group (shortcut_bar, 3, "Longer Shortcuts");
+ add_test_group (shortcut_bar, 4, "Very Long Shortcuts");
+ add_test_group (shortcut_bar, 5, "Incredibly Long Shortcuts");
+}
+
+
+static void
+add_test_group (EShortcutBar *shortcut_bar, gint i, gchar *group_name)
+{
+ gint group_num, item_num, num_items;
+ gchar buffer[128];
+ gint shortcut_type, j;
+
+ group_num = e_shortcut_bar_add_group (E_SHORTCUT_BAR (shortcut_bar),
+ group_name);
+
+ if (group_num % 2)
+ e_shortcut_bar_set_view_type (E_SHORTCUT_BAR (shortcut_bar),
+ group_num,
+ E_ICON_BAR_SMALL_ICONS);
+
+ num_items = get_random_int (5) + 3;
+ for (j = 1; j <= num_items; j++) {
+ if (j == 1)
+ sprintf (buffer, "A very long shortcut with proper words so I can test the wrapping and ellipsis behaviour");
+ else if (j == 2)
+ sprintf (buffer, "A very long shortcut with averylongworkinthemiddlesoIcantestthewrappingandellipsisbehaviour");
+ else
+ sprintf (buffer, "Item %i:%i\n", i, j);
+
+ shortcut_type = get_random_int (NUM_SHORTCUT_TYPES);
+ item_num = e_shortcut_bar_add_item (E_SHORTCUT_BAR (shortcut_bar), group_num, shortcut_types[shortcut_type], buffer);
+ }
+}
+
+
+/* Returns a random integer between 0 and max - 1. */
+static gint
+get_random_int (gint max)
+{
+ gint random_num;
+
+ random_num = (int) (max * (rand () / (RAND_MAX + 1.0)));
+#if 0
+ g_print ("Random num (%i): %i\n", max, random_num);
+#endif
+ return random_num;
+}
+
+
+static void
+on_shortcut_bar_item_selected (EShortcutBar *shortcut_bar,
+ GdkEvent *event, gint group_num, gint item_num)
+{
+ gchar buffer[256];
+
+ if (event->button.button == 1) {
+ sprintf (buffer, "Item Selected - %i:%i",
+ group_num + 1, item_num + 1);
+ gtk_label_set_text (GTK_LABEL (main_label), buffer);
+ } else if (event->button.button == 3) {
+ if (item_num == -1)
+ show_standard_popup (shortcut_bar, event, group_num);
+ else
+ show_context_popup (shortcut_bar, event, group_num,
+ item_num);
+ }
+}
+
+
+static void
+show_standard_popup (EShortcutBar *shortcut_bar,
+ GdkEvent *event,
+ gint group_num)
+{
+ GtkWidget *menu, *menuitem;
+
+ /* We don't have any commands if there aren't any groups yet. */
+ if (group_num == -1)
+ return;
+
+ menu = gtk_menu_new ();
+
+ menuitem = gtk_menu_item_new_with_label ("Large Icons");
+ gtk_widget_show (menuitem);
+ gtk_menu_append (GTK_MENU (menu), menuitem);
+ gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
+ GTK_SIGNAL_FUNC (set_large_icons), shortcut_bar);
+
+ menuitem = gtk_menu_item_new_with_label ("Small Icons");
+ gtk_widget_show (menuitem);
+ gtk_menu_append (GTK_MENU (menu), menuitem);
+ gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
+ GTK_SIGNAL_FUNC (set_small_icons), shortcut_bar);
+
+ menuitem = gtk_menu_item_new ();
+ gtk_widget_set_sensitive (menuitem, FALSE);
+ gtk_widget_show (menuitem);
+ gtk_menu_append (GTK_MENU (menu), menuitem);
+
+ menuitem = gtk_menu_item_new_with_label ("Add New Group");
+ gtk_widget_set_sensitive (menuitem, FALSE);
+ gtk_widget_show (menuitem);
+ gtk_menu_append (GTK_MENU (menu), menuitem);
+
+ menuitem = gtk_menu_item_new_with_label ("Remove Group");
+ gtk_widget_show (menuitem);
+ gtk_menu_append (GTK_MENU (menu), menuitem);
+ gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
+ GTK_SIGNAL_FUNC (remove_group), shortcut_bar);
+
+ menuitem = gtk_menu_item_new_with_label ("Rename Group");
+ gtk_widget_set_sensitive (menuitem, FALSE);
+ gtk_widget_show (menuitem);
+ gtk_menu_append (GTK_MENU (menu), menuitem);
+
+ menuitem = gtk_menu_item_new ();
+ gtk_widget_set_sensitive (menuitem, FALSE);
+ gtk_widget_show (menuitem);
+ gtk_menu_append (GTK_MENU (menu), menuitem);
+
+ menuitem = gtk_menu_item_new_with_label ("Add Shortcut...");
+ gtk_widget_set_sensitive (menuitem, FALSE);
+ gtk_widget_show (menuitem);
+ gtk_menu_append (GTK_MENU (menu), menuitem);
+
+ menuitem = gtk_menu_item_new ();
+ gtk_widget_set_sensitive (menuitem, FALSE);
+ gtk_widget_show (menuitem);
+ gtk_menu_append (GTK_MENU (menu), menuitem);
+
+ menuitem = gtk_menu_item_new_with_label ("Hide Shortcut Bar");
+ gtk_widget_set_sensitive (menuitem, FALSE);
+ gtk_widget_show (menuitem);
+ gtk_menu_append (GTK_MENU (menu), menuitem);
+
+ /* Save the group num so we can get it in the callbacks. */
+ gtk_object_set_data (GTK_OBJECT (menu), "group_num",
+ GINT_TO_POINTER (group_num));
+
+ /* FIXME: Destroy menu when finished with it somehow? */
+ gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
+ event->button.button, event->button.time);
+}
+
+
+static void
+set_large_icons (GtkWidget *menuitem,
+ EShortcutBar *shortcut_bar)
+{
+ GtkWidget *menu;
+ gint group_num;
+
+ menu = menuitem->parent;
+ g_return_if_fail (GTK_IS_MENU (menu));
+
+ group_num = GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (menu),
+ "group_num"));
+
+ e_shortcut_bar_set_view_type (shortcut_bar, group_num,
+ E_ICON_BAR_LARGE_ICONS);
+}
+
+
+static void
+set_small_icons (GtkWidget *menuitem,
+ EShortcutBar *shortcut_bar)
+{
+ GtkWidget *menu;
+ gint group_num;
+
+ menu = menuitem->parent;
+ g_return_if_fail (GTK_IS_MENU (menu));
+
+ group_num = GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (menu),
+ "group_num"));
+
+ e_shortcut_bar_set_view_type (shortcut_bar, group_num,
+ E_ICON_BAR_SMALL_ICONS);
+}
+
+
+static void
+remove_group (GtkWidget *menuitem,
+ EShortcutBar *shortcut_bar)
+{
+ GtkWidget *menu;
+ gint group_num;
+
+ menu = menuitem->parent;
+ g_return_if_fail (GTK_IS_MENU (menu));
+
+ group_num = GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (menu),
+ "group_num"));
+
+ e_shortcut_bar_remove_group (shortcut_bar, group_num);
+}
+
+
+static void
+show_context_popup (EShortcutBar *shortcut_bar,
+ GdkEvent *event,
+ gint group_num,
+ gint item_num)
+{
+ GtkWidget *menu, *menuitem, *label, *pixmap;
+
+ menu = gtk_menu_new ();
+
+ menuitem = gtk_pixmap_menu_item_new ();
+ label = gtk_label_new ("Open Folder");
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_widget_show (label);
+ gtk_container_add (GTK_CONTAINER (menuitem), label);
+ gtk_widget_set_sensitive (menuitem, FALSE);
+ gtk_widget_show (menuitem);
+ gtk_menu_append (GTK_MENU (menu), menuitem);
+ pixmap = gnome_stock_pixmap_widget (menu, GNOME_STOCK_MENU_OPEN);
+ if (pixmap) {
+ gtk_widget_show(pixmap);
+ gtk_pixmap_menu_item_set_pixmap (GTK_PIXMAP_MENU_ITEM (menuitem), pixmap);
+ }
+
+ menuitem = gtk_menu_item_new_with_label ("Open in New Window");
+ gtk_widget_set_sensitive (menuitem, FALSE);
+ gtk_widget_show (menuitem);
+ gtk_menu_append (GTK_MENU (menu), menuitem);
+
+ menuitem = gtk_menu_item_new_with_label ("Advanced Find");
+ gtk_widget_set_sensitive (menuitem, FALSE);
+ gtk_widget_show (menuitem);
+ gtk_menu_append (GTK_MENU (menu), menuitem);
+
+ menuitem = gtk_menu_item_new ();
+ gtk_widget_set_sensitive (menuitem, FALSE);
+ gtk_widget_show (menuitem);
+ gtk_menu_append (GTK_MENU (menu), menuitem);
+
+ menuitem = gtk_menu_item_new_with_label ("Remove from Shortcut Bar");
+ gtk_widget_show (menuitem);
+ gtk_menu_append (GTK_MENU (menu), menuitem);
+ gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
+ GTK_SIGNAL_FUNC (remove_item), shortcut_bar);
+
+ menuitem = gtk_menu_item_new_with_label ("Rename Shortcut");
+ gtk_widget_show (menuitem);
+ gtk_menu_append (GTK_MENU (menu), menuitem);
+ gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
+ GTK_SIGNAL_FUNC (rename_item), shortcut_bar);
+
+ menuitem = gtk_menu_item_new ();
+ gtk_widget_set_sensitive (menuitem, FALSE);
+ gtk_widget_show (menuitem);
+ gtk_menu_append (GTK_MENU (menu), menuitem);
+
+ menuitem = gtk_menu_item_new_with_label ("Properties");
+ gtk_widget_set_sensitive (menuitem, FALSE);
+ gtk_widget_show (menuitem);
+ gtk_menu_append (GTK_MENU (menu), menuitem);
+
+
+ /* Save the group & item nums so we can get them in the callbacks. */
+ gtk_object_set_data (GTK_OBJECT (menu), "group_num",
+ GINT_TO_POINTER (group_num));
+ gtk_object_set_data (GTK_OBJECT (menu), "item_num",
+ GINT_TO_POINTER (item_num));
+
+ /* FIXME: Destroy menu when finished with it somehow? */
+ gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
+ event->button.button, event->button.time);
+}
+
+
+static void
+rename_item (GtkWidget *menuitem,
+ EShortcutBar *shortcut_bar)
+{
+ GtkWidget *menu;
+ gint group_num, item_num;
+
+ menu = menuitem->parent;
+ g_return_if_fail (GTK_IS_MENU (menu));
+
+ group_num = GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (menu),
+ "group_num"));
+ item_num = GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (menu),
+ "item_num"));
+
+ e_shortcut_bar_start_editing_item (shortcut_bar, group_num, item_num);
+}
+
+
+static void
+remove_item (GtkWidget *menuitem,
+ EShortcutBar *shortcut_bar)
+{
+ GtkWidget *menu;
+ gint group_num, item_num;
+
+ menu = menuitem->parent;
+ g_return_if_fail (GTK_IS_MENU (menu));
+
+ group_num = GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (menu),
+ "group_num"));
+ item_num = GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (menu),
+ "item_num"));
+
+ e_shortcut_bar_remove_item (shortcut_bar, group_num, item_num);
+}
+
+
diff --git a/widgets/table-test.c b/widgets/table-test.c
deleted file mode 100644
index 9de673ede4..0000000000
--- a/widgets/table-test.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Test code for the ETable package
- *
- * Author:
- * Miguel de Icaza (miguel@gnu.org)
- */
-#include <config.h>
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <gnome.h>
-#include "e-cursors.h"
-#include "table-test.h"
-
-int
-main (int argc, char *argv [])
-{
-
- if (isatty (0)){
- int fd;
-
- close (0);
- fd = open ("sample.table", O_RDONLY);
- if (fd == -1){
- fprintf (stderr, "Could not find sample.table, try feeding a table on stdin");
- exit (1);
- }
- dup2 (fd, 0);
- }
-
- gnome_init ("TableTest", "TableTest", argc, argv);
- e_cursors_init ();
-
- table_browser_test ();
- multi_cols_test ();
- check_test ();
- e_table_test ();
-
- gtk_main ();
-
- e_cursors_shutdown ();
- return 0;
-}
diff --git a/widgets/table-test.h b/widgets/table-test.h
deleted file mode 100644
index ad8cfcc083..0000000000
--- a/widgets/table-test.h
+++ /dev/null
@@ -1,4 +0,0 @@
-void table_browser_test (void);
-void multi_cols_test (void);
-void check_test (void);
-void e_table_test (void);
diff --git a/widgets/table/e-cell-checkbox.c b/widgets/table/e-cell-checkbox.c
index 6e4b597abf..d77e1fa4cd 100644
--- a/widgets/table/e-cell-checkbox.c
+++ b/widgets/table/e-cell-checkbox.c
@@ -14,7 +14,7 @@
#include <gdk/gdkkeysyms.h>
#include <libgnomeui/gnome-canvas.h>
#include "e-cell-checkbox.h"
-#include "e-util.h"
+#include <e-util/e-util.h>
#include "e-table-item.h"
#include "check-empty.xpm"
diff --git a/widgets/table/e-cell-text.c b/widgets/table/e-cell-text.c
index 1b2205ba51..9ce8190a14 100644
--- a/widgets/table/e-cell-text.c
+++ b/widgets/table/e-cell-text.c
@@ -15,7 +15,7 @@
#include <libgnomeui/gnome-canvas.h>
#include <stdio.h>
#include "e-cell-text.h"
-#include "e-util.h"
+#include <e-util/e-util.h>
#include "e-table-item.h"
#define PARENT_TYPE e_cell_get_type()
diff --git a/widgets/table/e-cell-toggle.c b/widgets/table/e-cell-toggle.c
index 6ea181ea40..a933a62c49 100644
--- a/widgets/table/e-cell-toggle.c
+++ b/widgets/table/e-cell-toggle.c
@@ -14,7 +14,7 @@
#include <gdk/gdkkeysyms.h>
#include <libgnomeui/gnome-canvas.h>
#include "e-cell-toggle.h"
-#include "e-util.h"
+#include <e-util/e-util.h>
#include "e-table-item.h"
#define PARENT_TYPE e_cell_get_type()
diff --git a/widgets/table/e-cell.c b/widgets/table/e-cell.c
index 0f9297ecba..b5cbc0e850 100644
--- a/widgets/table/e-cell.c
+++ b/widgets/table/e-cell.c
@@ -8,7 +8,7 @@
*/
#include <config.h>
#include "e-cell.h"
-#include "e-util.h"
+#include <e-util/e-util.h>
#define PARENT_TYPE gtk_object_get_type()
diff --git a/widgets/table/e-table-col.c b/widgets/table/e-table-col.c
index 86392a9419..62a451ca4f 100644
--- a/widgets/table/e-table-col.c
+++ b/widgets/table/e-table-col.c
@@ -10,7 +10,7 @@
#include <gtk/gtkobject.h>
#include <gtk/gtksignal.h>
#include "e-table-col.h"
-#include "e-util.h"
+#include <e-util/e-util.h>
#define PARENT_TYPE (gtk_object_get_type ())
diff --git a/widgets/table/e-table-group.c b/widgets/table/e-table-group.c
index 8765c3b83c..14c7a33f79 100644
--- a/widgets/table/e-table-group.c
+++ b/widgets/table/e-table-group.c
@@ -12,7 +12,7 @@
#include "e-table-group.h"
#include "e-table-item.h"
#include <libgnomeui/gnome-canvas-rect-ellipse.h>
-#include "e-util.h"
+#include <e-util/e-util.h>
#define TITLE_HEIGHT 16
#define GROUP_INDENT 10
diff --git a/widgets/table/e-table-sorted.c b/widgets/table/e-table-sorted.c
index 6bc55ad9dc..b559b3d87f 100644
--- a/widgets/table/e-table-sorted.c
+++ b/widgets/table/e-table-sorted.c
@@ -8,7 +8,7 @@
*/
#include <config.h>
#include <stdlib.h>
-#include "e-util.h"
+#include <e-util/e-util.h>
#include "e-table-sorted.h"
#define PARENT_TYPE E_TABLE_SUBSET_TYPE
diff --git a/widgets/table/e-table-subset.c b/widgets/table/e-table-subset.c
index 88f5c18c85..be4c7ab732 100644
--- a/widgets/table/e-table-subset.c
+++ b/widgets/table/e-table-subset.c
@@ -9,7 +9,7 @@
#include <config.h>
#include <stdlib.h>
#include <gtk/gtksignal.h>
-#include "e-util.h"
+#include <e-util/e-util.h>
#include "e-table-subset.h"
#define PARENT_TYPE E_TABLE_MODEL_TYPE
diff --git a/widgets/table/e-table.c b/widgets/table/e-table.c
index 01389135bf..730306b374 100644
--- a/widgets/table/e-table.c
+++ b/widgets/table/e-table.c
@@ -14,8 +14,8 @@
#include <stdio.h>
#include <libgnomeui/gnome-canvas.h>
#include <gtk/gtksignal.h>
+#include <e-util/e-util.h>
#include "e-table.h"
-#include "e-util.h"
#include "e-table-header-item.h"
#include "e-table-subset.h"
#include "e-table-item.h"
diff --git a/widgets/test-check.c b/widgets/test-check.c
deleted file mode 100644
index b24a7aff64..0000000000
--- a/widgets/test-check.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Test code for the ETable package
- *
- * Author:
- * Miguel de Icaza (miguel@gnu.org)
- */
-#include <config.h>
-#include <stdio.h>
-#include <string.h>
-#include <gnome.h>
-#include "e-table-simple.h"
-#include "e-table-header.h"
-#include "e-table-header-item.h"
-#include "e-table-item.h"
-#include "e-cursors.h"
-#include "e-cell-text.h"
-#include "e-cell-checkbox.h"
-
-#include "table-test.h"
-
-#define LINES 4
-
-static struct {
- int value;
- char *string;
-} my_table [LINES] = {
- { 0, "Buy food" },
- { 1, "Breathe " },
- { 0, "Cancel gdb session with shrink" },
- { 1, "Make screenshots" },
-};
-/*
- * ETableSimple callbacks
- */
-static int
-col_count (ETableModel *etc, void *data)
-{
- return 2;
-}
-
-static int
-row_count (ETableModel *etc, void *data)
-{
- return LINES;
-}
-
-static void *
-value_at (ETableModel *etc, int col, int row, void *data)
-{
- g_assert (col < 2);
- g_assert (row < LINES);
-
- if (col == 0)
- return GINT_TO_POINTER (my_table [row].value);
- else
- return my_table [row].string;
-
-}
-
-static void
-set_value_at (ETableModel *etc, int col, int row, const void *val, void *data)
-{
- g_assert (col < 2);
- g_assert (row < LINES);
-
- if (col == 0){
- my_table [row].value = GPOINTER_TO_INT (val);
- printf ("Value at %d,%d set to %d\n", col, row, GPOINTER_TO_INT (val));
- } else {
- my_table [row].string = g_strdup (val);
- printf ("Value at %d,%d set to %s\n", col, row, (char *) val);
- }
-}
-
-static gboolean
-is_cell_editable (ETableModel *etc, int col, int row, void *data)
-{
- return TRUE;
-}
-
-static void
-set_canvas_size (GnomeCanvas *canvas, GtkAllocation *alloc)
-{
- gnome_canvas_set_scroll_region (canvas, 0, 0, alloc->width, alloc->height);
-}
-
-void
-check_test (void)
-{
- GtkWidget *canvas, *window;
- ETableModel *e_table_model;
- ETableHeader *e_table_header;
- ETableCol *col_0, *col_1;
- ECell *cell_left_just, *cell_image_check;
-
- gtk_widget_push_visual (gdk_rgb_get_visual ());
- gtk_widget_push_colormap (gdk_rgb_get_cmap ());
-
- e_table_model = e_table_simple_new (
- col_count, row_count, value_at,
- set_value_at, is_cell_editable, NULL);
-
- /*
- * Header
- */
- e_table_header = e_table_header_new ();
-
- cell_left_just = e_cell_text_new (e_table_model, NULL, GTK_JUSTIFY_LEFT);
-
- cell_image_check = e_cell_checkbox_new ();
- col_0 = e_table_col_new (0, "", 18, 18, cell_image_check, g_int_equal, TRUE);
- e_table_header_add_column (e_table_header, col_0, 0);
-
- col_1 = e_table_col_new (1, "Item Name", 180, 20, cell_left_just, g_str_equal, TRUE);
- e_table_header_add_column (e_table_header, col_1, 1);
-
- /*
- * GUI
- */
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- canvas = gnome_canvas_new ();
-
- gtk_signal_connect (GTK_OBJECT (canvas), "size_allocate",
- GTK_SIGNAL_FUNC (set_canvas_size), NULL);
-
- gtk_container_add (GTK_CONTAINER (window), canvas);
- gtk_widget_show_all (window);
- gnome_canvas_item_new (
- gnome_canvas_root (GNOME_CANVAS (canvas)),
- e_table_header_item_get_type (),
- "ETableHeader", e_table_header,
- "x", 0,
- "y", 0,
- NULL);
-
- gnome_canvas_item_new (
- gnome_canvas_root (GNOME_CANVAS (canvas)),
- e_table_item_get_type (),
- "ETableHeader", e_table_header,
- "ETableModel", e_table_model,
- "x", (double) 0,
- "y", (double) 30,
- "drawgrid", TRUE,
- "drawfocus", TRUE,
- "spreadsheet", TRUE,
- NULL);
-
-}
-
-
-
-
-
diff --git a/widgets/test-cols.c b/widgets/test-cols.c
deleted file mode 100644
index 6342a1739f..0000000000
--- a/widgets/test-cols.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Test code for the ETable package
- *
- * Author:
- * Miguel de Icaza (miguel@gnu.org)
- */
-#include <config.h>
-#include <stdio.h>
-#include <string.h>
-#include <gnome.h>
-#include "e-table-simple.h"
-#include "e-table-header.h"
-#include "e-table-header-item.h"
-#include "e-table-item.h"
-#include "e-cursors.h"
-#include "e-cell-text.h"
-#include "e-cell-toggle.h"
-
-#include "table-test.h"
-
-#define LINES 4
-
-static struct {
- int value;
- char *string;
-} my_table [LINES] = {
- { 0, "You are not" },
- { 1, "A beautiful and unique " },
- { 0, "Snowflake" },
- { 2, "You are not your wallet" },
-};
-/*
- * ETableSimple callbacks
- */
-static int
-col_count (ETableModel *etc, void *data)
-{
- return 2;
-}
-
-static int
-row_count (ETableModel *etc, void *data)
-{
- return LINES;
-}
-
-static void *
-value_at (ETableModel *etc, int col, int row, void *data)
-{
- g_assert (col < 2);
- g_assert (row < LINES);
-
- if (col == 0)
- return GINT_TO_POINTER (my_table [row].value);
- else
- return my_table [row].string;
-
-}
-
-static void
-set_value_at (ETableModel *etc, int col, int row, const void *val, void *data)
-{
- g_assert (col < 2);
- g_assert (row < LINES);
-
- if (col == 0){
- my_table [row].value = GPOINTER_TO_INT (val);
- printf ("Value at %d,%d set to %d\n", col, row, GPOINTER_TO_INT (val));
- } else {
- my_table [row].string = g_strdup (val);
- printf ("Value at %d,%d set to %s\n", col, row, (char *) val);
- }
-}
-
-static gboolean
-is_cell_editable (ETableModel *etc, int col, int row, void *data)
-{
- return TRUE;
-}
-
-static void
-set_canvas_size (GnomeCanvas *canvas, GtkAllocation *alloc)
-{
- gnome_canvas_set_scroll_region (canvas, 0, 0, alloc->width, alloc->height);
-}
-
-void
-multi_cols_test (void)
-{
- GtkWidget *canvas, *window;
- ETableModel *e_table_model;
- ETableHeader *e_table_header, *e_table_header_multiple;
- ETableCol *col_0, *col_1;
- ECell *cell_left_just, *cell_image_toggle;
-
- gtk_widget_push_visual (gdk_rgb_get_visual ());
- gtk_widget_push_colormap (gdk_rgb_get_cmap ());
-
- e_table_model = e_table_simple_new (
- col_count, row_count, value_at,
- set_value_at, is_cell_editable, NULL);
-
- /*
- * Header
- */
- e_table_header = e_table_header_new ();
-
- cell_left_just = e_cell_text_new (e_table_model, NULL, GTK_JUSTIFY_LEFT);
-
- {
- GdkPixbuf **images = g_new (GdkPixbuf *, 3);
- int i;
-
- images [0] = gdk_pixbuf_new_from_file ("image1.png");
- images [1] = gdk_pixbuf_new_from_file ("image2.png");
- images [2] = gdk_pixbuf_new_from_file ("image3.png");
-
- cell_image_toggle = e_cell_toggle_new (0, 3, images);
-
- for (i = 0; i < 3; i++)
- gdk_pixbuf_unref (images [i]);
-
- g_free (images);
- }
-
- col_1 = e_table_col_new (1, "Item Name", 180, 20, cell_left_just, g_str_equal, TRUE);
- e_table_header_add_column (e_table_header, col_1, 0);
-
- col_0 = e_table_col_new (0, "A", 48, 48, cell_image_toggle, g_int_equal, TRUE);
- e_table_header_add_column (e_table_header, col_0, 1);
-
- /*
- * Second test
- */
- e_table_header_multiple = e_table_header_new ();
- e_table_header_add_column (e_table_header_multiple, col_0, 0);
- e_table_header_add_column (e_table_header_multiple, col_1, 1);
- e_table_header_add_column (e_table_header_multiple, col_1, 2);
-
- /*
- * GUI
- */
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- canvas = gnome_canvas_new ();
-
- gtk_signal_connect (GTK_OBJECT (canvas), "size_allocate",
- GTK_SIGNAL_FUNC (set_canvas_size), NULL);
-
- gtk_container_add (GTK_CONTAINER (window), canvas);
- gtk_widget_show_all (window);
-
- gnome_canvas_item_new (
- gnome_canvas_root (GNOME_CANVAS (canvas)),
- e_table_header_item_get_type (),
- "ETableHeader", e_table_header,
- "x", 0,
- "y", 0,
- NULL);
-
- gnome_canvas_item_new (
- gnome_canvas_root (GNOME_CANVAS (canvas)),
- e_table_item_get_type (),
- "ETableHeader", e_table_header,
- "ETableModel", e_table_model,
- "x", (double) 0,
- "y", (double) 30,
- "drawgrid", TRUE,
- "drawfocus", TRUE,
- "spreadsheet", TRUE,
- NULL);
-
- gnome_canvas_item_new (
- gnome_canvas_root (GNOME_CANVAS (canvas)),
- e_table_header_item_get_type (),
- "ETableHeader", e_table_header_multiple,
- "x", 300,
- "y", 0,
- NULL);
- gnome_canvas_item_new (
- gnome_canvas_root (GNOME_CANVAS (canvas)),
- e_table_item_get_type (),
- "ETableHeader", e_table_header_multiple,
- "ETableModel", e_table_model,
- "x", (double) 300,
- "y", (double) 30,
- "drawgrid", TRUE,
- "drawfocus", TRUE,
- "spreadsheet", TRUE,
- NULL);
-
-}
-
-
-
-
-
diff --git a/widgets/test-table.c b/widgets/test-table.c
deleted file mode 100644
index 2e64826cba..0000000000
--- a/widgets/test-table.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Test code for the ETable package
- *
- * Author:
- * Miguel de Icaza (miguel@gnu.org)
- */
-#include <config.h>
-#include <stdio.h>
-#include <string.h>
-#include <gnome.h>
-#include "e-table-simple.h"
-#include "e-table-header.h"
-#include "e-table-header-item.h"
-#include "e-table-item.h"
-#include "e-cursors.h"
-#include "e-cell-text.h"
-#include "e-table.h"
-
-#include "table-test.h"
-
-char buffer [1024];
-char **column_labels;
-char ***table_data;
-int cols = 0;
-int lines = 0;
-int lines_alloc = 0;
-
-static void
-parse_headers ()
-{
- char *p, *s;
- int in_value = 0, i;
-
- fgets (buffer, sizeof (buffer)-1, stdin);
-
- for (p = buffer; *p; p++){
- if (*p == ' ' || *p == '\t'){
- if (in_value){
- cols++;
- in_value = 0;
- }
- } else
- in_value = 1;
- }
- if (in_value)
- cols++;
-
- if (!cols){
- fprintf (stderr, "No columns in first row\n");
- exit (1);
- }
-
- column_labels = g_new0 (char *, cols);
-
- p = buffer;
- for (i = 0; (s = strtok (p, " \t")) != NULL; i++){
- column_labels [i] = g_strdup (s);
- p = NULL;
- }
-
- printf ("%d headers:\n", cols);
- for (i = 0; i < cols; i++){
- printf ("header %d: %s\n", i, column_labels [i]);
- }
-}
-
-static char **
-load_line (char *buffer, int cols)
-{
- char **line = g_new0 (char *, cols);
- char *p;
- int i;
-
- for (i = 0; i < cols; i++){
- p = strtok (buffer, " \t\n");
- if (p == NULL){
- for (; i < cols; i++)
- line [i] = g_strdup ("");
- return line;
- } else
- line [i] = g_strdup (p);
- buffer = NULL;
- }
- return line;
-}
-
-static void
-append_line (char **line)
-{
- if (lines <= lines_alloc){
- lines_alloc = lines + 50;
- table_data = g_renew (char **, table_data, lines_alloc);
- }
- table_data [lines] = line;
- lines++;
-}
-
-static void
-load_data ()
-{
- int i;
-
- {
- static int loaded;
-
- if (loaded)
- return;
-
- loaded = TRUE;
- }
-
-
- parse_headers ();
-
- while (fgets (buffer, sizeof (buffer)-1, stdin) != NULL){
- char **line;
-
- if (buffer [0] == '\n')
- continue;
- line = load_line (buffer, cols);
- append_line (line);
- }
-
- for (i = 0; i < lines; i++){
- int j;
-
- printf ("Line %d: ", i);
- for (j = 0; j < cols; j++)
- printf ("[%s] ", table_data [i][j]);
- printf ("\n");
- }
-}
-
-/*
- * ETableSimple callbacks
- */
-static int
-col_count (ETableModel *etc, void *data)
-{
- return cols;
-}
-
-static int
-row_count (ETableModel *etc, void *data)
-{
- return lines;
-}
-
-static void *
-value_at (ETableModel *etc, int col, int row, void *data)
-{
- g_assert (col < cols);
- g_assert (row < lines);
-
- return (void *) table_data [row][col];
-}
-
-static void
-set_value_at (ETableModel *etc, int col, int row, const void *val, void *data)
-{
- g_assert (col < cols);
- g_assert (row < lines);
-
- g_free (table_data [row][col]);
- table_data [row][col] = g_strdup (val);
-
- printf ("Value at %d,%d set to %s\n", col, row, (char *) val);
-}
-
-static gboolean
-is_cell_editable (ETableModel *etc, int col, int row, void *data)
-{
- return TRUE;
-}
-
-static void
-set_canvas_size (GnomeCanvas *canvas, GtkAllocation *alloc)
-{
- gnome_canvas_set_scroll_region (canvas, 0, 0, alloc->width, alloc->height);
-}
-
-void
-table_browser_test (void)
-{
- GtkWidget *canvas, *window;
- ETableModel *e_table_model;
- ETableHeader *e_table_header;
- ECell *cell_left_just;
- GnomeCanvasItem *group;
- int i;
-
- load_data ();
-
- /*
- * Data model
- */
- e_table_model = e_table_simple_new (
- col_count, row_count, value_at,
- set_value_at, is_cell_editable, NULL);
-
- /*
- * Header
- */
- e_table_header = e_table_header_new ();
- cell_left_just = e_cell_text_new (e_table_model, NULL, GTK_JUSTIFY_LEFT);
-
- for (i = 0; i < cols; i++){
- ETableCol *ecol = e_table_col_new (
- i, column_labels [i],
- 80, 20, cell_left_just,
- g_str_equal, TRUE);
-
- e_table_header_add_column (e_table_header, ecol, i);
- }
-
- /*
- * Setup GUI
- */
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- canvas = gnome_canvas_new ();
-
- gtk_signal_connect (GTK_OBJECT (canvas), "size_allocate",
- GTK_SIGNAL_FUNC (set_canvas_size), NULL);
-
- gtk_container_add (GTK_CONTAINER (window), canvas);
- gtk_widget_show_all (window);
- gnome_canvas_item_new (
- gnome_canvas_root (GNOME_CANVAS (canvas)),
- e_table_header_item_get_type (),
- "ETableHeader", e_table_header,
- "x", 0,
- "y", 0,
- NULL);
-
- group = gnome_canvas_item_new (
- gnome_canvas_root (GNOME_CANVAS (canvas)),
- gnome_canvas_group_get_type (),
- "x", 30.0,
- "y", 30.0,
- NULL);
-
- gnome_canvas_item_new (
- GNOME_CANVAS_GROUP (group),
- e_table_item_get_type (),
- "ETableHeader", e_table_header,
- "ETableModel", e_table_model,
- "x", (double) 0,
- "y", (double) 0,
- "drawgrid", TRUE,
- "drawfocus", TRUE,
- "spreadsheet", TRUE,
- NULL);
-}
-
-static void
-do_e_table_demo (const char *col_spec, const char *group_spec)
-{
- GtkWidget *e_table, *window;
- ETableModel *e_table_model;
- ECell *cell_left_just;
- ETableHeader *full_header;
- int i;
-
- /*
- * Data model
- */
- e_table_model = e_table_simple_new (
- col_count, row_count, value_at,
- set_value_at, is_cell_editable, NULL);
-
- full_header = e_table_header_new ();
- cell_left_just = e_cell_text_new (e_table_model, NULL, GTK_JUSTIFY_LEFT);
-
- for (i = 0; i < cols; i++){
- ETableCol *ecol = e_table_col_new (
- i, column_labels [i],
- 80, 20, cell_left_just,
- g_str_equal, TRUE);
-
- e_table_header_add_column (full_header, ecol, i);
- }
-
-
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- e_table = e_table_new (full_header, e_table_model, col_spec, group_spec);
-
- gtk_container_add (GTK_CONTAINER (window), e_table);
-
- gtk_widget_set_usize (window, 200, 200);
- gtk_widget_show (e_table);
- gtk_widget_show (window);
-}
-
-void
-e_table_test (void)
-{
- load_data ();
-
- if (getenv ("DO")){
- do_e_table_demo ("0,1,2,3,4", NULL);
- do_e_table_demo ("0,1,2,3,4", "3,4");
- }
- do_e_table_demo ("0,1,2,3,4", "3");
-}
diff --git a/widgets/test.c b/widgets/test.c
deleted file mode 100644
index 0eece34467..0000000000
--- a/widgets/test.c
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <config.h>
-#include "e-table-simple.h"
-
-struct {
- char *str;
- int val;
-} data [] = {
- { "Miguel", 10 },
- { "Nat", 20 },
- { NULL, 0 },
-};
-
-main ()
-{
-
-}
-