Add example code to use beagle as a service provider.
[beagle.git] / Renderers / HitRenderer.cs
blob8a0afd8c8e491fb9b93bd27d726ac3d7d16f0724
1 //
2 // HitRenderer.cs
3 //
4 // Copyright (C) 2004 Novell, Inc.
5 //
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in all
16 // copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 // SOFTWARE.
28 using System;
29 using System.Collections;
31 namespace Beagle {
33 public abstract class HitRenderer {
35 public delegate void RefreshHandler (HitRenderer hr);
36 public event RefreshHandler RefreshEvent;
38 protected virtual bool ProcessHit (Hit hit)
40 return true;
43 protected virtual void ProcessClear ()
44 { }
47 // Widgety Goodness
50 public abstract Gtk.Widget Widget { get; }
51 protected abstract void DoRefresh ();
53 private uint timeoutId;
55 public void Refresh ()
57 lock (this) {
58 if (timeoutId != 0) {
59 GLib.Source.Remove (timeoutId);
60 timeoutId = 0;
62 DoRefresh ();
63 if (RefreshEvent != null)
64 RefreshEvent (this);
68 public void Flush ()
70 lock (this) {
71 if (timeoutId != 0)
72 Refresh ();
76 private bool HandleScheduled ()
78 lock (this) {
79 timeoutId = 0;
80 Refresh ();
82 return false;
85 public void ScheduleRefresh (uint time)
87 lock (this) {
88 if (timeoutId != 0)
89 return;
91 if (time == 0) {
92 GLib.IdleHandler handler;
93 handler = new GLib.IdleHandler (HandleScheduled);
94 timeoutId = GLib.Idle.Add (handler);
95 } else {
96 GLib.TimeoutHandler handler;
97 handler = new GLib.TimeoutHandler (HandleScheduled);
98 timeoutId = GLib.Timeout.Add (time, handler);
104 // Collect & Manage Hits
107 private ArrayList hits = new ArrayList ();
109 private int first = 0;
110 private int displayedCount = 10;
112 public int FirstDisplayed {
113 get { return first; }
115 set {
116 int f = (int) value;
117 f = Math.Max (0, Math.Min (f, hits.Count - displayedCount));
118 if (f != first) {
119 first = f;
120 ScheduleRefresh (0);
125 public int LastDisplayed {
126 get { return FirstDisplayed + DisplayedCount - 1; }
129 public int DisplayedCount {
130 get {
131 int n = hits.Count - first;
132 if (n < 0)
133 return 0;
134 if (n > displayedCount)
135 n = displayedCount;
136 return n;
139 set {
140 int dc = (int) value;
141 if (dc != displayedCount) {
142 displayedCount = dc;
143 ScheduleRefresh (0);
149 public void DisplayFirst ()
151 FirstDisplayed = 0;
154 public void DisplayPrev ()
156 FirstDisplayed -= displayedCount;
159 public void DisplayNext ()
161 FirstDisplayed += displayedCount;
164 public void DisplayLast ()
166 FirstDisplayed = hits.Count;
169 /////////////////////////////////////
172 public IList Hits {
173 get { return hits; }
176 public int TotalCount {
177 get { return hits.Count; }
180 public float MaxScore {
181 get {
182 if (hits.Count > 0)
183 return ((Hit) hits [0]).Score;
184 return 0;
188 public void Clear ()
190 lock (this) {
191 ProcessClear ();
192 hits.Clear ();
194 ScheduleRefresh (0);
197 // Return true if we need a refresh after this add.
198 private bool AddInRightPlace (Hit hit)
200 if (hits.Count == 0) {
201 hits.Add (hit);
202 if (first == 0)
203 return true;
204 } else {
205 int i = hits.BinarySearch (hit);
206 hits.Insert (i < 0 ? ~i : i, hit);
207 if (hits.Count >= first && i < first + displayedCount)
208 return true;
211 return false;
214 public void Add (Hit hit)
216 bool needRefresh = false;
217 lock (this) {
218 if (ProcessHit (hit))
219 needRefresh = AddInRightPlace (hit);
222 // ScheduleRefresh needs to acquire a lock,
223 // so we wait until hits is unlocked before
224 // calling it.
225 if (needRefresh)
226 ScheduleRefresh (100);
229 public void Add (ICollection _hits)
231 bool needRefresh = false;
232 lock (this) {
233 foreach (Hit hit in _hits)
234 if (ProcessHit (hit))
235 if (AddInRightPlace (hit))
236 needRefresh = true;
239 // Again, we do this here to avoid a potential
240 // deadlock.
241 if (needRefresh)
242 ScheduleRefresh (50);