From e8f3c3ca1641b74d0425a1f8b0896536bcb02ae0 Mon Sep 17 00:00:00 2001 From: Pavel Cisler Date: Thu, 5 Apr 2001 23:10:02 +0000 Subject: reviewed by: John Harper 2001-04-05 Pavel Cisler reviewed by: John Harper * libnautilus-extensions/nautilus-file.c: (nautilus_file_fit_date_as_string), (nautilus_file_fit_modified_date_as_string), (nautilus_file_get_date_as_string): * libnautilus-extensions/nautilus-file.h: Add a new function that returns a modified date string, formatted to fit a given width. Make the old nautilus_file_get_date_as_string call it. * src/file-manager/fm-list-view.c: (measure_width_callback), (trucante_middle_callback), (get_cell_text), (set_up_list): Hook up to the get_cell_text signal. For modified text return a nicely formatted text string, for everything else just ellipsize the result. --- ChangeLog | 19 +++ libnautilus-extensions/nautilus-file.c | 214 +++++++++++++++++++++++++++------ libnautilus-extensions/nautilus-file.h | 10 ++ libnautilus-private/nautilus-file.c | 214 +++++++++++++++++++++++++++------ libnautilus-private/nautilus-file.h | 10 ++ src/file-manager/fm-list-view.c | 56 +++++++++ 6 files changed, 451 insertions(+), 72 deletions(-) diff --git a/ChangeLog b/ChangeLog index 73d251928..cefedd633 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2001-04-05 Pavel Cisler + + reviewed by: John Harper + + * libnautilus-extensions/nautilus-file.c: + (nautilus_file_fit_date_as_string), + (nautilus_file_fit_modified_date_as_string), + (nautilus_file_get_date_as_string): + * libnautilus-extensions/nautilus-file.h: + Add a new function that returns a modified date string, + formatted to fit a given width. Make the old + nautilus_file_get_date_as_string call it. + + * src/file-manager/fm-list-view.c: (measure_width_callback), + (trucante_middle_callback), (get_cell_text), (set_up_list): + Hook up to the get_cell_text signal. For modified text return + a nicely formatted text string, for everything else just + ellipsize the result. + 2001-04-05 John Sullivan Fixed bug 7986 ("Paste Files" disabled in trash:) diff --git a/libnautilus-extensions/nautilus-file.c b/libnautilus-extensions/nautilus-file.c index c4c469110..8bd2b7c23 100644 --- a/libnautilus-extensions/nautilus-file.c +++ b/libnautilus-extensions/nautilus-file.c @@ -2218,25 +2218,103 @@ nautilus_file_get_where_string (NautilusFile *file) get_where_string, (file)); } -/** - * nautilus_file_get_date_as_string: - * - * Get a user-displayable string representing a file modification date. - * The caller is responsible for g_free-ing this string. - * @file: NautilusFile representing the file in question. - * - * Returns: Newly allocated string ready to display to the user. - * - **/ +const char *TODAY_TIME_FORMATS [] = { + /* Today, use special word. + * strftime patterns preceeded with the widest + * possible resulting string for that pattern. + * + * Note to localizers: You can look at man strftime + * for details on the format, but you should only use + * the specifiers from the C standard, not extensions. + * These include "%" followed by one of + * "aAbBcdHIjmMpSUwWxXyYZ". There are two extensions + * in the Nautilus version of strftime that can be + * used (and match GNU extensions). Putting a "-" + * between the "%" and any numeric directive will turn + * off zero padding, and putting a "_" there will use + * space padding instead of zero padding. + */ + N_("today at 00:00:00 PM"), + N_("today at %-I:%M:%S %p"), + + N_("today at 00:00 PM"), + N_("today at %-I:%M %p"), + + N_("today, 00:00 PM"), + N_("today, %-I:%M %p"), + + N_("today"), + N_("today"), + NULL +}; + +const char *YESTERDAY_TIME_FORMATS [] = { + /* Yesterday, use special word. + * Note to localizers: Same issues as "today" string. + */ + N_("yesterday at 00:00:00 PM"), + N_("yesterday at %-I:%M:%S %p"), + + N_("yesterday at 00:00 PM"), + N_("yesterday at %-I:%M %p"), + + N_("yesterday, 00:00 PM"), + N_("yesterday, %-I:%M %p"), + + N_("yesterday"), + N_("yesterday"), + NULL +}; + +const char *CURRENT_WEEK_TIME_FORMATS [] = { + /* Current week, include day of week. + * Note to localizers: Same issues as "today" string. + * The width measurement templates correspond to + * the day/month name with the most letters. + */ + N_("Wednesday, September 00 0000 at %00:00:00 PM"), + N_("%A, %B %-d %Y at %-I:%M:%S %p"), + + N_("Mon, Oct 00 0000 at 00:00:00 PM"), + N_("%a, %b %-d %Y at %-I:%M:%S %p"), + + N_("Mon, Oct 00 0000 at 00:00 PM"), + N_("%a, %b %-d %Y at %-I:%M %p"), + + N_("Oct 00 0000 at 00:00 PM"), + N_("%b %-d %Y at %-I:%M %p"), + + N_("Oct 00 0000, 00:00 PM"), + N_("%b %-d %Y, %-I:%M %p"), + + N_("00/00/00, 00:00 PM"), + N_("%m/%-d/%y, %-I:%M %p"), + + N_("00/00/00"), + N_("%m/%d/%y"), + + NULL +}; + static char * -nautilus_file_get_date_as_string (NautilusFile *file, NautilusDateType date_type) +nautilus_file_fit_date_as_string (NautilusFile *file, + NautilusDateType date_type, + int width, + NautilusWidthMeasureCallback measure_callback, + NautilusTruncateCallback truncate_callback, + void *measure_context) { time_t file_time_raw; struct tm *file_time; + const char **formats; + const char *width_template; const char *format; + char *date_string; + char *result; GDate *today; GDate *file_date; guint32 file_date_age; + int i; if (!nautilus_file_get_date (file, date_type, &file_time_raw)) { return NULL; @@ -2254,6 +2332,7 @@ nautilus_file_get_date_as_string (NautilusFile *file, NautilusDateType date_type g_date_free (file_date); g_date_free (today); + /* Format varies depending on how old the date is. This minimizes * the length (and thus clutter & complication) of typical dates * while providing sufficient detail for recent dates to make @@ -2263,37 +2342,100 @@ nautilus_file_get_date_as_string (NautilusFile *file, NautilusDateType date_type */ if (file_date_age == 0) { - /* Today, use special word. - * Note to localizers: You can look at man strftime - * for details on the format, but you should only use - * the specifiers from the C standard, not extensions. - * These include "%" followed by one of - * "aAbBcdHIjmMpSUwWxXyYZ". There are two extensions - * in the Nautilus version of strftime that can be - * used (and match GNU extensions). Putting a "-" - * between the "%" and any numeric directive will turn - * off zero padding, and putting a "_" there will use - * space padding instead of zero padding. - */ - format = _("today at %-I:%M %p"); + formats = TODAY_TIME_FORMATS; } else if (file_date_age == 1) { - /* Yesterday, use special word. - * Note to localizers: Same issues as "today" string. - */ - format = _("yesterday at %-I:%M %p"); + formats = YESTERDAY_TIME_FORMATS; } else if (file_date_age < 7) { - /* Current week, include day of week. - * Note to localizers: Same issues as "today" string. - */ - format = _("%A %-m/%-d/%y at %-I:%M %p"); + formats = CURRENT_WEEK_TIME_FORMATS; } else { - /* Other dates. - * Note to localizers: Same issues as "today" string. - */ - format = _("%-m/%-d/%y at %-I:%M %p"); + formats = CURRENT_WEEK_TIME_FORMATS; } + /* Find the date format that just fits the required width. Instead of measuring + * the resulting string width directly, measure the width of a template that represents + * the widest possible version of a date in a given format. This is done by using M, m + * and 0 for the variable letters/digits respectively. + */ + format = NULL; + + for (i = 0; ; i += 2) { + width_template = formats [i]; + if (width_template == NULL) { + /* no more formats left */ + g_assert (format != NULL); + + /* Can't fit even the shortest format -- return an ellipsized form in the + * shortest format + */ + + date_string = eel_strdup_strftime (format, file_time); + + if (truncate_callback == NULL) { + return date_string; + } + + result = (truncate_callback) (date_string, width, measure_context); + g_free (date_string); + return result; + } + + format = formats [i + 1]; + + if (measure_callback == NULL) { + /* don't care about fitting the width */ + break; + } + + if ((measure_callback) (width_template, measure_context) <= width) { + /* The template fits, this is the format we can fit. */ + break; + } + } + return eel_strdup_strftime (format, file_time); + +} + +/** + * nautilus_file_fit_modified_date_as_string: + * + * Get a user-displayable string representing a file modification date, + * truncated to @width using the measuring and truncating callbacks. + * @file: NautilusFile representing the file in question. + * @width: The desired resulting string width. + * @measure_callback: The callback used to measure the string width. + * @truncate_callback: The callback used to truncate the string to a desired width. + * @measure_context: Data neede when measuring and truncating. + * + * Returns: Newly allocated string ready to display to the user. + * + **/ +char * +nautilus_file_fit_modified_date_as_string (NautilusFile *file, + int width, + NautilusWidthMeasureCallback measure_callback, + NautilusTruncateCallback truncate_callback, + void *measure_context) +{ + return nautilus_file_fit_date_as_string (file, NAUTILUS_DATE_TYPE_MODIFIED, + width, measure_callback, truncate_callback, measure_context); +} + +/** + * nautilus_file_get_date_as_string: + * + * Get a user-displayable string representing a file modification date. + * The caller is responsible for g_free-ing this string. + * @file: NautilusFile representing the file in question. + * + * Returns: Newly allocated string ready to display to the user. + * + **/ +static char * +nautilus_file_get_date_as_string (NautilusFile *file, NautilusDateType date_type) +{ + return nautilus_file_fit_date_as_string (file, date_type, + 0, NULL, NULL, NULL); } static NautilusSpeedTradeoffValue show_directory_item_count; diff --git a/libnautilus-extensions/nautilus-file.h b/libnautilus-extensions/nautilus-file.h index f1a3fa364..8a4892969 100644 --- a/libnautilus-extensions/nautilus-file.h +++ b/libnautilus-extensions/nautilus-file.h @@ -77,6 +77,11 @@ typedef void (*NautilusFileCallback) (NautilusFile *file, typedef void (*NautilusFileOperationCallback) (NautilusFile *file, GnomeVFSResult result, gpointer callback_data); +typedef int (*NautilusWidthMeasureCallback) (const char *string, + void *context); +typedef char * (*NautilusTruncateCallback) (const char *string, + int width, + void *context); /* GtkObject requirements. */ GtkType nautilus_file_get_type (void); @@ -244,6 +249,11 @@ char * nautilus_file_get_string_attribute (Nautilu const char *attribute_name); char * nautilus_file_get_string_attribute_with_default (NautilusFile *file, const char *attribute_name); +char * nautilus_file_fit_modified_date_as_string (NautilusFile *file, + int width, + NautilusWidthMeasureCallback measure_callback, + NautilusTruncateCallback truncate_callback, + void *measure_truncate_context); /* Matching with another URI. */ gboolean nautilus_file_matches_uri (NautilusFile *file, diff --git a/libnautilus-private/nautilus-file.c b/libnautilus-private/nautilus-file.c index c4c469110..8bd2b7c23 100644 --- a/libnautilus-private/nautilus-file.c +++ b/libnautilus-private/nautilus-file.c @@ -2218,25 +2218,103 @@ nautilus_file_get_where_string (NautilusFile *file) get_where_string, (file)); } -/** - * nautilus_file_get_date_as_string: - * - * Get a user-displayable string representing a file modification date. - * The caller is responsible for g_free-ing this string. - * @file: NautilusFile representing the file in question. - * - * Returns: Newly allocated string ready to display to the user. - * - **/ +const char *TODAY_TIME_FORMATS [] = { + /* Today, use special word. + * strftime patterns preceeded with the widest + * possible resulting string for that pattern. + * + * Note to localizers: You can look at man strftime + * for details on the format, but you should only use + * the specifiers from the C standard, not extensions. + * These include "%" followed by one of + * "aAbBcdHIjmMpSUwWxXyYZ". There are two extensions + * in the Nautilus version of strftime that can be + * used (and match GNU extensions). Putting a "-" + * between the "%" and any numeric directive will turn + * off zero padding, and putting a "_" there will use + * space padding instead of zero padding. + */ + N_("today at 00:00:00 PM"), + N_("today at %-I:%M:%S %p"), + + N_("today at 00:00 PM"), + N_("today at %-I:%M %p"), + + N_("today, 00:00 PM"), + N_("today, %-I:%M %p"), + + N_("today"), + N_("today"), + NULL +}; + +const char *YESTERDAY_TIME_FORMATS [] = { + /* Yesterday, use special word. + * Note to localizers: Same issues as "today" string. + */ + N_("yesterday at 00:00:00 PM"), + N_("yesterday at %-I:%M:%S %p"), + + N_("yesterday at 00:00 PM"), + N_("yesterday at %-I:%M %p"), + + N_("yesterday, 00:00 PM"), + N_("yesterday, %-I:%M %p"), + + N_("yesterday"), + N_("yesterday"), + NULL +}; + +const char *CURRENT_WEEK_TIME_FORMATS [] = { + /* Current week, include day of week. + * Note to localizers: Same issues as "today" string. + * The width measurement templates correspond to + * the day/month name with the most letters. + */ + N_("Wednesday, September 00 0000 at %00:00:00 PM"), + N_("%A, %B %-d %Y at %-I:%M:%S %p"), + + N_("Mon, Oct 00 0000 at 00:00:00 PM"), + N_("%a, %b %-d %Y at %-I:%M:%S %p"), + + N_("Mon, Oct 00 0000 at 00:00 PM"), + N_("%a, %b %-d %Y at %-I:%M %p"), + + N_("Oct 00 0000 at 00:00 PM"), + N_("%b %-d %Y at %-I:%M %p"), + + N_("Oct 00 0000, 00:00 PM"), + N_("%b %-d %Y, %-I:%M %p"), + + N_("00/00/00, 00:00 PM"), + N_("%m/%-d/%y, %-I:%M %p"), + + N_("00/00/00"), + N_("%m/%d/%y"), + + NULL +}; + static char * -nautilus_file_get_date_as_string (NautilusFile *file, NautilusDateType date_type) +nautilus_file_fit_date_as_string (NautilusFile *file, + NautilusDateType date_type, + int width, + NautilusWidthMeasureCallback measure_callback, + NautilusTruncateCallback truncate_callback, + void *measure_context) { time_t file_time_raw; struct tm *file_time; + const char **formats; + const char *width_template; const char *format; + char *date_string; + char *result; GDate *today; GDate *file_date; guint32 file_date_age; + int i; if (!nautilus_file_get_date (file, date_type, &file_time_raw)) { return NULL; @@ -2254,6 +2332,7 @@ nautilus_file_get_date_as_string (NautilusFile *file, NautilusDateType date_type g_date_free (file_date); g_date_free (today); + /* Format varies depending on how old the date is. This minimizes * the length (and thus clutter & complication) of typical dates * while providing sufficient detail for recent dates to make @@ -2263,37 +2342,100 @@ nautilus_file_get_date_as_string (NautilusFile *file, NautilusDateType date_type */ if (file_date_age == 0) { - /* Today, use special word. - * Note to localizers: You can look at man strftime - * for details on the format, but you should only use - * the specifiers from the C standard, not extensions. - * These include "%" followed by one of - * "aAbBcdHIjmMpSUwWxXyYZ". There are two extensions - * in the Nautilus version of strftime that can be - * used (and match GNU extensions). Putting a "-" - * between the "%" and any numeric directive will turn - * off zero padding, and putting a "_" there will use - * space padding instead of zero padding. - */ - format = _("today at %-I:%M %p"); + formats = TODAY_TIME_FORMATS; } else if (file_date_age == 1) { - /* Yesterday, use special word. - * Note to localizers: Same issues as "today" string. - */ - format = _("yesterday at %-I:%M %p"); + formats = YESTERDAY_TIME_FORMATS; } else if (file_date_age < 7) { - /* Current week, include day of week. - * Note to localizers: Same issues as "today" string. - */ - format = _("%A %-m/%-d/%y at %-I:%M %p"); + formats = CURRENT_WEEK_TIME_FORMATS; } else { - /* Other dates. - * Note to localizers: Same issues as "today" string. - */ - format = _("%-m/%-d/%y at %-I:%M %p"); + formats = CURRENT_WEEK_TIME_FORMATS; } + /* Find the date format that just fits the required width. Instead of measuring + * the resulting string width directly, measure the width of a template that represents + * the widest possible version of a date in a given format. This is done by using M, m + * and 0 for the variable letters/digits respectively. + */ + format = NULL; + + for (i = 0; ; i += 2) { + width_template = formats [i]; + if (width_template == NULL) { + /* no more formats left */ + g_assert (format != NULL); + + /* Can't fit even the shortest format -- return an ellipsized form in the + * shortest format + */ + + date_string = eel_strdup_strftime (format, file_time); + + if (truncate_callback == NULL) { + return date_string; + } + + result = (truncate_callback) (date_string, width, measure_context); + g_free (date_string); + return result; + } + + format = formats [i + 1]; + + if (measure_callback == NULL) { + /* don't care about fitting the width */ + break; + } + + if ((measure_callback) (width_template, measure_context) <= width) { + /* The template fits, this is the format we can fit. */ + break; + } + } + return eel_strdup_strftime (format, file_time); + +} + +/** + * nautilus_file_fit_modified_date_as_string: + * + * Get a user-displayable string representing a file modification date, + * truncated to @width using the measuring and truncating callbacks. + * @file: NautilusFile representing the file in question. + * @width: The desired resulting string width. + * @measure_callback: The callback used to measure the string width. + * @truncate_callback: The callback used to truncate the string to a desired width. + * @measure_context: Data neede when measuring and truncating. + * + * Returns: Newly allocated string ready to display to the user. + * + **/ +char * +nautilus_file_fit_modified_date_as_string (NautilusFile *file, + int width, + NautilusWidthMeasureCallback measure_callback, + NautilusTruncateCallback truncate_callback, + void *measure_context) +{ + return nautilus_file_fit_date_as_string (file, NAUTILUS_DATE_TYPE_MODIFIED, + width, measure_callback, truncate_callback, measure_context); +} + +/** + * nautilus_file_get_date_as_string: + * + * Get a user-displayable string representing a file modification date. + * The caller is responsible for g_free-ing this string. + * @file: NautilusFile representing the file in question. + * + * Returns: Newly allocated string ready to display to the user. + * + **/ +static char * +nautilus_file_get_date_as_string (NautilusFile *file, NautilusDateType date_type) +{ + return nautilus_file_fit_date_as_string (file, date_type, + 0, NULL, NULL, NULL); } static NautilusSpeedTradeoffValue show_directory_item_count; diff --git a/libnautilus-private/nautilus-file.h b/libnautilus-private/nautilus-file.h index f1a3fa364..8a4892969 100644 --- a/libnautilus-private/nautilus-file.h +++ b/libnautilus-private/nautilus-file.h @@ -77,6 +77,11 @@ typedef void (*NautilusFileCallback) (NautilusFile *file, typedef void (*NautilusFileOperationCallback) (NautilusFile *file, GnomeVFSResult result, gpointer callback_data); +typedef int (*NautilusWidthMeasureCallback) (const char *string, + void *context); +typedef char * (*NautilusTruncateCallback) (const char *string, + int width, + void *context); /* GtkObject requirements. */ GtkType nautilus_file_get_type (void); @@ -244,6 +249,11 @@ char * nautilus_file_get_string_attribute (Nautilu const char *attribute_name); char * nautilus_file_get_string_attribute_with_default (NautilusFile *file, const char *attribute_name); +char * nautilus_file_fit_modified_date_as_string (NautilusFile *file, + int width, + NautilusWidthMeasureCallback measure_callback, + NautilusTruncateCallback truncate_callback, + void *measure_truncate_context); /* Matching with another URI. */ gboolean nautilus_file_matches_uri (NautilusFile *file, diff --git a/src/file-manager/fm-list-view.c b/src/file-manager/fm-list-view.c index 6180ec413..21cba49d2 100644 --- a/src/file-manager/fm-list-view.c +++ b/src/file-manager/fm-list-view.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -1066,6 +1067,57 @@ font_or_font_size_changed_callback (gpointer callback_data) fm_list_view_update_font (FM_LIST_VIEW (callback_data)); } +static int +measure_width_callback (const char *string, void *context) +{ + return gdk_string_width ((GdkFont *)context, string); +} + +static char * +truncate_middle_callback (const char *string, int width, void *context) +{ + return eel_string_ellipsize_middle (string, (GdkFont *)context, width); +} + +static char * +get_cell_text (GtkWidget *widget, int column_index, int cell_width, + EelCListRow *row, GdkFont *font, FMListView *list_view) +{ + const char *cell_text; + EelCList *clist; + FMListViewColumn specification; + + clist = EEL_CLIST (widget); + + get_column_specification (list_view, column_index, &specification); + + if (strcmp (specification.attribute, "date_modified") == 0) { + /* special handling of dates */ + return nautilus_file_fit_modified_date_as_string ( + NAUTILUS_FILE (row->data), + cell_width, + measure_width_callback, truncate_middle_callback, + font); + } + + switch ((EelCellType)row->cell[column_index].type) { + case EEL_CELL_PIXTEXT: + cell_text = EEL_CELL_PIXTEXT (row->cell[column_index])->text; + break; + case EEL_CELL_TEXT: + case EEL_CELL_LINK_TEXT: + cell_text = EEL_CELL_TEXT (row->cell[column_index])->text; + break; + default: + g_assert_not_reached (); + cell_text = NULL; + break; + } + + return eel_string_ellipsize_end (cell_text, font, cell_width); +} + + void set_up_list (FMListView *list_view) { @@ -1133,6 +1185,10 @@ set_up_list (FMListView *list_view) "get_sort_column_index", GTK_SIGNAL_FUNC (fm_list_get_sort_column_index), list_view); + gtk_signal_connect (GTK_OBJECT (list), + "get_cell_text", + GTK_SIGNAL_FUNC (get_cell_text), + list_view); /* Make height tall enough for icons to look good. * This must be done after the list widget is realized, due to -- cgit v1.2.1