Re: [PATCH] Icon view RTL layout



Am Freitag, den 03.03.2006, 18:17 +0100 schrieb Alexander Larsson:
> On Fri, 2006-03-03 at 15:56 +0100, Christian Neumair wrote:
> 
> > My first thought was: Well, let's calc. the width needed by the layout
> > and shift the final text position to the right by (max_width -
> > layout_width). This seemed to work totally fine, until I discovered what
> > happens when you mix RTL and LTR layouts. You may well up with something
> > like:
> > 
> > [                         alephbeth ]
> > [ somemorelatintext                 ]
> > 
> > So a simple offset will break your layout. A PangoLayout with a width of
> > max_width will never be appropriate for arbitrary mixtures of LTR/RTL,
> > because sometimes you just can't get the offset right.
> 
> I'm not sure what exactly the problem is here. Lets use some concrete
> examples. Say upper case is RTL and lower case is LTR, the main
> direction is RTL, and the max width is this:
> [            ]
> 
> Lets start with some simple string that fits in max-width: "ABC abc",
> "ABC", and "abc". These should be layed out as:
> [     abc CBA]
> 
> [         abc]
> 
> [         CBA]
> 
> This is not a problem. We set the max width, get the pixel width and we
> shift the layout by max-text-width - pixel_width.
> 
> With longer strings, like "abcd efgh ijkl mnop", "ABCD EFGH IJKL MNOP",
> "ABCD efgh ijkl MNOP" we get:
> 
> [   abcd efgh]
> [   ijkl mnop]
> 
> [   HGFE DCBA]
> [   PONM LKJI]
> 
> [   efgh DCBA]
> [   PONM ijkl]
> 
> For all these we can also just take max-text-width - pixel-width and
> shift the layout by it.
> 
> Can you give an example string in this "language" where this method
> would not work?

When you consider multiple paragraphs, they can independently be either
RTL or LTR, so a layout like

[      LTRLTRLTR ]
[ RTL            ]

is possible, i.e. there is one base directions for each of the
paragraphs. This could only be relevant if there are paragraph
separation characters in the layout - I don't know the RTL semantics.

I'm attaching a new patch which addresses your performance concerns by
setting the layout to single-paragraph mode, adapting its alignment,
calculating the base direction and adding an offset based on this data.
I hope the switch statements don't look too clumsy, I don't think
separating them out into an own helper buys us much.

