1
// SecondSearchController.cs
3
// GNOME Do is the legal property of its developers. Please refer to the
4
// COPYRIGHT file distributed with this source distribution.
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.
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.
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/>.
22
using System.Collections.Generic;
31
/// A search controller most useful in the second pane of Gnome-Do
33
public class SecondSearchController : SimpleSearchController
35
private ISearchController FirstController;
36
private uint timer = 0, wait_timer = 0;
37
private const int type_wait = 200;
39
private bool IsSearching {
41
return (timer > 0 || wait_timer > 0);
45
public override Item Selection {
49
return context.Selection;
53
public SecondSearchController(ISearchController FirstController) : base ()
55
this.FirstController = FirstController;
56
FirstController.SearchFinished += delegate (object o, SearchFinishState state) {
57
if (state.SelectionChanged)
58
OnUpstreamSelectionChanged ();
62
// Similar to running UpdateResults (), except we dont have any timeouts
63
private void FastSearch ()
65
if (FirstController.Selection == null)
70
GLib.Source.Remove (timer);
74
GLib.Source.Remove (wait_timer);
77
context.Results = GetContextResults ();
78
base.OnSearchFinished (true, true, Selection, Query);
81
protected override List<Item> InitialResults ()
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);
90
return new List<Item> (
91
Do.UniverseManager.Search (context.Query, SearchTypes, FirstController.Selection));
95
private void OnUpstreamSelectionChanged ()
99
GLib.Source.Remove (timer);
101
GLib.Source.Remove (wait_timer);
103
base.OnSearchStarted (true);// trigger our search start now
104
timer = GLib.Timeout.Add (type_wait, delegate {
106
context = new SimpleSearchContext ();
107
UpdateResults (true);
114
/// Set up our results list.
117
/// A <see cref="Item"/>
119
private Item [] GetContextResults ()
121
List<Item> results = new List<Item> ();
122
Item first = FirstController.Selection;
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)))
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)) {
142
return results.ToArray ();
145
protected override void UpdateResults ()
147
UpdateResults (false);
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.
156
private void UpdateResults (bool upstream_search)
158
DateTime time = DateTime.Now;
160
if (!upstream_search)
161
base.OnSearchStarted (false);
163
// if we dont have a first controller selection, we can stop now.
164
if (FirstController.Selection == null)
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);
171
context.Results = GetContextResults ();
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
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);
185
// yay, we beat the user with a stick
186
if (wait_timer > 0) {
187
GLib.Source.Remove (wait_timer);
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 {
194
Gdk.Threads.Enter ();
196
bool search_changed = (context.LastContext == null ||
197
context.Selection != context.LastContext.Selection);
198
base.OnSearchFinished (search_changed, true, Selection, Query);
200
Gdk.Threads.Leave ();
207
public override IEnumerable<Type> SearchTypes {
209
Item item = FirstController.Selection;
210
if (item.IsAction ()) {
211
foreach (Type t in item.AsAction ().Safe.SupportedItemTypes)
213
yield return typeof (Act);
214
} else if (TextMode) {
215
yield return typeof (ITextItem);
217
yield return typeof (Act);
222
public override void Reset ()
224
while (context.LastContext != null) {
225
context = context.LastContext;
229
base.OnSearchFinished (true, true, Selection, Query);
236
public override bool TextMode { // FIXME
238
return (textMode || ImplicitTextMode);
241
if (context.ParentContext != null) return;
244
textModeFinalize = false;
245
} else if (FirstController.Selection.IsAction ()) {
246
Act action = FirstController.Selection.AsAction ();
247
if (action.Safe.SupportsItem (new ImplicitTextItem (Query))) {
249
textModeFinalize = false;
253
if (textMode == value)
254
BuildNewContextFromQuery ();
258
public override void SetString (string str)
261
BuildNewContextFromQuery ();
265
/// Builds up a new context from a query from scratch. Useful after changing filters.
267
private void BuildNewContextFromQuery ()
269
string query = Query;
271
context = new SimpleSearchContext ();
272
context.Results = GetContextResults ();
274
foreach (char c in query.ToCharArray ()) {
275
context.LastContext = context.Clone () as SimpleSearchContext;
278
context.Results = GetContextResults ();
280
base.OnSearchFinished (true, true, Selection, Query);
283
protected override bool AcceptChildItem (Item item)
285
if (FirstController.Selection.IsAction ()) {
286
Act action = FirstController.Selection.AsAction ();
287
return action.Safe.SupportsItem (item);