Merge lp:~jeremywootten/pantheon-files/fix-focus-clipping-in-icon-view into lp:~elementary-apps/pantheon-files/trunk
- fix-focus-clipping-in-icon-view
- Merge into trunk
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 | ||||||||
Related bugs: |
|
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.
- 2467. By Jeremy Wootten
-
Merge trunk to r 2556 and resolve conflicts
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
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.
Danielle Foré (danrabbit) wrote : | # |
Changing my review to "abstain" so that it doesn't appear to need fixing on my account
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.
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"
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
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.
- 2474. By Jeremy Wootten
-
Add comment
Preview Diff
1 | === modified file 'src/TextRenderer.vala' | |||
2 | --- src/TextRenderer.vala 2017-02-15 18:54:50 +0000 | |||
3 | +++ src/TextRenderer.vala 2017-06-13 16:37:16 +0000 | |||
4 | @@ -20,18 +20,35 @@ | |||
5 | 20 | public class TextRenderer: Gtk.CellRendererText { | 20 | public class TextRenderer: Gtk.CellRendererText { |
6 | 21 | 21 | ||
7 | 22 | const int MAX_LINES = 5; | 22 | const int MAX_LINES = 5; |
9 | 23 | const uint BORDER_RADIUS = 6; | 23 | private int border_radius = 6; |
10 | 24 | 24 | ||
11 | 25 | public Marlin.ZoomLevel zoom_level {get; set;} | 25 | public Marlin.ZoomLevel zoom_level {get; set;} |
12 | 26 | public bool follow_state {get; set;} | ||
13 | 27 | public new string background { set; private get;} | 26 | public new string background { set; private get;} |
14 | 28 | public GOF.File? file {set; private get;} | 27 | public GOF.File? file {set; private get;} |
15 | 28 | private int _item_width; | ||
16 | 29 | public int item_width { | ||
17 | 30 | set { | ||
18 | 31 | _item_width = value; | ||
19 | 32 | if (xalign == 0.5) { | ||
20 | 33 | wrap_width = _item_width - 2 * (focus_border_width + (int)xpad + border_radius); | ||
21 | 34 | } else { | ||
22 | 35 | wrap_width = -1; | ||
23 | 36 | } | ||
24 | 37 | |||
25 | 38 | border_radius = 5 + wrap_width / 40; | ||
26 | 39 | } | ||
27 | 40 | |||
28 | 41 | private get { | ||
29 | 42 | return _item_width; | ||
30 | 43 | } | ||
31 | 44 | } | ||
32 | 45 | |||
33 | 29 | public int text_width; | 46 | public int text_width; |
34 | 30 | public int text_height; | 47 | public int text_height; |
35 | 31 | 48 | ||
36 | 32 | int char_width; | ||
37 | 33 | int char_height; | 49 | int char_height; |
38 | 34 | int focus_border_width; | 50 | int focus_border_width; |
39 | 51 | |||
40 | 35 | Pango.Layout layout; | 52 | Pango.Layout layout; |
41 | 36 | Gtk.Widget widget; | 53 | Gtk.Widget widget; |
42 | 37 | Marlin.AbstractEditableLabel entry; | 54 | Marlin.AbstractEditableLabel entry; |
43 | @@ -81,19 +98,29 @@ | |||
44 | 81 | style_context.save (); | 98 | style_context.save (); |
45 | 82 | style_context.set_state (state); | 99 | style_context.set_state (state); |
46 | 83 | 100 | ||
57 | 84 | if (follow_state || background != null) | 101 | int x_offset, y_offset, focus_rect_width, focus_rect_height; |
58 | 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, |
59 | 86 | 103 | out focus_rect_width, out focus_rect_height); | |
60 | 87 | int x_offset, y_offset; | 104 | |
61 | 88 | get_offsets (cell_area, text_width, text_height, xalign, out x_offset, out y_offset); | 105 | /* Position text relative to the focus rectangle */ |
62 | 89 | 106 | if (xalign == 0.5f) { | |
63 | 90 | /* Adjust text offsets for best appearance in each view */ | 107 | x_offset = (cell_area.width - wrap_width) / 2; |
64 | 91 | if (xalign == 0.5f) { /* Icon view */ | 108 | |
65 | 92 | x_offset = (cell_area.width - this.wrap_width) / 2; | 109 | if (widget.get_direction () == Gtk.TextDirection.RTL) { |
66 | 93 | y_offset += focus_border_width + (int)ypad; | 110 | x_offset -= focus_border_width; |
67 | 111 | } else { | ||
68 | 112 | x_offset += focus_border_width; | ||
69 | 113 | } | ||
70 | 114 | |||
71 | 115 | y_offset += (focus_rect_height - text_height) / 2; | ||
72 | 94 | } else { | 116 | } else { |
75 | 95 | x_offset += focus_border_width + 2 * (int)xpad; | 117 | y_offset = (cell_area.height - char_height) / 2; |
76 | 96 | y_offset += focus_border_width; | 118 | |
77 | 119 | if (widget.get_direction () == Gtk.TextDirection.RTL) { | ||
78 | 120 | x_offset += (focus_rect_width - text_width) - focus_border_width * 4; | ||
79 | 121 | } else { | ||
80 | 122 | x_offset += focus_border_width * 2 + (int)xpad; | ||
81 | 123 | } | ||
82 | 97 | } | 124 | } |
83 | 98 | 125 | ||
84 | 99 | style_context.render_layout (cr, | 126 | style_context.render_layout (cr, |
85 | @@ -189,8 +216,6 @@ | |||
86 | 189 | private void set_widget (Gtk.Widget? _widget) { | 216 | private void set_widget (Gtk.Widget? _widget) { |
87 | 190 | Pango.FontMetrics metrics; | 217 | Pango.FontMetrics metrics; |
88 | 191 | Pango.Context context; | 218 | Pango.Context context; |
89 | 192 | int focus_padding; | ||
90 | 193 | int focus_line_width; | ||
91 | 194 | 219 | ||
92 | 195 | if (_widget == widget) | 220 | if (_widget == widget) |
93 | 196 | return; | 221 | return; |
94 | @@ -208,16 +233,19 @@ | |||
95 | 208 | layout.set_auto_dir (false); | 233 | layout.set_auto_dir (false); |
96 | 209 | layout.set_single_paragraph_mode (true); | 234 | layout.set_single_paragraph_mode (true); |
97 | 210 | metrics = context.get_metrics (layout.get_font_description (), context.get_language ()); | 235 | metrics = context.get_metrics (layout.get_font_description (), context.get_language ()); |
98 | 211 | char_width = (metrics.get_approximate_char_width () + 512 ) >> 10; | ||
99 | 212 | char_height = (metrics.get_ascent () + metrics.get_descent () + 512) >> 10; | 236 | char_height = (metrics.get_ascent () + metrics.get_descent () + 512) >> 10; |
101 | 213 | if (wrap_width < 0) | 237 | |
102 | 238 | if (wrap_width < 0) { | ||
103 | 214 | (this as Gtk.CellRenderer).set_fixed_size (-1, char_height); | 239 | (this as Gtk.CellRenderer).set_fixed_size (-1, char_height); |
104 | 240 | } | ||
105 | 215 | 241 | ||
106 | 242 | int focus_padding; | ||
107 | 243 | int focus_line_width; | ||
108 | 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); |
109 | 217 | focus_border_width = int.max (focus_padding + focus_line_width, 2); | 245 | focus_border_width = int.max (focus_padding + focus_line_width, 2); |
110 | 246 | |||
111 | 218 | } else { | 247 | } else { |
112 | 219 | layout = null; | 248 | layout = null; |
113 | 220 | char_width = 0; | ||
114 | 221 | char_height = 0; | 249 | char_height = 0; |
115 | 222 | } | 250 | } |
116 | 223 | } | 251 | } |
117 | @@ -256,40 +284,49 @@ | |||
118 | 256 | Gdk.Rectangle cell_area, | 284 | Gdk.Rectangle cell_area, |
119 | 257 | Gtk.CellRendererState flags, | 285 | Gtk.CellRendererState flags, |
120 | 258 | Gtk.StyleContext style_context, | 286 | Gtk.StyleContext style_context, |
122 | 259 | Gtk.StateFlags state) { | 287 | Gtk.StateFlags state, |
123 | 288 | out int x_offset, | ||
124 | 289 | out int y_offset, | ||
125 | 290 | out int focus_rect_width, | ||
126 | 291 | out int focus_rect_height) { | ||
127 | 292 | |||
128 | 260 | bool selected = false; | 293 | bool selected = false; |
144 | 261 | float x; | 294 | focus_rect_width = 0; |
145 | 262 | int x_offset, y_offset, focus_rect_width, focus_rect_height; | 295 | focus_rect_height = 0; |
146 | 263 | 296 | x_offset = 0; | |
147 | 264 | if (follow_state) | 297 | y_offset = 0; |
148 | 265 | selected = ((flags & Gtk.CellRendererState.SELECTED) == Gtk.CellRendererState.SELECTED); | 298 | |
149 | 266 | 299 | selected = ((flags & Gtk.CellRendererState.SELECTED) == Gtk.CellRendererState.SELECTED); | |
150 | 267 | focus_rect_width = text_width + 4 * this.focus_border_width; | 300 | |
151 | 268 | focus_rect_height = text_height + 2 * this.focus_border_width; | 301 | focus_rect_height = text_height + 2 * (this.focus_border_width + border_radius); |
152 | 269 | 302 | focus_rect_width = text_width + 4 * (this.focus_border_width + border_radius); | |
153 | 270 | if (widget.get_direction () == Gtk.TextDirection.RTL) | 303 | |
154 | 271 | x = 1.0f - xalign; | 304 | /* Ensure that focus_rect is at least one pixel small than cell_area on each side */ |
155 | 272 | else | 305 | focus_rect_width = int.min (focus_rect_width, cell_area.width - 2); |
156 | 273 | x = xalign; | 306 | focus_rect_height = int.min (focus_rect_height, cell_area.height -2); |
157 | 274 | 307 | ||
158 | 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); |
159 | 309 | |||
160 | 310 | |||
161 | 276 | 311 | ||
162 | 277 | /* render the background if selected or colorized */ | 312 | /* render the background if selected or colorized */ |
163 | 278 | if (selected || this.background != null) { | 313 | if (selected || this.background != null) { |
166 | 279 | int x0 = cell_area.x + x_offset + (int)xpad; | 314 | int x0 = cell_area.x + x_offset; |
167 | 280 | int y0 = cell_area.y + y_offset + (int)ypad; | 315 | int y0 = cell_area.y + y_offset; |
168 | 281 | int x1 = x0 + focus_rect_width; | 316 | int x1 = x0 + focus_rect_width; |
169 | 282 | int y1 = y0 + focus_rect_height; | 317 | int y1 = y0 + focus_rect_height; |
180 | 283 | 318 | if (x1 >= cell_area.x + cell_area.width) { | |
181 | 284 | cr.move_to (x0 + BORDER_RADIUS, y0); | 319 | x1 = cell_area.x + cell_area.width - 1; |
182 | 285 | cr.line_to (x1 - BORDER_RADIUS, y0); | 320 | } |
183 | 286 | cr.curve_to (x1 - BORDER_RADIUS, y0, x1, y0, x1, y0 + BORDER_RADIUS); | 321 | cr.move_to (x0 + border_radius, y0); |
184 | 287 | cr.line_to (x1, y1 - BORDER_RADIUS); | 322 | cr.line_to (x1 - border_radius, y0); |
185 | 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); |
186 | 289 | cr.line_to (x0 + BORDER_RADIUS, y1); | 324 | cr.line_to (x1, y1 - border_radius); |
187 | 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); |
188 | 291 | cr.line_to (x0, y0 + BORDER_RADIUS); | 326 | cr.line_to (x0 + border_radius, y1); |
189 | 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); |
190 | 328 | cr.line_to (x0, y0 + border_radius); | ||
191 | 329 | cr.curve_to (x0, y0 + border_radius, x0, y0, x0 + border_radius, y0); | ||
192 | 293 | 330 | ||
193 | 294 | Gdk.RGBA color ={}; | 331 | Gdk.RGBA color ={}; |
194 | 295 | if (background != null && !selected) { | 332 | if (background != null && !selected) { |
195 | @@ -304,25 +341,30 @@ | |||
196 | 304 | cr.fill (); | 341 | cr.fill (); |
197 | 305 | } | 342 | } |
198 | 306 | /* draw the focus indicator */ | 343 | /* draw the focus indicator */ |
200 | 307 | if (follow_state && (flags & Gtk.CellRendererState.FOCUSED) != 0) | 344 | if ((flags & Gtk.CellRendererState.FOCUSED) != 0) { |
201 | 308 | style_context.render_focus (cr, | 345 | style_context.render_focus (cr, |
202 | 309 | cell_area.x + x_offset, | 346 | cell_area.x + x_offset, |
203 | 310 | cell_area.y + y_offset, | 347 | cell_area.y + y_offset, |
204 | 311 | focus_rect_width, | 348 | focus_rect_width, |
205 | 312 | focus_rect_height); | 349 | focus_rect_height); |
206 | 350 | } | ||
207 | 313 | } | 351 | } |
208 | 314 | 352 | ||
209 | 315 | private void get_offsets (Gdk.Rectangle cell_area, | 353 | private void get_offsets (Gdk.Rectangle cell_area, |
210 | 316 | int width, | 354 | int width, |
211 | 317 | int height, | 355 | int height, |
212 | 318 | float x, | ||
213 | 319 | out int x_offset, | 356 | out int x_offset, |
214 | 320 | out int y_offset) { | 357 | out int y_offset) { |
220 | 321 | x_offset = (int)(x * (cell_area.width - width - 2 * (int)xpad)); | 358 | |
221 | 322 | x_offset = int.max (x_offset, 0); | 359 | if (widget.get_direction () == Gtk.TextDirection.RTL) { |
222 | 323 | 360 | x_offset = (int)((1.0f - xalign) * (cell_area.width - width)); | |
223 | 324 | y_offset = (int)(yalign * (cell_area.height - height - 2 * (int)ypad)); | 361 | x_offset -= (int)xpad; |
224 | 325 | y_offset = int.max (y_offset, 0); | 362 | } else { |
225 | 363 | x_offset = (int)(xalign * (cell_area.width - width)); | ||
226 | 364 | x_offset += (int)xpad; | ||
227 | 365 | } | ||
228 | 366 | |||
229 | 367 | y_offset = (int)(yalign * (cell_area.height - height)); | ||
230 | 326 | } | 368 | } |
231 | 327 | } | 369 | } |
232 | 328 | } | 370 | } |
233 | 329 | 371 | ||
234 | === modified file 'src/View/AbstractDirectoryView.vala' | |||
235 | --- src/View/AbstractDirectoryView.vala 2017-06-06 09:00:33 +0000 | |||
236 | +++ src/View/AbstractDirectoryView.vala 2017-06-13 16:37:16 +0000 | |||
237 | @@ -352,7 +352,6 @@ | |||
238 | 352 | 352 | ||
239 | 353 | protected virtual void set_up_name_renderer () { | 353 | protected virtual void set_up_name_renderer () { |
240 | 354 | name_renderer.editable = false; | 354 | name_renderer.editable = false; |
241 | 355 | name_renderer.follow_state = true; | ||
242 | 356 | name_renderer.edited.connect (on_name_edited); | 355 | name_renderer.edited.connect (on_name_edited); |
243 | 357 | name_renderer.editing_canceled.connect (on_name_editing_canceled); | 356 | name_renderer.editing_canceled.connect (on_name_editing_canceled); |
244 | 358 | name_renderer.editing_started.connect (on_name_editing_started); | 357 | name_renderer.editing_started.connect (on_name_editing_started); |
245 | 359 | 358 | ||
246 | === modified file 'src/View/IconView.vala' | |||
247 | --- src/View/IconView.vala 2017-06-05 14:48:38 +0000 | |||
248 | +++ src/View/IconView.vala 2017-06-13 16:37:16 +0000 | |||
249 | @@ -34,6 +34,7 @@ | |||
250 | 34 | tree.set_selection_mode (Gtk.SelectionMode.MULTIPLE); | 34 | tree.set_selection_mode (Gtk.SelectionMode.MULTIPLE); |
251 | 35 | tree.set_columns (-1); | 35 | tree.set_columns (-1); |
252 | 36 | tree.set_reorderable (false); | 36 | tree.set_reorderable (false); |
253 | 37 | tree.set_item_padding (3); | ||
254 | 37 | 38 | ||
255 | 38 | name_renderer = new Marlin.TextRenderer (Marlin.ViewMode.ICON); | 39 | name_renderer = new Marlin.TextRenderer (Marlin.ViewMode.ICON); |
256 | 39 | set_up_name_renderer (); | 40 | set_up_name_renderer (); |
257 | @@ -106,15 +107,16 @@ | |||
258 | 106 | } | 107 | } |
259 | 107 | 108 | ||
260 | 108 | public override void change_zoom_level () { | 109 | public override void change_zoom_level () { |
261 | 110 | int spacing = (int)((double)icon_size * (0.3 - zoom_level * 0.03)); | ||
262 | 111 | int item_width = (int)((double)icon_size * (2.5 - zoom_level * 0.2)); | ||
263 | 109 | if (tree != null) { | 112 | if (tree != null) { |
271 | 110 | tree.set_column_spacing ((int)((double)icon_size * (0.3 - zoom_level * 0.03))); | 113 | tree.set_column_spacing (spacing); |
272 | 111 | tree.set_item_width ((int)((double)icon_size * (2.5 - zoom_level * 0.2))); | 114 | tree.set_item_width (item_width); |
266 | 112 | |||
267 | 113 | name_renderer.set_property ("wrap-width", tree.get_item_width ()); | ||
268 | 114 | name_renderer.set_property ("zoom-level", zoom_level); | ||
269 | 115 | |||
270 | 116 | base.change_zoom_level (); | ||
273 | 117 | } | 115 | } |
274 | 116 | name_renderer.item_width = item_width; | ||
275 | 117 | name_renderer.set_property ("zoom-level", zoom_level); | ||
276 | 118 | |||
277 | 119 | base.change_zoom_level (); | ||
278 | 118 | } | 120 | } |
279 | 119 | 121 | ||
280 | 120 | public override GLib.List<Gtk.TreePath> get_selected_paths () { | 122 | public override GLib.List<Gtk.TreePath> get_selected_paths () { |
Looks like this branch has merge conflicts