~do-win/do/test-paths

« back to all changes in this revision

Viewing changes to Do/src/Do.Core/SecondSearchController.cs

  • Committer: Hardeep S
  • Date: 2009-06-23 05:57:47 UTC
  • Revision ID: ootz0rz@gmail.com-20090623055747-3srobsuq3q8wbn81
initial adding of Do core stuff

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// SecondSearchController.cs
 
2
// 
 
3
// GNOME Do is the legal property of its developers. Please refer to the
 
4
// COPYRIGHT file distributed with this source distribution.
 
5
// 
 
6
// This program is free software: you can redistribute it and/or modify
 
7
// it under the terms of the GNU General Public License as published by
 
8
// the Free Software Foundation, either version 3 of the License, or
 
9
// (at your option) any later version.
 
10
// 
 
11
// This program is distributed in the hope that it will be useful,
 
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
// GNU General Public License for more details.
 
15
// 
 
16
// You should have received a copy of the GNU General Public License
 
17
// along with this program.  If not, see <http:// www.gnu.org/licenses/>.
 
18
// 
 
19
 
 
20
using System;
 
21
using System.Linq;
 
22
using System.Collections.Generic;
 
23
 
 
24
using Do.Platform;
 
25
using Do.Universe;
 
26
using Do.Interface;
 
27
 
 
28
namespace Do.Core
 