-- 
Christian Neumair <chris gnome-de org>
Index: libnautilus-private/nautilus-icon-canvas-item.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-icon-canvas-item.c,v
retrieving revision 1.197
diff -u -p -r1.197 nautilus-icon-canvas-item.c
--- libnautilus-private/nautilus-icon-canvas-item.c	3 Mar 2006 13:34:54 -0000	1.197
+++ libnautilus-private/nautilus-icon-canvas-item.c	4 Mar 2006 09:56:54 -0000
@@ -105,6 +105,8 @@ struct NautilusIconCanvasItemDetails {
 	
 	PangoLayout *editable_text_layout;
 	PangoLayout *additional_text_layout;
+	PangoDirection editable_text_dir;
+	PangoDirection additional_text_dir;
 	
 	GdkRectangle embedded_text_rect;
 	PangoLayout *embedded_text_layout;
@@ -198,6 +200,7 @@ static void     draw_mask               
 						      int                            x,
 						      int                            y);
 static PangoLayout *get_label_layout                 (PangoLayout                  **layout,
+						      PangoDirection                *dir,
 						      NautilusIconCanvasItem        *item,
 						      const char                    *text);
 static void     draw_label_layout                    (NautilusIconCanvasItem        *item,
@@ -942,7 +945,7 @@ draw_or_measure_label_text (NautilusIcon
 	int icon_width;
 	gboolean have_editable, have_additional, needs_highlight, needs_frame;
 	int max_text_width;
-	int x;
+	int x_additional, x_editable;
 	GdkGC *gc;
 	ArtIRect text_rect;
 	int text_back_padding_x, text_back_padding_y;
@@ -1002,7 +1005,9 @@ draw_or_measure_label_text (NautilusIcon
 	additional_layout = NULL;
 
 	if (have_editable) {
-		editable_layout = get_label_layout (&details->editable_text_layout, item, details->editable_text);
+		editable_layout = get_label_layout (&details->editable_text_layout,
+						    &details->editable_text_dir,
+						    item, details->editable_text);
 		
 		pango_layout_get_pixel_size (editable_layout, 
 					     &editable_width,
@@ -1010,7 +1015,9 @@ draw_or_measure_label_text (NautilusIcon
 	}
 
 	if (have_additional) {
-		additional_layout = get_label_layout (&details->additional_text_layout, item, details->additional_text);
+		additional_layout = get_label_layout (&details->additional_text_layout,
+						      &details->additional_text_dir,
+						      item, details->additional_text);
 
 		pango_layout_get_pixel_size (additional_layout, 
 					     &additional_width,
@@ -1066,14 +1073,39 @@ draw_or_measure_label_text (NautilusIcon
 			    text_rect.y1 - text_rect.y0);
 	}
 
-		
-	if (container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE) {
-		x = text_rect.x0 + 2;
-	} else {
-		x = text_rect.x0 + ((text_rect.x1 - text_rect.x0) - max_text_width) / 2;
+	x_additional = x_editable = 0;
+
+	if (container->details->label_position != NAUTILUS_ICON_LABEL_POSITION_BESIDE) {
+		x_additional = x_editable = text_rect.x0 + ((text_rect.x1 - text_rect.x0) - max_text_width) / 2;
 	}
 	
 	if (have_editable) {
+		if (container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE) {
+			switch (details->editable_text_dir) {
+				case PANGO_DIRECTION_LTR:
+				case PANGO_DIRECTION_TTB_LTR:
+				case PANGO_DIRECTION_WEAK_LTR:
+					x_editable = text_rect.x0 + text_back_padding_x;
+					break;
+
+				case PANGO_DIRECTION_RTL:
+				case PANGO_DIRECTION_TTB_RTL:
+				case PANGO_DIRECTION_WEAK_RTL:
+					x_editable = text_rect.x0 + MAX (editable_width, additional_width)
+								  - max_text_width + text_back_padding_x;
+					break;
+				case PANGO_DIRECTION_NEUTRAL:
+				default:
+					if (gtk_widget_get_direction (GTK_WIDGET (container)) == GTK_TEXT_DIR_LTR) {
+						x_editable = text_rect.x0 + text_back_padding_x;
+					} else {
+						x_editable = text_rect.x0 + MAX (editable_width, additional_width)
+									  - max_text_width + text_back_padding_x;
+					}
+					break;
+			}
+		}
+
 		gtk_widget_style_get (GTK_WIDGET (container),
 				      "frame_text", &needs_frame,
 				      NULL);
@@ -1095,11 +1127,37 @@ draw_or_measure_label_text (NautilusIcon
 		draw_label_layout (item, drawable,
 				   editable_layout, needs_highlight,
 				   label_color,
-				   x,
+				   x_editable,
 				   text_rect.y0 + text_back_padding_y, gc);
 	}
 
 	if (have_additional) {
+		if (container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE) {
+			switch (details->additional_text_dir) {
+				case PANGO_DIRECTION_LTR:
+				case PANGO_DIRECTION_TTB_LTR:
+				case PANGO_DIRECTION_WEAK_LTR:
+					x_additional = text_rect.x0 + text_back_padding_x;
+					break;
+
+				case PANGO_DIRECTION_RTL:
+				case PANGO_DIRECTION_TTB_RTL:
+				case PANGO_DIRECTION_WEAK_RTL:
+					x_additional = text_rect.x0 + MAX (additional_width, additional_width)
+								  - max_text_width + text_back_padding_x;
+					break;
+				case PANGO_DIRECTION_NEUTRAL:
+				default:
+					if (gtk_widget_get_direction (GTK_WIDGET (container)) == GTK_TEXT_DIR_LTR) {
+						x_additional = text_rect.x0 + text_back_padding_x;
+					} else {
+						x_additional = text_rect.x0 + MAX (additional_width, additional_width)
+									  - max_text_width + text_back_padding_x;
+					}
+					break;
+			}
+		}
+
 		gc = nautilus_icon_container_get_label_color_and_gc
 			(NAUTILUS_ICON_CONTAINER (canvas_item->canvas),
 			 &label_color, FALSE, needs_highlight);
@@ -1107,7 +1165,7 @@ draw_or_measure_label_text (NautilusIcon
 		draw_label_layout (item, drawable,
 				   additional_layout, needs_highlight,
 				   label_color,
-				   x,
+				   x_additional,
 				   text_rect.y0 + editable_height + LABEL_LINE_SPACING + text_back_padding_y, gc);
 	}
 
@@ -1638,13 +1696,18 @@ create_label_layout (NautilusIconCanvasI
 	pango_layout_set_width (layout, floor (nautilus_icon_canvas_item_get_max_text_width (item)) * PANGO_SCALE);
 			
 	if (container->details->label_position == NAUTILUS_ICON_LABEL_POSITION_BESIDE) {
-		pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT);
+		if (gtk_widget_get_direction (GTK_WIDGET (container)) == GTK_TEXT_DIR_LTR) {
+			pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT);
+		} else {
+			pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT);
+		}
 	} else {
 		pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
 	}
 
 	pango_layout_set_spacing (layout, LABEL_LINE_SPACING);
 	pango_layout_set_wrap (layout, PANGO_WRAP_WORD_CHAR);
+	pango_layout_set_single_paragraph_mode (layout, TRUE);
 
 	/* Create a font description */
 	if (container->details->font) {
@@ -1664,11 +1727,13 @@ create_label_layout (NautilusIconCanvasI
 
 static PangoLayout *
 get_label_layout (PangoLayout **layout,
+		  PangoDirection *dir,
 		  NautilusIconCanvasItem *item,
 		  const char *text)
 {
 	if (*layout == NULL) {
 		*layout = create_label_layout (item, text);
+		*dir = pango_find_base_dir (text, -1);
 	}
 	
 	g_object_ref (*layout);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]