nautilus r14514 - in trunk: . libnautilus-private
- From: cneumair svn gnome org
- To: svn-commits-list gnome org
- Subject: nautilus r14514 - in trunk: . libnautilus-private
- Date: Fri, 22 Aug 2008 12:44:55 +0000 (UTC)
Author: cneumair
Date: Fri Aug 22 12:44:54 2008
New Revision: 14514
URL: http://svn.gnome.org/viewvc/nautilus?rev=14514&view=rev
Log:
2008-08-22 Christian Neumair <cneumair gnome org>
* libnautilus-private/nautilus-icon-canvas-item.c
(nautilus_icon_canvas_item_invalidate_label_size),
(nautilus_icon_canvas_item_set_property), (compute_text_rectangle),
(nautilus_icon_canvas_item_update_bounds), (layout_get_full_size),
(layout_get_size_for_layout), (prepare_pango_layout_width),
(prepare_pango_layout_for_measure_entire_text),
(prepare_pango_layout_for_draw), (measure_label_text),
(draw_label_text), (create_label_layout),
(nautilus_icon_canvas_item_get_bounds_for_entire_item),
(nautilus_icon_canvas_item_ensure_bounds_up_to_date),
(nautilus_icon_canvas_item_get_text_rectangle),
(nautilus_icon_canvas_item_accessible_get_offset_at_point):
* libnautilus-private/nautilus-icon-canvas-item.h:
* libnautilus-private/nautilus-icon-container.c
(icon_get_bounding_box), (get_icon_bounds_for_canvas_bounds),
(get_all_icon_bounds),
(nautilus_icon_container_update_scroll_region),
(compare_icons_by_position), (placement_grid_mark_icon),
(find_empty_location), (lay_down_icons_vertical_desktop),
(finish_adding_new_icons):
Rework large chunks of canvas item text handling. Split text drawing
and measuring function.
Modified:
trunk/ChangeLog
trunk/libnautilus-private/nautilus-icon-canvas-item.c
trunk/libnautilus-private/nautilus-icon-canvas-item.h
trunk/libnautilus-private/nautilus-icon-container.c
Modified: trunk/libnautilus-private/nautilus-icon-canvas-item.c
==============================================================================
--- trunk/libnautilus-private/nautilus-icon-canvas-item.c (original)
+++ trunk/libnautilus-private/nautilus-icon-canvas-item.c Fri Aug 22 12:44:54 2008
@@ -64,6 +64,23 @@
#define MAX_TEXT_WIDTH_BESIDE 90
#define MAX_TEXT_WIDTH_BESIDE_TOP_TO_BOTTOM 150
+/* special text height handling
+ * each item has three text height variables:
+ * + text_height: actual height of the displayed (i.e. on-screen) PangoLayout.
+ * + text_height_for_layout: height used in icon grid layout algorithms.
+ * âsane amountâ of text.
+ * âsane amountâ as of
+ * + hard-coded to three lines in text-below-icon mode.
+ * + unlimited in text-besides-icon mode (see VOODOO-TODO)
+ *
+ * This layout height is used by grid layout algorithms, even
+ * though the actually displayed and/or requested text size may be larger
+ * and overlap adjacent icons, if an icon is selected.
+ *
+ * + text_height_for_entire_text: height needed to display the entire PangoLayout,
+ * if it wasn't ellipsized.
+ */
+
/* Private part of the NautilusIconCanvasItem structure. */
struct NautilusIconCanvasItemDetails {
/* The image, text, font. */
@@ -79,19 +96,16 @@
/* Size of the text at current font. */
int text_dx;
int text_width;
- /* actual size required for rendering the entire text */
+
+ /* actual size required for rendering the text to display */
int text_height;
- /* actual size needed for rendering a sane amount of text
- * âsane amountâ as of
- * + hard-coded to three lines in text-below-icon mode.
- * + unlimited in text-besides-icon mode (see VOODOO-TODO)
- *
- * This layout height is used by grid layout algorithms, even
- * though the actual icon may be larger and overlap adjacent
- * icons, if an icon is selected.
- */
+ /* actual size that would be required for rendering the entire text if it wasn't ellipsized */
+ int text_height_for_entire_text;
+ /* actual size needed for rendering a âsane amountâ of text */
int text_height_for_layout;
+ int editable_text_height;
+
/* whether the entire text must always be visible. In that case,
* text_height_for_layout will always be equal to text_height.
* Used for the last line of a line-wise icon layout. */
@@ -134,7 +148,8 @@
EelIRect bounds_cache;
EelIRect bounds_cache_for_layout;
-
+ EelIRect bounds_cache_for_entire_item;
+
/* Accessibility bits */
GailTextUtil *text_util;
};
@@ -189,10 +204,6 @@
static void nautilus_icon_canvas_item_init (NautilusIconCanvasItem *item);
/* private */
-static void draw_or_measure_label_text (NautilusIconCanvasItem *item,
- GdkDrawable *drawable,
- gboolean create_mask,
- EelIRect icon_rect);
static void draw_label_text (NautilusIconCanvasItem *item,
GdkDrawable *drawable,
gboolean create_mask,
@@ -342,14 +353,8 @@
item->details->text_width = -1;
item->details->text_height = -1;
item->details->text_height_for_layout = -1;
- if (item->details->editable_text_layout != NULL) {
- g_object_unref (item->details->editable_text_layout);
- item->details->editable_text_layout = NULL;
- }
- if (item->details->additional_text_layout != NULL) {
- g_object_unref (item->details->additional_text_layout);
- item->details->additional_text_layout = NULL;
- }
+ item->details->text_height_for_entire_text = -1;
+ item->details->editable_text_height = -1;
}
/* Set property handler for the icon item. */
@@ -385,6 +390,10 @@
}
nautilus_icon_canvas_item_invalidate_label_size (item);
+ if (details->editable_text_layout) {
+ g_object_unref (details->editable_text_layout);
+ details->editable_text_layout = NULL;
+ }
break;
case PROP_ADDITIONAL_TEXT:
@@ -397,6 +406,10 @@
details->additional_text = g_strdup (g_value_get_string (value));
nautilus_icon_canvas_item_invalidate_label_size (item);
+ if (details->additional_text_layout) {
+ g_object_unref (details->additional_text_layout);
+ details->additional_text_layout = NULL;
+ }
break;
case PROP_HIGHLIGHTED_FOR_SELECTION:
@@ -736,22 +749,24 @@
compute_text_rectangle (const NautilusIconCanvasItem *item,
EelIRect icon_rectangle,
gboolean canvas_coords,
- gboolean for_layout)
+ NautilusIconCanvasItemBoundsUsage usage)
{
EelIRect text_rectangle;
double pixels_per_unit;
- double text_width, text_height, text_height_for_layout, real_text_height, text_dx;
+ double text_width, text_height, text_height_for_layout, text_height_for_entire_text, real_text_height, text_dx;
pixels_per_unit = EEL_CANVAS_ITEM (item)->canvas->pixels_per_unit;
if (canvas_coords) {
text_width = item->details->text_width;
text_height = item->details->text_height;
text_height_for_layout = item->details->text_height_for_layout;
+ text_height_for_entire_text = item->details->text_height_for_entire_text;
text_dx = item->details->text_dx;
} else {
text_width = item->details->text_width / pixels_per_unit;
text_height = item->details->text_height / pixels_per_unit;
text_height_for_layout = item->details->text_height_for_layout / pixels_per_unit;
+ text_height_for_entire_text = item->details->text_height_for_entire_text / pixels_per_unit;
text_dx = item->details->text_dx / pixels_per_unit;
}
@@ -778,7 +793,7 @@
real_text_height = VOODOO();
} else {
#endif
- real_text_height = text_height;
+ real_text_height = text_height_for_entire_text;
#if 0
}
#endif
@@ -789,11 +804,18 @@
text_rectangle.x0 = (icon_rectangle.x0 + icon_rectangle.x1) / 2 - (int) text_width / 2;
text_rectangle.y0 = icon_rectangle.y1;
text_rectangle.x1 = text_rectangle.x0 + text_width;
- if (for_layout) {
- text_rectangle.y1 = text_rectangle.y0 + text_height_for_layout + LABEL_OFFSET / pixels_per_unit;
+
+ if (usage == BOUNDS_USAGE_FOR_LAYOUT) {
+ real_text_height = text_height_for_layout;
+ } else if (usage == BOUNDS_USAGE_FOR_ENTIRE_ITEM) {
+ real_text_height = text_height_for_entire_text;
+ } else if (usage == BOUNDS_USAGE_FOR_DISPLAY) {
+ real_text_height = text_height;
} else {
- text_rectangle.y1 = text_rectangle.y0 + text_height + LABEL_OFFSET / pixels_per_unit;
+ g_assert_not_reached ();
}
+
+ text_rectangle.y1 = text_rectangle.y0 + real_text_height + LABEL_OFFSET / pixels_per_unit;
}
return text_rectangle;
@@ -840,7 +862,8 @@
/* Update canvas and text rect cache */
get_icon_canvas_rectangle (item, &item->details->canvas_rect);
- item->details->text_rect = compute_text_rectangle (item, item->details->canvas_rect, TRUE, FALSE);
+ item->details->text_rect = compute_text_rectangle (item, item->details->canvas_rect,
+ TRUE, BOUNDS_USAGE_FOR_DISPLAY);
/* Update emblem rect cache */
item->details->emblem_rect.x0 = 0;
@@ -976,76 +999,151 @@
*/
static void
layout_get_full_size (PangoLayout *layout,
- int max_layout_line_count,
int *width,
int *height,
- int *height_for_layout,
int *dx)
{
- PangoLayoutIter *iter;
PangoRectangle logical_rect;
- int total_width, i;
+ int the_width, total_width;
pango_layout_get_extents (layout, NULL, &logical_rect);
- *width = (logical_rect.width + PANGO_SCALE / 2) / PANGO_SCALE;
+ the_width = (logical_rect.width + PANGO_SCALE / 2) / PANGO_SCALE;
total_width = (logical_rect.x + logical_rect.width + PANGO_SCALE / 2) / PANGO_SCALE;
- *dx = total_width - *width;
- *height = (logical_rect.height + PANGO_SCALE / 2) / PANGO_SCALE;
- if (height_for_layout != NULL) {
- /* only use the first three lines for the gridded auto layout */
- if (pango_layout_get_line_count (layout) <= max_layout_line_count) {
- *height_for_layout = *height;
- } else {
- *height_for_layout = 0;
- iter = pango_layout_get_iter (layout);
- /* VOODOO-TODO, determine number of lines based on the icon size for text besides icon.
- * cf. compute_text_rectangle() */
- for (i = 0; i < max_layout_line_count; i++) {
- pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
- *height_for_layout += (logical_rect.height + PANGO_SCALE / 2) / PANGO_SCALE;
+ if (width != NULL) {
+ *width = the_width;
+ }
- if (!pango_layout_iter_next_line (iter)) {
- break;
- }
+ if (height != NULL) {
+ *height = (logical_rect.height + PANGO_SCALE / 2) / PANGO_SCALE;
+ }
+
+ if (dx != NULL) {
+ *dx = total_width - the_width;
+ }
+}
+
+static void
+layout_get_size_for_layout (PangoLayout *layout,
+ int max_layout_line_count,
+ int height_for_entire_text,
+ int *height_for_layout)
+{
+ PangoLayoutIter *iter;
+ PangoRectangle logical_rect;
+ int i;
+
+ /* only use the first max_layout_line_count lines for the gridded auto layout */
+ if (pango_layout_get_line_count (layout) <= max_layout_line_count) {
+ *height_for_layout = height_for_entire_text;
+ } else {
+ *height_for_layout = 0;
+ iter = pango_layout_get_iter (layout);
+ /* VOODOO-TODO, determine number of lines based on the icon size for text besides icon.
+ * cf. compute_text_rectangle() */
+ for (i = 0; i < max_layout_line_count; i++) {
+ pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
+ *height_for_layout += (logical_rect.height + PANGO_SCALE / 2) / PANGO_SCALE;
- *height_for_layout += pango_layout_get_spacing (layout);
+ if (!pango_layout_iter_next_line (iter)) {
+ break;
}
- pango_layout_iter_free (iter);
+
+ *height_for_layout += pango_layout_get_spacing (layout);
}
+ pango_layout_iter_free (iter);
}
}
#define IS_COMPACT_VIEW(container) \
- container->details->layout_mode == NAUTILUS_ICON_LAYOUT_T_B_L_R && \
- container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE
-#include "nautilus-file.h"
+ (container->details->layout_mode == NAUTILUS_ICON_LAYOUT_T_B_L_R && \
+ container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE)
+
+#define TEXT_BACK_PADDING_X 4
+#define TEXT_BACK_PADDING_Y 1
+
+static void
+prepare_pango_layout_width (NautilusIconCanvasItem *item,
+ PangoLayout *layout)
+{
+ if (nautilus_icon_canvas_item_get_max_text_width (item) < 0) {
+ pango_layout_set_width (layout, -1);
+ } else {
+ pango_layout_set_width (layout, floor (nautilus_icon_canvas_item_get_max_text_width (item)) * PANGO_SCALE);
+ pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
+ }
+}
static void
-draw_or_measure_label_text (NautilusIconCanvasItem *item,
- GdkDrawable *drawable,
- gboolean create_mask,
- EelIRect icon_rect)
+prepare_pango_layout_for_measure_entire_text (NautilusIconCanvasItem *item,
+ PangoLayout *layout)
+{
+ NautilusIconContainer *container;
+
+ prepare_pango_layout_width (item, layout);
+
+ container = NAUTILUS_ICON_CONTAINER (EEL_CANVAS_ITEM (item)->canvas);
+
+ if (IS_COMPACT_VIEW (container)) {
+ pango_layout_set_height (layout, -1);
+ } else {
+ pango_layout_set_height (layout, G_MININT);
+ }
+}
+
+static void
+prepare_pango_layout_for_draw (NautilusIconCanvasItem *item,
+ PangoLayout *layout)
+{
+ NautilusIconCanvasItemDetails *details;
+ NautilusIconContainer *container;
+ gboolean needs_highlight;
+
+ prepare_pango_layout_width (item, layout);
+
+ container = NAUTILUS_ICON_CONTAINER (EEL_CANVAS_ITEM (item)->canvas);
+ details = item->details;
+
+ needs_highlight = details->is_highlighted_for_selection || details->is_highlighted_for_drop;
+
+ if (IS_COMPACT_VIEW (container)) {
+ pango_layout_set_height (layout, -1);
+ } else if (needs_highlight ||
+ details->is_prelit ||
+ details->entire_text ||
+ container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE) {
+ /* VOODOO-TODO, cf. compute_text_rectangle() */
+ pango_layout_set_height (layout, G_MININT);
+ } else {
+ /* TODO? we might save some resources, when the re-layout is not neccessary in case
+ * the layout height already fits into max. layout lines. But pango should figure this
+ * out itself (which it doesn't ATM).
+ */
+ pango_layout_set_height (layout,
+ nautilus_icon_container_get_max_layout_lines_for_pango (container));
+ }
+}
+
+static void
+measure_label_text (NautilusIconCanvasItem *item)
{
NautilusIconCanvasItemDetails *details;
NautilusIconContainer *container;
- gint editable_height, editable_for_layout_height, editable_width, editable_dx;
+ gint editable_height, editable_height_for_layout, editable_height_for_entire_text, editable_width, editable_dx;
gint additional_height, additional_width, additional_dx;
EelCanvasItem *canvas_item;
PangoLayout *editable_layout;
PangoLayout *additional_layout;
- GdkColor *label_color;
- int icon_width;
- gboolean have_editable, have_additional, needs_highlight, needs_frame, prelight_label, is_rtl_label_beside;
+ gboolean have_editable, have_additional, needs_highlight;
int max_text_width;
- int x;
- GdkGC *gc;
- EelIRect text_rect;
- int text_back_padding_x, text_back_padding_y;
- int height;
+
+ /* check to see if the cached values are still valid; if so, there's
+ * no work necessary
+ */
- icon_width = 0;
- gc = NULL;
+ if (item->details->text_width >= 0 && item->details->text_height >= 0) {
+ return;
+ }
details = item->details;
needs_highlight = details->is_highlighted_for_selection || details->is_highlighted_for_drop;
@@ -1057,42 +1155,26 @@
if (!have_editable && !have_additional) {
details->text_height = 0;
details->text_height_for_layout = 0;
+ details->text_height_for_entire_text = 0;
details->text_width = 0;
return;
}
-#if (defined PERFORMANCE_TEST_MEASURE_DISABLE && defined PERFORMANCE_TEST_DRAW_DISABLE)
- /* don't do any drawing and fake out the width */
+#ifdef PERFORMANCE_TEST_MEASURE_DISABLE
+ /* fake out the width */
details->text_width = 80;
details->text_height = 20;
details->text_height_for_layout = 20;
+ details->text_height_for_entire_text = 20;
return;
#endif
-#ifdef PERFORMANCE_TEST_MEASURE_DISABLE
- if (drawable == NULL) {
- /* fake out the width */
- details->text_width = 80;
- details->text_height = 20;
- details->text_height_for_layout = 20;
- return;
- }
-#endif
-
-#ifdef PERFORMANCE_TEST_DRAW_DISABLE
- if (drawable != NULL) {
- return;
- }
-#endif
-
canvas_item = EEL_CANVAS_ITEM (item);
- if (drawable != NULL) {
- icon_width = details->pixbuf == NULL ? 0 : gdk_pixbuf_get_width (details->pixbuf);
- }
-
+
editable_width = 0;
editable_height = 0;
- editable_for_layout_height = 0;
+ editable_height_for_layout = 0;
+ editable_height_for_entire_text = 0;
editable_dx = 0;
additional_width = 0;
additional_height = 0;
@@ -1105,31 +1187,38 @@
additional_layout = NULL;
if (have_editable) {
+ /* first, measure required text height: editable_height_for_entire_text
+ * then, measure text height applicable for layout: editable_height_for_layout
+ * next, measure actually displayed height: editable_height
+ */
editable_layout = get_label_layout (&details->editable_text_layout, item, details->editable_text);
- if (IS_COMPACT_VIEW (container)) {
- pango_layout_set_height (editable_layout, -1);
- } else if (needs_highlight ||
- details->is_prelit ||
- details->entire_text ||
- container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE) {
- /* VOODOO-TODO, cf. compute_text_rectangle() */
- pango_layout_set_height (editable_layout, G_MININT);
- } else {
- pango_layout_set_height (editable_layout,
- nautilus_icon_container_get_max_layout_lines_for_pango (container));
- }
+
+ prepare_pango_layout_for_measure_entire_text (item, editable_layout);
layout_get_full_size (editable_layout,
- nautilus_icon_container_get_max_layout_lines (container),
- &editable_width, &editable_height, &editable_for_layout_height, &editable_dx);
+ NULL,
+ &editable_height_for_entire_text,
+ NULL);
+ layout_get_size_for_layout (editable_layout,
+ nautilus_icon_container_get_max_layout_lines (container),
+ editable_height_for_entire_text,
+ &editable_height_for_layout);
+
+ prepare_pango_layout_for_draw (item, editable_layout);
+ layout_get_full_size (editable_layout,
+ &editable_width,
+ &editable_height,
+ &editable_dx);
}
if (have_additional) {
additional_layout = get_label_layout (&details->additional_text_layout, item, details->additional_text);
+ prepare_pango_layout_for_draw (item, additional_layout);
layout_get_full_size (additional_layout,
- nautilus_icon_container_get_max_layout_lines (container),
- &additional_width, &additional_height, NULL, &additional_dx);
+ &additional_width, &additional_height, &additional_dx);
}
+ details->editable_text_height = editable_height;
+
if (editable_width > additional_width) {
details->text_width = editable_width;
details->text_dx = editable_dx;
@@ -1140,41 +1229,87 @@
if (have_additional) {
details->text_height = editable_height + LABEL_LINE_SPACING + additional_height;
- details->text_height_for_layout = editable_for_layout_height + LABEL_LINE_SPACING + additional_height;
+ details->text_height_for_layout = editable_height_for_layout + LABEL_LINE_SPACING + additional_height;
+ details->text_height_for_entire_text = editable_height_for_entire_text + LABEL_LINE_SPACING + additional_height;
} else {
details->text_height = editable_height;
- details->text_height_for_layout = editable_for_layout_height;
+ details->text_height_for_layout = editable_height_for_layout;
+ details->text_height_for_entire_text = editable_height_for_entire_text;
}
/* add some extra space for highlighting even when we don't highlight so things won't move */
- text_back_padding_x = 4;
- text_back_padding_y = 1;
- details->text_height += text_back_padding_y*2; /* extra slop for nicer highlighting */
- details->text_height_for_layout += text_back_padding_y*2; /* extra slop for nicer highlighting */
- details->text_width += text_back_padding_x*2; /* extra to make it look nicer */
+ /* extra slop for nicer highlighting */
+ details->text_height += TEXT_BACK_PADDING_Y*2;
+ details->text_height_for_layout += TEXT_BACK_PADDING_Y*2;
+ details->text_height_for_entire_text += TEXT_BACK_PADDING_Y*2;
+ details->editable_text_height += TEXT_BACK_PADDING_Y*2;
- /* if measuring, we are done */
- if (!drawable) {
- if (editable_layout) {
- g_object_unref (editable_layout);
- }
+ /* extra to make it look nicer */
+ details->text_width += TEXT_BACK_PADDING_X*2;
- if (additional_layout) {
- g_object_unref (additional_layout);
- }
+ if (editable_layout) {
+ g_object_unref (editable_layout);
+ }
+
+ if (additional_layout) {
+ g_object_unref (additional_layout);
+ }
+}
+
+static void
+draw_label_text (NautilusIconCanvasItem *item,
+ GdkDrawable *drawable,
+ gboolean create_mask,
+ EelIRect icon_rect)
+{
+ EelCanvasItem *canvas_item;
+ NautilusIconCanvasItemDetails *details;
+ NautilusIconContainer *container;
+ PangoLayout *editable_layout;
+ PangoLayout *additional_layout;
+ GdkColor *label_color;
+ GdkGC *gc;
+ gboolean have_editable, have_additional;
+ gboolean needs_frame, needs_highlight, prelight_label, is_rtl_label_beside;
+ EelIRect text_rect;
+ int x;
+ int max_text_width;
+#ifdef PERFORMANCE_TEST_DRAW_DISABLE
+ return;
+#endif
+
+ gc = NULL;
+
+ canvas_item = EEL_CANVAS_ITEM (item);
+ details = item->details;
+
+ measure_label_text (item);
+ if (details->text_height == 0 ||
+ details->text_width == 0) {
return;
}
- text_rect = compute_text_rectangle (item, icon_rect, TRUE, FALSE);
+ container = NAUTILUS_ICON_CONTAINER (EEL_CANVAS_ITEM (item)->canvas);
+
+ text_rect = compute_text_rectangle (item, icon_rect, TRUE, BOUNDS_USAGE_FOR_DISPLAY);
+ needs_highlight = details->is_highlighted_for_selection || details->is_highlighted_for_drop;
is_rtl_label_beside = nautilus_icon_container_is_layout_rtl (container) &&
container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE;
+ editable_layout = NULL;
+ additional_layout = NULL;
+
+ have_editable = details->editable_text != NULL && details->editable_text[0] != '\0';
+ have_additional = details->additional_text != NULL && details->additional_text[0] != '\0';
+ g_assert (have_editable || have_additional);
+
+ max_text_width = floor (nautilus_icon_canvas_item_get_max_text_width (item));
+
/* if the icon is highlighted, do some set-up */
- if (needs_highlight && !details->is_renaming &&
- details->text_width > 0 && details->text_height > 0) {
+ if (needs_highlight && !details->is_renaming) {
draw_frame (item,
drawable,
GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (container)) ? container->details->highlight_color_rgba : container->details->active_color_rgba,
@@ -1184,15 +1319,13 @@
is_rtl_label_beside ? text_rect.x1 - text_rect.x0 - item->details->text_dx : text_rect.x1 - text_rect.x0,
text_rect.y1 - text_rect.y0);
} else if (!needs_highlight && !details->is_renaming &&
- details->text_height_for_layout != details->text_height &&
- details->text_width > 0 && details->text_height > 0) {
+ details->text_height_for_layout != details->text_height) {
/* clear the underlying icons, where the text overlaps them. */
- height = details->text_height - details->text_height_for_layout;
gdk_window_clear_area (EEL_CANVAS (container)->layout.bin_window,
text_rect.x0,
- text_rect.y1 - height,
+ text_rect.y0,
text_rect.x1 - text_rect.x0,
- height);
+ text_rect.y1 - text_rect.y0);
}
if (container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE) {
@@ -1202,6 +1335,9 @@
}
if (have_editable) {
+ editable_layout = get_label_layout (&item->details->editable_text_layout, item, item->details->editable_text);
+ prepare_pango_layout_for_draw (item, editable_layout);
+
gtk_widget_style_get (GTK_WIDGET (container),
"frame_text", &needs_frame,
"activate_prelight_icon_label", &prelight_label,
@@ -1237,10 +1373,13 @@
editable_layout, needs_highlight,
label_color,
x,
- text_rect.y0 + text_back_padding_y, gc);
+ text_rect.y0 + TEXT_BACK_PADDING_Y, gc);
}
if (have_additional) {
+ additional_layout = get_label_layout (&item->details->additional_text_layout, item, item->details->additional_text);
+ prepare_pango_layout_for_draw (item, additional_layout);
+
gc = nautilus_icon_container_get_label_color_and_gc
(NAUTILUS_ICON_CONTAINER (canvas_item->canvas),
&label_color, FALSE, needs_highlight,
@@ -1250,7 +1389,7 @@
additional_layout, needs_highlight,
label_color,
x,
- text_rect.y0 + editable_height + LABEL_LINE_SPACING + text_back_padding_y, gc);
+ text_rect.y0 + details->editable_text_height + LABEL_LINE_SPACING + TEXT_BACK_PADDING_Y, gc);
}
if (!create_mask && item->details->is_highlighted_as_keyboard_focus) {
@@ -1266,38 +1405,15 @@
text_rect.y1 - text_rect.y0);
}
- if (editable_layout) {
+ if (editable_layout != NULL) {
g_object_unref (editable_layout);
}
- if (additional_layout) {
+ if (additional_layout != NULL) {
g_object_unref (additional_layout);
}
}
-static void
-measure_label_text (NautilusIconCanvasItem *item)
-{
- EelIRect rect = {0, };
-
- /* check to see if the cached values are still valid; if so, there's
- * no work necessary
- */
-
- if (item->details->text_width >= 0 && item->details->text_height >= 0) {
- return;
- }
-
- draw_or_measure_label_text (item, NULL, FALSE, rect);
-}
-
-static void
-draw_label_text (NautilusIconCanvasItem *item, GdkDrawable *drawable,
- gboolean create_mask, EelIRect icon_rect)
-{
- draw_or_measure_label_text (item, drawable, create_mask, icon_rect);
-}
-
void
nautilus_icon_canvas_item_set_is_visible (NautilusIconCanvasItem *item,
gboolean visible)
@@ -1969,13 +2085,6 @@
}
pango_layout_set_text (layout, zeroified_text, -1);
- if (nautilus_icon_canvas_item_get_max_text_width (item) < 0) {
- pango_layout_set_width (layout, -1);
- } else {
- pango_layout_set_width (layout, floor (nautilus_icon_canvas_item_get_max_text_width (item)) * PANGO_SCALE);
- pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
- }
-
pango_layout_set_auto_dir (layout, FALSE);
if (container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE) {
@@ -1990,9 +2099,6 @@
pango_layout_set_spacing (layout, LABEL_LINE_SPACING);
pango_layout_set_wrap (layout, PANGO_WRAP_WORD_CHAR);
- if (IS_COMPACT_VIEW (container)) {
- pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
- }
/* Create a font description */
if (container->details->font) {
@@ -2298,6 +2404,35 @@
*y2 = (int)details->y + total_rect->y1 + 1;
}
}
+
+void
+nautilus_icon_canvas_item_get_bounds_for_entire_item (NautilusIconCanvasItem *icon_item,
+ double *x1, double *y1, double *x2, double *y2)
+{
+ NautilusIconCanvasItemDetails *details;
+ EelIRect *total_rect;
+
+ details = icon_item->details;
+
+ nautilus_icon_canvas_item_ensure_bounds_up_to_date (icon_item);
+ g_assert (details->bounds_cached);
+
+ total_rect = &details->bounds_cache_for_entire_item;
+
+ /* Return the result. */
+ if (x1 != NULL) {
+ *x1 = (int)details->x + total_rect->x0;
+ }
+ if (y1 != NULL) {
+ *y1 = (int)details->y + total_rect->y0;
+ }
+ if (x2 != NULL) {
+ *x2 = (int)details->x + total_rect->x1 + 1;
+ }
+ if (y2 != NULL) {
+ *y2 = (int)details->y + total_rect->y1 + 1;
+ }
+}
/* Bounds handler for the icon canvas item. */
static void
@@ -2332,7 +2467,9 @@
nautilus_icon_canvas_item_ensure_bounds_up_to_date (NautilusIconCanvasItem *icon_item)
{
NautilusIconCanvasItemDetails *details;
- EelIRect icon_rect, text_rect, text_rect_for_layout, total_rect, total_rect_for_layout, emblem_rect;
+ EelIRect icon_rect, emblem_rect;
+ EelIRect text_rect, text_rect_for_layout, text_rect_for_entire_text;
+ EelIRect total_rect, total_rect_for_layout, total_rect_for_entire_text;
EelCanvasItem *item;
double pixels_per_unit;
EmblemLayout emblem_layout;
@@ -2359,14 +2496,16 @@
}
/* Compute text rectangle. */
- text_rect = compute_text_rectangle (icon_item, icon_rect, FALSE, FALSE);
- text_rect_for_layout = compute_text_rectangle (icon_item, icon_rect, FALSE, TRUE);
+ text_rect = compute_text_rectangle (icon_item, icon_rect, FALSE, BOUNDS_USAGE_FOR_DISPLAY);
+ text_rect_for_layout = compute_text_rectangle (icon_item, icon_rect, FALSE, BOUNDS_USAGE_FOR_LAYOUT);
+ text_rect_for_entire_text = compute_text_rectangle (icon_item, icon_rect, FALSE, BOUNDS_USAGE_FOR_ENTIRE_ITEM);
is_rtl = nautilus_icon_container_is_layout_rtl (NAUTILUS_ICON_CONTAINER (item->canvas));
/* Compute total rectangle, adding in emblem rectangles. */
eel_irect_union (&total_rect, &icon_rect, &text_rect);
eel_irect_union (&total_rect_for_layout, &icon_rect, &text_rect_for_layout);
+ eel_irect_union (&total_rect_for_entire_text, &icon_rect, &text_rect_for_entire_text);
emblem_layout_reset (&emblem_layout, icon_item, icon_rect, is_rtl);
while (emblem_layout_next (&emblem_layout, &emblem_pixbuf, &emblem_rect, is_rtl)) {
emblem_rect.x0 = floor (emblem_rect.x0 / pixels_per_unit);
@@ -2376,10 +2515,12 @@
eel_irect_union (&total_rect, &total_rect, &emblem_rect);
eel_irect_union (&total_rect_for_layout, &total_rect_for_layout, &emblem_rect);
+ eel_irect_union (&total_rect_for_entire_text, &total_rect_for_entire_text, &emblem_rect);
}
details->bounds_cache = total_rect;
details->bounds_cache_for_layout = total_rect_for_layout;
+ details->bounds_cache_for_entire_item = total_rect_for_entire_text;
details->bounds_cached = TRUE;
}
}
@@ -2437,7 +2578,8 @@
measure_label_text (item);
- text_rectangle = compute_text_rectangle (item, icon_rectangle, FALSE, for_layout);
+ text_rectangle = compute_text_rectangle (item, icon_rectangle, FALSE,
+ for_layout ? BOUNDS_USAGE_FOR_LAYOUT : BOUNDS_USAGE_FOR_DISPLAY);
ret.x0 = text_rectangle.x0;
ret.y0 = text_rectangle.y0;
@@ -3129,9 +3271,11 @@
additional_layout = NULL;
if (have_editable) {
editable_layout = get_label_layout (&item->details->editable_text_layout, item, item->details->editable_text);
+ prepare_pango_layout_for_draw (item, editable_layout);
pango_layout_get_pixel_size (editable_layout, NULL, &editable_height);
if (y >= editable_height &&
have_additional) {
+ prepare_pango_layout_for_draw (item, editable_layout);
additional_layout = get_label_layout (&item->details->additional_text_layout, item, item->details->additional_text);
layout = additional_layout;
icon_text = item->details->additional_text;
@@ -3142,6 +3286,7 @@
}
} else if (have_additional) {
additional_layout = get_label_layout (&item->details->additional_text_layout, item, item->details->additional_text);
+ prepare_pango_layout_for_draw (item, additional_layout);
layout = additional_layout;
icon_text = item->details->additional_text;
} else {
Modified: trunk/libnautilus-private/nautilus-icon-canvas-item.h
==============================================================================
--- trunk/libnautilus-private/nautilus-icon-canvas-item.h (original)
+++ trunk/libnautilus-private/nautilus-icon-canvas-item.h Fri Aug 22 12:44:54 2008
@@ -55,6 +55,13 @@
EelCanvasItemClass parent_class;
};
+/* not namespaced due to their length */
+typedef enum {
+ BOUNDS_USAGE_FOR_LAYOUT,
+ BOUNDS_USAGE_FOR_ENTIRE_ITEM,
+ BOUNDS_USAGE_FOR_DISPLAY
+} NautilusIconCanvasItemBoundsUsage;
+
/* GObject */
GType nautilus_icon_canvas_item_get_type (void);
@@ -92,6 +99,8 @@
gboolean for_layout);
void nautilus_icon_canvas_item_get_bounds_for_layout (NautilusIconCanvasItem *item,
double *x1, double *y1, double *x2, double *y2);
+void nautilus_icon_canvas_item_get_bounds_for_entire_item (NautilusIconCanvasItem *item,
+ double *x1, double *y1, double *x2, double *y2);
void nautilus_icon_canvas_item_update_bounds (NautilusIconCanvasItem *item,
double i2w_dx, double i2w_dy);
void nautilus_icon_canvas_item_set_is_visible (NautilusIconCanvasItem *item,
Modified: trunk/libnautilus-private/nautilus-icon-container.c
==============================================================================
--- trunk/libnautilus-private/nautilus-icon-container.c (original)
+++ trunk/libnautilus-private/nautilus-icon-container.c Fri Aug 22 12:44:54 2008
@@ -189,12 +189,8 @@
int *x1_return,
int *y1_return,
int *x2_return,
- int *y2_return);
-static void icon_get_bounding_box_for_layout (NautilusIcon *icon,
- int *x1_return,
- int *y1_return,
- int *x2_return,
- int *y2_return);
+ int *y2_return,
+ NautilusIconCanvasItemBoundsUsage usage);
static gboolean is_renaming (NautilusIconContainer *container);
static gboolean is_renaming_pending (NautilusIconContainer *container);
static void process_pending_icon_to_rename (NautilusIconContainer *container);
@@ -506,36 +502,42 @@
return TRUE;
}
-static void
+static inline void
icon_get_bounding_box (NautilusIcon *icon,
int *x1_return, int *y1_return,
- int *x2_return, int *y2_return)
+ int *x2_return, int *y2_return,
+ NautilusIconCanvasItemBoundsUsage usage)
{
double x1, y1, x2, y2;
- eel_canvas_item_get_bounds (EEL_CANVAS_ITEM (icon->item),
- &x1, &y1, &x2, &y2);
+ if (usage == BOUNDS_USAGE_FOR_DISPLAY) {
+ eel_canvas_item_get_bounds (EEL_CANVAS_ITEM (icon->item),
+ &x1, &y1, &x2, &y2);
+ } else if (usage == BOUNDS_USAGE_FOR_LAYOUT) {
+ nautilus_icon_canvas_item_get_bounds_for_layout (icon->item,
+ &x1, &y1, &x2, &y2);
+ } else if (usage == BOUNDS_USAGE_FOR_ENTIRE_ITEM) {
+ nautilus_icon_canvas_item_get_bounds_for_entire_item (icon->item,
+ &x1, &y1, &x2, &y2);
+ } else {
+ g_assert_not_reached ();
+ }
- *x1_return = x1;
- *y1_return = y1;
- *x2_return = x2;
- *y2_return = y2;
-}
+ if (x1_return != NULL) {
+ *x1_return = x1;
+ }
-static void
-icon_get_bounding_box_for_layout (NautilusIcon *icon,
- int *x1_return, int *y1_return,
- int *x2_return, int *y2_return)
-{
- double x1, y1, x2, y2;
+ if (y1_return != NULL) {
+ *y1_return = y1;
+ }
- nautilus_icon_canvas_item_get_bounds_for_layout (icon->item,
- &x1, &y1, &x2, &y2);
+ if (x2_return != NULL) {
+ *x2_return = x2;
+ }
- *x1_return = x1;
- *y1_return = y1;
- *x2_return = x2;
- *y2_return = y2;
+ if (y2_return != NULL) {
+ *y2_return = y2;
+ }
}
/* Utility functions for NautilusIconContainer. */
@@ -797,17 +799,129 @@
container->details->keyboard_rubberband_start = NULL;
}
+/* carbon-copy of eel_canvas_group_bounds(), but
+ * for NautilusIconContainerItems it returns the
+ * bounds for the âentire itemâ.
+ */
+static void
+get_icon_bounds_for_canvas_bounds (EelCanvasGroup *group,
+ double *x1, double *y1,
+ double *x2, double *y2,
+ NautilusIconCanvasItemBoundsUsage usage)
+{
+ EelCanvasItem *child;
+ GList *list;
+ double tx1, ty1, tx2, ty2;
+ double minx, miny, maxx, maxy;
+ int set;
+
+ /* Get the bounds of the first visible item */
+
+ child = NULL; /* Unnecessary but eliminates a warning. */
+
+ set = FALSE;
+
+ for (list = group->item_list; list; list = list->next) {
+ child = list->data;
+
+ if (child->object.flags & EEL_CANVAS_ITEM_MAPPED) {
+ set = TRUE;
+ if (!NAUTILUS_IS_ICON_CANVAS_ITEM (child) ||
+ usage == BOUNDS_USAGE_FOR_DISPLAY) {
+ eel_canvas_item_get_bounds (child, &minx, &miny, &maxx, &maxy);
+ } else if (usage == BOUNDS_USAGE_FOR_LAYOUT) {
+ nautilus_icon_canvas_item_get_bounds_for_layout (NAUTILUS_ICON_CANVAS_ITEM (child),
+ &minx, &miny, &maxx, &maxy);
+ } else if (usage == BOUNDS_USAGE_FOR_ENTIRE_ITEM) {
+ nautilus_icon_canvas_item_get_bounds_for_entire_item (NAUTILUS_ICON_CANVAS_ITEM (child),
+ &minx, &miny, &maxx, &maxy);
+ } else {
+ g_assert_not_reached ();
+ }
+ break;
+ }
+ }
+
+ /* If there were no visible items, return an empty bounding box */
+
+ if (!set) {
+ *x1 = *y1 = *x2 = *y2 = 0.0;
+ return;
+ }
+
+ /* Now we can grow the bounds using the rest of the items */
+
+ list = list->next;
+
+ for (; list; list = list->next) {
+ child = list->data;
+
+ if (!(child->object.flags & EEL_CANVAS_ITEM_MAPPED))
+ continue;
+
+ if (!NAUTILUS_IS_ICON_CANVAS_ITEM (child) ||
+ usage == BOUNDS_USAGE_FOR_DISPLAY) {
+ eel_canvas_item_get_bounds (child, &tx1, &ty1, &tx2, &ty2);
+ } else if (usage == BOUNDS_USAGE_FOR_LAYOUT) {
+ nautilus_icon_canvas_item_get_bounds_for_layout (NAUTILUS_ICON_CANVAS_ITEM (child),
+ &tx1, &ty1, &tx2, &ty2);
+ } else if (usage == BOUNDS_USAGE_FOR_ENTIRE_ITEM) {
+ nautilus_icon_canvas_item_get_bounds_for_entire_item (NAUTILUS_ICON_CANVAS_ITEM (child),
+ &tx1, &ty1, &tx2, &ty2);
+ } else {
+ g_assert_not_reached ();
+ }
+
+ if (tx1 < minx)
+ minx = tx1;
+
+ if (ty1 < miny)
+ miny = ty1;
+
+ if (tx2 > maxx)
+ maxx = tx2;
+
+ if (ty2 > maxy)
+ maxy = ty2;
+ }
+
+ /* Make the bounds be relative to our parent's coordinate system */
+
+ if (EEL_CANVAS_ITEM (group)->parent) {
+ minx += group->xpos;
+ miny += group->ypos;
+ maxx += group->xpos;
+ maxy += group->ypos;
+ }
+
+ if (x1 != NULL) {
+ *x1 = minx;
+ }
+
+ if (y1 != NULL) {
+ *y1 = miny;
+ }
+
+ if (x2 != NULL) {
+ *x2 = maxx;
+ }
+
+ if (y2 != NULL) {
+ *y2 = maxy;
+ }
+}
+
static void
get_all_icon_bounds (NautilusIconContainer *container,
double *x1, double *y1,
- double *x2, double *y2)
+ double *x2, double *y2,
+ NautilusIconCanvasItemBoundsUsage usage)
{
/* FIXME bugzilla.gnome.org 42477: Do we have to do something about the rubberband
* here? Any other non-icon items?
*/
- eel_canvas_item_get_bounds
- (EEL_CANVAS (container)->root,
- x1, y1, x2, y2);
+ get_icon_bounds_for_canvas_bounds (EEL_CANVAS_GROUP (EEL_CANVAS (container)->root),
+ x1, y1, x2, y2, usage);
}
/* Don't preserve visible white space the next time the scroll region
@@ -888,7 +1002,7 @@
container->details->reset_scroll_region_trigger = FALSE;
}
- get_all_icon_bounds (container, &x1, &y1, &x2, &y2);
+ get_all_icon_bounds (container, &x1, &y1, &x2, &y2, BOUNDS_USAGE_FOR_ENTIRE_ITEM);
/* Auto-layout assumes a 0, 0 scroll origin */
if (nautilus_icon_container_is_auto_layout (container)) {
@@ -1465,9 +1579,11 @@
icon_a = (NautilusIcon*)a;
icon_b = (NautilusIcon*)b;
- icon_get_bounding_box (icon_a, &x1, &y1, &x2, &y2);
+ icon_get_bounding_box (icon_a, &x1, &y1, &x2, &y2,
+ BOUNDS_USAGE_FOR_DISPLAY);
center_a = x1 + (x2 - x1) / 2;
- icon_get_bounding_box (icon_b, &x1, &y1, &x2, &y2);
+ icon_get_bounding_box (icon_b, &x1, &y1, &x2, &y2,
+ BOUNDS_USAGE_FOR_DISPLAY);
center_b = x1 + (x2 - x1) / 2;
return center_a == center_b ?
@@ -1589,9 +1705,10 @@
EelIRect icon_pos;
EelIRect grid_pos;
- icon_get_bounding_box_for_layout (icon,
- &icon_pos.x0, &icon_pos.y0,
- &icon_pos.x1, &icon_pos.y1);
+ icon_get_bounding_box (icon,
+ &icon_pos.x0, &icon_pos.y0,
+ &icon_pos.x1, &icon_pos.y1,
+ BOUNDS_USAGE_FOR_LAYOUT);
canvas_position_to_grid_position (grid,
icon_pos,
&grid_pos);
@@ -1610,6 +1727,7 @@
double icon_width, icon_height;
int canvas_width;
int canvas_height;
+ int y2_for_bound_check;
EelIRect icon_position;
EelDRect pixbuf_rect;
gboolean collision;
@@ -1618,12 +1736,16 @@
canvas_width = CANVAS_WIDTH(container);
canvas_height = CANVAS_HEIGHT(container);
- icon_get_bounding_box_for_layout (icon,
- &icon_position.x0, &icon_position.y0,
- &icon_position.x1, &icon_position.y1);
+ icon_get_bounding_box (icon,
+ &icon_position.x0, &icon_position.y0,
+ &icon_position.x1, &icon_position.y1,
+ BOUNDS_USAGE_FOR_LAYOUT);
icon_width = icon_position.x1 - icon_position.x0;
icon_height = icon_position.y1 - icon_position.y0;
-
+
+ icon_get_bounding_box (icon, NULL, NULL, NULL, &y2_for_bound_check,
+ BOUNDS_USAGE_FOR_ENTIRE_ITEM);
+
pixbuf_rect = nautilus_icon_canvas_item_get_icon_rectangle (icon->item);
/* Start the icon on a grid location */
@@ -1636,6 +1758,7 @@
do {
EelIRect grid_position;
+ gboolean need_new_column;
collision = FALSE;
@@ -1643,11 +1766,14 @@
icon_position,
&grid_position);
- if (!placement_grid_position_is_free (grid, grid_position)) {
+ need_new_column = y2_for_bound_check + DESKTOP_PAD_VERTICAL > canvas_height;
+
+ if (need_new_column ||
+ !placement_grid_position_is_free (grid, grid_position)) {
icon_position.y0 += SNAP_SIZE_Y;
icon_position.y1 = icon_position.y0 + icon_height;
- if (icon_position.y1 + DESKTOP_PAD_VERTICAL > canvas_height) {
+ if (need_new_column) {
/* Move to the next column */
icon_position.y0 = DESKTOP_PAD_VERTICAL + SNAP_SIZE_Y - (pixbuf_rect.y1 - pixbuf_rect.y0);
while (icon_position.y0 < DESKTOP_PAD_VERTICAL) {
@@ -1820,6 +1946,8 @@
while (icons != NULL) {
int center_x;
int baseline;
+ int icon_height_for_bound_check;
+ int y2_for_bound_check;
gboolean should_snap;
should_snap = !(container->details->tighter_layout && !container->details->keep_aligned);
@@ -1831,10 +1959,14 @@
/* Calculate max width for column */
for (p = icons; p != NULL; p = p->next) {
icon = p->data;
- icon_get_bounding_box_for_layout (icon, &x1, &y1, &x2, &y2);
+ icon_get_bounding_box (icon, &x1, &y1, &x2, &y2,
+ BOUNDS_USAGE_FOR_LAYOUT);
+ icon_get_bounding_box (icon, NULL, NULL, NULL, &y2_for_bound_check,
+ BOUNDS_USAGE_FOR_ENTIRE_ITEM);
icon_width = x2 - x1;
icon_height = y2 - y1;
+ icon_height_for_bound_check = y2_for_bound_check - y1;
if (should_snap) {
/* Snap the baseline to a grid position */
@@ -1845,7 +1977,7 @@
}
/* Check and see if we need to move to a new column */
- if (y != DESKTOP_PAD_VERTICAL && y > height - icon_height) {
+ if (y != DESKTOP_PAD_VERTICAL && y > height - icon_height_for_bound_check) {
break;
}
@@ -1869,9 +2001,13 @@
/* Lay out column */
for (p = icons; p != NULL; p = p->next) {
icon = p->data;
- icon_get_bounding_box_for_layout (icon, &x1, &y1, &x2, &y2);
+ icon_get_bounding_box (icon, &x1, &y1, &x2, &y2,
+ BOUNDS_USAGE_FOR_LAYOUT);
+ icon_get_bounding_box (icon, NULL, NULL, NULL, &y2_for_bound_check,
+ BOUNDS_USAGE_FOR_ENTIRE_ITEM);
icon_height = y2 - y1;
+ icon_height_for_bound_check = y2_for_bound_check - y1;
icon_rect = nautilus_icon_canvas_item_get_icon_rectangle (icon->item);
@@ -1882,7 +2018,7 @@
}
/* Check and see if we need to move to a new column */
- if (y != DESKTOP_PAD_VERTICAL && y > height - icon_height &&
+ if (y != DESKTOP_PAD_VERTICAL && y > height - icon_height_for_bound_check &&
/* Make sure we lay out at least one icon per column, to make progress */
p != icons) {
x += column_width + DESKTOP_PAD_HORIZONTAL;
@@ -6668,7 +6804,7 @@
g_assert (!container->details->auto_layout);
sort_icons (container, &no_position_icons);
- get_all_icon_bounds (container, NULL, NULL, NULL, &bottom);
+ get_all_icon_bounds (container, NULL, NULL, NULL, &bottom, BOUNDS_USAGE_FOR_LAYOUT);
lay_down_icons (container, no_position_icons, bottom + ICON_PAD_BOTTOM);
g_list_free (no_position_icons);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]