Merge lp:~jeremywootten/pantheon-files/fix-focus-clipping-in-icon-view into lp:~elementary-apps/pantheon-files/trunk

Proposed by Jeremy Wootten
Status: Merged
Approved by: Danielle Foré
Approved revision: 2474
Merged at revision: 2581
Proposed branch: lp:~jeremywootten/pantheon-files/fix-focus-clipping-in-icon-view
Merge into: lp:~elementary-apps/pantheon-files/trunk
Diff against target: 280 lines (+106/-63)
3 files modified
src/TextRenderer.vala (+97/-55)
src/View/AbstractDirectoryView.vala (+0/-1)
src/View/IconView.vala (+9/-7)
To merge this branch: bzr merge lp:~jeremywootten/pantheon-files/fix-focus-clipping-in-icon-view
Reviewer Review Type Date Requested Status
Zisu Andrei (community) Approve
Danielle Foré Abstain
Review via email: mp+316409@code.launchpad.net

Commit message

fixes visual glitches in the text rendering:
* clipping of the focus rectangle in icon view
* Incorrect alignment in ListView with RTL language
* Reduce excess vertical spacing of icons with short names

Description of the change

This branch builds on lp:~jeremywootten/pantheon-files/fix-1658417-long-name-in-grid-view, (now merged).

It fixes some visual glitches in the text rendering:

1) clipping of the focus/color rectangle in icon view at some zoom levels/name lengths.
2) Incorrect alignment in ListView with RTL language

It also reduces the excess vertical spacing of icons with short names.

To post a comment you must log in.
Revision history for this message
Danielle Foré (danrabbit) wrote :

Looks like this branch has merge conflicts

review: Needs Fixing
2467. By Jeremy Wootten

Merge trunk to r 2556 and resolve conflicts

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

Trunk merged to r2556 and conflicts resolved.

2468. By Jeremy Wootten

Merge trunk to r2563

2469. By Jeremy Wootten

Ensure no clipping, improve centering with LTR and RTL

Revision history for this message
Dieter Debast (ddieter) wrote :

Issue #1405853 also says that clicking on the whitespace (when the file is highlighted) doesn't select the file/folder, but this isn't fixed in this branch (maybe this can be put into a separate issue?). Dragging a selection box over this whitespace does seem to work.

Revision history for this message
Danielle Foré (danrabbit) wrote :

Changing my review to "abstain" so that it doesn't appear to need fixing on my account

review: Abstain
Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

Dieter: I have removed the second, unconnected issue from #1405853 and asked the reported to refile that as a separate bug. So this branch is only intended to fix the excess whitespace and clipping issues.

Revision history for this message
Zisu Andrei (matzipan) wrote :

Some feedback. I confirm it fixes the rounded corners issue. And I confirm there is a reduction of the "excess spacing"

review: Needs Fixing
Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

See replies to inline comments. Will address the code style issues.

2470. By Jeremy Wootten

Uncapitalize BORDER_RADIUS

2471. By Jeremy Wootten

Insert missing brackets

2472. By Jeremy Wootten

Remove superfluous brackets

2473. By Jeremy Wootten

Merge trunk to r2578

Revision history for this message
Zisu Andrei (matzipan) wrote :

As discussed on slack, perhaps the line below should be a comment in the code, to clarify:
> To ensure the focus_rect is at least one pixel smaller than cell_area on each side. Helps prevent clipping.

Other than that. LGTM.

review: Approve
2474. By Jeremy Wootten

