~ubuntu-branches/ubuntu/quantal/pdfmod/quantal

« back to all changes in this revision

Viewing changes to .pc/0001-Fix-compilation-under-Mono-2.10-bgo-644516.patch/src/PdfMod/Gui/DocumentIconView.cs

  • Committer: Bazaar Package Importer
  • Author(s): Iain Lane, b137df1
  • Date: 2011-05-22 15:03:24 UTC
  • Revision ID: james.westby@ubuntu.com-20110522150324-unsk7tidvcr2l8tp
Tags: 0.9.1-2
[b137df1] Cherry-pick commit a29cfe7f8f by Nuno Araujo to fix 2.10
compilation

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (C) 2009-2011 Novell, Inc.
 
2
// Copyright (C) 2009 Julien Rebetez
 
3
// Copyright (C) 2009 Igor Vatavuk
 
4
//
 
5
// This program is free software; you can redistribute it and/or
 
6
// modify it under the terms of the GNU General Public License
 
7
// as published by the Free Software Foundation; either version 2
 
8
// of the License, or (at your option) any later version.
 
9
//
 
10
// This program is distributed in the hope that it will be useful,
 
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
// GNU General Public License for more details.
 
14
//
 
15
// You should have received a copy of the GNU General Public License
 
16
// along with this program; if not, write to the Free Software
 
17
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
18
 
 
19
using System;
 
20
using System.Collections.Generic;
 
21
using System.Linq;
 
22
 
 
23
using Gtk;
 
24
using Gdk;
 
25
 
 
26
using PdfSharp.Pdf;
 
27
 
 
28
using PdfMod.Pdf;
 
29
using PdfMod.Pdf.Actions;
 
30
 
 
31
namespace PdfMod.Gui
 