29
{
 
30
        /// <summary>
 
31
        /// A search controller most useful in the second pane of Gnome-Do
 
32
        /// </summary>
 
33
        public class SecondSearchController : SimpleSearchController
 
34
        {
 
35
                private ISearchController FirstController;
 
36
                private uint timer = 0, wait_timer = 0;
 
37
                private const int type_wait = 200;
 
38
                
 
39
                private bool IsSearching {
 
40
                        get {
 
41
                                return (timer > 0 || wait_timer > 0);
 
42
                        }
 
43
                }
 
44
                
 
45
                public override Item Selection {
 
46
                        get { 
 
47
                                if (IsSearching)
 
48
                                        FastSearch ();
 
49
                                return context.Selection;
 
50
                        }
 
51
                }
 
52
 
 
53
                public SecondSearchController(ISearchController FirstController) : base ()
 
54
                {
 
55
                        this.FirstController = FirstController;
 
56
                        FirstController.SearchFinished += delegate (object o, SearchFinishState state) {
 
57
                                if (state.SelectionChanged)
 
58
                                        OnUpstreamSelectionChanged ();
 
59
                        };
 
60
                }
 
61
                
 
62
                // Similar to running UpdateResults (), except we dont have any timeouts
 
63
                private void FastSearch ()
 
64
                {
 
65
                        if (FirstController.Selection == null)
 
66
                                return;
 
67
                        
 
68
                        // Clear our timers
 
69
                        if (timer > 0) {
 
70
                                GLib.Source.Remove (timer);
 
71
                                timer = 0;
 
72
                        }
 
73
                        if (wait_timer > 0) {
 
74
                                GLib.Source.Remove (wait_timer);
 
75
                                wait_timer = 0;
 
76
                        }
 
77
                        context.Results = GetContextResults ();
 
78
                        base.OnSearchFinished (true, true, Selection, Query);
 
79
                }
 
80
                
 
81
                protected override List<Item> InitialResults ()
 
82
                {
 
83
                        // We continue off our previous results if possible
 
84
                        if (context.LastContext != null && context.LastContext.Results.Any ()) {
 
85
                                return new List<Item> (
 
86
                                        Do.UniverseManager.Search (context.Query, SearchTypes, context.LastContext.Results, FirstController.Selection));
 
87
                        } else if (context.ParentContext != null && context.Results.Any ()) {
 
88
                                return new List<Item> (context.Results);
 
89
                        } else { 
 
90
                                return new List<Item> (
 
91
                                        Do.UniverseManager.Search (context.Query, SearchTypes, FirstController.Selection));
 
92
                        }
 
93
                }
 
94
 
 
95
                private void OnUpstreamSelectionChanged ()
 
96
                {
 
97
                        textMode = false;
 
98
                        if (timer > 0)
 
99
                                GLib.Source.Remove (timer);
 
100
                        if (wait_timer > 0)
 
101
                                GLib.Source.Remove (wait_timer);
 
102
                        
 
103
                        base.OnSearchStarted (true);// trigger our search start now
 
104
                        timer = GLib.Timeout.Add (type_wait, delegate {
 
105
                                context.Destroy ();
 
106
                                context = new SimpleSearchContext ();
 
107
                                UpdateResults (true);
 
108
                                timer = 0;
 
109
                                return false;
 
110
                        });
 
111
                }
 
112
 
 
113
                /// <summary>
 
114
                /// Set up our results list.
 
115
                /// </summary>
 
116
                /// <returns>
 
117
                /// A <see cref="Item"/>
 
118
                /// </returns>
 
119
                private Item [] GetContextResults ()
 
120
                {
 
121
                        List<Item> results = new List<Item> ();
 
122
                        Item first = FirstController.Selection;
 
123
                        
 
124
                        if (first.IsAction ()) {
 
125
                                // We need to find items for this action
 
126
                                Act action = first.AsAction ();
 
127
                                foreach (Item item in InitialResults ()) {
 
128
                                        if (action.Safe.SupportsItem (item) || (item.IsAction () && item.AsAction ().Safe.SupportsItem (action)))
 
129
                                                results.Add (item);
 
130
                                }
 
131
                        } else {
 
132
                                // We need to find actions for this item
 
133
                                // TODO -- Make this work for multiple items
 
134
                                foreach (Item item in InitialResults ()) {
 
135
                                        Act action = item.AsAction ();
 
136
                                        if (action != null && action.Safe.SupportsItem (first)) {
 
137
                                                results.Add (item);
 
138
                                        }
 
139
                                }
 
140
                        }
 
141
                        
 
142
                        return results.ToArray ();
 
143
                }
 
144
                
 
145
                protected override void UpdateResults ()
 
146
                {
 
147
                        UpdateResults (false);
 
148
                }
 
149
 
 
150
                
 
151
                /// <summary>
 
152
                /// This method is pretty much a wrapper around GetContextResults () with a timer at the
 
153
                /// end.  This is very useful since we might not want this timer and adding a bool to turn
 
154
                /// this on is more stateful than i would like.
 
155
                /// </summary>
 
156
                private void UpdateResults (bool upstream_search)
 
157
                {
 
158
                        DateTime time = DateTime.Now;
 
159
                        
 
160
                        if (!upstream_search)
 
161
                                base.OnSearchStarted (false);
 
162
                        
 
163
                        // if we dont have a first controller selection, we can stop now.
 
164
                        if (FirstController.Selection == null)
 
165
                                return;
 
166
                        
 
167
                        // we only do this if its false because we already did it up before the timeout
 
168
                        if (!upstream_search)
 
169
                                base.OnSearchStarted (false);
 
170
                        
 
171
                        context.Results = GetContextResults ();
 
172
                        
 
173
                        // we now want to know how many ms have elapsed since we started this process
 
174
                        uint ms = Convert.ToUInt32 (DateTime.Now.Subtract (time).TotalMilliseconds);
 
175
                        ms += type_wait; // we also know we waited this long at the start
 
176
                        if (ms > Timeout || !upstream_search) {
 
177
                                // we were too slow, our engine has been defeated and we must return results as
 
178
                                // quickly as possible
 
179
                                
 
180
                                // Check and see if our selection changed
 
181
                                bool selection_changed = (context.LastContext != null && 
 
182
                                                          context.Selection != context.LastContext.Selection);
 
183
                                base.OnSearchFinished (selection_changed, true, Selection, Query);
 
184
                        } else {
 
185
                                // yay, we beat the user with a stick
 
186
                                if (wait_timer > 0) {
 
187
                                        GLib.Source.Remove (wait_timer);
 
188
                                }
 
189
                                
 
190
                                // So the idea here is that we will wait long enough that we still go the full
 
191
                                // 250ms before showing results.
 
192
                                wait_timer = GLib.Timeout.Add (Timeout - ms, delegate {
 
193
                                        wait_timer = 0;
 
194
                                        Gdk.Threads.Enter ();
 
195
                                        try {
 
196
                                                bool search_changed = (context.LastContext == null || 
 
197
                                                                       context.Selection != context.LastContext.Selection);
 
198
                                                base.OnSearchFinished (search_changed, true, Selection, Query);
 
199
                                        } finally {
 
200
                                                Gdk.Threads.Leave ();
 
201
                                        }
 
202
                                        return false;
 
203
                                });
 
204
                        }
 
205
                }
 
206
 
 
207
                public override IEnumerable<Type> SearchTypes {
 
208
                        get { 
 
209
                                Item item = FirstController.Selection;
 
210
                                if (item.IsAction ()) {
 
211
                                        foreach (Type t in item.AsAction ().Safe.SupportedItemTypes)
 
212
                                                yield return t;
 
213
                                        yield return typeof (Act);
 
214
                                } else if (TextMode) {
 
215
                                        yield return typeof (ITextItem);
 
216
                                } else {
 
217
                                        yield return typeof (Act);
 
218
                                }
 
219
                        }
 
220
                }
 
221
                
 
222
                public override void Reset ()
 
223
                {
 
224
                        while (context.LastContext != null) {
 
225
                                context = context.LastContext;
 
226
                        }
 
227
                        textMode = false;
 
228
                        
 
229
                        base.OnSearchFinished (true, true, Selection, Query);
 
230
                }
 
231
 
 
232
 
 
233
                /// <value>
 
234
                /// Set text mode.
 
235
                /// </value>
 
236
                public override bool TextMode { // FIXME
 
237
                        get { 
 
238
                                return (textMode || ImplicitTextMode);
 
239
                        }
 
240
                        set {
 
241
                                if (context.ParentContext != null) return;
 
242
                                if (!value) {
 
243
                                        textMode = value;
 
244
                                        textModeFinalize = false;
 
245
                                } else if (FirstController.Selection.IsAction ()) {
 
246
                                        Act action = FirstController.Selection.AsAction ();
 
247
                                        if (action.Safe.SupportsItem (new ImplicitTextItem (Query))) {
 
248
                                                textMode = value;
 
249
                                                textModeFinalize = false;
 
250
                                        }
 
251
                                }
 
252
                                
 
253
                                if (textMode == value)
 
254
                                        BuildNewContextFromQuery ();
 
255
                        }
 
256
                }
 
257
                
 
258
                public override void SetString (string str)
 
259
                {
 
260
                        context.Query = str;
 
261
                        BuildNewContextFromQuery ();
 
262
                }
 
263
 
 
264
                /// <summary>
 
265
                /// Builds up a new context from a query from scratch.  Useful after changing filters.
 
266
                /// </summary>
 
267
                private void BuildNewContextFromQuery ()
 
268
                {
 
269
                        string query = Query;
 
270
                        
 
271
                        context = new SimpleSearchContext ();
 
272
                        context.Results = GetContextResults ();
 
273
                        
 
274
                        foreach (char c in query.ToCharArray ()) {
 
275
                                context.LastContext = context.Clone () as SimpleSearchContext;
 
276
                                context.Query += c;
 
277
 
 
278
                                context.Results = GetContextResults ();
 
279
                        }
 
280
                        base.OnSearchFinished (true, true, Selection, Query);
 
281
                }
 
282
                
 
283
                protected override bool AcceptChildItem (Item item)
 
284
                {
 
285
                        if (FirstController.Selection.IsAction ()) {
 
286
                                Act action = FirstController.Selection.AsAction ();
 
287
                                return action.Safe.SupportsItem (item);
 
288
                        }
 
289
                        return true;
 
290
                }
 
291
        }
 
292
}