Add comment

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/TextRenderer.vala'
--- src/TextRenderer.vala 2017-02-15 18:54:50 +0000
+++ src/TextRenderer.vala 2017-06-13 16:37:16 +0000
@@ -20,18 +20,35 @@
20 public class TextRenderer: Gtk.CellRendererText {20 public class TextRenderer: Gtk.CellRendererText {
2121
22 const int MAX_LINES = 5;22 const int MAX_LINES = 5;
23 const uint BORDER_RADIUS = 6;23 private int border_radius = 6;
2424
25 public Marlin.ZoomLevel zoom_level {get; set;}25 public Marlin.ZoomLevel zoom_level {get; set;}
26 public bool follow_state {get; set;}
27 public new string background { set; private get;}26 public new string background { set; private get;}
28 public GOF.File? file {set; private get;}27 public GOF.File? file {set; private get;}
28 private int _item_width;
29 public int item_width {
30 set {
31 _item_width = value;
32 if (xalign == 0.5) {
33 wrap_width = _item_width - 2 * (focus_border_width + (int)xpad + border_radius);
34 } else {
35 wrap_width = -1;
36 }
37
38 border_radius = 5 + wrap_width / 40;
39 }
40
41 private get {
42 return _item_width;
43 }
44 }
45
29 public int text_width;46 public int text_width;
30 public int text_height;47 public int text_height;
3148
32 int char_width;
33 int char_height;49 int char_height;
34 int focus_border_width;50 int focus_border_width;
51
35 Pango.Layout layout;52 Pango.Layout layout;
36 Gtk.Widget widget;53 Gtk.Widget widget;
37 Marlin.AbstractEditableLabel entry;54 Marlin.AbstractEditableLabel entry;
@@ -81,19 +98,29 @@
81 style_context.save ();98 style_context.save ();
82 style_context.set_state (state);99 style_context.set_state (state);
83100
84 if (follow_state || background != null)101 int x_offset, y_offset, focus_rect_width, focus_rect_height;
85 draw_focus (cr, cell_area, flags, style_context, state);102 draw_focus (cr, cell_area, flags, style_context, state, out x_offset, out y_offset,
86103 out focus_rect_width, out focus_rect_height);
87 int x_offset, y_offset;104
88 get_offsets (cell_area, text_width, text_height, xalign, out x_offset, out y_offset);105 /* Position text relative to the focus rectangle */
89106 if (xalign == 0.5f) {
90 /* Adjust text offsets for best appearance in each view */107 x_offset = (cell_area.width - wrap_width) / 2;
91 if (xalign == 0.5f) { /* Icon view */108
92 x_offset = (cell_area.width - this.wrap_width) / 2;109 if (widget.get_direction () == Gtk.TextDirection.RTL) {
93 y_offset += focus_border_width + (int)ypad;110 x_offset -= focus_border_width;
111 } else {
112 x_offset += focus_border_width;
113 }
114
115 y_offset += (focus_rect_height - text_height) / 2;
94 } else {116 } else {
95 x_offset += focus_border_width + 2 * (int)xpad;117 y_offset = (cell_area.height - char_height) / 2;
96 y_offset += focus_border_width;118
119 if (widget.get_direction () == Gtk.TextDirection.RTL) {
120 x_offset += (focus_rect_width - text_width) - focus_border_width * 4;
121 } else {
122 x_offset += focus_border_width * 2 + (int)xpad;
123 }
97 }124 }
98125
99 style_context.render_layout (cr,126 style_context.render_layout (cr,
@@ -189,8 +216,6 @@
189 private void set_widget (Gtk.Widget? _widget) {216 private void set_widget (Gtk.Widget? _widget) {
190 Pango.FontMetrics metrics;217 Pango.FontMetrics metrics;
191 Pango.Context context;218 Pango.Context context;
192 int focus_padding;
193 int focus_line_width;
194219
195 if (_widget == widget)220 if (_widget == widget)
196 return;221 return;
@@ -208,16 +233,19 @@
208 layout.set_auto_dir (false);233 layout.set_auto_dir (false);
209 layout.set_single_paragraph_mode (true);234 layout.set_single_paragraph_mode (true);
210 metrics = context.get_metrics (layout.get_font_description (), context.get_language ());235 metrics = context.get_metrics (layout.get_font_description (), context.get_language ());
211 char_width = (metrics.get_approximate_char_width () + 512 ) >> 10;
212 char_height = (metrics.get_ascent () + metrics.get_descent () + 512) >> 10;236 char_height = (metrics.get_ascent () + metrics.get_descent () + 512) >> 10;
213 if (wrap_width < 0)237
238 if (wrap_width < 0) {
214 (this as Gtk.CellRenderer).set_fixed_size (-1, char_height);239 (this as Gtk.CellRenderer).set_fixed_size (-1, char_height);
240 }
215241
242 int focus_padding;
243 int focus_line_width;
216 widget.style_get ("focus-padding", out focus_padding, "focus-line-width", out focus_line_width);244 widget.style_get ("focus-padding", out focus_padding, "focus-line-width", out focus_line_width);
217 focus_border_width = int.max (focus_padding + focus_line_width, 2);245 focus_border_width = int.max (focus_padding + focus_line_width, 2);
246
218 } else {247 } else {
219 layout = null;248 layout = null;
220 char_width = 0;
221 char_height = 0;249 char_height = 0;
222 }250 }
223 }251 }
@@ -256,40 +284,49 @@
256 Gdk.Rectangle cell_area,284 Gdk.Rectangle cell_area,
257 Gtk.CellRendererState flags,285 Gtk.CellRendererState flags,
258 Gtk.StyleContext style_context,286 Gtk.StyleContext style_context,
259 Gtk.StateFlags state) {287 Gtk.StateFlags state,
288 out int x_offset,
289 out int y_offset,
290 out int focus_rect_width,
291 out int focus_rect_height) {
292
260 bool selected = false;293 bool selected = false;
261 float x;294 focus_rect_width = 0;
262 int x_offset, y_offset, focus_rect_width, focus_rect_height;295 focus_rect_height = 0;
263296 x_offset = 0;
264 if (follow_state)297 y_offset = 0;
265 selected = ((flags & Gtk.CellRendererState.SELECTED) == Gtk.CellRendererState.SELECTED);298
266299 selected = ((flags & Gtk.CellRendererState.SELECTED) == Gtk.CellRendererState.SELECTED);
267 focus_rect_width = text_width + 4 * this.focus_border_width;300
268 focus_rect_height = text_height + 2 * this.focus_border_width;301 focus_rect_height = text_height + 2 * (this.focus_border_width + border_radius);
269302 focus_rect_width = text_width + 4 * (this.focus_border_width + border_radius);
270 if (widget.get_direction () == Gtk.TextDirection.RTL)303
271 x = 1.0f - xalign;304 /* Ensure that focus_rect is at least one pixel small than cell_area on each side */
272 else305 focus_rect_width = int.min (focus_rect_width, cell_area.width - 2);
273 x = xalign;306 focus_rect_height = int.min (focus_rect_height, cell_area.height -2);
274307
275 get_offsets (cell_area, focus_rect_width, focus_rect_height, x, out x_offset, out y_offset);308 get_offsets (cell_area, focus_rect_width, focus_rect_height, out x_offset, out y_offset);
309
310
276311
277 /* render the background if selected or colorized */312 /* render the background if selected or colorized */
278 if (selected || this.background != null) {313 if (selected || this.background != null) {
279 int x0 = cell_area.x + x_offset + (int)xpad;314 int x0 = cell_area.x + x_offset;
280 int y0 = cell_area.y + y_offset + (int)ypad;315 int y0 = cell_area.y + y_offset;
281 int x1 = x0 + focus_rect_width;316 int x1 = x0 + focus_rect_width;
282 int y1 = y0 + focus_rect_height;317 int y1 = y0 + focus_rect_height;
283318 if (x1 >= cell_area.x + cell_area.width) {
284 cr.move_to (x0 + BORDER_RADIUS, y0);319 x1 = cell_area.x + cell_area.width - 1;
285 cr.line_to (x1 - BORDER_RADIUS, y0);320 }
286 cr.curve_to (x1 - BORDER_RADIUS, y0, x1, y0, x1, y0 + BORDER_RADIUS);321 cr.move_to (x0 + border_radius, y0);
287 cr.line_to (x1, y1 - BORDER_RADIUS);322 cr.line_to (x1 - border_radius, y0);
288 cr.curve_to (x1, y1 - BORDER_RADIUS, x1, y1, x1 - BORDER_RADIUS, y1);323 cr.curve_to (x1 - border_radius, y0, x1, y0, x1, y0 + border_radius);
289 cr.line_to (x0 + BORDER_RADIUS, y1);324 cr.line_to (x1, y1 - border_radius);
290 cr.curve_to (x0 + BORDER_RADIUS, y1, x0, y1, x0, y1 - BORDER_RADIUS);325 cr.curve_to (x1, y1 - border_radius, x1, y1, x1 - border_radius, y1);
291 cr.line_to (x0, y0 + BORDER_RADIUS);326 cr.line_to (x0 + border_radius, y1);
292 cr.curve_to (x0, y0 + BORDER_RADIUS, x0, y0, x0 + BORDER_RADIUS, y0);327 cr.curve_to (x0 + border_radius, y1, x0, y1, x0, y1 - border_radius);
328 cr.line_to (x0, y0 + border_radius);
329 cr.curve_to (x0, y0 + border_radius, x0, y0, x0 + border_radius, y0);
293330
294 Gdk.RGBA color ={};331 Gdk.RGBA color ={};
295 if (background != null && !selected) {332 if (background != null && !selected) {
@@ -304,25 +341,30 @@
304 cr.fill ();341 cr.fill ();
305 }342 }
306 /* draw the focus indicator */343 /* draw the focus indicator */
307 if (follow_state && (flags & Gtk.CellRendererState.FOCUSED) != 0)344 if ((flags & Gtk.CellRendererState.FOCUSED) != 0) {
308 style_context.render_focus (cr,345 style_context.render_focus (cr,
309 cell_area.x + x_offset,346 cell_area.x + x_offset,
310 cell_area.y + y_offset,347 cell_area.y + y_offset,
311 focus_rect_width,348 focus_rect_width,
312 focus_rect_height);349 focus_rect_height);
350 }
313 }351 }
314352
315 private void get_offsets (Gdk.Rectangle cell_area,353 private void get_offsets (Gdk.Rectangle cell_area,
316 int width,354 int width,
317 int height,355 int height,
318 float x,
319 out int x_offset,356 out int x_offset,
320 out int y_offset) {357 out int y_offset) {
321 x_offset = (int)(x * (cell_area.width - width - 2 * (int)xpad));358
322 x_offset = int.max (x_offset, 0);359 if (widget.get_direction () == Gtk.TextDirection.RTL) {
323360 x_offset = (int)((1.0f - xalign) * (cell_area.width - width));
324 y_offset = (int)(yalign * (cell_area.height - height - 2 * (int)ypad));361 x_offset -= (int)xpad;
325 y_offset = int.max (y_offset, 0);362 } else {
363 x_offset = (int)(xalign * (cell_area.width - width));
364 x_offset += (int)xpad;
365 }
366
367 y_offset = (int)(yalign * (cell_area.height - height));
326 }368 }
327 }369 }
328}370}
329371
=== modified file 'src/View/AbstractDirectoryView.vala'
--- src/View/AbstractDirectoryView.vala 2017-06-06 09:00:33 +0000
+++ src/View/AbstractDirectoryView.vala 2017-06-13 16:37:16 +0000
@@ -352,7 +352,6 @@
352352
353 protected virtual void set_up_name_renderer () {353 protected virtual void set_up_name_renderer () {
354 name_renderer.editable = false;354 name_renderer.editable = false;
355 name_renderer.follow_state = true;
356 name_renderer.edited.connect (on_name_edited);355 name_renderer.edited.connect (on_name_edited);
357 name_renderer.editing_canceled.connect (on_name_editing_canceled);356 name_renderer.editing_canceled.connect (on_name_editing_canceled);
358 name_renderer.editing_started.connect (on_name_editing_started);357 name_renderer.editing_started.connect (on_name_editing_started);
359358
=== modified file 'src/View/IconView.vala'
--- src/View/IconView.vala 2017-06-05 14:48:38 +0000
+++ src/View/IconView.vala 2017-06-13 16:37:16 +0000
@@ -34,6 +34,7 @@
34 tree.set_selection_mode (Gtk.SelectionMode.MULTIPLE);34 tree.set_selection_mode (Gtk.SelectionMode.MULTIPLE);
35 tree.set_columns (-1);35 tree.set_columns (-1);
36 tree.set_reorderable (false);36 tree.set_reorderable (false);
37 tree.set_item_padding (3);
3738
38 name_renderer = new Marlin.TextRenderer (Marlin.ViewMode.ICON);39 name_renderer = new Marlin.TextRenderer (Marlin.ViewMode.ICON);
39 set_up_name_renderer ();40 set_up_name_renderer ();
@@ -106,15 +107,16 @@
106 }107 }
107108
108 public override void change_zoom_level () {109 public override void change_zoom_level () {
110 int spacing = (int)((double)icon_size * (0.3 - zoom_level * 0.03));
111 int item_width = (int)((double)icon_size * (2.5 - zoom_level * 0.2));
109 if (tree != null) {112 if (tree != null) {
110 tree.set_column_spacing ((int)((double)icon_size * (0.3 - zoom_level * 0.03)));113 tree.set_column_spacing (spacing);
111 tree.set_item_width ((int)((double)icon_size * (2.5 - zoom_level * 0.2)));114 tree.set_item_width (item_width);
112
113 name_renderer.set_property ("wrap-width", tree.get_item_width ());
114 name_renderer.set_property ("zoom-level", zoom_level);
115
116 base.change_zoom_level ();
117 }115 }
116 name_renderer.item_width = item_width;
117 name_renderer.set_property ("zoom-level", zoom_level);
118
119 base.change_zoom_level ();
118 }120 }
119121
120 public override GLib.List<Gtk.TreePath> get_selected_paths () {122 public override GLib.List<Gtk.TreePath> get_selected_paths () {

Subscribers

People subscribed via source and target branches

to all changes: