cvsimport
[beagle.git] / search / Category.cs
blob41b264aaca18e729b0eef1d931b76615bc881496
1 using Gtk;
2 using Gdk;
3 using System;
4 using System.Collections;
5 using Mono.Unix;
7 namespace Search {
9 public abstract class Category : Container {
11 SortedTileList tiles;
12 int page;
14 protected Gtk.HBox header;
15 Gtk.Label position;
16 Gtk.Button prev, next;
17 Gtk.Expander headerExpander;
18 int fewRows, manyRows, columns;
19 int few, many;
20 bool extended, expanded;
21 ScopeType scope;
23 public Category (Tiles.TileGroupInfo info, int columns)
25 WidgetFlags |= WidgetFlags.NoWindow;
27 header = new Gtk.HBox (false, 0);
29 headerExpander = new Gtk.Expander ("<big><b>" + GLib.Markup.EscapeText (info.Name) + "</b></big>");
30 ((Gtk.Label) headerExpander.LabelWidget).SetAlignment (0.0f, 0.5f);
31 headerExpander.UseMarkup = true;
32 headerExpander.UseUnderline = true;
33 headerExpander.Show ();
34 header.PackStart (headerExpander, true, true, 0);
36 headerExpander.Activated += OnActivated;
38 scope = Tiles.Utils.TileGroupToScopeType(info.Group);
40 position = new Gtk.Label ();
41 position.ModifyFg (Gtk.StateType.Normal, position.Style.Base (Gtk.StateType.Selected));
42 header.PackStart (position, false, false, 0);
43 position.Show ();
45 prev = MakeButton (header, Gtk.Stock.GoBack, OnPrev);
46 next = MakeButton (header, Gtk.Stock.GoForward, OnNext);
48 header.Show ();
49 header.Parent = this;
50 header.SizeRequested += HeaderSizeRequested;
52 tiles = new SortedTileList (SortType.Relevance);
53 page = 0;
55 fewRows = info.Rows;
56 manyRows = info.Rows * 2;
57 Columns = columns;
59 UpdateButtons ();
60 //headerExpander.Expanded = true;
61 Expanded = true;
64 private Gtk.Button MakeButton (Gtk.HBox header, string icon, EventHandler handler)
66 Gtk.Button button = new Gtk.Button ();
67 Gtk.Image img = new Gtk.Image (icon, Gtk.IconSize.Button);
68 button.Add (img);
69 button.Relief = Gtk.ReliefStyle.None;
70 button.Clicked += handler;
72 header.PackStart (button, false, false, 0);
73 button.ShowAll ();
75 return button;
78 public bool Expanded {
79 get {
80 return expanded;
82 set {
83 expanded = value;
84 if (expanded)
85 ShowTiles (false);
86 else
87 HideTiles ();
88 headerExpander.Expanded = expanded;
92 protected int Columns {
93 get {
94 return columns;
96 set {
97 HideTiles ();
98 columns = value;
99 few = fewRows * columns;
100 many = manyRows * columns;
101 ShowTiles (true);
105 void HeaderSizeRequested (object obj, Gtk.SizeRequestedArgs args)
107 Gtk.Requisition req = args.Requisition;
108 Gtk.Requisition labelReq = headerExpander.ChildRequisition;
110 req.Height = (int) (labelReq.Height * 1.5);
112 int icon_height, icon_width;
114 if (Gtk.Icon.SizeLookup (Gtk.IconSize.Button, out icon_height, out icon_width) && req.Height < icon_height * 1.5)
115 req.Height = (int) (icon_height * 1.5);
117 args.Requisition = req;
120 void UpdateButtons ()
122 if (tiles.Count <= FirstVisible && page > 0) {
123 // The page we were viewing disappeared
124 page--;
127 prev.Sensitive = (page != 0);
128 next.Sensitive = (tiles.Count > LastVisible + 1);
130 if (tiles.Count > 0) {
131 if (FirstVisible == 0 && LastVisible + 1 == tiles.Count)
132 position.LabelProp = String.Format (Catalog.GetPluralString ("{0} result", "{0} results", tiles.Count), tiles.Count);
133 else
134 position.LabelProp = String.Format (Catalog.GetString ("{0}-{1} of {2}"), FirstVisible + 1, LastVisible + 1, tiles.Count);
135 } else
136 position.LabelProp = "";
139 protected override void OnAdded (Gtk.Widget widget)
141 HideTiles ();
142 widget.ChildVisible = false;
143 tiles.Add ((Tiles.Tile)widget);
144 widget.Parent = this;
145 if (Expanded)
146 ShowTiles (true);
149 protected override void OnRemoved (Gtk.Widget widget)
151 HideTiles ();
152 tiles.Remove ((Tiles.Tile)widget);
153 widget.Unparent ();
154 if (Expanded)
155 ShowTiles (true);
158 private Tiles.Tile lastTarget;
159 private bool hadFocus;
161 void HideTiles ()
163 lastTarget = null;
164 foreach (Tiles.Tile tile in VisibleTiles) {
165 if (tile.HasFocus || lastTarget == null) {
166 lastTarget = tile;
167 hadFocus = tile.HasFocus;
169 tile.ChildVisible = false;
171 QueueResize ();
174 void ShowTiles (bool recenter)
176 if (recenter && lastTarget != null) {
177 int index = tiles.IndexOf (lastTarget);
178 if (hadFocus || page > 0) {
179 if (index < few)
180 page = 0;
181 else if (extended)
182 page = index / (manyRows * columns);
183 else
184 page = ((index - few) / (manyRows * columns)) + 1;
188 foreach (Tiles.Tile tile in VisibleTiles) {
189 tile.ChildVisible = true;
190 if (tile == lastTarget && hadFocus && !tile.HasFocus)
191 tile.GrabFocus ();
194 UpdateButtons ();
195 QueueResize ();
198 private bool showingMany {
199 get {
200 // Show extra tiles on every page after the first, unless
201 // there are only two pages and the second one only has
202 // enough tiles to fit the "fewer" size.
203 return (page > 0 && tiles.Count > 2 * few) || extended;
207 void OnPrev (object obj, EventArgs args)
209 HideTiles ();
210 page--;
211 if (!Expanded)
212 OnActivated (obj, args);
213 else
214 ShowTiles (false);
217 void OnNext (object obj, EventArgs args)
219 HideTiles ();
220 page++;
221 if (!Expanded)
222 OnActivated (obj, args);
223 else
224 ShowTiles (false);
227 protected void OnActivated (object obj, EventArgs args)
229 Expanded = !Expanded;
230 CategoryToggle (scope);
233 public delegate void CategoryToggleDelegate (ScopeType scope);
234 public event CategoryToggleDelegate CategoryToggle;
236 protected int PageSize {
237 get {
238 return Math.Min (showingMany ? many : few, tiles.Count);
242 protected int FirstVisible {
243 get {
244 if (page == 0)
245 return 0;
246 else if (extended)
247 return page * many;
248 else
249 return few + (page - 1) * many;
253 protected int LastVisible {
254 get {
255 return Math.Min (FirstVisible + PageSize, tiles.Count) - 1;
259 protected IList VisibleTiles {
260 get {
261 return tiles.GetRange (FirstVisible, LastVisible - FirstVisible + 1);
265 public IEnumerable AllTiles {
266 get {
267 return tiles;
271 protected override void ForAll (bool include_internals, Callback callback)
273 foreach (Widget w in (SortedTileList)tiles.Clone ())
274 callback (w);
275 if (include_internals)
276 callback (header);
279 protected override bool OnExposeEvent (Gdk.EventExpose evt)
281 Rectangle headerRect, bgRect;
282 int headerHeight = header.Allocation.Height;
283 Gdk.Color white, bg, mid;
285 headerRect = bgRect = Allocation;
286 headerRect.Height = headerHeight;
287 bgRect.Y += headerHeight;
288 bgRect.Height -= headerHeight;
290 GdkWindow.DrawRectangle (Style.BaseGC (State), true, bgRect);
292 white = Style.Base (State);
293 bg = Style.Background (State);
295 mid = new Gdk.Color ();
296 mid.Red = (ushort)((white.Red + bg.Red) / 2);
297 mid.Green = (ushort)((white.Green + bg.Green) / 2);
298 mid.Blue = (ushort)((white.Blue + bg.Blue) / 2);
299 Style.BaseGC (State).RgbFgColor = mid;
300 GdkWindow.DrawRectangle (Style.BaseGC (State), true, headerRect);
301 Style.BaseGC (State).Foreground = white;
303 return base.OnExposeEvent (evt);
306 public void Clear ()
308 while (tiles.Count > 0)
309 Remove (tiles[tiles.Count - 1]);
312 public bool Empty {
313 get {
314 return tiles.Count == 0;
318 public int Count {
319 get {
320 return tiles.Count;
324 public Search.SortType Sort {
325 set {
326 HideTiles ();
327 tiles.Sort = value;
328 ShowTiles (true);
332 public void Select (bool focus, bool extended)
334 if (extended) {
335 HideTiles ();
336 this.extended = extended;
337 ShowTiles (false);
339 if (focus && !Empty)
340 ((Gtk.Widget)VisibleTiles[0]).GrabFocus ();