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 *cur_dir
= g_get_current_dir ();
333 gtk_dtree_select_dir (GTK_DTREE (panel
->tree
), cur_dir
);
336 gtk_dtree_select_dir (GTK_DTREE (panel
->tree
), panel
->cwd
);
338 gtk_signal_handler_unblock_by_data (GTK_OBJECT (panel
->tree
), panel
);
342 gmc_panel_set_size (int index
, int boot
)
347 w
= (Widget
*) get_panel_widget (index
);
351 set_panel_formats (p
);
361 x_panel_set_size (int index
)
363 printf ("WARNING: set size called\n");
364 gmc_panel_set_size (index
, 1);
368 * Invoked when the f.mark field of a file item changes
371 x_panel_select_item (WPanel
*panel
, int index
, int value
)
375 color
= file_compute_color (NORMAL
, &panel
->dir
.list
[index
]);
376 panel_file_list_set_row_colors (CLIST_FROM_SW (panel
->list
), index
, color
);
380 x_select_item (WPanel
*panel
)
382 if (is_a_desktop_panel (panel
))
385 do_file_mark (panel
, panel
->selected
, 1);
386 display_mini_info (panel
);
388 if (panel
->list_type
== list_icons
) {
389 GnomeIconList
*list
= ILIST_FROM_SW (panel
->icons
);
391 gnome_icon_list_select_icon (list
, panel
->selected
);
392 if (GTK_WIDGET (list
)->allocation
.x
!= -1)
393 if (gnome_icon_list_icon_is_visible (list
, panel
->selected
) != GTK_VISIBILITY_FULL
)
394 gnome_icon_list_moveto (list
, panel
->selected
, 0.5);
396 GtkCList
*clist
= CLIST_FROM_SW (panel
->list
);
398 gtk_clist_select_row (clist
, panel
->selected
, 0);
400 /* Make it visible */
401 if (gtk_clist_row_is_visible (clist
, panel
->selected
) != GTK_VISIBILITY_FULL
)
402 gtk_clist_moveto (clist
, panel
->selected
, 0, 0.5, 0.0);
407 x_unselect_item (WPanel
*panel
)
409 int selected
= panel
->selected
;
411 if (panel
->list_type
== list_icons
)
412 gnome_icon_list_unselect_all (ILIST_FROM_SW (panel
->icons
), NULL
, NULL
);
414 gtk_clist_unselect_all (CLIST_FROM_SW (panel
->list
));
416 panel
->selected
= selected
;
420 x_filter_changed (WPanel
*panel
)
425 x_adjust_top_file (WPanel
*panel
)
427 /* gtk_clist_moveto (GTK_CLIST (panel->list), panel->top_file, 0, 0.0, 0.0); */
431 panel_file_list_select_row (GtkWidget
*file_list
, gint row
, gint column
,
432 GdkEvent
*event
, gpointer data
)
438 panel
->selected
= row
;
439 do_file_mark (panel
, row
, 1);
440 display_mini_info (panel
);
441 execute_hooks (select_file_hook
);
445 panel_file_list_unselect_row (GtkWidget
*widget
, int row
, int columns
, GdkEvent
*event
, gpointer data
)
450 do_file_mark (panel
, row
, 0);
451 display_mini_info (panel
);
453 if (panel
->marked
== 0)
458 panel_file_list_resize_callback (GtkCList
*clist
, gint column
, gint width
, WPanel
*panel
)
462 p
= column_width_pos
[panel
->list_type
]; /* offset in column_width */
465 panel
->column_width
[p
+ column
] = width
;
467 /* make this default */
468 memcpy (default_column_width
, panel
->column_width
, sizeof (default_column_width
));
472 panel_file_list_column_callback (GtkWidget
*widget
, int col
, WPanel
*panel
)
477 for (i
= 0, format
= panel
->format
; format
; format
= format
->next
){
478 if (!format
->use_in_gui
)
481 sortfn
*sorting_routine
;
483 sorting_routine
= get_sort_fn (format
->id
);
484 if (!sorting_routine
)
487 if (sorting_routine
== panel
->sort_type
)
488 panel
->reverse
= !panel
->reverse
;
489 panel
->sort_type
= sorting_routine
;
498 /* Convenience function to load a pixmap and mask from xpm data */
500 create_pixmap (char **data
, GdkPixmap
**pixmap
, GdkBitmap
**mask
)
504 im
= gdk_imlib_create_image_from_xpm_data (data
);
505 gdk_imlib_render (im
, im
->rgb_width
, im
->rgb_height
);
506 *pixmap
= gdk_imlib_copy_image (im
);
507 *mask
= gdk_imlib_copy_mask (im
);
508 gdk_imlib_destroy_image (im
);
512 panel_create_pixmaps (void)
514 pixmaps_ready
= TRUE
;
516 create_pixmap (DIRECTORY_CLOSE_XPM
, &icon_directory_pixmap
, &icon_directory_mask
);
517 create_pixmap (link_xpm
, &icon_link_pixmap
, &icon_link_mask
);
518 create_pixmap (dev_xpm
, &icon_dev_pixmap
, &icon_dev_mask
);
521 typedef gboolean (*desirable_fn
)(WPanel
*p
, int x
, int y
);
522 typedef gboolean (*scroll_fn
)(gpointer data
);
524 /* Sets up a timer to scroll a panel component when something is being dragged
525 * over it. The `desirable' function should return whether it is desirable to
526 * scroll at the specified coordinates; and the `scroll' function should
527 * actually scroll the view.
530 panel_setup_drag_scroll (WPanel
*panel
, int x
, int y
, desirable_fn desirable
, scroll_fn scroll
)
532 panel_cancel_drag_scroll (panel
);
534 panel
->drag_motion_x
= x
;
535 panel
->drag_motion_y
= y
;
537 if ((* desirable
) (panel
, x
, y
))
538 panel
->timer_id
= gtk_timeout_add (SCROLL_TIMEOUT
, scroll
, panel
);
542 panel_file_list_configure (WPanel
*panel
, GtkWidget
*sw
, GtkWidget
*file_list
)
544 format_e
*format
= panel
->format
;
547 /* Set sorting callback */
548 gtk_signal_connect (GTK_OBJECT (file_list
), "click_column",
549 GTK_SIGNAL_FUNC (panel_file_list_column_callback
), panel
);
551 /* Set column resize callback */
552 gtk_signal_connect (GTK_OBJECT (file_list
), "resize_column",
553 GTK_SIGNAL_FUNC (panel_file_list_resize_callback
), panel
);
555 /* Avoid clist's broken focusing behavior */
556 GTK_WIDGET_UNSET_FLAGS (file_list
, GTK_CAN_FOCUS
);
558 /* Semi-sane selection mode */
559 gtk_clist_set_selection_mode (GTK_CLIST (file_list
), GTK_SELECTION_EXTENDED
);
561 for (i
= 0, format
= panel
->format
; format
; format
= format
->next
) {
562 GtkJustification just
= GTK_JUSTIFY_LEFT
;
564 if (!format
->use_in_gui
)
567 /* Set desired justification */
568 switch (HIDE_FIT (format
->just_mode
)) {
570 just
= GTK_JUSTIFY_LEFT
;
574 just
= GTK_JUSTIFY_RIGHT
;
578 just
= GTK_JUSTIFY_CENTER
;
582 gtk_clist_set_column_justification (GTK_CLIST (file_list
), i
, just
);
587 /* Creates an URI list to be transferred during a drop operation */
589 panel_build_selected_file_list (WPanel
*panel
, int *file_list_len
)
595 int cwdlen
= strlen (panel
->cwd
) + 1;
596 int filelen
= strlen ("file:");
597 int seplen
= strlen ("\r\n");
599 /* first pass, compute the length */
601 for (i
= 0; i
< panel
->count
; i
++)
602 if (panel
->dir
.list
[i
].f
.marked
)
603 total_len
+= (filelen
+ cwdlen
604 + panel
->dir
.list
[i
].fnamelen
608 data
= copy
= g_malloc (total_len
+1);
609 for (i
= 0; i
< panel
->count
; i
++)
610 if (panel
->dir
.list
[i
].f
.marked
){
611 strcpy (copy
, "file:");
612 strcpy (©
[filelen
], panel
->cwd
);
613 copy
[filelen
+cwdlen
-1] = '/';
614 strcpy (©
[filelen
+ cwdlen
], panel
->dir
.list
[i
].fname
);
615 strcpy (©
[filelen
+ cwdlen
+ panel
->dir
.list
[i
].fnamelen
], sep
);
616 copy
+= filelen
+ cwdlen
+ panel
->dir
.list
[i
].fnamelen
+ seplen
;
618 data
[total_len
] = 0;
619 *file_list_len
= total_len
;
622 char *fullname
, *uri
;
624 fullname
= concat_dir_and_file (panel
->cwd
, panel
->dir
.list
[panel
->selected
].fname
);
626 uri
= g_strconcat ("file:", fullname
, NULL
);
629 *file_list_len
= strlen (uri
) + 1;
635 * panel_drag_data_get:
637 * Invoked when a drag operation has been performed, this routine
638 * provides the data to be transfered
641 panel_drag_data_get (GtkWidget
*widget
,
642 GdkDragContext
*context
,
643 GtkSelectionData
*selection_data
,
652 panel_cancel_drag_scroll (panel
);
653 data
= panel_build_selected_file_list (panel
, &len
);
656 case TARGET_URI_LIST
:
657 case TARGET_TEXT_PLAIN
:
658 gtk_selection_data_set (selection_data
, selection_data
->target
, 8, data
, len
);
662 files
= gnome_uri_list_extract_uris (data
);
664 gtk_selection_data_set (selection_data
,
665 selection_data
->target
,
668 strlen (files
->data
));
670 gnome_uri_list_free_strings (files
);
674 g_assert_not_reached ();
681 * panel_drag_data_delete:
683 * Invoked when the destination requests the information to be deleted
684 * possibly because the operation was MOVE.
687 panel_drag_data_delete (GtkWidget
*widget
, GdkDragContext
*context
, WPanel
*panel
)
689 /* Things is: The File manager already handles file moving */
692 /* Performs a drop on a panel. If idx is -1, then drops on the panel's cwd
696 drop_on_panel (WPanel
*panel
, int idx
, GdkDragContext
*context
, GtkSelectionData
*selection_data
)
701 file_entry
*fe
= NULL
;
703 g_assert (panel
!= NULL
);
704 g_assert (idx
== -1 || idx
< panel
->count
);
705 g_assert (context
!= NULL
);
706 g_assert (selection_data
!= NULL
);
713 fe
= &panel
->dir
.list
[idx
];
714 file
= g_concat_dir_and_file (panel
->cwd
, fe
->fname
);
716 if (!((S_ISDIR (fe
->buf
.st_mode
) || fe
->f
.link_to_dir
)
717 || gdnd_can_drop_on_file (file
, fe
))) {
725 fe
= file_entry_from_file (file
);
730 reload
= gdnd_perform_drop (context
, selection_data
, file
, fe
);
732 if (file
!= panel
->cwd
)
736 file_entry_free (fe
);
739 update_panels (UP_OPTIMIZE
, UP_KEEPSEL
);
745 * panel_icon_list_drag_data_received:
747 * Invoked on the target side of a Drag and Drop operation when data has been
751 panel_icon_list_drag_data_received (GtkWidget
*widget
,
752 GdkDragContext
*context
,
755 GtkSelectionData
*selection_data
,
762 idx
= gnome_icon_list_get_icon_at (GNOME_ICON_LIST (widget
), x
, y
);
763 drop_on_panel (panel
, idx
, context
, selection_data
);
767 * panel_clist_drag_data_received:
769 * Invoked on the target side of a Drag and Drop operation when data has been
773 panel_clist_drag_data_received (GtkWidget
*widget
,
774 GdkDragContext
*context
,
777 GtkSelectionData
*selection_data
,
785 clist
= GTK_CLIST (widget
);
787 /* Normalize the y coordinate to the clist_window */
789 y
-= (GTK_CONTAINER (clist
)->border_width
790 + clist
->column_title_area
.y
791 + clist
->column_title_area
.height
);
793 if (gtk_clist_get_selection_info (GTK_CLIST (widget
), x
, y
, &row
, NULL
) == 0)
796 drop_on_panel (panel
, row
, context
, selection_data
);
800 * panel_tree_drag_data_received:
802 * Invoked on the target side when a drop has been received in the Tree
805 panel_tree_drag_data_received (GtkWidget
*widget
,
806 GdkDragContext
*context
,
809 GtkSelectionData
*selection_data
,
814 GtkDTree
*dtree
= GTK_DTREE (widget
);
821 if (!gtk_clist_get_selection_info (GTK_CLIST (dtree
), x
, y
, &row
, &col
))
824 node
= gtk_ctree_node_nth (GTK_CTREE (dtree
), row
);
828 path
= gtk_dtree_get_row_path (dtree
, node
);
829 fe
= file_entry_from_file (path
);
835 reload
= gdnd_perform_drop (context
, selection_data
, path
, fe
);
837 file_entry_free (fe
);
841 update_panels (UP_OPTIMIZE
, UP_KEEPSEL
);
847 load_dnd_icons (void)
850 drag_directory
= gnome_stock_transparent_window (GNOME_STOCK_PIXMAP_NOT
, NULL
);
852 if (!drag_directory_ok
)
853 drag_directory_ok
= gnome_stock_transparent_window (GNOME_STOCK_PIXMAP_NEW
, NULL
);
856 drag_multiple
= gnome_stock_transparent_window (GNOME_STOCK_PIXMAP_NOT
, NULL
);
858 if (!drag_multiple_ok
)
859 drag_multiple_ok
= gnome_stock_transparent_window (GNOME_STOCK_PIXMAP_MULTIPLE
, NULL
);
862 /* Convenience function to start a drag operation for the icon and file lists */
864 start_drag (GtkWidget
*widget
, int button
, GdkEvent
*event
)
867 GdkDragContext
*context
;
869 list
= gtk_target_list_new (drag_types
, ELEMENTS (drag_types
));
871 context
= gtk_drag_begin (widget
, list
,
872 (GDK_ACTION_COPY
| GDK_ACTION_MOVE
873 | GDK_ACTION_LINK
| GDK_ACTION_ASK
),
875 gtk_drag_set_icon_default (context
);
879 panel_widget_motion (GtkWidget
*widget
, GdkEventMotion
*event
, WPanel
*panel
)
881 if (!panel
->maybe_start_drag
)
884 if (!((panel
->maybe_start_drag
== 1 && (event
->state
& GDK_BUTTON1_MASK
))
885 || (panel
->maybe_start_drag
== 2 && (event
->state
& GDK_BUTTON2_MASK
))))
888 /* This is the same threshold value that is used in gtkdnd.c */
890 if (MAX (abs (panel
->click_x
- event
->x
),
891 abs (panel
->click_y
- event
->y
)) <= 3)
894 start_drag (widget
, panel
->maybe_start_drag
, (GdkEvent
*) event
);
901 * Invoked when a drag is starting in the List view or the Icon view
904 panel_drag_begin (GtkWidget
*widget
, GdkDragContext
*context
, WPanel
*panel
)
912 * Invoked when a drag has finished in the List view or the Icon view
915 panel_drag_end (GtkWidget
*widget
, GdkDragContext
*context
, WPanel
*panel
)
917 panel_cancel_drag_scroll (panel
);
922 * panel_clist_scrolling_is_desirable:
924 * If the cursor is in a position close to either edge (top or bottom)
925 * and there is possible to scroll the window, this routine returns
929 panel_clist_scrolling_is_desirable (WPanel
*panel
, int x
, int y
)
933 va
= scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (panel
->list
));
936 if (va
->value
> va
->lower
)
939 if (y
> (CLIST_FROM_SW (panel
->list
)->clist_window_height
- 10)) {
940 if (va
->value
< va
->upper
- va
->page_size
)
950 * panel_clist_scroll:
952 * Timer callback invoked to scroll the clist window
955 panel_clist_scroll (gpointer data
)
957 WPanel
*panel
= data
;
961 va
= scrolled_window_get_vadjustment (panel
->list
);
963 if (panel
->drag_motion_y
< 10) {
964 v
= va
->value
- va
->step_increment
;
968 gtk_adjustment_set_value (va
, v
);
970 v
= va
->value
+ va
->step_increment
;
971 if (v
> va
->upper
- va
->page_size
)
972 v
= va
->upper
- va
->page_size
;
974 gtk_adjustment_set_value (va
, v
);
980 /* Callback used for drag motion events over the clist. We set up
981 * auto-scrolling and validate the drop to present the user with the correct
985 panel_clist_drag_motion (GtkWidget
*widget
, GdkDragContext
*context
, gint x
, gint y
, guint time
,
990 GdkDragAction action
;
991 GtkWidget
*source_widget
;
998 /* Normalize the y coordinate to the clist_window */
1000 clist
= CLIST_FROM_SW (panel
->list
);
1001 y
-= (GTK_CONTAINER (clist
)->border_width
1002 + clist
->column_title_area
.y
1003 + clist
->column_title_area
.height
);
1006 gdk_drag_status (context
, 0, time
);
1010 /* Set up auto-scrolling */
1012 panel_setup_drag_scroll (panel
, x
, y
,
1013 panel_clist_scrolling_is_desirable
,
1014 panel_clist_scroll
);
1016 /* Validate the drop */
1018 gdnd_find_panel_by_drag_context (context
, &source_widget
);
1020 if (!gtk_clist_get_selection_info (GTK_CLIST (widget
), x
, y
, &idx
, NULL
))
1023 fe
= &panel
->dir
.list
[idx
];
1025 full_name
= fe
? g_concat_dir_and_file (panel
->cwd
, fe
->fname
) : panel
->cwd
;
1027 action
= gdnd_validate_action (context
,
1029 source_widget
!= NULL
,
1030 source_widget
== widget
,
1033 fe
? fe
->f
.marked
: FALSE
);
1035 if (full_name
!= panel
->cwd
)
1038 gdk_drag_status (context
, action
, time
);
1041 gtk_signal_emit_stop_by_name (GTK_OBJECT (widget
), "drag_motion");
1046 * panel_clist_drag_leave
1048 * Invoked when the dragged object has left our region
1051 panel_clist_drag_leave (GtkWidget
*widget
, GdkDragContext
*context
, guint time
, gpointer data
)
1056 panel_cancel_drag_scroll (panel
);
1060 * panel_icon_list_scrolling_is_desirable:
1062 * If the cursor is in a position close to either edge (top or bottom)
1063 * and there is possible to scroll the window, this routine returns
1067 panel_icon_list_scrolling_is_desirable (WPanel
*panel
, int x
, int y
)
1071 va
= scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (panel
->icons
));
1074 if (va
->value
> va
->lower
)
1077 if (y
> (GTK_WIDGET (ILIST_FROM_SW (panel
->icons
))->allocation
.height
- 10)) {
1078 if (va
->value
< va
->upper
- va
->page_size
)
1088 * panel_icon_list_scroll:
1090 * Timer callback invoked to scroll the clist window
1093 panel_icon_list_scroll (gpointer data
)
1095 WPanel
*panel
= data
;
1099 va
= scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (panel
->icons
));
1101 if (panel
->drag_motion_y
< 10) {
1102 v
= va
->value
- va
->step_increment
;
1106 gtk_adjustment_set_value (va
, v
);
1108 v
= va
->value
+ va
->step_increment
;
1109 if (v
> va
->upper
- va
->page_size
)
1110 v
= va
->upper
- va
->page_size
;
1112 gtk_adjustment_set_value (va
, v
);
1118 /* Callback used for drag motion events in the icon list. We need to set up
1119 * auto-scrolling and validate the drop to present the user with the correct
1123 panel_icon_list_drag_motion (GtkWidget
*widget
, GdkDragContext
*context
, gint x
, gint y
, guint time
,
1127 GdkDragAction action
;
1128 GtkWidget
*source_widget
;
1135 /* Set up auto-scrolling */
1137 panel_setup_drag_scroll (panel
, x
, y
,
1138 panel_icon_list_scrolling_is_desirable
,
1139 panel_icon_list_scroll
);
1141 /* Validate the drop */
1143 gdnd_find_panel_by_drag_context (context
, &source_widget
);
1145 idx
= gnome_icon_list_get_icon_at (GNOME_ICON_LIST (widget
), x
, y
);
1146 fe
= (idx
== -1) ? NULL
: &panel
->dir
.list
[idx
];
1148 full_name
= fe
? g_concat_dir_and_file (panel
->cwd
, fe
->fname
) : panel
->cwd
;
1150 action
= gdnd_validate_action (context
,
1152 source_widget
!= NULL
,
1153 source_widget
== widget
,
1156 fe
? fe
->f
.marked
: FALSE
);
1158 if (full_name
!= panel
->cwd
)
1161 gdk_drag_status (context
, action
, time
);
1166 * panel_icon_list_drag_leave:
1168 * Invoked when the dragged object has left our region
1171 panel_icon_list_drag_leave (GtkWidget
*widget
, GdkDragContext
*context
, guint time
, gpointer data
)
1173 WPanel
*panel
= data
;
1175 panel_cancel_drag_scroll (panel
);
1178 /* Handler for the row_popup_menu signal of the file list. */
1180 panel_file_list_row_popup_menu (GtkFList
*flist
, GdkEventButton
*event
, gpointer data
)
1185 gpopup_do_popup2 (event
, panel
, NULL
);
1188 /* Handler for the empty_popup_menu signal of the file list. */
1190 panel_file_list_empty_popup_menu (GtkFList
*flist
, GdkEventButton
*event
, gpointer data
)
1195 file_list_popup (event
, panel
);
1198 /* Handler for the open_row signal of the file list */
1200 panel_file_list_open_row (GtkFList
*flist
, gpointer data
)
1208 /* Handler for the start_drag signal of the file list */
1210 panel_file_list_start_drag (GtkFList
*flist
, gint button
, GdkEvent
*event
, gpointer data
)
1212 start_drag (GTK_WIDGET (flist
), button
, event
);
1216 * Create, setup the file listing display.
1219 panel_create_file_list (WPanel
*panel
)
1221 const int items
= panel
->format
->items
;
1222 format_e
*format
= panel
->format
;
1223 GtkWidget
*file_list
;
1228 titles
= g_new (char *, items
);
1229 for (i
= 0; i
< items
; format
= format
->next
)
1230 if (format
->use_in_gui
)
1231 titles
[i
++] = format
->title
;
1233 sw
= gtk_scrolled_window_new (NULL
, NULL
);
1234 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw
),
1235 GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1237 file_list
= gtk_flist_new_with_titles (panel
, items
, titles
);
1238 gtk_container_add (GTK_CONTAINER (sw
), file_list
);
1239 gtk_widget_show (file_list
);
1241 panel_file_list_configure (panel
, sw
, file_list
);
1244 gtk_signal_connect (GTK_OBJECT (file_list
), "select_row",
1245 GTK_SIGNAL_FUNC (panel_file_list_select_row
),
1247 gtk_signal_connect (GTK_OBJECT (file_list
), "unselect_row",
1248 GTK_SIGNAL_FUNC (panel_file_list_unselect_row
),
1251 /* Connect to the flist signals */
1253 gtk_signal_connect (GTK_OBJECT (file_list
), "row_popup_menu",
1254 GTK_SIGNAL_FUNC (panel_file_list_row_popup_menu
),
1256 gtk_signal_connect (GTK_OBJECT (file_list
), "empty_popup_menu",
1257 GTK_SIGNAL_FUNC (panel_file_list_empty_popup_menu
),
1259 gtk_signal_connect (GTK_OBJECT (file_list
), "open_row",
1260 GTK_SIGNAL_FUNC (panel_file_list_open_row
),
1262 gtk_signal_connect (GTK_OBJECT (file_list
), "start_drag",
1263 GTK_SIGNAL_FUNC (panel_file_list_start_drag
),
1266 /* Set up drag and drop */
1270 gtk_drag_dest_set (GTK_WIDGET (file_list
),
1271 GTK_DEST_DEFAULT_DROP
,
1272 drop_types
, ELEMENTS (drop_types
),
1273 GDK_ACTION_COPY
| GDK_ACTION_MOVE
| GDK_ACTION_LINK
| GDK_ACTION_ASK
);
1275 gtk_signal_connect (GTK_OBJECT (file_list
), "drag_data_get",
1276 GTK_SIGNAL_FUNC (panel_drag_data_get
), panel
);
1277 gtk_signal_connect (GTK_OBJECT (file_list
), "drag_data_delete",
1278 GTK_SIGNAL_FUNC (panel_drag_data_delete
), panel
);
1279 gtk_signal_connect (GTK_OBJECT (file_list
), "drag_data_received",
1280 GTK_SIGNAL_FUNC (panel_clist_drag_data_received
), panel
);
1283 * This signal is provided for scrolling the main window
1284 * if data is being dragged
1286 gtk_signal_connect (GTK_OBJECT (file_list
), "drag_motion",
1287 GTK_SIGNAL_FUNC (panel_clist_drag_motion
), panel
);
1288 gtk_signal_connect (GTK_OBJECT (file_list
), "drag_leave",
1289 GTK_SIGNAL_FUNC (panel_clist_drag_leave
), panel
);
1290 gtk_signal_connect (GTK_OBJECT (file_list
), "drag_begin",
1291 GTK_SIGNAL_FUNC (panel_drag_begin
), panel
);
1292 gtk_signal_connect (GTK_OBJECT (file_list
), "drag_end",
1293 GTK_SIGNAL_FUNC (panel_drag_end
), panel
);
1299 * Callback: icon selected
1302 panel_icon_list_select_icon (GtkWidget
*widget
, int index
, GdkEvent
*event
, WPanel
*panel
)
1304 panel
->selected
= index
;
1305 do_file_mark (panel
, index
, 1);
1306 display_mini_info (panel
);
1307 execute_hooks (select_file_hook
);
1309 /* Do not let the user select .. */
1310 if (strcmp (panel
->dir
.list
[index
].fname
, "..") == 0)
1311 gnome_icon_list_unselect_icon (GNOME_ICON_LIST (widget
), index
);
1316 switch (event
->type
){
1317 case GDK_BUTTON_PRESS
:
1318 if (event
->button
.button
== 3)
1319 gpopup_do_popup2 ((GdkEventButton
*) event
, panel
, NULL
);
1323 case GDK_2BUTTON_PRESS
:
1324 if (event
->button
.button
== 1) {
1335 panel_icon_list_unselect_icon (GtkWidget
*widget
, int index
, GdkEvent
*event
, WPanel
*panel
)
1337 do_file_mark (panel
, index
, 0);
1338 display_mini_info (panel
);
1339 if (panel
->marked
== 0)
1340 panel
->selected
= 0;
1344 queue_reread_cmd (gpointer data
)
1350 /* Renames a file using a file operation context. Returns FILE_CONT on success. */
1352 rename_file_with_context (char *source
, char *dest
)
1360 if (mc_lstat (source
, &s
) != 0)
1363 ctx
= file_op_context_new ();
1364 file_op_context_create_ui (ctx
, OP_MOVE
, FALSE
);
1369 retval
= move_file_file (ctx
, source
, dest
, &count
, &bytes
);
1370 file_op_context_destroy (ctx
);
1376 panel_icon_renamed (GtkWidget
*widget
, int index
, char *dest
, WPanel
*panel
)
1382 if (strcmp (dest
, panel
->dir
.list
[index
].fname
) == 0)
1383 return TRUE
; /* do nothing if the name did not change */
1385 source
= g_concat_dir_and_file (cpanel
->cwd
, panel
->dir
.list
[index
].fname
);
1386 fullname
= g_concat_dir_and_file (cpanel
->cwd
, dest
);
1388 if (rename_file_with_context (source
, dest
) == FILE_CONT
) {
1389 g_free (panel
->dir
.list
[index
].fname
);
1390 panel
->dir
.list
[index
].fname
= g_strdup (dest
);
1392 gtk_idle_add (queue_reread_cmd
, NULL
);
1403 /* Callback for rescanning the cwd */
1405 handle_rescan_directory (GtkWidget
*widget
, gpointer data
)
1410 /* The popup menu for file panels */
1411 static GnomeUIInfo file_list_popup_items
[] = {
1412 GNOMEUIINFO_ITEM_NONE (N_("_Rescan Directory"), N_("Reloads the current directory"),
1413 handle_rescan_directory
),
1414 GNOMEUIINFO_ITEM_NONE (N_("New _Directory..."), N_("Creates a new directory here"),
1419 /* The popup menu for file panels */
1420 static GnomeUIInfo trash_file_list_popup_items
[] = {
1421 GNOMEUIINFO_ITEM_NONE (N_("Empty _Trash"), N_("Empties the Trash"),
1423 GNOMEUIINFO_ITEM_NONE (N_("_Rescan Directory"), N_("Reloads the current directory"),
1424 handle_rescan_directory
),
1425 GNOMEUIINFO_ITEM_NONE (N_("New _Directory..."), N_("Creates a new directory here"),
1430 /* Creates the popup menu when the user clicks button 3 on the blank area of the
1434 file_list_popup (GdkEventButton
*event
, WPanel
*panel
)
1438 GnomeUIInfo
*items
= file_list_popup_items
;
1440 trash_dir
= g_strconcat (gnome_user_home_dir
, "/",
1441 DESKTOP_DIR_NAME
, "/",
1445 if ((strncmp (panel
->cwd
, trash_dir
, strlen (trash_dir
)) == 0) && (panel
->count
!= 1))
1446 items
= trash_file_list_popup_items
;
1449 popup
= gnome_popup_menu_new (items
);
1450 gnome_popup_menu_do_popup_modal (popup
, NULL
, NULL
, event
, panel
);
1451 gtk_widget_destroy (popup
);
1455 /* Returns whether an icon in the icon list is being edited. FIXME: This
1456 * function uses a fantastically ugly hack to figure this out. It would be
1457 * saner to have a function provided by the icon list widget to do it, but we
1458 * can't break forwards compatibility at this point. It would be even saner to
1459 * have a good DnD API for the icon list.
1462 editing_icon_list (GnomeIconList
*gil
)
1464 GnomeCanvasItem
*item
;
1466 item
= GNOME_CANVAS (gil
)->focused_item
;
1467 return (item
&& GNOME_IS_ICON_TEXT_ITEM (item
) && GNOME_ICON_TEXT_ITEM (item
)->editing
);
1471 * Strategy for activaing the drags from the icon-list:
1473 * The icon-list uses the button-press/motion-notify events for
1474 * the banding selection. We catch the events and only if the
1475 * click happens in an icon and the user moves the mouse enough (a
1476 * threshold to give it a better feel) activa the drag and drop.
1480 panel_icon_list_button_press (GtkWidget
*widget
, GdkEventButton
*event
, WPanel
*panel
)
1482 GnomeIconList
*gil
= GNOME_ICON_LIST (widget
);
1485 if (editing_icon_list (gil
))
1488 if (event
->type
!= GDK_BUTTON_PRESS
)
1491 icon
= gnome_icon_list_get_icon_at (gil
, event
->x
, event
->y
);
1494 if (event
->button
== 3) {
1495 file_list_popup (event
, panel
);
1498 } else if (event
->button
!= 3)
1499 panel
->maybe_start_drag
= event
->button
;
1501 panel
->click_x
= event
->x
;
1502 panel
->click_y
= event
->y
;
1507 panel_icon_list_button_release (GtkWidget
*widget
, GdkEventButton
*event
, WPanel
*panel
)
1509 panel
->maybe_start_drag
= 0;
1510 if (event
->button
== 2){
1515 GnomeIconList
*gil
= GNOME_ICON_LIST (widget
);
1516 icon
= gnome_icon_list_get_icon_at (gil
, event
->x
, event
->y
);
1517 fe
= &panel
->dir
.list
[icon
];
1519 if (S_ISDIR (fe
->buf
.st_mode
) || fe
->f
.link_to_dir
){
1520 fullname
= concat_dir_and_file (panel
->cwd
, fe
->fname
);
1521 new_panel_at (fullname
);
1530 /* Create and setup the icon field display */
1532 panel_create_icon_display (WPanel
*panel
)
1535 GnomeIconList
*ilist
;
1537 sw
= gtk_scrolled_window_new (NULL
, NULL
);
1538 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw
),
1539 GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
1541 ilist
= GNOME_ICON_LIST (
1542 gnome_icon_list_new_flags (90, NULL
,
1543 (GNOME_ICON_LIST_IS_EDITABLE
1544 | GNOME_ICON_LIST_STATIC_TEXT
)));
1545 gtk_container_add (GTK_CONTAINER (sw
), GTK_WIDGET (ilist
));
1546 gtk_widget_show (GTK_WIDGET (ilist
));
1548 gnome_icon_list_set_separators (ilist
, " /-_.");
1549 gnome_icon_list_set_row_spacing (ilist
, 2);
1550 gnome_icon_list_set_col_spacing (ilist
, 2);
1551 gnome_icon_list_set_icon_border (ilist
, 2);
1552 gnome_icon_list_set_text_spacing (ilist
, 2);
1554 gnome_icon_list_set_selection_mode (ilist
, GTK_SELECTION_MULTIPLE
);
1555 GTK_WIDGET_SET_FLAGS (ilist
, GTK_CAN_FOCUS
);
1557 gtk_signal_connect (GTK_OBJECT (ilist
), "select_icon",
1558 GTK_SIGNAL_FUNC (panel_icon_list_select_icon
),
1560 gtk_signal_connect (GTK_OBJECT (ilist
), "unselect_icon",
1561 GTK_SIGNAL_FUNC (panel_icon_list_unselect_icon
),
1563 gtk_signal_connect (GTK_OBJECT (ilist
), "text_changed",
1564 GTK_SIGNAL_FUNC (panel_icon_renamed
),
1567 /* Setup the icons and DnD */
1571 gtk_drag_dest_set (GTK_WIDGET (ilist
),
1572 GTK_DEST_DEFAULT_DROP
,
1573 drop_types
, ELEMENTS (drop_types
),
1574 GDK_ACTION_COPY
| GDK_ACTION_MOVE
| GDK_ACTION_LINK
| GDK_ACTION_ASK
);
1576 gtk_signal_connect (GTK_OBJECT (ilist
), "drag_data_get",
1577 GTK_SIGNAL_FUNC (panel_drag_data_get
),
1579 gtk_signal_connect (GTK_OBJECT (ilist
), "drag_data_delete",
1580 GTK_SIGNAL_FUNC (panel_drag_data_delete
),
1582 gtk_signal_connect (GTK_OBJECT (ilist
), "drag_data_received",
1583 GTK_SIGNAL_FUNC (panel_icon_list_drag_data_received
),
1585 gtk_signal_connect (GTK_OBJECT (ilist
), "drag_begin",
1586 GTK_SIGNAL_FUNC (panel_drag_begin
), panel
);
1587 gtk_signal_connect (GTK_OBJECT (ilist
), "drag_end",
1588 GTK_SIGNAL_FUNC (panel_drag_end
), panel
);
1590 /* These implement our drag-start activation code, as we have a pretty oveloaded widget */
1592 gtk_signal_connect (GTK_OBJECT (ilist
), "button_press_event",
1593 GTK_SIGNAL_FUNC (panel_icon_list_button_press
),
1595 gtk_signal_connect (GTK_OBJECT (ilist
), "button_release_event",
1596 GTK_SIGNAL_FUNC (panel_icon_list_button_release
),
1598 gtk_signal_connect (GTK_OBJECT (ilist
), "motion_notify_event",
1599 GTK_SIGNAL_FUNC (panel_widget_motion
),
1602 /* This signal is provide for scrolling the main window if data is being
1605 gtk_signal_connect (GTK_OBJECT (ilist
), "drag_motion",
1606 GTK_SIGNAL_FUNC (panel_icon_list_drag_motion
), panel
);
1607 gtk_signal_connect (GTK_OBJECT (ilist
), "drag_leave",
1608 GTK_SIGNAL_FUNC (panel_icon_list_drag_leave
), panel
);
1614 panel_switch_new_display_mode (WPanel
*panel
)
1616 GtkWidget
*old_list
= panel
->list
;
1621 panel
->list
= panel_create_file_list (panel
);
1622 gtk_widget_destroy (old_list
);
1623 gtk_container_add (GTK_CONTAINER (panel
->panel_listbox
), panel
->list
);
1624 gtk_widget_show_all (panel
->list
);
1628 panel_create_cwd (Dlg_head
*h
, WPanel
*panel
, void **entry
)
1632 in
= input_new (0, 0, 0, 10, "", "cwd");
1635 /* Force the creation of the gtk widget */
1636 send_message_to (h
, (Widget
*) in
, WIDGET_INIT
, 0);
1639 /* FIXME: for now, we set the usize. Ultimately, toolbar
1640 * will let you expand it, we hope.
1642 gtk_widget_set_usize (GTK_WIDGET (in
->widget
.wdata
), 296, -1);
1643 return GTK_WIDGET (in
->widget
.wdata
);
1647 display_mini_info (WPanel
*panel
)
1649 GnomeAppBar
*bar
= GNOME_APPBAR (panel
->ministatus
);
1651 if (panel
->searching
) {
1654 buf
= g_strdup_printf (_("Search: %s"), panel
->search_buffer
);
1655 gnome_appbar_pop (bar
);
1656 gnome_appbar_push (bar
, buf
);
1664 buf
= g_strdup_printf ((panel
->marked
== 1) ? _("%s bytes in %d file") : _("%s bytes in %d files"),
1665 size_trunc_sep (panel
->total
),
1667 gnome_appbar_pop (bar
);
1668 gnome_appbar_push (bar
, buf
);
1673 if (S_ISLNK (panel
->dir
.list
[panel
->selected
].buf
.st_mode
)){
1674 char *link
, link_target
[MC_MAXPATHLEN
];
1677 link
= concat_dir_and_file (panel
->cwd
, panel
->dir
.list
[panel
->selected
].fname
);
1678 len
= mc_readlink (link
, link_target
, MC_MAXPATHLEN
);
1682 link_target
[len
] = 0;
1683 /* FIXME: Links should be handled differently */
1684 /* str = g_strconcat ("-> ", link_target, NULL); */
1685 gnome_appbar_pop (bar
);
1686 gnome_appbar_push (bar
, " ");
1689 gnome_appbar_pop (bar
);
1690 gnome_appbar_push (bar
, _("<readlink failed>"));
1695 if (panel
->estimated_total
> 8){
1696 int len
= panel
->estimated_total
;
1699 buffer
= g_malloc (len
+ 2);
1700 format_file (buffer
, panel
, panel
->selected
, panel
->estimated_total
-2, 0, 1);
1702 gnome_appbar_pop (bar
);
1703 gnome_appbar_push (bar
, buffer
);
1706 if (panel
->list_type
== list_icons
){
1707 if (panel
->marked
== 0){
1708 gnome_appbar_pop (bar
);
1709 gnome_appbar_push (bar
, " ");
1714 /* Signal handler for DTree's "directory_changed" signal */
1716 panel_chdir (GtkDTree
*dtree
, char *path
, WPanel
*panel
)
1718 if (panel
->dragging
)
1721 if (do_panel_cd (panel
, path
, cd_exact
))
1722 return; /* success */
1724 if (panel
->list_type
== list_icons
)
1725 gnome_icon_list_clear (ILIST_FROM_SW (panel
->icons
));
1727 gtk_clist_clear (CLIST_FROM_SW (panel
->list
));
1729 strncpy (panel
->cwd
, path
, sizeof (panel
->cwd
));
1734 panel_tree_scan_begin (GtkWidget
*widget
, gpointer data
)
1739 set_cursor_busy (panel
);
1743 panel_tree_scan_end (GtkWidget
*widget
, gpointer data
)
1748 set_cursor_normal (panel
);
1751 /* Handler for the possibly_ungrab signal of the dtree widget */
1753 panel_tree_possibly_ungrab (GtkWidget
*widget
, gpointer data
)
1759 /* The stupid clist button press handler grabs the mouse. We will get
1760 * called when the user presses the mouse on the tree, so we ungrab it.
1761 * Also, we have to make sure we don't knock away a DnD grab.
1763 if (!panel
->drag_tree_dragging_over
)
1764 gdk_pointer_ungrab (GDK_CURRENT_TIME
);
1767 /* Callback for the drag_begin signal of the tree */
1769 panel_tree_drag_begin (GtkWidget
*widget
, GdkDragContext
*context
, gpointer data
)
1774 dtree
= GTK_DTREE (widget
);
1777 panel
->dragging
= TRUE
;
1778 dtree
->drag_dir
= g_strdup (dtree
->current_path
);
1781 /* Callback for the drag_end signal of the tree */
1783 panel_tree_drag_end (GtkWidget
*widget
, GdkDragContext
*context
, gpointer data
)
1788 dtree
= GTK_DTREE (widget
);
1791 panel
->dragging
= FALSE
;
1792 g_free (dtree
->drag_dir
);
1793 dtree
->drag_dir
= NULL
;
1796 /* Callback for the drag_data_get signal of the tree */
1798 panel_tree_drag_data_get (GtkWidget
*widget
, GdkDragContext
*context
,
1799 GtkSelectionData
*selection_data
, guint info
, guint time
, gpointer data
)
1804 dtree
= GTK_DTREE (widget
);
1807 case TARGET_URI_LIST
:
1808 case TARGET_TEXT_PLAIN
:
1809 str
= g_strconcat ("file:", dtree
->drag_dir
, NULL
);
1810 gtk_selection_data_set (selection_data
, selection_data
->target
, 8,
1811 str
, strlen (str
) + 1);
1815 /* FIXME: handle TARGET_URL */
1821 * tree_drag_open_directory:
1823 * This routine is invoked in a delayed fashion if the user
1824 * keeps the drag cursor still over the widget.
1827 tree_drag_open_directory (gpointer data
)
1834 dtree
= GTK_DTREE (panel
->tree
);
1836 node
= gtk_ctree_node_nth (GTK_CTREE (panel
->tree
), panel
->drag_tree_row
);
1837 g_assert (node
!= NULL
);
1839 if (!GTK_CTREE_ROW (node
)->expanded
) {
1841 /* FIXME: Disabled until fully debugged. Should also be configurable. */
1842 dtree
->auto_expanded_nodes
= g_list_append (dtree
->auto_expanded_nodes
, node
);
1844 gtk_ctree_expand (GTK_CTREE (panel
->tree
), node
);
1850 /* Handles automatic collapsing of the tree nodes when doing drag and drop */
1852 panel_tree_check_auto_expand (WPanel
*panel
, GtkCTreeNode
*current
)
1860 dtree
= GTK_DTREE (panel
->tree
);
1861 ctree
= GTK_CTREE (panel
->tree
);
1862 clist
= GTK_CLIST (panel
->tree
);
1863 tmp_list
= dtree
->auto_expanded_nodes
;
1866 for (; tmp_list
; tmp_list
= tmp_list
->next
)
1867 if (!gtk_dtree_is_ancestor (dtree
, tmp_list
->data
, current
))
1870 /* Collapse the rows as necessary. If possible, try to do so that the
1871 * "current" stays the same place on the screen.
1877 row
= g_list_position (clist
->row_list
, (GList
*) current
);
1878 old_y
= row
* clist
->row_height
- clist
->vadjustment
->value
;
1881 free_list
= tmp_list
;
1883 for (; tmp_list
; tmp_list
= tmp_list
->next
)
1884 gtk_ctree_collapse (GTK_CTREE (panel
->tree
), tmp_list
->data
);
1886 /* We have to calculate the row position again because rows may
1887 * have shifted during the collapse.
1890 row
= g_list_position (clist
->row_list
, (GList
*) current
);
1891 new_y
= row
* clist
->row_height
- clist
->vadjustment
->value
;
1894 gtk_adjustment_set_value (clist
->vadjustment
,
1895 clist
->vadjustment
->value
+ new_y
- old_y
);
1898 if (free_list
->prev
)
1899 free_list
->prev
->next
= NULL
;
1901 dtree
->auto_expanded_nodes
= NULL
;
1903 free_list
->prev
= NULL
;
1904 g_list_free (free_list
);
1909 * panel_tree_scrolling_is_desirable:
1911 * If the cursor is in a position close to either edge (top or bottom)
1912 * and there is possible to scroll the window, this routine returns
1916 panel_tree_scrolling_is_desirable (WPanel
*panel
, int x
, int y
)
1918 GtkDTree
*dtree
= GTK_DTREE (panel
->tree
);
1921 va
= scrolled_window_get_vadjustment (panel
->tree_scrolled_window
);
1924 if (va
->value
> va
->lower
)
1927 if (y
> (GTK_WIDGET (dtree
)->allocation
.height
- 10)){
1928 if (va
->value
< va
->upper
- va
->page_size
)
1936 /* Timer callback to scroll the tree */
1938 panel_tree_scroll (gpointer data
)
1940 WPanel
*panel
= data
;
1944 va
= scrolled_window_get_vadjustment (panel
->tree_scrolled_window
);
1946 if (panel
->drag_motion_y
< 10) {
1947 v
= va
->value
- va
->step_increment
;
1951 gtk_adjustment_set_value (va
, v
);
1953 v
= va
->value
+ va
->step_increment
;
1954 if (v
> va
->upper
- va
->page_size
)
1955 v
= va
->upper
- va
->page_size
;
1957 gtk_adjustment_set_value (va
, v
);
1963 /* Callback for the drag_motion signal of the tree. We set up a timer to
1964 * automatically open nodes if the user hovers over them.
1967 panel_tree_drag_motion (GtkWidget
*widget
, GdkDragContext
*context
, int x
, int y
, guint time
,
1972 int on_row
, row
, col
;
1974 GdkDragAction action
;
1975 GtkWidget
*source_widget
;
1979 dtree
= GTK_DTREE (widget
);
1982 panel
->drag_tree_dragging_over
= TRUE
;
1983 panel_setup_drag_scroll (panel
, x
, y
,
1984 panel_tree_scrolling_is_desirable
,
1987 on_row
= gtk_clist_get_selection_info (GTK_CLIST (widget
), x
, y
, &row
, &col
);
1989 /* Remove the auto-expansion timeout if we are on the blank area of the
1990 * tree or on a row different from the previous one.
1992 if ((!on_row
|| row
!= panel
->drag_tree_row
) && panel
->drag_tree_timeout_id
!= 0) {
1993 gtk_timeout_remove (panel
->drag_tree_timeout_id
);
1994 panel
->drag_tree_timeout_id
= 0;
1996 if (panel
->drag_tree_fe
) {
1997 file_entry_free (panel
->drag_tree_fe
);
1998 panel
->drag_tree_fe
= NULL
;
2005 node
= gtk_ctree_node_nth (GTK_CTREE (dtree
), row
);
2006 row_path
= gtk_dtree_get_row_path (dtree
, node
);
2008 if (row
!= panel
->drag_tree_row
) {
2009 /* Highlight the row by selecting it */
2011 panel_tree_check_auto_expand (panel
, node
);
2013 dtree
->internal
= TRUE
;
2014 gtk_clist_select_row (GTK_CLIST (widget
), row
, 0);
2015 dtree
->internal
= FALSE
;
2017 /* Create the file entry to validate drops */
2019 panel
->drag_tree_fe
= file_entry_from_file (row_path
);
2021 /* Install the timeout handler for auto-expansion */
2023 panel
->drag_tree_timeout_id
= gtk_timeout_add (TREE_OPEN_TIMEOUT
,
2024 tree_drag_open_directory
,
2026 panel
->drag_tree_row
= row
;
2029 /* Validate the action */
2031 gdnd_find_panel_by_drag_context (context
, &source_widget
);
2033 /* If this tree is the drag source, see if the user is trying to
2034 * drop on the row being dragged. Otherwise, consider all rows
2037 if (source_widget
== widget
) {
2038 g_assert (dtree
->drag_dir
!= NULL
);
2039 on_drag_row
= strcmp (row_path
, dtree
->drag_dir
) == 0;
2041 on_drag_row
= FALSE
;
2043 action
= gdnd_validate_action (context
,
2045 source_widget
!= NULL
,
2046 source_widget
== widget
,
2048 panel
->drag_tree_fe
,
2053 panel
->drag_tree_row
= -1;
2054 panel_tree_check_auto_expand (panel
, NULL
);
2057 gdk_drag_status (context
, action
, time
);
2061 /* Callback for the drag_leave signal of the tree. We deactivate the timeout for
2062 * automatic branch expansion.
2065 panel_tree_drag_leave (GtkWidget
*widget
, GdkDragContext
*context
, guint time
, gpointer data
)
2071 panel
->drag_tree_dragging_over
= FALSE
;
2072 panel_cancel_drag_scroll (panel
);
2074 if (panel
->drag_tree_timeout_id
!= 0) {
2075 gtk_timeout_remove (panel
->drag_tree_timeout_id
);
2076 panel
->drag_tree_timeout_id
= 0;
2079 if (panel
->drag_tree_fe
) {
2080 file_entry_free (panel
->drag_tree_fe
);
2081 panel
->drag_tree_fe
= NULL
;
2084 if (panel
->drag_tree_row
!= -1)
2085 panel_tree_check_auto_expand (panel
, NULL
);
2087 panel
->drag_tree_row
= -1;
2090 #if CONTEXT_MENU_ON_TREE
2092 tree_do_op (GtkWidget
*tree
, WPanel
*panel
, int operation
)
2097 tree_copy_cmd (GtkWidget
*tree
, WPanel
*panel
)
2099 tree_do_op (tree
, panel
, OP_COPY
);
2103 tree_del_cmd (GtkWidget
*tree
, WPanel
*panel
)
2105 tree_do_op (tree
, panel
, OP_DELETE
);
2109 tree_ren_cmd (GtkWidget
*tree
, WPanel
*panel
)
2111 tree_do_op (tree
, panel
, OP_MOVE
);
2114 static GnomeUIInfo tree_popup_items
[] = {
2115 GNOMEUIINFO_ITEM_STOCK(N_("_Copy..."), N_("Copy directory"), tree_copy_cmd
, GNOME_STOCK_PIXMAP_COPY
),
2116 GNOMEUIINFO_ITEM_STOCK(N_("_Delete..."), N_("Delete directory"), tree_del_cmd
, GNOME_STOCK_PIXMAP_TRASH
),
2117 GNOMEUIINFO_ITEM_NONE(N_("_Move..."), N_("Rename or move directory"), tree_ren_cmd
),
2123 panel_tree_button_press (GtkWidget
*widget
, GdkEventButton
*event
, WPanel
*panel
)
2127 if (event
->type
!= GDK_BUTTON_PRESS
)
2130 if (event
->button
!= 3)
2133 popup
= gnome_popup_menu_new (tree_popup_items
);
2134 gnome_popup_menu_do_popup_modal (popup
, NULL
, NULL
, event
, panel
);
2135 gtk_widget_destroy (popup
);
2140 * Middle click on the directory tree opens a new window.
2143 panel_tree_button_release (GtkWidget
*widget
, GdkEventButton
*event
, WPanel
*panel
)
2150 if (event
->type
!= GDK_BUTTON_RELEASE
)
2153 if (event
->button
!= 2)
2156 dtree
= GTK_DTREE (widget
);
2157 if (!gtk_clist_get_selection_info (GTK_CLIST (dtree
), event
->x
, event
->y
, &row
, NULL
))
2160 node
= gtk_ctree_node_nth (GTK_CTREE (dtree
), row
);
2164 path
= gtk_dtree_get_row_path (dtree
, node
);
2168 new_panel_at (path
);
2172 * panel_create_tree_view:
2174 * Create and initializes the GtkDTree widget for being used in the
2178 panel_create_tree_view (WPanel
*panel
)
2182 tree
= gtk_dtree_new ();
2183 /*gtk_ctree_set_line_style (GTK_CTREE (tree), GTK_CTREE_LINES_DOTTED);*/
2184 /*gtk_ctree_set_expander_style (GTK_CTREE (tree), GTK_CTREE_EXPANDER_SQUARE);*/
2185 gtk_ctree_set_indent (GTK_CTREE (tree
), 10);
2189 gtk_signal_connect (GTK_OBJECT (tree
), "directory_changed",
2190 GTK_SIGNAL_FUNC (panel_chdir
), panel
);
2191 gtk_signal_connect (GTK_OBJECT (tree
), "scan_begin",
2192 GTK_SIGNAL_FUNC (panel_tree_scan_begin
), panel
);
2193 gtk_signal_connect (GTK_OBJECT (tree
), "scan_end",
2194 GTK_SIGNAL_FUNC (panel_tree_scan_end
), panel
);
2195 gtk_signal_connect (GTK_OBJECT (tree
), "possibly_ungrab",
2196 GTK_SIGNAL_FUNC (panel_tree_possibly_ungrab
), panel
);
2198 /* Set up drag source */
2200 gtk_drag_source_set (GTK_WIDGET (tree
), GDK_BUTTON1_MASK
| GDK_BUTTON2_MASK
,
2201 drag_types
, ELEMENTS (drag_types
),
2202 (GDK_ACTION_LINK
| GDK_ACTION_MOVE
| GDK_ACTION_COPY
2203 | GDK_ACTION_ASK
| GDK_ACTION_DEFAULT
));
2205 gtk_signal_connect (GTK_OBJECT (tree
), "drag_begin",
2206 GTK_SIGNAL_FUNC (panel_tree_drag_begin
), panel
);
2207 gtk_signal_connect (GTK_OBJECT (tree
), "drag_end",
2208 GTK_SIGNAL_FUNC (panel_tree_drag_end
), panel
);
2209 gtk_signal_connect (GTK_OBJECT (tree
), "drag_data_get",
2210 GTK_SIGNAL_FUNC (panel_tree_drag_data_get
), panel
);
2212 /* Set up drag destination */
2214 gtk_drag_dest_set (GTK_WIDGET (tree
),
2215 GTK_DEST_DEFAULT_DROP
,
2216 drop_types
, ELEMENTS (drop_types
),
2217 GDK_ACTION_COPY
| GDK_ACTION_MOVE
| GDK_ACTION_LINK
| GDK_ACTION_ASK
);
2219 gtk_signal_connect (GTK_OBJECT (tree
), "drag_motion",
2220 GTK_SIGNAL_FUNC (panel_tree_drag_motion
), panel
);
2221 gtk_signal_connect (GTK_OBJECT (tree
), "drag_leave",
2222 GTK_SIGNAL_FUNC (panel_tree_drag_leave
), panel
);
2223 gtk_signal_connect (GTK_OBJECT (tree
), "drag_data_received",
2224 GTK_SIGNAL_FUNC (panel_tree_drag_data_received
), panel
);
2226 #ifdef CONTEXT_MENU_ON_TREE
2227 /* Context sensitive menu */
2228 gtk_signal_connect_after (GTK_OBJECT (tree
), "button_press_event",
2229 GTK_SIGNAL_FUNC (panel_tree_button_press
), panel
);
2230 gtk_clist_set_button_actions (GTK_CLIST (tree
), 2, GTK_BUTTON_SELECTS
);
2233 gtk_signal_connect_after (GTK_OBJECT (tree
), "button_release_event",
2234 GTK_SIGNAL_FUNC (panel_tree_button_release
), panel
);
2239 * create_and_setup_pane:
2241 * Creates the horizontal GtkPaned widget that holds the tree
2242 * and the listing/iconing displays
2245 create_and_setup_pane (WPanel
*panel
)
2248 GtkWidget
*tree
= panel
->tree
;
2249 GdkFont
*tree_font
= tree
->style
->font
;
2252 pane
= gtk_hpaned_new ();
2254 if (tree_panel_visible
== -1)
2255 size
= 20 * gdk_string_width (tree_font
, "W");
2257 if (tree_panel_visible
)
2258 size
= tree_panel_visible
;
2263 gtk_paned_set_position (GTK_PANED (pane
), size
);
2266 * Hack: set the default startup size for the pane without
2267 * using _set_usize which would set the minimal size
2269 GTK_PANED (pane
)->child1_size
= size
;
2270 GTK_PANED (pane
)->position_set
= TRUE
;
2272 gtk_widget_show (pane
);
2278 panel_back (GtkWidget
*button
, WPanel
*panel
)
2280 directory_history_prev (panel
);
2284 panel_fwd (GtkWidget
*button
, WPanel
*panel
)
2286 directory_history_next (panel
);
2290 panel_up (GtkWidget
*button
, WPanel
*panel
)
2292 do_panel_cd (panel
, "..", cd_exact
);
2296 rescan_panel (GtkWidget
*widget
, gpointer data
)
2302 go_home (GtkWidget
*widget
, WPanel
*panel
)
2304 do_panel_cd (panel
, "~", cd_exact
);
2309 static GnomeUIInfo toolbar
[] = {
2310 GNOMEUIINFO_ITEM_STOCK (N_("Back"), N_("Go to the previously visited directory"),
2311 panel_back
, GNOME_STOCK_PIXMAP_BACK
),
2312 GNOMEUIINFO_ITEM_STOCK (N_("Up"), N_("Go up a level in the directory hierarchy"),
2313 panel_up
, GNOME_STOCK_PIXMAP_UP
),
2314 GNOMEUIINFO_ITEM_STOCK (N_("Forward"), N_("Go to the next directory"),
2315 panel_fwd
, GNOME_STOCK_PIXMAP_FORWARD
),
2316 GNOMEUIINFO_SEPARATOR
,
2317 GNOMEUIINFO_ITEM_STOCK (N_("Rescan"), N_("Rescan the current directory"),
2318 rescan_panel
, GNOME_STOCK_PIXMAP_REFRESH
),
2319 GNOMEUIINFO_SEPARATOR
,
2320 GNOMEUIINFO_ITEM_STOCK (N_("Home"), N_("Go to your home directory"),
2321 go_home
, GNOME_STOCK_PIXMAP_HOME
),
2322 GNOMEUIINFO_SEPARATOR
,
2323 GNOMEUIINFO_RADIOLIST(panel_view_toolbar_uiinfo
),
2328 do_ui_signal_connect (GnomeUIInfo
*uiinfo
, gchar
*signal_name
,
2329 GnomeUIBuilderData
*uibdata
)
2331 if (uiinfo
->moreinfo
)
2332 gtk_signal_connect (GTK_OBJECT (uiinfo
->widget
),
2333 signal_name
, uiinfo
->moreinfo
, uibdata
->data
?
2334 uibdata
->data
: uiinfo
->user_data
);
2338 tree_size_allocate (GtkWidget
*widget
, GtkAllocation
*allocation
, WPanel
*panel
)
2340 if (allocation
->width
<= 0){
2341 tree_panel_visible
= 0;
2343 tree_panel_visible
= allocation
->width
;
2346 if (auto_save_setup
) {
2352 x_create_panel (Dlg_head
*h
, widget_data parent
, WPanel
*panel
)
2354 GtkWidget
*status_line
, *vbox
, *ministatus_box
;
2357 GnomeUIBuilderData uibdata
;
2359 panel
->xwindow
= gtk_widget_get_toplevel (GTK_WIDGET (panel
->widget
.wdata
));
2361 panel
->table
= gtk_table_new (2, 1, 0);
2366 panel
->tree_scrolled_window
= gtk_scrolled_window_new (NULL
, NULL
);
2367 gtk_scrolled_window_set_policy (
2368 GTK_SCROLLED_WINDOW (panel
->tree_scrolled_window
),
2369 GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
2370 panel
->tree
= panel_create_tree_view (panel
);
2371 gtk_container_add (GTK_CONTAINER (panel
->tree_scrolled_window
), panel
->tree
);
2372 gtk_widget_show_all (panel
->tree_scrolled_window
);
2375 * Icon and Listing display
2377 panel
->notebook
= gtk_notebook_new ();
2378 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (panel
->notebook
), FALSE
);
2379 gtk_widget_show (panel
->notebook
);
2381 panel
->icons
= panel_create_icon_display (panel
);
2382 gtk_widget_show (panel
->icons
);
2384 memcpy (panel
->column_width
, default_column_width
, sizeof (default_column_width
));
2385 panel
->list
= panel_create_file_list (panel
);
2386 gtk_widget_ref (panel
->icons
);
2387 gtk_widget_ref (panel
->list
);
2389 panel
->panel_listbox
= gtk_event_box_new ();
2390 gtk_widget_show (panel
->panel_listbox
);
2391 gtk_container_add (GTK_CONTAINER (panel
->panel_listbox
), panel
->list
);
2393 gtk_notebook_append_page (GTK_NOTEBOOK (panel
->notebook
), panel
->icons
, NULL
);
2394 gtk_notebook_append_page (GTK_NOTEBOOK (panel
->notebook
), panel
->panel_listbox
, NULL
);
2395 gtk_notebook_set_page (GTK_NOTEBOOK (panel
->notebook
),
2396 panel
->list_type
== list_icons
? 0 : 1);
2398 gtk_widget_show (panel
->icons
);
2399 gtk_widget_show (panel
->list
);
2400 gtk_widget_show (panel
->notebook
);
2405 panel
->pane
= create_and_setup_pane (panel
);
2406 gtk_paned_add1 (GTK_PANED (panel
->pane
), panel
->tree_scrolled_window
);
2407 gtk_signal_connect (GTK_OBJECT (panel
->tree_scrolled_window
), "size_allocate",
2408 GTK_SIGNAL_FUNC (tree_size_allocate
), panel
);
2411 * Current Working directory
2414 cwd
= panel_create_cwd (h
, panel
, &panel
->current_dir
);
2417 * We go through a lot of pain, wrestling with gnome_app* and gmc's @#$&*#$ internal structure and
2418 * make the #@$*&@#$ toolbars here...
2421 status_line
= gtk_toolbar_new (GTK_ORIENTATION_HORIZONTAL
, GTK_TOOLBAR_BOTH
);
2422 uibdata
.connect_func
= do_ui_signal_connect
;
2423 uibdata
.data
= panel
;
2424 uibdata
.is_interp
= FALSE
;
2425 uibdata
.relay_func
= NULL
;
2426 uibdata
.destroy_func
= NULL
;
2428 gnome_app_fill_toolbar_custom (GTK_TOOLBAR (status_line
), toolbar
, &uibdata
, NULL
);
2429 gnome_app_add_toolbar (GNOME_APP (panel
->xwindow
),
2430 GTK_TOOLBAR (status_line
),
2432 GNOME_DOCK_ITEM_BEH_EXCLUSIVE
,
2435 panel
->view_toolbar_items
= copy_uiinfo_widgets (panel_view_toolbar_uiinfo
);
2437 panel
->back_b
= toolbar
[0].widget
;
2438 panel
->up_b
= toolbar
[1].widget
;
2439 panel
->fwd_b
= toolbar
[2].widget
;
2440 panel_update_marks (panel
);
2442 /* Set the list type by poking a toolbar item. Yes, this is hackish.
2443 * We fall back to icon view if a certain listing type is not supported.
2444 * Be sure to keep this in sync with the uiinfo arrays in glayout.c.
2447 if (panel
->list_type
== list_brief
)
2448 gtk_toggle_button_set_active (
2449 GTK_TOGGLE_BUTTON (panel_view_toolbar_uiinfo
[1].widget
), TRUE
);
2450 else if (panel
->list_type
== list_full
)
2451 gtk_toggle_button_set_active (
2452 GTK_TOGGLE_BUTTON (panel_view_toolbar_uiinfo
[2].widget
), TRUE
);
2453 else if (panel
->list_type
== list_user
)
2454 gtk_toggle_button_set_active (
2455 GTK_TOGGLE_BUTTON (panel_view_toolbar_uiinfo
[3].widget
), TRUE
);
2457 gtk_toggle_button_set_active (
2458 GTK_TOGGLE_BUTTON (panel_view_toolbar_uiinfo
[0].widget
), TRUE
);
2460 status_line
= gtk_hbox_new (FALSE
, 2);
2461 gtk_container_set_border_width (GTK_CONTAINER (status_line
), 3);
2462 gtk_box_pack_start (GTK_BOX (status_line
),
2463 gtk_label_new (_("Location:")), FALSE
, FALSE
, 0);
2464 gtk_box_pack_start (GTK_BOX (status_line
), cwd
, TRUE
, TRUE
, 0);
2466 dock
= gnome_dock_item_new ("gmc-toolbar1",
2467 (GNOME_DOCK_ITEM_BEH_EXCLUSIVE
2468 | GNOME_DOCK_ITEM_BEH_NEVER_VERTICAL
));
2469 gtk_container_add (GTK_CONTAINER (dock
), status_line
);
2470 gnome_dock_add_item (GNOME_DOCK (GNOME_APP (panel
->xwindow
)->dock
),
2471 GNOME_DOCK_ITEM (dock
), GNOME_DOCK_TOP
, 1, 0, 0, FALSE
);
2473 gtk_widget_show_all (dock
);
2475 panel
->view_table
= gtk_table_new (1, 1, 0);
2476 gtk_widget_show (panel
->view_table
);
2481 ministatus_box
= gtk_frame_new (NULL
);
2482 gtk_frame_set_shadow_type (GTK_FRAME (ministatus_box
), GTK_SHADOW_IN
);
2484 panel
->status
= gtk_label_new (_("Show all files"));
2485 gtk_misc_set_alignment (GTK_MISC (panel
->status
), 0.0, 0.0);
2486 gtk_misc_set_padding (GTK_MISC (panel
->status
), 2, 0);
2488 gtk_box_pack_start (GTK_BOX (panel
->ministatus
), ministatus_box
, FALSE
, FALSE
, 0);
2489 gtk_container_add (GTK_CONTAINER (ministatus_box
), panel
->status
);
2491 gtk_widget_show (ministatus_box
);
2492 gtk_widget_show (panel
->status
);
2495 * Put the icon list and the file listing in a nice frame
2498 /* Add both the icon view and the listing view */
2499 gtk_table_attach (GTK_TABLE (panel
->view_table
), panel
->notebook
, 0, 1, 0, 1,
2500 GTK_EXPAND
| GTK_FILL
| GTK_SHRINK
,
2501 GTK_EXPAND
| GTK_FILL
| GTK_SHRINK
,
2504 gtk_table_attach (GTK_TABLE (panel
->table
), panel
->pane
, 0, 1, 1, 2,
2505 GTK_EXPAND
| GTK_FILL
| GTK_SHRINK
,
2506 GTK_EXPAND
| GTK_FILL
| GTK_SHRINK
,
2509 gtk_paned_add2 (GTK_PANED (panel
->pane
), panel
->view_table
);
2512 * ministatus_box is a container created just to put the
2513 * panel->ministatus inside.
2515 * Then the resize mode for ministatus_box is changed to stop
2516 * any size-changed messages to be propagated above.
2518 * This is required as the panel->ministatus Label is changed
2519 * very often (to display status information). If this hack
2520 * is not made, then the resize is queued and the whole window
2521 * flickers each time this changes
2524 ministatus_box
= gtk_hbox_new (FALSE
, 0);
2525 gtk_container_add (GTK_CONTAINER (ministatus_box
), panel
->ministatus
);
2526 gtk_widget_show (ministatus_box
);
2527 gtk_container_set_resize_mode (GTK_CONTAINER (ministatus_box
), GTK_RESIZE_QUEUE
);
2528 gtk_table_attach (GTK_TABLE (panel
->table
), ministatus_box
, 0, 1, 2, 3,
2529 GTK_EXPAND
| GTK_FILL
| GTK_SHRINK
,
2532 gtk_table_attach (GTK_TABLE (panel
->table
), frame
, 0, 1, 3, 4,
2533 GTK_EXPAND
| GTK_FILL
,
2537 /* Ultra nasty hack: pull the vbox from wdata */
2538 vbox
= GTK_WIDGET (panel
->widget
.wdata
);
2540 panel
->widget
.wdata
= (widget_data
) panel
->table
;
2542 /* Now, insert our table in our parent */
2543 gtk_container_add (GTK_CONTAINER (vbox
), panel
->table
);
2544 gtk_widget_show (vbox
);
2545 gtk_widget_show (panel
->table
);
2547 if (!(panel
->widget
.options
& W_PANEL_HIDDEN
) && !is_trash_panel
)
2548 gtk_widget_show (gtk_widget_get_toplevel (panel
->table
));
2551 panel_create_pixmaps ();
2553 /* In GNOME the panel wants to have the cursor, to avoid "auto" focusing the
2556 panel
->widget
.options
|= W_WANT_CURSOR
;
2557 panel
->estimated_total
= 0;
2559 panel
->timer_id
= -1;
2561 /* re-set the user_format explicitly */
2562 if (default_user_format
!= NULL
) {
2563 g_free (panel
->user_format
);
2564 panel
->user_format
= g_strdup (default_user_format
);
2569 panel_update_cols (Widget
*panel
, int frame_size
)
2576 get_nth_panel_name (int num
)
2578 static char buffer
[BUF_TINY
];
2581 return "New Left Panel";
2583 return "New Right Panel";
2585 g_snprintf (buffer
, sizeof (buffer
), "%ith Panel", num
);
2595 if ((hint
= get_random_hint ())){
2600 set_hintbar ("The GNOME File Manager " VERSION
);
2605 paint_frame (WPanel
*panel
)
2610 x_reset_sort_labels (WPanel
*panel
)
2614 if (!panel
->notebook
)
2617 if (panel
->list_type
== list_icons
){
2621 panel_switch_new_display_mode (panel
);
2623 gtk_notebook_set_page (GTK_NOTEBOOK (panel
->notebook
), page
);
2626 /* Releases all of the X resources allocated */
2628 x_panel_destroy (WPanel
*panel
)
2630 gtk_widget_destroy (GTK_WIDGET (panel
->xwindow
));