~jeremywootten/pantheon-files/fix-1611022-stop-on-eject-if-possible

« back to all changes in this revision

Viewing changes to src/IconRenderer.vala

  • Committer: Jeremy Wootten
  • Date: 2017-02-04 13:40:05 UTC
  • mfrom: (2280.2.190 pantheon-files)
  • Revision ID: jeremy@elementaryos.org-20170204134005-q97gij7ndqhrpxi9
Merge trunk to r2470

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***
 
2
    Copyright (c) 2016 elementary LLC (http://launchpad.net/elementary)
 
3
 
 
4
    Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
 
5
    Copyright (c) 2011  ammonkey <am.monkeyd@gmail.com>
 
6
 
 
7
    Transcribed from marlin-icon-renderer
 
8
    Originaly Written in gtk+: gtkcellrendererpixbuf
 
9
 
 
10
    Pantheon Files is free software; you can redistribute it and/or
 
11
    modify it under the terms of the GNU General Public License as
 
12
    published by the Free Software Foundation; either version 2 of the
 
13
    License, or (at your option) any later version.
 
14
 
 
15
    Pantheon Files is distributed in the hope that it will be useful,
 
16
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
18
    General Public License for more details.
 
19
 
 
20
    You should have received a copy of the GNU General Public
 
21
    License along with this program; see the file COPYING.  If not,
 
22
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
23
    Boston, MA 02111-1307, USA.
 
24
 
 
25
    Author(s):  Jeremy Wootten <jeremy@elementaryos.org>
 
26
 
 
27
***/
 
28
 
 
29
 
 
30
namespace Marlin {
 
31
 
 
32
    public class IconRenderer : Gtk.CellRenderer {
 
33
        public Marlin.IconSize helper_size {get; private set; default = Marlin.IconSize.EMBLEM;}
 
34
        public bool follow_state {get; set;}
 
35
        public GOF.File drop_file {get; set;}
 
36
        public bool selection_helpers {get; set; default = true;}
 
37
 
 
38
        public Marlin.ZoomLevel zoom_level {
 
39
            get {
 
40
                return _zoom_level;
 
41
            }
 
42
            set {
 
43
                _zoom_level = value;
 
44
                helper_size = _zoom_level > Marlin.ZoomLevel.LARGER ? Marlin.IconSize.LARGE_EMBLEM : Marlin.IconSize.EMBLEM;
 
45
                emblem_overlap = helper_size / 4;
 
46
                icon_size = Marlin.zoom_level_to_icon_size (_zoom_level);
 
47
                show_emblems = _zoom_level > Marlin.ZoomLevel.SMALLEST;
 
48
            }
 
49
        }
 
50
 
 
51
        public GOF.File? file {
 
52
            get {
 
53
                return _file;
 
54
            }
 
55
            set {
 
56
                _file = value;
 
57
                if (_file != null) {
 
58
                    _file.update_icon (icon_size);
 
59
                }
 
60
            }
 
61
        }
 
62
        private bool show_emblems = true;
 
63
        private Marlin.ZoomLevel _zoom_level = Marlin.ZoomLevel.NORMAL;
 
64
        private GOF.File? _file;
 
65
        private Marlin.IconSize icon_size;
 
66
        private int emblem_overlap = 0;
 
67
        private unowned Gdk.Pixbuf? pixbuf {
 
68
            get {
 
69
                return _file != null ? _file.pix : null;
 
70
            }
 
71
        }
 
72
        private double scale;
 
73
        private ClipboardManager clipboard;
 
74
 
 
75
        public IconRenderer () {
 
76
            clipboard = Marlin.ClipboardManager.get_for_display ();
 
77
        }
 
78
 
 
79
        public override void render (Cairo.Context cr, Gtk.Widget widget, Gdk.Rectangle background_area,
 
80
                                     Gdk.Rectangle cell_area, Gtk.CellRendererState flags) {
 
81
 
 
82
            if (file == null || pixbuf == null) {
 
83
                return;
 
84
            }
 
85
 
 
86
            Gdk.Pixbuf? pb = pixbuf;
 
87
 
 
88
            var pix_rect = Gdk.Rectangle ();
 
89
 
 
90
            pix_rect.width = pixbuf.get_width ();
 
91
            pix_rect.height = pixbuf.get_height ();
 
92
            pix_rect.x = cell_area.x + (cell_area.width - pix_rect.width) / 2;
 
93
            pix_rect.y = cell_area.y + (cell_area.height - pix_rect.height) / 2;
 
94
 
 
95
            var draw_rect = Gdk.Rectangle ();
 
96
            if (!cell_area.intersect (pix_rect, out draw_rect)) {
 
97
                return;
 
98
            }
 
99
 
 
100
            string? special_icon_name = null;
 
101
            if (file == drop_file) {
 
102
                flags |= Gtk.CellRendererState.PRELIT;
 
103
                special_icon_name = "folder-drag-accept";
 
104
 
 
105
            } else if (file.is_directory && file.is_expanded) {
 
106
                special_icon_name = "folder-open";
 
107
            }
 
108
 
 
109
            if (special_icon_name != null) {
 
110
                var nicon = Marlin.IconInfo.lookup_from_name (special_icon_name, icon_size);
 
111
                if (nicon != null) {
 
112
                    pb = nicon.get_pixbuf_nodefault ();
 
113
                }
 
114
            }
 
115
 
 
116
            if (clipboard.has_cutted_file (file)) {
 
117
                /* 50% translucent for cutted files */
 
118
                pb = Eel.gdk_pixbuf_lucent (pixbuf, 50);
 
119
            }
 
120
            if (file.is_hidden) {
 
121
                /* 75% translucent for hidden files */
 
122
                pb = Eel.gdk_pixbuf_lucent (pixbuf, 75);
 
123
                pb = Eel.create_darkened_pixbuf (pb, 150, 200);
 
124
            }
 
125
 
 
126
            var style_context = widget.get_parent ().get_style_context ();
 
127
            style_context.save ();
 
128
 
 
129
            bool prelit = (flags & Gtk.CellRendererState.PRELIT) > 0;
 
130
            bool selected = (flags & Gtk.CellRendererState.SELECTED) > 0;
 
131
            var state = Gtk.StateFlags.NORMAL;
 
132
 
 
133
            if (!widget.sensitive || !this.sensitive) {
 
134
                state |= Gtk.StateFlags.INSENSITIVE;
 
135
            } else if (follow_state) {
 
136
                if (selected) {
 
137
                    state = Gtk.StateFlags.SELECTED;
 
138
                    state |= widget.get_state_flags ();
 
139
                    var color = style_context.get_background_color (state);
 
140
                    pb = Eel.create_colorized_pixbuf (pb, color);
 
141
                }
 
142
                if (prelit) {
 
143
                    pb = Eel.create_spotlight_pixbuf (pb);
 
144
                }
 
145
            }
 
146
 
 
147
            if (pb == null) {
 
148
                return;
 
149
            }
 
150
 
 
151
            style_context.render_icon (cr, pb, draw_rect.x, draw_rect.y);
 
152
            style_context.restore ();
 
153
 
 
154
            /* Do not show selection helpers or emblems for very small icons */
 
155
            if (selection_helpers && show_emblems &&
 
156
                (selected || prelit) &&
 
157
                file != drop_file) {
 
158
 
 
159
                special_icon_name = null;
 
160
                if (selected && prelit) {
 
161
                    special_icon_name = "selection-remove";
 
162
                } else if (selected) {
 
163
                    special_icon_name = "selection-checked";
 
164
                } else if (prelit) {
 
165
                    special_icon_name = "selection-add";
 
166
                }
 
167
 
 
168
                if (special_icon_name != null) {
 
169
                    var nicon = Marlin.IconInfo.lookup_from_name (special_icon_name, helper_size);
 
170
                    Gdk.Pixbuf? pix = null;
 
171
                    if (nicon != null) {
 
172
                        pix = nicon.get_pixbuf_nodefault ();
 
173
                    }
 
174
 
 
175
                    if (pix != null) {
 
176
                        var helper_area = Gdk.Rectangle ();
 
177
                        helper_area.x = draw_rect.x - helper_size / 2;
 
178
                        helper_area.y = draw_rect.y - helper_size / 2;
 
179
 
 
180
                        if (helper_area.y < background_area.y) {
 
181
                            helper_area.y = background_area.y;
 
182
                        }
 
183
 
 
184
                        if (helper_area.x < background_area.x) {
 
185
                            helper_area.x = background_area.x;
 
186
                        }
 
187
 
 
188
                        Gdk.cairo_set_source_pixbuf (cr, pix, helper_area.x, helper_area.y);
 
189
                        cr.paint ();
 
190
                    }
 
191
                }
 
192
            }
 
193
 
 
194
            /* check if we should render emblems as well */
 
195
            /* Still show emblems when selection helpers hidden in double click mode */
 
196
            /* How many emblems can be shown depends on icon icon_size (zoom lebel) */
 
197
            if (show_emblems) {
 
198
                int pos = 0;
 
199
                var emblem_area = Gdk.Rectangle ();
 
200
 
 
201
                foreach (string emblem in file.emblems_list) {
 
202
                    if (pos > zoom_level) {
 
203
                        break;
 
204
                    }
 
205
 
 
206
                    Gdk.Pixbuf? pix = null;
 
207
                    var nicon = Marlin.IconInfo.lookup_from_name (emblem, helper_size);
 
208
 
 
209
                    if (nicon == null) {
 
210
                        continue;
 
211
                    }
 
212
 
 
213
                    pix = nicon.get_pixbuf_nodefault ();
 
214
 
 
215
                    if  (pix == null) {
 
216
                        continue;
 
217
                    }
 
218
 
 
219
                    emblem_area.x = draw_rect.x + draw_rect.width - emblem_overlap;
 
220
                    emblem_area.y = draw_rect.y + draw_rect.height - helper_size;
 
221
                    emblem_area.y -= helper_size * pos;
 
222
 
 
223
                    if (emblem_area.y < background_area.y) {
 
224
                        break;
 
225
                    }
 
226
 
 
227
                    if (emblem_area.x + helper_size > (background_area.x + background_area.width)) {
 
228
                        emblem_area.x = (background_area.x + background_area.width) - helper_size;
 
229
                    }
 
230
 
 
231
                    Gdk.cairo_set_source_pixbuf (cr, pix, emblem_area.x, emblem_area.y);
 
232
                    cr.paint ();
 
233
                    pos++;
 
234
                }
 
235
            }
 
236
        }
 
237
 
 
238
        /* We still have to implement this even though it is deprecated */
 
239
        public override void get_size (Gtk.Widget widget, Gdk.Rectangle? cell_area,
 
240
                                       out int x_offset, out int y_offset,
 
241
                                       out int width, out int height) {
 
242
 
 
243
            width = -1;
 
244
            height = -1;
 
245
            x_offset = 0;
 
246
            y_offset = 0;
 
247
 
 
248
            if (pixbuf == null || !(pixbuf is Gdk.Pixbuf)) {
 
249
                return;
 
250
            }
 
251
 
 
252
 
 
253
            int pixbuf_width = pixbuf.get_width ();
 
254
            int pixbuf_height = pixbuf.get_height ();
 
255
 
 
256
            int calc_width = pixbuf_width;
 
257
            int calc_height = pixbuf_height;
 
258
 
 
259
            if (cell_area != null && pixbuf_width > 0 && pixbuf_height > 0) {
 
260
                float xalign, yalign;
 
261
                bool rtl = widget.get_direction () == Gtk.TextDirection.RTL;
 
262
                get_alignment (out xalign, out yalign);
 
263
                x_offset = (int)(rtl ? (1.0 -xalign) : xalign) * (cell_area.width - calc_width);
 
264
                x_offset = int.max (x_offset, 0);
 
265
                y_offset = (int)(yalign * (cell_area.height - calc_height));
 
266
                y_offset = int.max (y_offset, 0);
 
267
            } else {
 
268
                x_offset = 0;
 
269
                y_offset = 0;
 
270
            }
 
271
 
 
272
            /* Even if the last new pixbuf corresponding to the last requested icon_size isn't generated
 
273
               yet, we can still determine its dimensions. This allow to asyncronously load the thumbnails
 
274
               pixbuf */
 
275
 
 
276
            int s = int.max (pixbuf_width, pixbuf_height);
 
277
            scale = double.min (1.0, (double)icon_size / s); /* scaling to make pix required icon_size (not taking into account screen scaling) */ 
 
278
 
 
279
            width = (int)(calc_width * scale);
 
280
            height = (int)(calc_height * scale);
 
281
        }
 
282
    }
 
283
}