1 /* GNU Midnight Commander -- GNOME edition
3 * Directory display routines
5 * Copyright (C) 1997 The Free Software Foundation
7 * Authors: Miguel de Icaza
19 #define WANT_WIDGETS /* bleah */
23 #include "layout.h" /* get_panel_widget */
24 #include "ext.h" /* regex_command */
25 #include "cmd.h" /* copy_cmd, ren_cmd, delete_cmd, ... */
31 #include "fileopctx.h"
39 #include "../vfs/vfs.h"
40 #include <gdk/gdkprivate.h>
43 # define MAX(a,b) ((a) > (b) ? a : b)
46 /* Offsets within the default_column_width array for the different listing types */
47 static const int column_width_pos
[LIST_TYPES
] = {
51 GMC_COLUMNS_BRIEF
+ GMC_COLUMNS_DETAILED
,
55 /* Default column widths for file listings */
56 int default_column_width
[GMC_COLUMNS
];
58 /* default format for custom view */
59 char* default_user_format
= NULL
;
61 /* Whether to display the tree view on the left */
62 int tree_panel_visible
= -1;
65 #include "dir-close.xpm"
69 /* Timeout for auto-scroll on drag */
70 #define SCROLL_TIMEOUT 100
72 /* Timeout for opening a tree branch on drag */
73 #define TREE_OPEN_TIMEOUT 1000
75 /* This is used to initialize our pixmaps */
76 static int pixmaps_ready
;
77 GdkPixmap
*icon_directory_pixmap
;
78 GdkBitmap
*icon_directory_mask
;
79 GdkPixmap
*icon_link_pixmap
;
80 GdkBitmap
*icon_link_mask
;
81 GdkPixmap
*icon_dev_pixmap
;
82 GdkBitmap
*icon_dev_mask
;
84 static GtkTargetEntry drag_types
[] = {
85 { TARGET_URI_LIST_TYPE
, 0, TARGET_URI_LIST
},
86 { TARGET_TEXT_PLAIN_TYPE
, 0, TARGET_TEXT_PLAIN
},
87 { TARGET_URL_TYPE
, 0, TARGET_URL
}
90 static GtkTargetEntry drop_types
[] = {
91 { TARGET_URI_LIST_TYPE
, 0, TARGET_URI_LIST
},
92 { TARGET_URL_TYPE
, 0, TARGET_URL
}
95 #define ELEMENTS(x) (sizeof (x) / sizeof (x[0]))
97 /* GtkWidgets with the shaped windows for dragging */
98 GtkWidget
*drag_directory
= NULL
;
99 GtkWidget
*drag_directory_ok
= NULL
;
100 GtkWidget
*drag_multiple
= NULL
;
101 GtkWidget
*drag_multiple_ok
= NULL
;
103 static void file_list_popup (GdkEventButton
*event
, WPanel
*panel
);
107 repaint_file (WPanel
*panel
, int file_index
, int move
, int attr
, int isstatus
)
112 * Invoked by the generic code: show current working directory
115 show_dir (WPanel
*panel
)
117 assign_text (panel
->current_dir
, panel
->cwd
);
118 update_input (panel
->current_dir
, 1);
119 gtk_window_set_title (GTK_WINDOW (panel
->xwindow
), panel
->cwd
);
123 * Utility routine: Try to load a bitmap for a file_entry
126 panel_file_list_set_type_bitmap (GtkCList
*cl
, int row
, int column
, int color
, file_entry
*fe
)
128 /* Here, add more icons */
130 case DIRECTORY_COLOR
:
131 gtk_clist_set_pixmap (cl
, row
, column
, icon_directory_pixmap
, icon_directory_mask
);
134 gtk_clist_set_pixmap (cl
, row
, column
, icon_link_pixmap
, icon_link_mask
);
137 gtk_clist_set_pixmap (cl
, row
, column
, icon_dev_pixmap
, icon_dev_mask
);
143 panel_cancel_drag_scroll (WPanel
*panel
)
145 g_return_if_fail (panel
!= NULL
);
147 if (panel
->timer_id
!= -1){
148 gtk_timeout_remove (panel
->timer_id
);
149 panel
->timer_id
= -1;
154 * Sets the color attributes for a given row.
157 panel_file_list_set_row_colors (GtkCList
*cl
, int row
, int color_pair
)
159 gtk_clist_set_foreground (cl
, row
, gmc_color_pairs
[color_pair
].fore
);
160 gtk_clist_set_background (cl
, row
, gmc_color_pairs
[color_pair
].back
);
164 * Update the status of the back and forward history buttons.
165 * Called from the generic code
168 x_panel_update_marks (WPanel
*panel
)
170 int ff
= panel
->dir_history
->next
? 1 : 0;
171 int bf
= panel
->dir_history
->prev
? 1 : 0;
176 gtk_widget_set_sensitive (panel
->fwd_b
, ff
);
177 gtk_widget_set_sensitive (panel
->back_b
, bf
);
180 static GtkAdjustment
*
181 scrolled_window_get_vadjustment (GtkScrolledWindow
*sw
)
183 GtkRange
*vsb
= GTK_RANGE (sw
->vscrollbar
);
184 GtkAdjustment
*va
= vsb
->adjustment
;
190 * Listing view: Load the contents
193 panel_fill_panel_list (WPanel
*panel
)
195 const int top
= panel
->count
;
196 const int items
= panel
->format
->items
;
197 const int selected
= panel
->selected
;
198 GtkCList
*cl
= CLIST_FROM_SW (panel
->list
);
199 int i
, col
, type_col
, color
;
205 texts
= g_new (char *, items
+ 1);
207 /* CList doesn't restore its vertical scroll position when its cleared,
208 * so we need to do it manually.
211 /* Save the vertical position */
212 va
= scrolled_window_get_vadjustment (panel
->list
);
213 clist_v_pos
= va
->value
;
215 gtk_clist_freeze (GTK_CLIST (cl
));
216 gtk_clist_clear (GTK_CLIST (cl
));
218 /* which column holds the type information */
221 g_assert (items
== cl
->columns
);
223 texts
[items
] = NULL
;
224 for (i
= 0; i
< top
; i
++){
225 file_entry
*fe
= &panel
->dir
.list
[i
];
226 format_e
*format
= panel
->format
;
229 for (col
= 0; format
; format
= format
->next
){
230 if (!format
->use_in_gui
)
234 if (strcmp (format
->id
, "type") == 0)
237 if (!format
->string_fn
)
240 texts
[col
] = (* format
->string_fn
) (fe
, 10);
244 n
= gtk_clist_append (cl
, texts
);
246 /* Do not let the user select .. */
247 if (strcmp (fe
->fname
, "..") == 0)
248 gtk_clist_set_selectable (cl
, n
, FALSE
);
250 color
= file_compute_color (NORMAL
, fe
);
251 panel_file_list_set_row_colors (cl
, i
, color
);
254 panel_file_list_set_type_bitmap (cl
, i
, type_col
, color
, fe
);
257 gtk_clist_select_row (cl
, i
, 0);
259 gtk_clist_unselect_row (cl
, i
, 0);
265 /* This is needed as the gtk_clist_append changes selected under us :-( */
266 panel
->selected
= selected
;
268 p
= column_width_pos
[panel
->list_type
]; /* offset in column_width */
270 for (i
= 0; i
< items
; i
++) {
271 width
= panel
->column_width
[p
+ i
];
273 width
= gtk_clist_optimal_column_width (cl
, i
);
275 gtk_clist_set_column_width (cl
, i
, width
);
278 /* Now restore the clist's vertical position */
279 gtk_adjustment_set_value (va
, clist_v_pos
);
281 gtk_clist_thaw (GTK_CLIST (cl
));
285 * Icon view: load the panel contents
288 panel_fill_panel_icons (WPanel
*panel
)
290 const int top
= panel
->count
;
291 const int selected
= panel
->selected
;
292 GnomeIconList
*icons
= ILIST_FROM_SW (panel
->icons
);
294 GdkImlibImage
*image
;
296 gnome_icon_list_freeze (icons
);
297 gnome_icon_list_clear (icons
);
299 for (i
= 0; i
< top
; i
++) {
300 file_entry
*fe
= &panel
->dir
.list
[i
];
303 image
= gicon_get_icon_for_file (panel
->cwd
, fe
, TRUE
);
304 p
= gnome_icon_list_append_imlib (icons
, image
, fe
->fname
);
307 gnome_icon_list_select_icon (icons
, p
);
309 gnome_icon_list_unselect_icon (icons
, p
);
312 /* This is needed as the gtk_gnome_icon_list_append_imlib changes selected under us :-( */
313 panel
->selected
= selected
;
315 gnome_icon_list_thaw (icons
);
319 * Invoked from the generic code to fill the display
322 x_fill_panel (WPanel
*panel
)
324 if (panel
->list_type
== list_icons
)
325 panel_fill_panel_icons (panel
);
327 panel_fill_panel_list (panel
);
329 gtk_signal_handler_block_by_data (GTK_OBJECT (panel
->tree
), panel
);
331 if (vfs_current_is_local ()){
332 char buffer
[MC_MAXPATHLEN
];
334 get_current_wd (buffer
, sizeof (buffer
)-1);
335 gtk_dtree_select_dir (GTK_DTREE (panel
->tree
), buffer
);
337 gtk_dtree_select_dir (GTK_DTREE (panel
->tree
), panel
->cwd
);
339 gtk_signal_handler_unblock_by_data (GTK_OBJECT (panel
->tree
), panel
);
343 gmc_panel_set_size (int index
, int boot
)
348 w
= (Widget
*) get_panel_widget (index
);
352 set_panel_formats (p
);
362 x_panel_set_size (int index
)
364 printf ("WARNING: set size called\n");
365 gmc_panel_set_size (index
, 1);
369 * Invoked when the f.mark field of a file item changes
372 x_panel_select_item (WPanel
*panel
, int index
, int value
)
376 color
= file_compute_color (NORMAL
, &panel
->dir
.list
[index
]);
377 panel_file_list_set_row_colors (CLIST_FROM_SW (panel
->list
), index
, color
);
381 x_select_item (WPanel
*panel
)
383 if (is_a_desktop_panel (panel
))
386 do_file_mark (panel
, panel
->selected
, 1);
387 display_mini_info (panel
);
389 if (panel
->list_type
== list_icons
) {
390 GnomeIconList
*list
= ILIST_FROM_SW (panel
->icons
);
392 gnome_icon_list_select_icon (list
, panel
->selected
);
393 if (GTK_WIDGET (list
)->allocation
.x
!= -1)
394 if (gnome_icon_list_icon_is_visible (list
, panel
->selected
) != GTK_VISIBILITY_FULL
)
395 gnome_icon_list_moveto (list
, panel
->selected
, 0.5);
397 GtkCList
*clist
= CLIST_FROM_SW (panel
->list
);
399 gtk_clist_select_row (clist
, panel
->selected
, 0);
401 /* Make it visible */
402 if (gtk_clist_row_is_visible (clist
, panel
->selected
) != GTK_VISIBILITY_FULL
)
403 gtk_clist_moveto (clist
, panel
->selected
, 0, 0.5, 0.0);
408 x_unselect_item (WPanel
*panel
)
410 int selected
= panel
->selected
;
412 if (panel
->list_type
== list_icons
)
413 gnome_icon_list_unselect_all (ILIST_FROM_SW (panel
->icons
), NULL
, NULL
);
415 gtk_clist_unselect_all (CLIST_FROM_SW (panel
->list
));
417 panel
->selected
= selected
;
421 x_filter_changed (WPanel
*panel
)
426 x_adjust_top_file (WPanel
*panel
)
428 /* gtk_clist_moveto (GTK_CLIST (panel->list), panel->top_file, 0, 0.0, 0.0); */
432 panel_file_list_select_row (GtkWidget
*file_list
, gint row
, gint column
,
433 GdkEvent
*event
, gpointer data
)
439 panel
->selected
= row
;
440 do_file_mark (panel
, row
, 1);
441 display_mini_info (panel
);
442 execute_hooks (select_file_hook
);
446 panel_file_list_unselect_row (GtkWidget
*widget
, int row
, int columns
, GdkEvent
*event
, gpointer data
)
451 do_file_mark (panel
, row
, 0);
452 display_mini_info (panel
);
454 if (panel
->marked
== 0)
459 panel_file_list_resize_callback (GtkCList
*clist
, gint column
, gint width
, WPanel
*panel
)
463 p
= column_width_pos
[panel
->list_type
]; /* offset in column_width */
466 panel
->column_width
[p
+ column
] = width
;
468 /* make this default */
469 memcpy (default_column_width
, panel
->column_width
, sizeof (default_column_width
));
473 panel_file_list_column_callback (GtkWidget
*widget
, int col
, WPanel
*panel
)
478 for (i
= 0, format
= panel
->format
; format
; format
= format
->next
){
479 if (!format
->use_in_gui
)
482 sortfn
*sorting_routine
;
484 sorting_routine
= get_sort_fn (format
->id
);
485 if (!sorting_routine
)
488 if (sorting_routine
== panel
->sort_type
)
489 panel
->reverse
= !panel
->reverse
;
490 panel
->sort_type
= sorting_routine
;
499 /* Convenience function to load a pixmap and mask from xpm data */
501 create_pixmap (char **data
, GdkPixmap
**pixmap
, GdkBitmap
**mask
)
505 im
= gdk_imlib_create_image_from_xpm_data (data
);
506 gdk_imlib_render (im
, im
->rgb_width
, im
->rgb_height
);
507 *pixmap
= gdk_imlib_copy_image (im
);
508 *mask
= gdk_imlib_copy_mask (im
);
509 gdk_imlib_destroy_image (im
);
513 panel_create_pixmaps (void)
515 pixmaps_ready
= TRUE
;
517 create_pixmap (DIRECTORY_CLOSE_XPM
, &icon_directory_pixmap
, &icon_directory_mask
);
518 create_pixmap (link_xpm
, &icon_link_pixmap
, &icon_link_mask
);
519 create_pixmap (dev_xpm
, &icon_dev_pixmap
, &icon_dev_mask
);
522 typedef gboolean (*desirable_fn
)(WPanel
*p
, int x
, int y
);
523 typedef gboolean (*scroll_fn
)(gpointer data
);
525 /* Sets up a timer to scroll a panel component when something is being dragged
526 * over it. The `desirable' function should return whether it is desirable to
527 * scroll at the specified coordinates; and the `scroll' function should
528 * actually scroll the view.
531 panel_setup_drag_scroll (WPanel
*panel
, int x
, int y
, desirable_fn desirable
, scroll_fn scroll
)
533 panel_cancel_drag_scroll (panel
);
535 panel
->drag_motion_x
= x
;
536 panel
->drag_motion_y
= y
;
538 if ((* desirable
) (panel
, x
, y
))
539 panel
->timer_id
= gtk_timeout_add (SCROLL_TIMEOUT
, scroll
, panel
);
543 panel_file_list_configure (WPanel
*panel
, GtkWidget
*sw
, GtkWidget
*file_list
)
545 format_e
*format
= panel
->format
;
548 /* Set sorting callback */
549 gtk_signal_connect (GTK_OBJECT (file_list
), "click_column",
550 GTK_SIGNAL_FUNC (panel_file_list_column_callback
), panel
);
552 /* Set column resize callback */
553 gtk_signal_connect (GTK_OBJECT (file_list
), "resize_column",
554 GTK_SIGNAL_FUNC (panel_file_list_resize_callback
), panel
);
556 /* Avoid clist's broken focusing behavior */
557 GTK_WIDGET_UNSET_FLAGS (file_list
, GTK_CAN_FOCUS
);
559 /* Semi-sane selection mode */
560 gtk_clist_set_selection_mode (GTK_CLIST (file_list
), GTK_SELECTION_EXTENDED
);
562 for (i
= 0, format
= panel
->format
; format
; format
= format
->next
) {
563 GtkJustification just
= GTK_JUSTIFY_LEFT
;
565 if (!format
->use_in_gui
)
568 /* Set desired justification */
569 switch (HIDE_FIT (format
->just_mode
)) {
571 just
= GTK_JUSTIFY_LEFT
;
575 just
= GTK_JUSTIFY_RIGHT
;
579 just
= GTK_JUSTIFY_CENTER
;
583 gtk_clist_set_column_justification (GTK_CLIST (file_list
), i
, just
);
588 /* Creates an URI list to be transferred during a drop operation */
590 panel_build_selected_file_list (WPanel
*panel
, int *file_list_len
)
596 int cwdlen
= strlen (panel
->cwd
) + 1;
597 int filelen
= strlen ("file:");
598 int seplen
= strlen ("\r\n");
600 /* first pass, compute the length */
602 for (i
= 0; i
< panel
->count
; i
++)
603 if (panel
->dir
.list
[i
].f
.marked
)
604 total_len
+= (filelen
+ cwdlen
605 + panel
->dir
.list
[i
].fnamelen
609 data
= copy
= g_malloc (total_len
+1);
610 for (i
= 0; i
< panel
->count
; i
++)
611 if (panel
->dir
.list
[i
].f
.marked
){
612 strcpy (copy
, "file:");
613 strcpy (©
[filelen
], panel
->cwd
);
614 copy
[filelen
+cwdlen
-1] = '/';
615 strcpy (©
[filelen
+ cwdlen
], panel
->dir
.list
[i
].fname
);
616 strcpy (©
[filelen
+ cwdlen
+ panel
->dir
.list
[i
].fnamelen
], sep
);
617 copy
+= filelen
+ cwdlen
+ panel
->dir
.list
[i
].fnamelen
+ seplen
;
619 data
[total_len
] = 0;
620 *file_list_len
= total_len
;
623 char *fullname
, *uri
;
625 fullname
= concat_dir_and_file (panel
->cwd
, panel
->dir
.list
[panel
->selected
].fname
);
627 uri
= g_strconcat ("file:", fullname
, NULL
);
630 *file_list_len
= strlen (uri
) + 1;
636 * panel_drag_data_get:
638 * Invoked when a drag operation has been performed, this routine
639 * provides the data to be transfered
642 panel_drag_data_get (GtkWidget
*widget
,
643 GdkDragContext
*context
,
644 GtkSelectionData
*selection_data
,
653 panel_cancel_drag_scroll (panel
);
654 data
= panel_build_selected_file_list (panel
, &len
);
657 case TARGET_URI_LIST
:
658 case TARGET_TEXT_PLAIN
:
659 gtk_selection_data_set (selection_data
, selection_data
->target
, 8, data
, len
);
663 files
= gnome_uri_list_extract_uris (data
);
665 gtk_selection_data_set (selection_data
,
666 selection_data
->target
,
669 strlen (files
->data
));
671 gnome_uri_list_free_strings (files
);
675 g_assert_not_reached ();
682 * panel_drag_data_delete:
684 * Invoked when the destination requests the information to be deleted
685 * possibly because the operation was MOVE.
688 panel_drag_data_delete (GtkWidget
*widget
, GdkDragContext
*context
, WPanel
*panel
)
690 /* Things is: The File manager already handles file moving */
693 /* Performs a drop on a panel. If idx is -1, then drops on the panel's cwd
697 drop_on_panel (WPanel
*panel
, int idx
, GdkDragContext
*context
, GtkSelectionData
*selection_data
)
704 g_assert (panel
!= NULL
);
705 g_assert (idx
== -1 || idx
< panel
->count
);
706 g_assert (context
!= NULL
);
707 g_assert (selection_data
!= NULL
);
714 fe
= &panel
->dir
.list
[idx
];
715 file
= g_concat_dir_and_file (panel
->cwd
, fe
->fname
);
717 if (!((S_ISDIR (fe
->buf
.st_mode
) || fe
->f
.link_to_dir
)
718 || gdnd_can_drop_on_file (file
, fe
))) {
726 fe
= file_entry_from_file (file
);
731 reload
= gdnd_perform_drop (context
, selection_data
, file
, fe
);
733 if (file
!= panel
->cwd
)
737 file_entry_free (fe
);
740 update_panels (UP_OPTIMIZE
, UP_KEEPSEL
);
746 * panel_icon_list_drag_data_received:
748 * Invoked on the target side of a Drag and Drop operation when data has been
752 panel_icon_list_drag_data_received (GtkWidget
*widget
,
753 GdkDragContext
*context
,
756 GtkSelectionData
*selection_data
,
763 idx
= gnome_icon_list_get_icon_at (GNOME_ICON_LIST (widget
), x
, y
);
764 drop_on_panel (panel
, idx
, context
, selection_data
);
768 * panel_clist_drag_data_received:
770 * Invoked on the target side of a Drag and Drop operation when data has been
774 panel_clist_drag_data_received (GtkWidget
*widget
,
775 GdkDragContext
*context
,
778 GtkSelectionData
*selection_data
,
786 clist
= GTK_CLIST (widget
);
788 /* Normalize the y coordinate to the clist_window */
790 y
-= (GTK_CONTAINER (clist
)->border_width
791 + clist
->column_title_area
.y
792 + clist
->column_title_area
.height
);
794 if (gtk_clist_get_selection_info (GTK_CLIST (widget
), x
, y
, &row
, NULL
) == 0)
797 drop_on_panel (panel
, row
, context
, selection_data
);
801 * panel_tree_drag_data_received:
803 * Invoked on the target side when a drop has been received in the Tree
806 panel_tree_drag_data_received (GtkWidget
*widget
,
807 GdkDragContext
*context
,
810 GtkSelectionData
*selection_data
,
815 GtkDTree
*dtree
= GTK_DTREE (widget
);
822 if (!gtk_clist_get_selection_info (GTK_CLIST (dtree
), x
, y
, &row
, &col
))
825 node
= gtk_ctree_node_nth (GTK_CTREE (dtree
), row
);
829 path
= gtk_dtree_get_row_path (dtree
, node
);
830 fe
= file_entry_from_file (path
);
836 reload
= gdnd_perform_drop (context
, selection_data
, path
, fe
);
838 file_entry_free (fe
);
842 update_panels (UP_OPTIMIZE
, UP_KEEPSEL
);
848 load_dnd_icons (void)
851 drag_directory
= gnome_stock_transparent_window (GNOME_STOCK_PIXMAP_NOT
, NULL
);
853 if (!drag_directory_ok
)
854 drag_directory_ok
= gnome_stock_transparent_window (GNOME_STOCK_PIXMAP_NEW
, NULL
);
857 drag_multiple
= gnome_stock_transparent_window (GNOME_STOCK_PIXMAP_NOT
, NULL
);
859 if (!drag_multiple_ok
)
860 drag_multiple_ok
= gnome_stock_transparent_window (GNOME_STOCK_PIXMAP_MULTIPLE
, NULL
);
863 /* Convenience function to start a drag operation for the icon and file lists */
865 start_drag (GtkWidget
*widget
, int button
, GdkEvent
*event
)
868 GdkDragContext
*context
;
870 list
= gtk_target_list_new (drag_types
, ELEMENTS (drag_types
));
872 context
= gtk_drag_begin (widget
, list
,
873 (GDK_ACTION_COPY
| GDK_ACTION_MOVE
874 | GDK_ACTION_LINK
| GDK_ACTION_ASK
),
876 gtk_drag_set_icon_default (context
);
880 panel_widget_motion (GtkWidget
*widget
, GdkEventMotion
*event
, WPanel
*panel
)
882 if (!panel
->maybe_start_drag
)
885 if (!((panel
->maybe_start_drag
== 1 && (event
->state
& GDK_BUTTON1_MASK
))
886 || (panel
->maybe_start_drag
== 2 && (event
->state
& GDK_BUTTON2_MASK
))))
889 /* This is the same threshold value that is used in gtkdnd.c */
891 if (MAX (abs (panel
->click_x
- event
->x
),
892 abs (panel
->click_y
- event
->y
)) <= 3)
895 start_drag (widget
, panel
->maybe_start_drag
, (GdkEvent
*) event
);
902 * Invoked when a drag is starting in the List view or the Icon view
905 panel_drag_begin (GtkWidget
*widget
, GdkDragContext
*context
, WPanel
*panel
)
913 * Invoked when a drag has finished in the List view or the Icon view
916 panel_drag_end (GtkWidget
*widget
, GdkDragContext
*context
, WPanel
*panel
)
918 panel_cancel_drag_scroll (panel
);
923 * panel_clist_scrolling_is_desirable:
925 * If the cursor is in a position close to either edge (top or bottom)
926 * and there is possible to scroll the window, this routine returns
930 panel_clist_scrolling_is_desirable (WPanel
*panel
, int x
, int y
)
934 va
= scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (panel
->list
));
937 if (va
->value
> va
->lower
)
940 if (y
> (CLIST_FROM_SW (panel
->list
)->clist_window_height
- 10)) {
941 if (va
->value
< va
->upper
- va
->page_size
)
951 * panel_clist_scroll:
953 * Timer callback invoked to scroll the clist window
956 panel_clist_scroll (gpointer data
)
958 WPanel
*panel
= data
;
962 va
= scrolled_window_get_vadjustment (panel
->list
);
964 if (panel
->drag_motion_y
< 10) {
965 v
= va
->value
- va
->step_increment
;
969 gtk_adjustment_set_value (va
, v
);
971 v
= va
->value
+ va
->step_increment
;
972 if (v
> va
->upper
- va
->page_size
)
973 v
= va
->upper
- va
->page_size
;
975 gtk_adjustment_set_value (va
, v
);
981 /* Callback used for drag motion events over the clist. We set up
982 * auto-scrolling and validate the drop to present the user with the correct
986 panel_clist_drag_motion (GtkWidget
*widget
, GdkDragContext
*context
, gint x
, gint y
, guint time
,
991 GdkDragAction action
;
992 GtkWidget
*source_widget
;
999 /* Normalize the y coordinate to the clist_window */
1001 clist
= CLIST_FROM_SW (panel
->list
);
1002 y
-= (GTK_CONTAINER (clist
)->border_width
1003 + clist
->column_title_area
.y
1004 + clist
->column_title_area
.height
);
1007 gdk_drag_status (context
, 0, time
);
1011 /* Set up auto-scrolling */
1013 panel_setup_drag_scroll (panel
, x
, y
,
1014 panel_clist_scrolling_is_desirable
,
1015 panel_clist_scroll
);
1017 /* Validate the drop */
1019 gdnd_find_panel_by_drag_context (context
, &source_widget
);
1021 if (!gtk_clist_get_selection_info (GTK_CLIST (widget
), x
, y
, &idx
, NULL
))
1024 fe
= &panel
->dir
.list
[idx
];
1026 full_name
= fe
? g_concat_dir_and_file (panel
->cwd
, fe
->fname
) : panel
->cwd
;
1028 action
= gdnd_validate_action (context
,
1030 source_widget
!= NULL
,
1031 source_widget
== widget
,
1034 fe
? fe
->f
.marked
: FALSE
);
1036 if (full_name
!= panel
->cwd
)
1039 gdk_drag_status (context
, action
, time
);
1042 gtk_signal_emit_stop_by_name (GTK_OBJECT (widget
), "drag_motion");
1047 * panel_clist_drag_leave
1049 * Invoked when the dragged object has left our region
1052 panel_clist_drag_leave (GtkWidget
*widget
, GdkDragContext
*context
, guint time
, gpointer data
)
1057 panel_cancel_drag_scroll (panel
);
1061 * panel_icon_list_scrolling_is_desirable:
1063 * If the cursor is in a position close to either edge (top or bottom)
1064 * and there is possible to scroll the window, this routine returns
1068 panel_icon_list_scrolling_is_desirable (WPanel
*panel
, int x
, int y
)
1072 va
= scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (panel
->icons
));
1075 if (va
->value
> va
->lower
)
1078 if (y
> (GTK_WIDGET (ILIST_FROM_SW (panel
->icons
))->allocation
.height
- 10)) {
1079 if (va
->value
< va
->upper
- va
->page_size
)
1089 * panel_icon_list_scroll:
1091 * Timer callback invoked to scroll the clist window
1094 panel_icon_list_scroll (gpointer data
)
1096 WPanel
*panel
= data
;
1100 va
= scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (panel
->icons
));
1102 if (panel
->drag_motion_y
< 10) {
1103 v
= va
->value
- va
->step_increment
;
1107 gtk_adjustment_set_value (va
, v
);
1109 v
= va
->value
+ va
->step_increment
;
1110 if (v
> va
->upper
- va
->page_size
)
1111 v
= va
->upper
- va
->page_size
;
1113 gtk_adjustment_set_value (va
, v
);
1119 /* Callback used for drag motion events in the icon list. We need to set up
1120 * auto-scrolling and validate the drop to present the user with the correct
1124 panel_icon_list_drag_motion (GtkWidget
*widget
, GdkDragContext
*context
, gint x
, gint y
, guint time
,
1128 GdkDragAction action
;
1129 GtkWidget
*source_widget
;
1136 /* Set up auto-scrolling */
1138 panel_setup_drag_scroll (panel
, x
, y
,
1139 panel_icon_list_scrolling_is_desirable
,
1140 panel_icon_list_scroll
);
1142 /* Validate the drop */
1144 gdnd_find_panel_by_drag_context (context
, &source_widget
);
1146 idx
= gnome_icon_list_get_icon_at (GNOME_ICON_LIST (widget
), x
, y
);
1147 fe
= (idx
== -1) ? NULL
: &panel
->dir
.list
[idx
];
1149 full_name
= fe
? g_concat_dir_and_file (panel
->cwd
, fe
->fname
) : panel
->cwd
;
1151 action
= gdnd_validate_action (context
,
1153 source_widget
!= NULL
,
1154 source_widget
== widget
,
1157 fe
? fe
->f
.marked
: FALSE
);
1159 if (full_name
!= panel
->cwd
)
1162 gdk_drag_status (context
, action
, time
);
1167 * panel_icon_list_drag_leave:
1169 * Invoked when the dragged object has left our region
1172 panel_icon_list_drag_leave (GtkWidget
*widget
, GdkDragContext
*context
, guint time
, gpointer data
)
1174 WPanel
*panel
= data
;
1176 panel_cancel_drag_scroll (panel
);
1179 /* Handler for the row_popup_menu signal of the file list. */
1181 panel_file_list_row_popup_menu (GtkFList
*flist
, GdkEventButton
*event
, gpointer data
)
1186 gpopup_do_popup2 (event
, panel
, NULL
);
1189 /* Handler for the empty_popup_menu signal of the file list. */
1191 panel_file_list_empty_popup_menu (GtkFList
*flist
, GdkEventButton
*event
, gpointer data
)
1196 file_list_popup (event
, panel
);
1199 /* Handler for the open_row signal of the file list */
1201 panel_file_list_open_row (GtkFList
*flist
, gpointer data
)
1209 /* Handler for the start_drag signal of the file list */
1211 panel_file_list_start_drag (GtkFList
*flist
, gint button
, GdkEvent
*event
, gpointer data
)
1213 start_drag (GTK_WIDGET (flist
), button
, event
);
1217 * Create, setup the file listing display.
1220 panel_create_file_list (WPanel
*panel
)
1222 const int items
= panel
->format
->items
;
1223 format_e
*format
= panel
->format
;
1224 GtkWidget
*file_list
;
1229 titles
= g_new (char *, items
);
1230 for (i
= 0; i
< items
; format
= format
->next
)
1231 if (format
->use_in_gui
)
1232 titles
[i
++] = format
->title
;
1234 sw
= gtk_scrolled_window_new (NULL
, NULL
);
1235 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw
),
1236 GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1238 file_list
= gtk_flist_new_with_titles (panel
, items
, titles
);
1239 gtk_container_add (GTK_CONTAINER (sw
), file_list
);
1240 gtk_widget_show (file_list
);
1242 panel_file_list_configure (panel
, sw
, file_list
);
1245 gtk_signal_connect (GTK_OBJECT (file_list
), "select_row",
1246 GTK_SIGNAL_FUNC (panel_file_list_select_row
),
1248 gtk_signal_connect (GTK_OBJECT (file_list
), "unselect_row",
1249 GTK_SIGNAL_FUNC (panel_file_list_unselect_row
),
1252 /* Connect to the flist signals */
1254 gtk_signal_connect (GTK_OBJECT (file_list
), "row_popup_menu",
1255 GTK_SIGNAL_FUNC (panel_file_list_row_popup_menu
),
1257 gtk_signal_connect (GTK_OBJECT (file_list
), "empty_popup_menu",
1258 GTK_SIGNAL_FUNC (panel_file_list_empty_popup_menu
),
1260 gtk_signal_connect (GTK_OBJECT (file_list
), "open_row",
1261 GTK_SIGNAL_FUNC (panel_file_list_open_row
),
1263 gtk_signal_connect (GTK_OBJECT (file_list
), "start_drag",
1264 GTK_SIGNAL_FUNC (panel_file_list_start_drag
),
1267 /* Set up drag and drop */
1271 gtk_drag_dest_set (GTK_WIDGET (file_list
),
1272 GTK_DEST_DEFAULT_DROP
,
1273 drop_types
, ELEMENTS (drop_types
),
1274 GDK_ACTION_COPY
| GDK_ACTION_MOVE
| GDK_ACTION_LINK
| GDK_ACTION_ASK
);
1276 gtk_signal_connect (GTK_OBJECT (file_list
), "drag_data_get",
1277 GTK_SIGNAL_FUNC (panel_drag_data_get
), panel
);
1278 gtk_signal_connect (GTK_OBJECT (file_list
), "drag_data_delete",
1279 GTK_SIGNAL_FUNC (panel_drag_data_delete
), panel
);
1280 gtk_signal_connect (GTK_OBJECT (file_list
), "drag_data_received",
1281 GTK_SIGNAL_FUNC (panel_clist_drag_data_received
), panel
);
1284 * This signal is provided for scrolling the main window
1285 * if data is being dragged
1287 gtk_signal_connect (GTK_OBJECT (file_list
), "drag_motion",
1288 GTK_SIGNAL_FUNC (panel_clist_drag_motion
), panel
);
1289 gtk_signal_connect (GTK_OBJECT (file_list
), "drag_leave",
1290 GTK_SIGNAL_FUNC (panel_clist_drag_leave
), panel
);
1291 gtk_signal_connect (GTK_OBJECT (file_list
), "drag_begin",
1292 GTK_SIGNAL_FUNC (panel_drag_begin
), panel
);
1293 gtk_signal_connect (GTK_OBJECT (file_list
), "drag_end",
1294 GTK_SIGNAL_FUNC (panel_drag_end
), panel
);
1300 * Callback: icon selected
1303 panel_icon_list_select_icon (GtkWidget
*widget
, int index
, GdkEvent
*event
, WPanel
*panel
)
1305 panel
->selected
= index
;
1306 do_file_mark (panel
, index
, 1);
1307 display_mini_info (panel
);
1308 execute_hooks (select_file_hook
);
1310 /* Do not let the user select .. */
1311 if (strcmp (panel
->dir
.list
[index
].fname
, "..") == 0)
1312 gnome_icon_list_unselect_icon (GNOME_ICON_LIST (widget
), index
);
1317 switch (event
->type
){
1318 case GDK_BUTTON_PRESS
:
1319 if (event
->button
.button
== 3)
1320 gpopup_do_popup2 ((GdkEventButton
*) event
, panel
, NULL
);
1324 case GDK_BUTTON_RELEASE
:
1325 if (event
->button
.button
== 2){
1328 if (S_ISDIR (panel
->dir
.list
[index
].buf
.st_mode
) ||
1329 panel
->dir
.list
[index
].f
.link_to_dir
){
1330 fullname
= concat_dir_and_file (panel
->cwd
, panel
->dir
.list
[index
].fname
);
1331 new_panel_at (fullname
);
1337 case GDK_2BUTTON_PRESS
:
1338 if (event
->button
.button
== 1) {
1349 panel_icon_list_unselect_icon (GtkWidget
*widget
, int index
, GdkEvent
*event
, WPanel
*panel
)
1351 do_file_mark (panel
, index
, 0);
1352 display_mini_info (panel
);
1353 if (panel
->marked
== 0)
1354 panel
->selected
= 0;
1358 queue_reread_cmd (gpointer data
)
1364 /* Renames a file using a file operation context. Returns FILE_CONT on success. */
1366 rename_file_with_context (char *source
, char *dest
)
1374 if (mc_lstat (source
, &s
) != 0)
1377 ctx
= file_op_context_new ();
1378 file_op_context_create_ui (ctx
, OP_MOVE
, FALSE
);
1383 retval
= move_file_file (ctx
, source
, dest
, &count
, &bytes
);
1384 file_op_context_destroy (ctx
);
1390 panel_icon_renamed (GtkWidget
*widget
, int index
, char *dest
, WPanel
*panel
)
1396 if (strcmp (dest
, panel
->dir
.list
[index
].fname
) == 0)
1397 return TRUE
; /* do nothing if the name did not change */
1399 source
= g_concat_dir_and_file (cpanel
->cwd
, panel
->dir
.list
[index
].fname
);
1400 fullname
= g_concat_dir_and_file (cpanel
->cwd
, dest
);
1402 if (rename_file_with_context (source
, dest
) == FILE_CONT
) {
1403 g_free (panel
->dir
.list
[index
].fname
);
1404 panel
->dir
.list
[index
].fname
= g_strdup (dest
);
1406 gtk_idle_add (queue_reread_cmd
, NULL
);
1417 /* Callback for rescanning the cwd */
1419 handle_rescan_directory (GtkWidget
*widget
, gpointer data
)
1424 /* The popup menu for file panels */
1425 static GnomeUIInfo file_list_popup_items
[] = {
1426 GNOMEUIINFO_ITEM_NONE (N_("_Rescan Directory"), N_("Reloads the current directory"),
1427 handle_rescan_directory
),
1428 GNOMEUIINFO_ITEM_NONE (N_("New _Directory..."), N_("Creates a new directory here"),
1433 /* The popup menu for file panels */
1434 static GnomeUIInfo trash_file_list_popup_items
[] = {
1435 GNOMEUIINFO_ITEM_NONE (N_("Empty _Trash"), N_("Empties the Trash"),
1437 GNOMEUIINFO_ITEM_NONE (N_("_Rescan Directory"), N_("Reloads the current directory"),
1438 handle_rescan_directory
),
1439 GNOMEUIINFO_ITEM_NONE (N_("New _Directory..."), N_("Creates a new directory here"),
1444 /* Creates the popup menu when the user clicks button 3 on the blank area of the
1448 file_list_popup (GdkEventButton
*event
, WPanel
*panel
)
1452 GnomeUIInfo
*items
= file_list_popup_items
;
1454 trash_dir
= g_strconcat (gnome_user_home_dir
, "/",
1455 DESKTOP_DIR_NAME
, "/",
1459 if ((strncmp (panel
->cwd
, trash_dir
, strlen (trash_dir
)) == 0) && (panel
->count
!= 1))
1460 items
= trash_file_list_popup_items
;
1463 popup
= gnome_popup_menu_new (items
);
1464 gnome_popup_menu_do_popup_modal (popup
, NULL
, NULL
, event
, panel
);
1465 gtk_widget_destroy (popup
);
1469 /* Returns whether an icon in the icon list is being edited. FIXME: This
1470 * function uses a fantastically ugly hack to figure this out. It would be
1471 * saner to have a function provided by the icon list widget to do it, but we
1472 * can't break forwards compatibility at this point. It would be even saner to
1473 * have a good DnD API for the icon list.
1476 editing_icon_list (GnomeIconList
*gil
)
1478 GnomeCanvasItem
*item
;
1480 item
= GNOME_CANVAS (gil
)->focused_item
;
1481 return (item
&& GNOME_IS_ICON_TEXT_ITEM (item
) && GNOME_ICON_TEXT_ITEM (item
)->editing
);
1485 * Strategy for activaing the drags from the icon-list:
1487 * The icon-list uses the button-press/motion-notify events for
1488 * the banding selection. We catch the events and only if the
1489 * click happens in an icon and the user moves the mouse enough (a
1490 * threshold to give it a better feel) activa the drag and drop.
1494 panel_icon_list_button_press (GtkWidget
*widget
, GdkEventButton
*event
, WPanel
*panel
)
1496 GnomeIconList
*gil
= GNOME_ICON_LIST (widget
);
1499 if (editing_icon_list (gil
))
1502 if (event
->type
!= GDK_BUTTON_PRESS
)
1505 icon
= gnome_icon_list_get_icon_at (gil
, event
->x
, event
->y
);
1508 if (event
->button
== 3) {
1509 file_list_popup (event
, panel
);
1512 } else if (event
->button
!= 3)
1513 panel
->maybe_start_drag
= event
->button
;
1515 panel
->click_x
= event
->x
;
1516 panel
->click_y
= event
->y
;
1521 panel_icon_list_button_release (GtkWidget
*widget
, GdkEventButton
*event
, WPanel
*panel
)
1523 panel
->maybe_start_drag
= 0;
1527 /* Create and setup the icon field display */
1529 panel_create_icon_display (WPanel
*panel
)
1532 GnomeIconList
*ilist
;
1534 sw
= gtk_scrolled_window_new (NULL
, NULL
);
1535 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw
),
1536 GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1538 ilist
= GNOME_ICON_LIST (
1539 gnome_icon_list_new_flags (90, NULL
,
1540 (GNOME_ICON_LIST_IS_EDITABLE
1541 | GNOME_ICON_LIST_STATIC_TEXT
)));
1542 gtk_container_add (GTK_CONTAINER (sw
), GTK_WIDGET (ilist
));
1543 gtk_widget_show (GTK_WIDGET (ilist
));
1545 gnome_icon_list_set_separators (ilist
, " /-_.");
1546 gnome_icon_list_set_row_spacing (ilist
, 2);
1547 gnome_icon_list_set_col_spacing (ilist
, 2);
1548 gnome_icon_list_set_icon_border (ilist
, 2);
1549 gnome_icon_list_set_text_spacing (ilist
, 2);
1551 gnome_icon_list_set_selection_mode (ilist
, GTK_SELECTION_MULTIPLE
);
1552 GTK_WIDGET_SET_FLAGS (ilist
, GTK_CAN_FOCUS
);
1554 gtk_signal_connect (GTK_OBJECT (ilist
), "select_icon",
1555 GTK_SIGNAL_FUNC (panel_icon_list_select_icon
),
1557 gtk_signal_connect (GTK_OBJECT (ilist
), "unselect_icon",
1558 GTK_SIGNAL_FUNC (panel_icon_list_unselect_icon
),
1560 gtk_signal_connect (GTK_OBJECT (ilist
), "text_changed",
1561 GTK_SIGNAL_FUNC (panel_icon_renamed
),
1564 /* Setup the icons and DnD */
1568 gtk_drag_dest_set (GTK_WIDGET (ilist
),
1569 GTK_DEST_DEFAULT_DROP
,
1570 drop_types
, ELEMENTS (drop_types
),
1571 GDK_ACTION_COPY
| GDK_ACTION_MOVE
| GDK_ACTION_LINK
| GDK_ACTION_ASK
);
1573 gtk_signal_connect (GTK_OBJECT (ilist
), "drag_data_get",
1574 GTK_SIGNAL_FUNC (panel_drag_data_get
),
1576 gtk_signal_connect (GTK_OBJECT (ilist
), "drag_data_delete",
1577 GTK_SIGNAL_FUNC (panel_drag_data_delete
),
1579 gtk_signal_connect (GTK_OBJECT (ilist
), "drag_data_received",
1580 GTK_SIGNAL_FUNC (panel_icon_list_drag_data_received
),
1582 gtk_signal_connect (GTK_OBJECT (ilist
), "drag_begin",
1583 GTK_SIGNAL_FUNC (panel_drag_begin
), panel
);
1584 gtk_signal_connect (GTK_OBJECT (ilist
), "drag_end",
1585 GTK_SIGNAL_FUNC (panel_drag_end
), panel
);
1587 /* These implement our drag-start activation code, as we have a pretty oveloaded widget */
1589 gtk_signal_connect (GTK_OBJECT (ilist
), "button_press_event",
1590 GTK_SIGNAL_FUNC (panel_icon_list_button_press
),
1592 gtk_signal_connect (GTK_OBJECT (ilist
), "button_release_event",
1593 GTK_SIGNAL_FUNC (panel_icon_list_button_release
),
1595 gtk_signal_connect (GTK_OBJECT (ilist
), "motion_notify_event",
1596 GTK_SIGNAL_FUNC (panel_widget_motion
),
1599 /* This signal is provide for scrolling the main window if data is being
1602 gtk_signal_connect (GTK_OBJECT (ilist
), "drag_motion",
1603 GTK_SIGNAL_FUNC (panel_icon_list_drag_motion
), panel
);
1604 gtk_signal_connect (GTK_OBJECT (ilist
), "drag_leave",
1605 GTK_SIGNAL_FUNC (panel_icon_list_drag_leave
), panel
);
1611 panel_switch_new_display_mode (WPanel
*panel
)
1613 GtkWidget
*old_list
= panel
->list
;
1618 panel
->list
= panel_create_file_list (panel
);
1619 gtk_widget_destroy (old_list
);
1620 gtk_container_add (GTK_CONTAINER (panel
->panel_listbox
), panel
->list
);
1621 gtk_widget_show_all (panel
->list
);
1625 panel_create_cwd (Dlg_head
*h
, WPanel
*panel
, void **entry
)
1629 in
= input_new (0, 0, 0, 10, "", "cwd");
1632 /* Force the creation of the gtk widget */
1633 send_message_to (h
, (Widget
*) in
, WIDGET_INIT
, 0);
1636 /* FIXME: for now, we set the usize. Ultimately, toolbar
1637 * will let you expand it, we hope.
1639 gtk_widget_set_usize (GTK_WIDGET (in
->widget
.wdata
), 296, -1);
1640 return GTK_WIDGET (in
->widget
.wdata
);
1644 display_mini_info (WPanel
*panel
)
1646 GnomeAppBar
*bar
= GNOME_APPBAR (panel
->ministatus
);
1648 if (panel
->searching
) {
1651 buf
= g_strdup_printf (_("Search: %s"), panel
->search_buffer
);
1652 gnome_appbar_pop (bar
);
1653 gnome_appbar_push (bar
, buf
);
1661 buf
= g_strdup_printf ((panel
->marked
== 1) ? _("%s bytes in %d file") : _("%s bytes in %d files"),
1662 size_trunc_sep (panel
->total
),
1664 gnome_appbar_pop (bar
);
1665 gnome_appbar_push (bar
, buf
);
1670 if (S_ISLNK (panel
->dir
.list
[panel
->selected
].buf
.st_mode
)){
1671 char *link
, link_target
[MC_MAXPATHLEN
];
1674 link
= concat_dir_and_file (panel
->cwd
, panel
->dir
.list
[panel
->selected
].fname
);
1675 len
= mc_readlink (link
, link_target
, MC_MAXPATHLEN
);
1679 link_target
[len
] = 0;
1680 /* FIXME: Links should be handled differently */
1681 /* str = g_strconcat ("-> ", link_target, NULL); */
1682 gnome_appbar_pop (bar
);
1683 gnome_appbar_push (bar
, " ");
1686 gnome_appbar_pop (bar
);
1687 gnome_appbar_push (bar
, _("<readlink failed>"));
1692 if (panel
->estimated_total
> 8){
1693 int len
= panel
->estimated_total
;
1696 buffer
= g_malloc (len
+ 2);
1697 format_file (buffer
, panel
, panel
->selected
, panel
->estimated_total
-2, 0, 1);
1699 gnome_appbar_pop (bar
);
1700 gnome_appbar_push (bar
, buffer
);
1703 if (panel
->list_type
== list_icons
){
1704 if (panel
->marked
== 0){
1705 gnome_appbar_pop (bar
);
1706 gnome_appbar_push (bar
, " ");
1711 /* Signal handler for DTree's "directory_changed" signal */
1713 panel_chdir (GtkDTree
*dtree
, char *path
, WPanel
*panel
)
1715 if (panel
->dragging
)
1718 if (do_panel_cd (panel
, path
, cd_exact
))
1719 return; /* success */
1721 if (panel
->list_type
== list_icons
)
1722 gnome_icon_list_clear (ILIST_FROM_SW (panel
->icons
));
1724 gtk_clist_clear (CLIST_FROM_SW (panel
->list
));
1726 strncpy (panel
->cwd
, path
, sizeof (panel
->cwd
));
1731 panel_tree_scan_begin (GtkWidget
*widget
, gpointer data
)
1736 set_cursor_busy (panel
);
1740 panel_tree_scan_end (GtkWidget
*widget
, gpointer data
)
1745 set_cursor_normal (panel
);
1748 /* Handler for the possibly_ungrab signal of the dtree widget */
1750 panel_tree_possibly_ungrab (GtkWidget
*widget
, gpointer data
)
1756 /* The stupid clist button press handler grabs the mouse. We will get
1757 * called when the user presses the mouse on the tree, so we ungrab it.
1758 * Also, we have to make sure we don't knock away a DnD grab.
1760 if (!panel
->drag_tree_dragging_over
)
1761 gdk_pointer_ungrab (GDK_CURRENT_TIME
);
1764 /* Callback for the drag_begin signal of the tree */
1766 panel_tree_drag_begin (GtkWidget
*widget
, GdkDragContext
*context
, gpointer data
)
1771 dtree
= GTK_DTREE (widget
);
1774 panel
->dragging
= TRUE
;
1775 dtree
->drag_dir
= g_strdup (dtree
->current_path
);
1778 /* Callback for the drag_end signal of the tree */
1780 panel_tree_drag_end (GtkWidget
*widget
, GdkDragContext
*context
, gpointer data
)
1785 dtree
= GTK_DTREE (widget
);
1788 panel
->dragging
= FALSE
;
1789 g_free (dtree
->drag_dir
);
1790 dtree
->drag_dir
= NULL
;
1793 /* Callback for the drag_data_get signal of the tree */
1795 panel_tree_drag_data_get (GtkWidget
*widget
, GdkDragContext
*context
,
1796 GtkSelectionData
*selection_data
, guint info
, guint time
, gpointer data
)
1801 dtree
= GTK_DTREE (widget
);
1804 case TARGET_URI_LIST
:
1805 case TARGET_TEXT_PLAIN
:
1806 str
= g_strconcat ("file:", dtree
->drag_dir
, NULL
);
1807 gtk_selection_data_set (selection_data
, selection_data
->target
, 8,
1808 str
, strlen (str
) + 1);
1812 /* FIXME: handle TARGET_URL */
1818 * tree_drag_open_directory:
1820 * This routine is invoked in a delayed fashion if the user
1821 * keeps the drag cursor still over the widget.
1824 tree_drag_open_directory (gpointer data
)
1831 dtree
= GTK_DTREE (panel
->tree
);
1833 node
= gtk_ctree_node_nth (GTK_CTREE (panel
->tree
), panel
->drag_tree_row
);
1834 g_assert (node
!= NULL
);
1836 if (!GTK_CTREE_ROW (node
)->expanded
) {
1838 /* FIXME: Disabled until fully debugged. Should also be configurable. */
1839 dtree
->auto_expanded_nodes
= g_list_append (dtree
->auto_expanded_nodes
, node
);
1841 gtk_ctree_expand (GTK_CTREE (panel
->tree
), node
);
1847 /* Handles automatic collapsing of the tree nodes when doing drag and drop */
1849 panel_tree_check_auto_expand (WPanel
*panel
, GtkCTreeNode
*current
)
1856 gint row
, old_y
, new_y
;
1858 dtree
= GTK_DTREE (panel
->tree
);
1859 ctree
= GTK_CTREE (panel
->tree
);
1860 clist
= GTK_CLIST (panel
->tree
);
1861 tmp_list
= dtree
->auto_expanded_nodes
;
1864 for (; tmp_list
; tmp_list
= tmp_list
->next
)
1865 if (!gtk_dtree_is_ancestor (dtree
, tmp_list
->data
, current
))
1868 /* Collapse the rows as necessary. If possible, try to do so that the
1869 * "current" stays the same place on the screen.
1873 row
= g_list_position (clist
->row_list
, (GList
*) current
);
1874 old_y
= row
* clist
->row_height
- clist
->vadjustment
->value
;
1877 free_list
= tmp_list
;
1879 for (; tmp_list
; tmp_list
= tmp_list
->next
)
1880 gtk_ctree_collapse (GTK_CTREE (panel
->tree
), tmp_list
->data
);
1882 /* We have to calculate the row position again because rows may
1883 * have shifted during the collapse.
1886 row
= g_list_position (clist
->row_list
, (GList
*) current
);
1887 new_y
= row
* clist
->row_height
- clist
->vadjustment
->value
;
1890 gtk_adjustment_set_value (clist
->vadjustment
,
1891 clist
->vadjustment
->value
+ new_y
- old_y
);
1894 if (free_list
->prev
)
1895 free_list
->prev
->next
= NULL
;
1897 dtree
->auto_expanded_nodes
= NULL
;
1899 free_list
->prev
= NULL
;
1900 g_list_free (free_list
);
1905 * panel_tree_scrolling_is_desirable:
1907 * If the cursor is in a position close to either edge (top or bottom)
1908 * and there is possible to scroll the window, this routine returns
1912 panel_tree_scrolling_is_desirable (WPanel
*panel
, int x
, int y
)
1914 GtkDTree
*dtree
= GTK_DTREE (panel
->tree
);
1917 va
= scrolled_window_get_vadjustment (panel
->tree_scrolled_window
);
1920 if (va
->value
> va
->lower
)
1923 if (y
> (GTK_WIDGET (dtree
)->allocation
.height
- 10)){
1924 if (va
->value
< va
->upper
- va
->page_size
)
1932 /* Timer callback to scroll the tree */
1934 panel_tree_scroll (gpointer data
)
1936 WPanel
*panel
= data
;
1940 va
= scrolled_window_get_vadjustment (panel
->tree_scrolled_window
);
1942 if (panel
->drag_motion_y
< 10) {
1943 v
= va
->value
- va
->step_increment
;
1947 gtk_adjustment_set_value (va
, v
);
1949 v
= va
->value
+ va
->step_increment
;
1950 if (v
> va
->upper
- va
->page_size
)
1951 v
= va
->upper
- va
->page_size
;
1953 gtk_adjustment_set_value (va
, v
);
1959 /* Callback for the drag_motion signal of the tree. We set up a timer to
1960 * automatically open nodes if the user hovers over them.
1963 panel_tree_drag_motion (GtkWidget
*widget
, GdkDragContext
*context
, int x
, int y
, guint time
,
1968 int on_row
, row
, col
;
1970 GdkDragAction action
;
1971 GtkWidget
*source_widget
;
1975 dtree
= GTK_DTREE (widget
);
1978 panel
->drag_tree_dragging_over
= TRUE
;
1979 panel_setup_drag_scroll (panel
, x
, y
,
1980 panel_tree_scrolling_is_desirable
,
1983 on_row
= gtk_clist_get_selection_info (GTK_CLIST (widget
), x
, y
, &row
, &col
);
1985 /* Remove the auto-expansion timeout if we are on the blank area of the
1986 * tree or on a row different from the previous one.
1988 if ((!on_row
|| row
!= panel
->drag_tree_row
) && panel
->drag_tree_timeout_id
!= 0) {
1989 gtk_timeout_remove (panel
->drag_tree_timeout_id
);
1990 panel
->drag_tree_timeout_id
= 0;
1992 if (panel
->drag_tree_fe
) {
1993 file_entry_free (panel
->drag_tree_fe
);
1994 panel
->drag_tree_fe
= NULL
;
2001 node
= gtk_ctree_node_nth (GTK_CTREE (dtree
), row
);
2002 row_path
= gtk_dtree_get_row_path (dtree
, node
);
2004 if (row
!= panel
->drag_tree_row
) {
2005 /* Highlight the row by selecting it */
2007 panel_tree_check_auto_expand (panel
, node
);
2009 dtree
->internal
= TRUE
;
2010 gtk_clist_select_row (GTK_CLIST (widget
), row
, 0);
2011 dtree
->internal
= FALSE
;
2013 /* Create the file entry to validate drops */
2015 panel
->drag_tree_fe
= file_entry_from_file (row_path
);
2017 /* Install the timeout handler for auto-expansion */
2019 panel
->drag_tree_timeout_id
= gtk_timeout_add (TREE_OPEN_TIMEOUT
,
2020 tree_drag_open_directory
,
2022 panel
->drag_tree_row
= row
;
2025 /* Validate the action */
2027 gdnd_find_panel_by_drag_context (context
, &source_widget
);
2029 /* If this tree is the drag source, see if the user is trying to
2030 * drop on the row being dragged. Otherwise, consider all rows
2033 if (source_widget
== widget
) {
2034 g_assert (dtree
->drag_dir
!= NULL
);
2035 on_drag_row
= strcmp (row_path
, dtree
->drag_dir
) == 0;
2037 on_drag_row
= FALSE
;
2039 action
= gdnd_validate_action (context
,
2041 source_widget
!= NULL
,
2042 source_widget
== widget
,
2044 panel
->drag_tree_fe
,
2049 panel
->drag_tree_row
= -1;
2050 panel_tree_check_auto_expand (panel
, NULL
);
2053 gdk_drag_status (context
, action
, time
);
2057 /* Callback for the drag_leave signal of the tree. We deactivate the timeout for
2058 * automatic branch expansion.
2061 panel_tree_drag_leave (GtkWidget
*widget
, GdkDragContext
*context
, guint time
, gpointer data
)
2067 panel
->drag_tree_dragging_over
= FALSE
;
2068 panel_cancel_drag_scroll (panel
);
2070 if (panel
->drag_tree_timeout_id
!= 0) {
2071 gtk_timeout_remove (panel
->drag_tree_timeout_id
);
2072 panel
->drag_tree_timeout_id
= 0;
2075 if (panel
->drag_tree_fe
) {
2076 file_entry_free (panel
->drag_tree_fe
);
2077 panel
->drag_tree_fe
= NULL
;
2080 if (panel
->drag_tree_row
!= -1)
2081 panel_tree_check_auto_expand (panel
, NULL
);
2083 panel
->drag_tree_row
= -1;
2086 #if CONTEXT_MENU_ON_TREE
2088 tree_do_op (GtkWidget
*tree
, WPanel
*panel
, int operation
)
2093 tree_copy_cmd (GtkWidget
*tree
, WPanel
*panel
)
2095 tree_do_op (tree
, panel
, OP_COPY
);
2099 tree_del_cmd (GtkWidget
*tree
, WPanel
*panel
)
2101 tree_do_op (tree
, panel
, OP_DELETE
);
2105 tree_ren_cmd (GtkWidget
*tree
, WPanel
*panel
)
2107 tree_do_op (tree
, panel
, OP_MOVE
);
2110 static GnomeUIInfo tree_popup_items
[] = {
2111 GNOMEUIINFO_ITEM_STOCK(N_("_Copy..."), N_("Copy directory"), tree_copy_cmd
, GNOME_STOCK_PIXMAP_COPY
),
2112 GNOMEUIINFO_ITEM_STOCK(N_("_Delete..."), N_("Delete directory"), tree_del_cmd
, GNOME_STOCK_PIXMAP_TRASH
),
2113 GNOMEUIINFO_ITEM_NONE(N_("_Move..."), N_("Rename or move directory"), tree_ren_cmd
),
2119 panel_tree_button_press (GtkWidget
*widget
, GdkEventButton
*event
, WPanel
*panel
)
2123 if (event
->type
!= GDK_BUTTON_PRESS
)
2126 if (event
->button
!= 3)
2129 popup
= gnome_popup_menu_new (tree_popup_items
);
2130 gnome_popup_menu_do_popup_modal (popup
, NULL
, NULL
, event
, panel
);
2131 gtk_widget_destroy (popup
);
2136 * panel_create_tree_view:
2138 * Create and initializes the GtkDTree widget for being used in the
2142 panel_create_tree_view (WPanel
*panel
)
2146 tree
= gtk_dtree_new ();
2147 /*gtk_ctree_set_line_style (GTK_CTREE (tree), GTK_CTREE_LINES_DOTTED);*/
2148 /*gtk_ctree_set_expander_style (GTK_CTREE (tree), GTK_CTREE_EXPANDER_SQUARE);*/
2149 gtk_ctree_set_indent (GTK_CTREE (tree
), 10);
2153 gtk_signal_connect (GTK_OBJECT (tree
), "directory_changed",
2154 GTK_SIGNAL_FUNC (panel_chdir
), panel
);
2155 gtk_signal_connect (GTK_OBJECT (tree
), "scan_begin",
2156 GTK_SIGNAL_FUNC (panel_tree_scan_begin
), panel
);
2157 gtk_signal_connect (GTK_OBJECT (tree
), "scan_end",
2158 GTK_SIGNAL_FUNC (panel_tree_scan_end
), panel
);
2159 gtk_signal_connect (GTK_OBJECT (tree
), "possibly_ungrab",
2160 GTK_SIGNAL_FUNC (panel_tree_possibly_ungrab
), panel
);
2162 /* Set up drag source */
2164 gtk_drag_source_set (GTK_WIDGET (tree
), GDK_BUTTON1_MASK
| GDK_BUTTON2_MASK
,
2165 drag_types
, ELEMENTS (drag_types
),
2166 (GDK_ACTION_LINK
| GDK_ACTION_MOVE
| GDK_ACTION_COPY
2167 | GDK_ACTION_ASK
| GDK_ACTION_DEFAULT
));
2169 gtk_signal_connect (GTK_OBJECT (tree
), "drag_begin",
2170 GTK_SIGNAL_FUNC (panel_tree_drag_begin
), panel
);
2171 gtk_signal_connect (GTK_OBJECT (tree
), "drag_end",
2172 GTK_SIGNAL_FUNC (panel_tree_drag_end
), panel
);
2173 gtk_signal_connect (GTK_OBJECT (tree
), "drag_data_get",
2174 GTK_SIGNAL_FUNC (panel_tree_drag_data_get
), panel
);
2176 /* Set up drag destination */
2178 gtk_drag_dest_set (GTK_WIDGET (tree
),
2179 GTK_DEST_DEFAULT_DROP
,
2180 drop_types
, ELEMENTS (drop_types
),
2181 GDK_ACTION_COPY
| GDK_ACTION_MOVE
| GDK_ACTION_LINK
| GDK_ACTION_ASK
);
2183 gtk_signal_connect (GTK_OBJECT (tree
), "drag_motion",
2184 GTK_SIGNAL_FUNC (panel_tree_drag_motion
), panel
);
2185 gtk_signal_connect (GTK_OBJECT (tree
), "drag_leave",
2186 GTK_SIGNAL_FUNC (panel_tree_drag_leave
), panel
);
2187 gtk_signal_connect (GTK_OBJECT (tree
), "drag_data_received",
2188 GTK_SIGNAL_FUNC (panel_tree_drag_data_received
), panel
);
2190 #ifdef CONTEXT_MENU_ON_TREE
2191 /* Context sensitive menu */
2192 gtk_signal_connect_after (GTK_OBJECT (tree
), "button_press_event",
2193 GTK_SIGNAL_FUNC (panel_tree_button_press
), panel
);
2194 gtk_clist_set_button_actions (GTK_CLIST (tree
), 2, GTK_BUTTON_SELECTS
);
2200 * create_and_setup_pane:
2202 * Creates the horizontal GtkPaned widget that holds the tree
2203 * and the listing/iconing displays
2206 create_and_setup_pane (WPanel
*panel
)
2209 GtkWidget
*tree
= panel
->tree
;
2210 GdkFont
*tree_font
= tree
->style
->font
;
2213 pane
= gtk_hpaned_new ();
2215 if (tree_panel_visible
== -1)
2216 size
= 20 * gdk_string_width (tree_font
, "W");
2218 if (tree_panel_visible
)
2219 size
= tree_panel_visible
;
2224 gtk_paned_set_position (GTK_PANED (pane
), size
);
2227 * Hack: set the default startup size for the pane without
2228 * using _set_usize which would set the minimal size
2230 GTK_PANED (pane
)->child1_size
= size
;
2231 GTK_PANED (pane
)->position_set
= TRUE
;
2233 gtk_widget_show (pane
);
2239 panel_back (GtkWidget
*button
, WPanel
*panel
)
2241 directory_history_prev (panel
);
2245 panel_fwd (GtkWidget
*button
, WPanel
*panel
)
2247 directory_history_next (panel
);
2251 panel_up (GtkWidget
*button
, WPanel
*panel
)
2253 do_panel_cd (panel
, "..", cd_exact
);
2257 rescan_panel (GtkWidget
*widget
, gpointer data
)
2263 go_home (GtkWidget
*widget
, WPanel
*panel
)
2265 do_panel_cd (panel
, "~", cd_exact
);
2270 static GnomeUIInfo toolbar
[] = {
2271 GNOMEUIINFO_ITEM_STOCK (N_("Back"), N_("Go to the previously visited directory"),
2272 panel_back
, GNOME_STOCK_PIXMAP_BACK
),
2273 GNOMEUIINFO_ITEM_STOCK (N_("Up"), N_("Go up a level in the directory hierarchy"),
2274 panel_up
, GNOME_STOCK_PIXMAP_UP
),
2275 GNOMEUIINFO_ITEM_STOCK (N_("Forward"), N_("Go to the next directory"),
2276 panel_fwd
, GNOME_STOCK_PIXMAP_FORWARD
),
2277 GNOMEUIINFO_SEPARATOR
,
2278 GNOMEUIINFO_ITEM_STOCK (N_("Rescan"), N_("Rescan the current directory"),
2279 rescan_panel
, GNOME_STOCK_PIXMAP_REFRESH
),
2280 GNOMEUIINFO_SEPARATOR
,
2281 GNOMEUIINFO_ITEM_STOCK (N_("Home"), N_("Go to your home directory"),
2282 go_home
, GNOME_STOCK_PIXMAP_HOME
),
2283 GNOMEUIINFO_SEPARATOR
,
2284 GNOMEUIINFO_RADIOLIST(panel_view_toolbar_uiinfo
),
2289 do_ui_signal_connect (GnomeUIInfo
*uiinfo
, gchar
*signal_name
,
2290 GnomeUIBuilderData
*uibdata
)
2292 if (uiinfo
->moreinfo
)
2293 gtk_signal_connect (GTK_OBJECT (uiinfo
->widget
),
2294 signal_name
, uiinfo
->moreinfo
, uibdata
->data
?
2295 uibdata
->data
: uiinfo
->user_data
);
2299 tree_size_allocate (GtkWidget
*widget
, GtkAllocation
*allocation
, WPanel
*panel
)
2301 if (allocation
->width
<= 0){
2302 tree_panel_visible
= 0;
2304 tree_panel_visible
= allocation
->width
;
2307 if (auto_save_setup
) {
2313 x_create_panel (Dlg_head
*h
, widget_data parent
, WPanel
*panel
)
2315 GtkWidget
*status_line
, *vbox
, *ministatus_box
;
2318 GnomeUIBuilderData uibdata
;
2320 panel
->xwindow
= gtk_widget_get_toplevel (GTK_WIDGET (panel
->widget
.wdata
));
2322 panel
->table
= gtk_table_new (2, 1, 0);
2327 panel
->tree_scrolled_window
= gtk_scrolled_window_new (NULL
, NULL
);
2328 gtk_scrolled_window_set_policy (
2329 GTK_SCROLLED_WINDOW (panel
->tree_scrolled_window
),
2330 GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2331 panel
->tree
= panel_create_tree_view (panel
);
2332 gtk_container_add (GTK_CONTAINER (panel
->tree_scrolled_window
), panel
->tree
);
2333 gtk_widget_show_all (panel
->tree_scrolled_window
);
2336 * Icon and Listing display
2338 panel
->notebook
= gtk_notebook_new ();
2339 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (panel
->notebook
), FALSE
);
2340 gtk_widget_show (panel
->notebook
);
2342 panel
->icons
= panel_create_icon_display (panel
);
2343 gtk_widget_show (panel
->icons
);
2345 memcpy (panel
->column_width
, default_column_width
, sizeof (default_column_width
));
2346 panel
->list
= panel_create_file_list (panel
);
2347 gtk_widget_ref (panel
->icons
);
2348 gtk_widget_ref (panel
->list
);
2350 panel
->panel_listbox
= gtk_event_box_new ();
2351 gtk_widget_show (panel
->panel_listbox
);
2352 gtk_container_add (GTK_CONTAINER (panel
->panel_listbox
), panel
->list
);
2354 gtk_notebook_append_page (GTK_NOTEBOOK (panel
->notebook
), panel
->icons
, NULL
);
2355 gtk_notebook_append_page (GTK_NOTEBOOK (panel
->notebook
), panel
->panel_listbox
, NULL
);
2356 gtk_notebook_set_page (GTK_NOTEBOOK (panel
->notebook
),
2357 panel
->list_type
== list_icons
? 0 : 1);
2359 gtk_widget_show (panel
->icons
);
2360 gtk_widget_show (panel
->list
);
2361 gtk_widget_show (panel
->notebook
);
2366 panel
->pane
= create_and_setup_pane (panel
);
2367 gtk_paned_add1 (GTK_PANED (panel
->pane
), panel
->tree_scrolled_window
);
2368 gtk_signal_connect (GTK_OBJECT (panel
->tree_scrolled_window
), "size_allocate",
2369 GTK_SIGNAL_FUNC (tree_size_allocate
), panel
);
2372 * Current Working directory
2375 cwd
= panel_create_cwd (h
, panel
, &panel
->current_dir
);
2378 * We go through a lot of pain, wrestling with gnome_app* and gmc's @#$&*#$ internal structure and
2379 * make the #@$*&@#$ toolbars here...
2382 status_line
= gtk_toolbar_new (GTK_ORIENTATION_HORIZONTAL
, GTK_TOOLBAR_BOTH
);
2383 uibdata
.connect_func
= do_ui_signal_connect
;
2384 uibdata
.data
= panel
;
2385 uibdata
.is_interp
= FALSE
;
2386 uibdata
.relay_func
= NULL
;
2387 uibdata
.destroy_func
= NULL
;
2389 gnome_app_fill_toolbar_custom (GTK_TOOLBAR (status_line
), toolbar
, &uibdata
, NULL
);
2390 gnome_app_add_toolbar (GNOME_APP (panel
->xwindow
),
2391 GTK_TOOLBAR (status_line
),
2393 GNOME_DOCK_ITEM_BEH_EXCLUSIVE
,
2396 panel
->view_toolbar_items
= copy_uiinfo_widgets (panel_view_toolbar_uiinfo
);
2398 panel
->back_b
= toolbar
[0].widget
;
2399 panel
->up_b
= toolbar
[1].widget
;
2400 panel
->fwd_b
= toolbar
[2].widget
;
2401 panel_update_marks (panel
);
2403 /* Set the list type by poking a toolbar item. Yes, this is hackish.
2404 * We fall back to icon view if a certain listing type is not supported.
2405 * Be sure to keep this in sync with the uiinfo arrays in glayout.c.
2408 if (panel
->list_type
== list_brief
)
2409 gtk_toggle_button_set_active (
2410 GTK_TOGGLE_BUTTON (panel_view_toolbar_uiinfo
[1].widget
), TRUE
);
2411 else if (panel
->list_type
== list_full
)
2412 gtk_toggle_button_set_active (
2413 GTK_TOGGLE_BUTTON (panel_view_toolbar_uiinfo
[2].widget
), TRUE
);
2414 else if (panel
->list_type
== list_user
)
2415 gtk_toggle_button_set_active (
2416 GTK_TOGGLE_BUTTON (panel_view_toolbar_uiinfo
[3].widget
), TRUE
);
2418 gtk_toggle_button_set_active (
2419 GTK_TOGGLE_BUTTON (panel_view_toolbar_uiinfo
[0].widget
), TRUE
);
2421 status_line
= gtk_hbox_new (FALSE
, 2);
2422 gtk_container_set_border_width (GTK_CONTAINER (status_line
), 3);
2423 gtk_box_pack_start (GTK_BOX (status_line
),
2424 gtk_label_new (_("Location:")), FALSE
, FALSE
, 0);
2425 gtk_box_pack_start (GTK_BOX (status_line
), cwd
, TRUE
, TRUE
, 0);
2427 dock
= gnome_dock_item_new ("gmc-toolbar1",
2428 (GNOME_DOCK_ITEM_BEH_EXCLUSIVE
2429 | GNOME_DOCK_ITEM_BEH_NEVER_VERTICAL
));
2430 gtk_container_add (GTK_CONTAINER (dock
), status_line
);
2431 gnome_dock_add_item (GNOME_DOCK (GNOME_APP (panel
->xwindow
)->dock
),
2432 GNOME_DOCK_ITEM (dock
), GNOME_DOCK_TOP
, 1, 0, 0, FALSE
);
2434 gtk_widget_show_all (dock
);
2436 panel
->view_table
= gtk_table_new (1, 1, 0);
2437 gtk_widget_show (panel
->view_table
);
2442 ministatus_box
= gtk_frame_new (NULL
);
2443 gtk_frame_set_shadow_type (GTK_FRAME (ministatus_box
), GTK_SHADOW_IN
);
2445 panel
->status
= gtk_label_new (_("Show all files"));
2446 gtk_misc_set_alignment (GTK_MISC (panel
->status
), 0.0, 0.0);
2447 gtk_misc_set_padding (GTK_MISC (panel
->status
), 2, 0);
2449 gtk_box_pack_start (GTK_BOX (panel
->ministatus
), ministatus_box
, FALSE
, FALSE
, 0);
2450 gtk_container_add (GTK_CONTAINER (ministatus_box
), panel
->status
);
2452 gtk_widget_show (ministatus_box
);
2453 gtk_widget_show (panel
->status
);
2456 * Put the icon list and the file listing in a nice frame
2459 /* Add both the icon view and the listing view */
2460 gtk_table_attach (GTK_TABLE (panel
->view_table
), panel
->notebook
, 0, 1, 0, 1,
2461 GTK_EXPAND
| GTK_FILL
| GTK_SHRINK
,
2462 GTK_EXPAND
| GTK_FILL
| GTK_SHRINK
,
2465 gtk_table_attach (GTK_TABLE (panel
->table
), panel
->pane
, 0, 1, 1, 2,
2466 GTK_EXPAND
| GTK_FILL
| GTK_SHRINK
,
2467 GTK_EXPAND
| GTK_FILL
| GTK_SHRINK
,
2470 gtk_paned_add2 (GTK_PANED (panel
->pane
), panel
->view_table
);
2473 * ministatus_box is a container created just to put the
2474 * panel->ministatus inside.
2476 * Then the resize mode for ministatus_box is changed to stop
2477 * any size-changed messages to be propagated above.
2479 * This is required as the panel->ministatus Label is changed
2480 * very often (to display status information). If this hack
2481 * is not made, then the resize is queued and the whole window
2482 * flickers each time this changes
2485 ministatus_box
= gtk_hbox_new (FALSE
, 0);
2486 gtk_container_add (GTK_CONTAINER (ministatus_box
), panel
->ministatus
);
2487 gtk_widget_show (ministatus_box
);
2488 gtk_container_set_resize_mode (GTK_CONTAINER (ministatus_box
), GTK_RESIZE_QUEUE
);
2489 gtk_table_attach (GTK_TABLE (panel
->table
), ministatus_box
, 0, 1, 2, 3,
2490 GTK_EXPAND
| GTK_FILL
| GTK_SHRINK
,
2493 gtk_table_attach (GTK_TABLE (panel
->table
), frame
, 0, 1, 3, 4,
2494 GTK_EXPAND
| GTK_FILL
,
2498 /* Ultra nasty hack: pull the vbox from wdata */
2499 vbox
= GTK_WIDGET (panel
->widget
.wdata
);
2501 panel
->widget
.wdata
= (widget_data
) panel
->table
;
2503 /* Now, insert our table in our parent */
2504 gtk_container_add (GTK_CONTAINER (vbox
), panel
->table
);
2505 gtk_widget_show (vbox
);
2506 gtk_widget_show (panel
->table
);
2508 if (!(panel
->widget
.options
& W_PANEL_HIDDEN
) && !is_trash_panel
)
2509 gtk_widget_show (gtk_widget_get_toplevel (panel
->table
));
2512 panel_create_pixmaps ();
2514 /* In GNOME the panel wants to have the cursor, to avoid "auto" focusing the
2517 panel
->widget
.options
|= W_WANT_CURSOR
;
2518 panel
->estimated_total
= 0;
2520 panel
->timer_id
= -1;
2522 /* re-set the user_format explicitly */
2523 if (default_user_format
!= NULL
) {
2524 g_free (panel
->user_format
);
2525 panel
->user_format
= g_strdup (default_user_format
);
2530 panel_update_cols (Widget
*panel
, int frame_size
)
2537 get_nth_panel_name (int num
)
2539 static char buffer
[BUF_TINY
];
2542 return "New Left Panel";
2544 return "New Right Panel";
2546 g_snprintf (buffer
, sizeof (buffer
), "%ith Panel", num
);
2556 if ((hint
= get_random_hint ())){
2561 set_hintbar ("The GNOME File Manager " VERSION
);
2566 paint_frame (WPanel
*panel
)
2571 x_reset_sort_labels (WPanel
*panel
)
2575 if (!panel
->notebook
)
2578 if (panel
->list_type
== list_icons
){
2582 panel_switch_new_display_mode (panel
);
2584 gtk_notebook_set_page (GTK_NOTEBOOK (panel
->notebook
), page
);
2587 /* Releases all of the X resources allocated */
2589 x_panel_destroy (WPanel
*panel
)
2591 gtk_widget_destroy (GTK_WIDGET (panel
->xwindow
));