32
{
 
33
    public enum PageSelectionMode {
 
34
        None,
 
35
        Evens,
 
36
        Odds,
 
37
        Matching,
 
38
        Inverse,
 
39
        All
 
40
    }
 
41
 
 
42
    public class DocumentIconView : Gtk.IconView, IDisposable
 
43
    {
 
44
        public const int MIN_WIDTH = 128;
 
45
        public const int MAX_WIDTH = 2054;
 
46
 
 
47
        enum Target {
 
48
            UriSrc,
 
49
            UriDest,
 
50
            MoveInternal,
 
51
            MoveExternal
 
52
        }
 
53
 
 
54
        static readonly TargetEntry uri_src_target = new TargetEntry ("text/uri-list", 0, (uint)Target.UriSrc);
 
55
        static readonly TargetEntry uri_dest_target = new TargetEntry ("text/uri-list", TargetFlags.OtherApp, (uint)Target.UriDest);
 
56
        static readonly TargetEntry move_internal_target = new TargetEntry ("pdfmod/page-list", TargetFlags.Widget, (uint)Target.MoveInternal);
 
57
        static readonly TargetEntry move_external_target = new TargetEntry ("pdfmod/page-list-external", 0, (uint)Target.MoveExternal);
 
58
 
 
59
        Client app;
 
60
        Document document;
 
61
        PageListStore store;
 
62
        PageCell page_renderer;
 
63
        PageSelectionMode page_selection_mode = PageSelectionMode.None;
 
64
        bool highlighted;
 
65
 
 
66
        public PageListStore Store { get { return store; } }
 
67
        public bool CanZoomIn { get; private set; }
 
68
        public bool CanZoomOut { get; private set; }
 
69
 
 
70
        public IEnumerable<Page> SelectedPages {
 
71
            get {
 
72
                var pages = new List<Page> ();
 
73
                foreach (var path in SelectedItems) {
 
74
                    TreeIter iter;
 
75
                    store.GetIter (out iter, path);
 
76
                    pages.Add (store.GetValue (iter, PageListStore.PageColumn) as Page);
 
77
                }
 
78
                pages.Sort ((a, b) => { return a.Index < b.Index ? -1 : 1; });
 
79
                return pages;
 
80
            }
 
81
        }
 
82
 
 
83
        public event System.Action ZoomChanged;
 
84
 
 
85
        public DocumentIconView (Client app) : base ()
 
86
        {
 
87
            this.app = app;
 
88
 
 
89
            TooltipColumn = PageListStore.TooltipColumn;
 
90
            SelectionMode = SelectionMode.Multiple;
 
91
            ColumnSpacing = RowSpacing = Margin;
 
92
            Model = store = new PageListStore ();
 
93
            Reorderable = false;
 
94
            Spacing = 0;
 
95
            Orientation = Orientation.Vertical;
 
96
 
 
97
            // Properties not bound in Gtk#
 
98
            SetProperty ("item-padding", new GLib.Value ((int)0));
 
99
 
 
100
            CanZoomIn = CanZoomOut = true;
 
101
 
 
102
            page_renderer = new PageCell (this);
 
103
            PackStart (page_renderer, false);
 
104
            AddAttribute (page_renderer, "page", PageListStore.PageColumn);
 
105
 
 
106
            // TODO enable uri-list as drag source target for drag-out-of-pdfmod-to-extract feature
 
107
            EnableModelDragSource (Gdk.ModifierType.None, new TargetEntry [] { move_internal_target, move_external_target, uri_src_target }, Gdk.DragAction.Default | Gdk.DragAction.Move);
 
108
            EnableModelDragDest (new TargetEntry [] { move_internal_target, move_external_target, uri_dest_target }, Gdk.DragAction.Default | Gdk.DragAction.Move);
 
109
 
 
110
            SizeAllocated += HandleSizeAllocated;
 
111
            PopupMenu += HandlePopupMenu;
 
112
            ButtonPressEvent += HandleButtonPressEvent;
 
113
            SelectionChanged += HandleSelectionChanged;
 
114
            DragDataReceived += HandleDragDataReceived;
 
115
            DragDataGet += HandleDragDataGet;
 
116
            DragBegin += HandleDragBegin;
 
117
            DragLeave += HandleDragLeave;
 
118
        }
 
119
 
 
120
        public override void Dispose ()
 
121
        {
 
122
            page_renderer.Dispose ();
 
123
            base.Dispose ();
 
124
        }
 
125
 
 
126
        #region Gtk.Widget event handlers/overrides
 
127
 
 
128
        protected override bool OnScrollEvent (Gdk.EventScroll evnt)
 
129
        {
 
130
            if ((evnt.State & Gdk.ModifierType.ControlMask) != 0) {
 
131
                Zoom (evnt.Direction == ScrollDirection.Down ? -20 : 20);
 
132
                return true;
 
133
            } else {
 
134
                return base.OnScrollEvent (evnt);
 
135
            }
 
136
        }
 
137
 
 
138
        void HandleSizeAllocated (object o, EventArgs args)
 
139
        {
 
140
            if (!zoom_manually_set) {
 
141
                ZoomFit ();
 
142
            }
 
143
        }
 
144
 
 
145
        void HandleSelectionChanged (object o, EventArgs args)
 
146
        {
 
147
            if (!refreshing_selection) {
 
148
                page_selection_mode = PageSelectionMode.None;
 
149
            }
 
150
        }
 
151
 
 
152
        void HandleButtonPressEvent (object o, ButtonPressEventArgs args)
 
153
        {
 
154
            if (args.Event.Button == 3) {
 
155
                var path = GetPathAtPos ((int)args.Event.X, (int)args.Event.Y);
 
156
                if (path != null) {
 
157
                    if (!PathIsSelected (path)) {
 
158
                        bool ctrl = (args.Event.State & Gdk.ModifierType.ControlMask) != 0;
 
159
                        bool shift = (args.Event.State & Gdk.ModifierType.ShiftMask) != 0;
 
160
                        if (ctrl) {
 
161
                            SelectPath (path);
 
162
                        } else if (shift) {
 
163
                            TreePath cursor;
 
164
                            CellRenderer cell;
 
165
                            if (GetCursor (out cursor, out cell)) {
 
166
                                TreePath first = cursor.Compare (path) < 0 ? cursor : path;
 
167
                                do {
 
168
                                    SelectPath (first);
 
169
                                    first.Next ();
 
170
                                } while (first != path && first != cursor && first != null);
 
171
                            } else {
 
172
                                SelectPath (path);
 
173
                            }
 
174
                        } else {
 
175
                            UnselectAll ();
 
176
                            SelectPath (path);
 
177
                        }
 
178
                    }
 
179
                    HandlePopupMenu (null, null);
 
180
                    args.RetVal = true;
 
181
                }
 
182
            }
 
183
        }
 
184
 
 
185
        void HandlePopupMenu (object o, PopupMenuArgs args)
 
186
        {
 
187
            app.Actions["PageContextMenu"].Activate ();
 
188
        }
 
189
 
 
190
        #endregion
 
191
 
 
192
        #region Drag and Drop event handling
 
193
 
 
194
        void HandleDragBegin (object o, DragBeginArgs args)
 
195
        {
 
196
            // Set the drag icon, otherwise it will be a whole page cell rendering,
 
197
            // which can be quite large and obscure the drop points
 
198
            bool single = SelectedItems.Length == 1;
 
199
            Gtk.Drag.SetIconStock (args.Context, single ? Stock.Dnd : Stock.DndMultiple, 0, 0);
 
200
        }
 
201
 
 
202
        void HandleDragLeave (object o, DragLeaveArgs args)
 
203
        {
 
204
            if (highlighted) {
 
205
                Gtk.Drag.Unhighlight (this);
 
206
                highlighted = false;
 
207
            }
 
208
            args.RetVal = true;
 
209
        }
 
210
 
 
211
        protected override bool OnDragMotion (Gdk.DragContext context, int x, int y, uint time_)
 
212
        {
 
213
            // Scroll if within 20 pixels of the top or bottom
 
214
            var parent = Parent.Parent as Gtk.ScrolledWindow;
 
215
            double rel_y = y - parent.Vadjustment.Value;
 
216
            if (rel_y < 20) {
 
217
                parent.Vadjustment.Value -= 30;
 
218
            } else if ((parent.Allocation.Height - rel_y) < 20) {
 
219
                parent.Vadjustment.Value = Math.Min (parent.Vadjustment.Upper - parent.Allocation.Height, parent.Vadjustment.Value + 30);
 
220
            }
 
221
 
 
222
            var targets = context.Targets.Select (t => (string)t);
 
223
 
 
224
            if (targets.Contains (move_internal_target.Target) || targets.Contains (move_external_target.Target)) {
 
225
                bool ret = base.OnDragMotion (context, x, y, time_);
 
226
                SetDestInfo (x, y);
 
227
                return ret;
 
228
            } else if (targets.Contains (uri_dest_target.Target)) {
 
229
                // TODO could do this (from Gtk+ docs) to make sure the uris are all .pdfs (or mime-sniffed as pdfs):
 
230
                /* If the decision whether the drop will be accepted or rejected can't be made based solely on the
 
231
                   cursor position and the type of the data, the handler may inspect the dragged data by calling gtk_drag_get_data() and
 
232
                   defer the gdk_drag_status() call to the "drag-data-received" handler. Note that you cannot not pass GTK_DEST_DEFAULT_DROP,
 
233
                   GTK_DEST_DEFAULT_MOTION or GTK_DEST_DEFAULT_ALL to gtk_drag_dest_set() when using the drag-motion signal that way. */
 
234
                Gdk.Drag.Status (context, DragAction.Copy, time_);
 
235
                if (!highlighted) {
 
236
                    Gtk.Drag.Highlight (this);
 
237
                    highlighted = true;
 
238
                }
 
239
 
 
240
                SetDestInfo (x, y);
 
241
 
 
242
                return true;
 
243
            }
 
244
 
 
245
            Gdk.Drag.Abort (context, time_);
 
246
            return false;
 
247
        }
 
248
 
 
249
        void SetDestInfo (int x, int y)
 
250
        {
 
251
            TreePath path;
 
252
            IconViewDropPosition pos;
 
253
            GetCorrectedPathAndPosition (x, y, out path, out pos);
 
254
            SetDragDestItem (path, pos);
 
255
        }
 
256
 
 
257
        void HandleDragDataGet(object o, DragDataGetArgs args)
 
258
        {
 
259
            if (args.Info == move_internal_target.Info) {
 
260
                var pages = new Hyena.Gui.DragDropList<Page> ();
 
261
                pages.AddRange (SelectedPages);
 
262
                pages.AssignToSelection (args.SelectionData, Gdk.Atom.Intern (move_internal_target.Target, false));
 
263
                args.RetVal = true;
 
264
            } else if (args.Info == move_external_target.Info) {
 
265
                string doc_and_pages = String.Format ("{0}{1}{2}", document.CurrentStateUri, newline[0], String.Join (",", SelectedPages.Select (p => p.Index.ToString ()).ToArray ()));
 
266
                byte [] data = System.Text.Encoding.UTF8.GetBytes (doc_and_pages);
 
267
                args.SelectionData.Set (Gdk.Atom.Intern (move_external_target.Target, false), 8, data);
 
268
                args.RetVal = true;
 
269
            } else if (args.Info == uri_src_target.Info) {
 
270
                // TODO implement page extraction via DnD?
 
271
                Console.WriteLine ("HandleDragDataGet, wants a uri list...");
 
272
            }
 
273
        }
 
274
 
 
275
        void GetCorrectedPathAndPosition (int x, int y, out TreePath path, out IconViewDropPosition pos)
 
276
        {
 
277
            GetDestItemAtPos (x, y, out path, out pos);
 
278
 
 
279
            // Convert drop above/below/into into DropLeft or DropRight based on the x coordinate
 
280
            if (path != null && (pos == IconViewDropPosition.DropAbove || pos == IconViewDropPosition.DropBelow || pos == IconViewDropPosition.DropInto)) {
 
281
                if (!path.Equals (GetPathAtPos (x + ItemSize/2, y))) {
 
282
                    pos = IconViewDropPosition.DropRight;
 
283
                } else {
 
284
                    pos = IconViewDropPosition.DropLeft;
 
285
                }
 
286
            }
 
287
        }
 
288
 
 
289
        int GetDropIndex (int x, int y)
 
290
        {
 
291
            TreePath path;
 
292
            TreeIter iter;
 
293
            IconViewDropPosition pos;
 
294
            GetCorrectedPathAndPosition (x, y, out path, out pos);
 
295
            if (path == null) {
 
296
                return -1;
 
297
            }
 
298
 
 
299
            store.GetIter (out iter, path);
 
300
            if (TreeIter.Zero.Equals (iter))
 
301
                return -1;
 
302
 
 
303
            var to_index = (store.GetValue (iter, PageListStore.PageColumn) as Page).Index;
 
304
            if (pos == IconViewDropPosition.DropRight) {
 
305
                to_index++;
 
306
            }
 
307
 
 
308
            return to_index;
 
309
        }
 
310
 
 
311
        static string [] newline = new string [] { "\r\n" };
 
312
        void HandleDragDataReceived (object o, DragDataReceivedArgs args)
 
313
        {
 
314
            args.RetVal = false;
 
315
            string target = (string)args.SelectionData.Target;
 
316
            if (target == move_internal_target.Target) {
 
317
                // Move pages within the document
 
318
                int to_index = GetDropIndex (args.X, args.Y);
 
319
                if (to_index < 0)
 
320
                    return;
 
321
 
 
322
                var pages = args.SelectionData.Data as Hyena.Gui.DragDropList<Page>;
 
323
                to_index -= pages.Count (p => p.Index < to_index);
 
324
                var action = new MoveAction (document, pages, to_index);
 
325
                action.Do ();
 
326
                app.Actions.UndoManager.AddUndoAction (action);
 
327
                args.RetVal = true;
 
328
            } else if (target == move_external_target.Target) {
 
329
                int to_index = GetDropIndex (args.X, args.Y);
 
330
                if (to_index < 0)
 
331
                    return;
 
332
 
 
333
                string doc_and_pages = System.Text.Encoding.UTF8.GetString (args.SelectionData.Data);
 
334
                var pieces = doc_and_pages.Split (newline, StringSplitOptions.RemoveEmptyEntries);
 
335
                string uri = pieces[0];
 
336
                int [] pages = pieces[1].Split (',').Select (p => Int32.Parse (p)).ToArray ();
 
337
 
 
338
                document.AddFromUri (new Uri (uri), to_index, pages);
 
339
                args.RetVal = true;
 
340
            } else if (target == uri_src_target.Target) {
 
341
                var uris = System.Text.Encoding.UTF8.GetString (args.SelectionData.Data).Split (newline, StringSplitOptions.RemoveEmptyEntries);
 
342
                if (uris.Length == 1 && app.Document == null) {
 
343
                    app.LoadPath (uris[0]);
 
344
                    args.RetVal = true;
 
345
                } else {
 
346
                    int to_index = GetDropIndex (args.X, args.Y);
 
347
                    int uri_i = 0;
 
348
 
 
349
                    var add_pages = new System.Action (delegate {
 
350
                        // TODO somehow ask user for which pages of the docs to insert?
 
351
                        // TODO pwd handling - keyring#?
 
352
                        // TODO make action/undoable
 
353
                        for (; uri_i < uris.Length; uri_i++) {
 
354
                            var before_count = document.Count;
 
355
                            document.AddFromUri (new Uri (uris[uri_i]), to_index);
 
356
                            to_index += document.Count - before_count;
 
357
                        }
 
358
                    });
 
359
 
 
360
                    if (document == null || to_index < 0) {
 
361
                        // Load the first page, then add the other pages to it
 
362
                        app.LoadPath (uris[uri_i++], null, delegate {
 
363
                            if (document != null) {
 
364
                                to_index = document.Count;
 
365
                                add_pages ();
 
366
                            }
 
367
                        });
 
368
                    } else {
 
369
                        add_pages ();
 
370
                    }
 
371
 
 
372
                    args.RetVal = true;
 
373
                }
 
374
            }
 
375
 
 
376
            Gtk.Drag.Finish (args.Context, (bool)args.RetVal, false, args.Time);
 
377
        }
 
378
 
 
379
        #endregion
 
380
 
 
381
        #region Document event handling
 
382
 
 
383
        public void SetDocument (Document new_doc)
 
384
        {
 
385
            if (document != null) {
 
386
                document.PagesAdded   -= OnPagesAdded;
 
387
                document.PagesChanged -= OnPagesChanged;
 
388
                document.PagesRemoved -= OnPagesRemoved;
 
389
                document.PagesMoved   -= OnPagesMoved;
 
390
            }
 
391
 
 
392
            document = new_doc;
 
393
            document.PagesAdded   += OnPagesAdded;
 
394
            document.PagesChanged += OnPagesChanged;
 
395
            document.PagesRemoved += OnPagesRemoved;
 
396
            document.PagesMoved   += OnPagesMoved;
 
397
 
 
398
            store.SetDocument (document);
 
399
            page_selection_mode = PageSelectionMode.None;
 
400
            Refresh ();
 
401
            GrabFocus ();
 
402
        }
 
403
 
 
404
        void OnPagesAdded (int index, Page [] pages)
 
405
        {
 
406
            foreach (var page in pages) {
 
407
                store.InsertWithValues (index, store.GetValuesForPage (page));
 
408
            }
 
409
 
 
410
            UpdateAllPages ();
 
411
            Refresh ();
 
412
        }
 
413
 
 
414
        void OnPagesChanged (Page [] pages)
 
415
        {
 
416
            Refresh ();
 
417
        }
 
418
 
 
419
        void OnPagesRemoved (Page [] pages)
 
420
        {
 
421
            foreach (var page in pages) {
 
422
                var iter = store.GetIterForPage (page);
 
423
                if (!TreeIter.Zero.Equals (iter)) {
 
424
                    store.Remove (ref iter);
 
425
                }
 
426
            }
 
427
 
 
428
            UpdateAllPages ();
 
429
            Refresh ();
 
430
        }
 
431
 
 
432
        void OnPagesMoved ()
 
433
        {
 
434
            UpdateAllPages ();
 
435
            Refresh ();
 
436
        }
 
437
 
 
438
        void Refresh ()
 
439
        {
 
440
            if (!zoom_manually_set) {
 
441
                ZoomFit ();
 
442
            }
 
443
 
 
444
            RefreshSelection ();
 
445
        }
 
446
 
 
447
        void UpdateAllPages ()
 
448
        {
 
449
            foreach (var page in document.Pages) {
 
450
                var iter = store.GetIterForPage (page);
 
451
                if (!TreeIter.Zero.Equals (iter)) {
 
452
                    store.UpdateForPage (iter, page);
 
453
                    store.EmitRowChanged (store.GetPath (iter), iter);
 
454
                }
 
455
            }
 
456
        }
 
457
 
 
458
        #endregion
 
459
 
 
460
        bool zoom_manually_set;
 
461
        public void Zoom (int pixels)
 
462
        {
 
463
            Zoom (pixels, false);
 
464
        }
 
465
 
 
466
        public void Zoom (int pixels, bool absolute)
 
467
        {
 
468
            CanZoomIn = CanZoomOut = true;
 
469
 
 
470
            if (!zoom_manually_set) {
 
471
                zoom_manually_set = true;
 
472
                (app.Actions["ZoomFit"] as ToggleAction).Active = false;
 
473
            }
 
474
 
 
475
            int new_width = absolute ? pixels : ItemSize + pixels;
 
476
            if (new_width <= MIN_WIDTH) {
 
477
                CanZoomOut = false;
 
478
                new_width = MIN_WIDTH;
 
479
            } else if (new_width >= MAX_WIDTH) {
 
480
                CanZoomIn = false;
 
481
                new_width = MAX_WIDTH;
 
482
            }
 
483
 
 
484
            if (ItemSize == new_width) {
 
485
                return;
 
486
            }
 
487
 
 
488
            SetItemSize (new_width);
 
489
 
 
490
            var handler = ZoomChanged;
 
491
            if (handler != null) {
 
492
                handler ();
 
493
            }
 
494
        }
 
495
 
 
496
        int last_zoom, before_last_zoom;
 
497
        public void ZoomFit ()
 
498
        {
 
499
            if (document == null)
 
500
                return;
 
501
 
 
502
            if ((app.Actions["ZoomFit"] as ToggleAction).Active == false)
 
503
                return;
 
504
 
 
505
            zoom_manually_set = false;
 
506
            // Try to fit all pages into the view, with a minimum size
 
507
            var n = (double)document.Count;
 
508
            var width = (double)(Parent.Allocation.Width - 2 * (Margin + BorderWidth + 8)); // HACK this + 8 is total hack
 
509
            var height = (double)(Parent.Allocation.Height - 2 * (Margin + BorderWidth + 8)); // same
 
510
 
 
511
            var n_across = (int)Math.Ceiling (Math.Sqrt (width * n / height));
 
512
            var best_width = (int)Math.Floor ((width - (n_across + 1)*ColumnSpacing - n_across*2*FocusLineWidth) / n_across);
 
513
 
 
514
            // restrict to min/max
 
515
            best_width = Math.Min (MAX_WIDTH, Math.Max (MIN_WIDTH, best_width));
 
516
 
 
517
            if (best_width == ItemSize) {
 
518
                return;
 
519
            }
 
520
 
 
521
            // Total hack to avoid infinite SizeAllocate/ZoomFit loop
 
522
            if (best_width == before_last_zoom || best_width == last_zoom) {
 
523
                return;
 
524
            }
 
525
 
 
526
            before_last_zoom = last_zoom;
 
527
            last_zoom = ItemSize;
 
528
 
 
529
            SetItemSize (best_width);
 
530
            CanZoomOut = ItemSize > MIN_WIDTH;
 
531
            CanZoomIn  = ItemSize < MAX_WIDTH;
 
532
 
 
533
            var handler = ZoomChanged;
 
534
            if (handler != null) {
 
535
                handler ();
 
536
            }
 
537
        }
 
538
 
 
539
        public int ItemSize {
 
540
            get { return page_renderer.ItemSize; }
 
541
            set { page_renderer.ItemSize = value; }
 
542
        }
 
543
 
 
544
        private void SetItemSize (int w)
 
545
        {
 
546
            ItemSize = w;
 
547
 
 
548
            // HACK trigger gtk_icon_view_invalidate_sizes and queue_layout
 
549
            Orientation = Orientation.Horizontal;
 
550
            Orientation = Orientation.Vertical;
 
551
        }
 
552
 
 
553
        #region Selection
 
554
 
 
555
        string selection_match_query;
 
556
        public void SetSelectionMatchQuery (string query)
 
557
        {
 
558
            selection_match_query = query;
 
559
            SetPageSelectionMode (PageSelectionMode.Matching);
 
560
        }
 
561
 
 
562
        public void SetPageSelectionMode (PageSelectionMode mode)
 
563
        {
 
564
            page_selection_mode = mode;
 
565
            RefreshSelection ();
 
566
        }
 
567
 
 
568
        bool refreshing_selection;
 
569
        void RefreshSelection ()
 
570
        {
 
571
            refreshing_selection = true;
 
572
 
 
573
            if (page_selection_mode == PageSelectionMode.All) {
 
574
                SelectAll ();
 
575
            } else if (page_selection_mode != PageSelectionMode.None) {
 
576
                List<Page> matches = null;
 
577
                if (page_selection_mode == PageSelectionMode.Matching) {
 
578
                    matches = new List<Page> (app.Document.FindPagesMatching (selection_match_query));
 
579
                }
 
580
 
 
581
                int i = 1;
 
582
                foreach (var iter in store.TreeIters) {
 
583
                    var path = store.GetPath (iter);
 
584
                    bool select = false;
 
585
 
 
586
                    switch (page_selection_mode) {
 
587
                        case PageSelectionMode.Evens:
 
588
                            select = (i % 2) == 0;
 
589
                            break;
 
590
                        case PageSelectionMode.Odds:
 
591
                            select = (i % 2) == 1;
 
592
                            break;
 
593
                        case PageSelectionMode.Matching:
 
594
                            select = matches.Contains (store.GetValue (iter, PageListStore.PageColumn) as Page);
 
595
                            break;
 
596
                        case PageSelectionMode.Inverse:
 
597
                            select = !PathIsSelected (path);
 
598
                            break;
 
599
                    }
 
600
 
 
601
                    if (select) {
 
602
                        SelectPath (path);
 
603
                    } else {
 
604
                        UnselectPath (path);
 
605
                    }
 
606
                    i++;
 
607
                }
 
608
            }
 
609
 
 
610
            refreshing_selection = false;
 
611
            QueueDraw ();
 
612
        }
 
613
 
 
614
        #endregion
 
615
    }
 
616
}