2006-02-27 Gabor Kelemen <kelemeng@gnome.hu>
[beagle.git] / search / Category.cs
blobedced6030e54ea510effe533c3607ab55ae04005
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 headerLabel, position;
16 Gtk.Button prev, next;
17 int fewRows, manyRows, columns;
18 int few, many;
19 bool expanded;
21 public Category (string name, int rows, int columns)
23 WidgetFlags |= WidgetFlags.NoWindow;
25 header = new Gtk.HBox (false, 0);
27 headerLabel = new Gtk.Label ();
28 headerLabel.Markup = "<big><b>" + GLib.Markup.EscapeText (name) + "</b></big>";
29 headerLabel.SetAlignment (0.0f, 0.5f);
30 headerLabel.Show ();
31 header.PackStart (headerLabel, true, true, 0);
33 position = new Gtk.Label ();
34 position.ModifyFg (Gtk.StateType.Normal, position.Style.Base (Gtk.StateType.Selected));
35 header.PackStart (position, false, false, 0);
36 position.Show ();
38 prev = MakeButton (header, Gtk.Stock.GoBack, OnPrev);
39 next = MakeButton (header, Gtk.Stock.GoForward, OnNext);
41 header.Show ();
42 header.Parent = this;
43 header.SizeRequested += HeaderSizeRequested;
45 tiles = new SortedTileList (SortType.Relevance);
46 page = 0;
48 fewRows = rows;
49 manyRows = rows * 2;
50 Columns = columns;
52 UpdateButtons ();
55 private Gtk.Button MakeButton (Gtk.HBox header, string icon, EventHandler handler)
57 Gtk.Button button = new Gtk.Button ();
58 Gtk.Image img = new Gtk.Image (icon, Gtk.IconSize.Button);
59 button.Add (img);
60 button.Relief = Gtk.ReliefStyle.None;
61 button.Clicked += handler;
63 header.PackStart (button, false, false, 0);
64 button.ShowAll ();
66 return button;
69 protected int Columns {
70 get {
71 return columns;
73 set {
74 HideTiles ();
76 if (page > 0) {
77 // Adjust page so that the first visible tile
78 // remains visible
79 if (expanded)
80 page = FirstVisible / (manyRows * value);
81 else
82 page = ((FirstVisible - few) / (manyRows * value)) + 1;
85 columns = value;
86 few = fewRows * columns;
87 many = manyRows * columns;
89 UpdateButtons ();
90 ShowTiles ();
91 QueueResize ();
95 void HeaderSizeRequested (object obj, Gtk.SizeRequestedArgs args)
97 Gtk.Requisition req = args.Requisition;
98 Gtk.Requisition labelReq = headerLabel.ChildRequisition;
100 req.Height = (int)(labelReq.Height * 1.5);
102 args.Requisition = req;
105 void UpdateButtons ()
107 if (tiles.Count <= FirstVisible && page > 0) {
108 // The page we were viewing disappeared
109 page--;
112 prev.Sensitive = (page != 0);
113 next.Sensitive = (tiles.Count > LastVisible + 1);
115 if (tiles.Count > 0)
116 position.LabelProp = String.Format (Catalog.GetString ("{0}-{1} of {2}"), FirstVisible + 1, LastVisible + 1, tiles.Count);
117 else
118 position.LabelProp = "";
121 protected override void OnAdded (Gtk.Widget widget)
123 widget.ChildVisible = false;
124 HideTiles ();
125 tiles.Add ((Tiles.Tile)widget);
126 widget.Parent = this;
127 ShowTiles ();
129 UpdateButtons ();
132 protected override void OnRemoved (Gtk.Widget widget)
134 tiles.Remove ((Tiles.Tile)widget);
135 widget.Unparent ();
136 ShowTiles ();
138 UpdateButtons ();
141 void HideTiles ()
143 foreach (Widget tile in VisibleTiles)
144 tile.ChildVisible = false;
145 QueueResize ();
148 void ShowTiles ()
150 foreach (Widget tile in VisibleTiles)
151 tile.ChildVisible = true;
152 QueueResize ();
155 private bool showingMany {
156 get {
157 // Show extra tiles on every page after the first, unless
158 // there are only two pages and the second one only has
159 // enough tiles to fit the "fewer" size.
160 return (page > 0 && tiles.Count > 2 * few) || expanded;
164 void OnPrev (object obj, EventArgs args)
166 HideTiles ();
167 page--;
168 ShowTiles ();
169 UpdateButtons ();
172 void OnNext (object obj, EventArgs args)
174 HideTiles ();
175 page++;
176 ShowTiles ();
177 UpdateButtons ();
180 protected int PageSize {
181 get {
182 return Math.Min (showingMany ? many : few, tiles.Count);
186 protected int FirstVisible {
187 get {
188 if (page == 0)
189 return 0;
190 else if (expanded)
191 return page * many;
192 else
193 return few + (page - 1) * many;
197 protected int LastVisible {
198 get {
199 return Math.Min (FirstVisible + PageSize, tiles.Count) - 1;
203 protected IList VisibleTiles {
204 get {
205 return tiles.GetRange (FirstVisible, LastVisible - FirstVisible + 1);
209 public IEnumerable AllTiles {
210 get {
211 return tiles;
215 protected override void ForAll (bool include_internals, Callback callback)
217 foreach (Widget w in (SortedTileList)tiles.Clone ())
218 callback (w);
219 if (include_internals)
220 callback (header);
223 protected override bool OnExposeEvent (Gdk.EventExpose evt)
225 Rectangle headerRect, bgRect;
226 int headerHeight = header.Allocation.Height;
227 Gdk.Color white, bg, mid;
229 headerRect = bgRect = Allocation;
230 headerRect.Height = headerHeight;
231 bgRect.Y += headerHeight;
232 bgRect.Height -= headerHeight;
234 GdkWindow.DrawRectangle (Style.BaseGC (State), true, bgRect);
236 white = Style.Base (State);
237 bg = Style.Background (State);
239 mid = new Gdk.Color ();
240 mid.Red = (ushort)((white.Red + bg.Red) / 2);
241 mid.Green = (ushort)((white.Green + bg.Green) / 2);
242 mid.Blue = (ushort)((white.Blue + bg.Blue) / 2);
243 Style.BaseGC (State).RgbFgColor = mid;
244 GdkWindow.DrawRectangle (Style.BaseGC (State), true, headerRect);
245 Style.BaseGC (State).Foreground = white;
247 return base.OnExposeEvent (evt);
250 public void Clear ()
252 while (tiles.Count > 0)
253 Remove (tiles[tiles.Count - 1]);
256 public bool Empty {
257 get {
258 return tiles.Count == 0;
262 public int Count {
263 get {
264 return tiles.Count;
268 public Search.SortType Sort {
269 set {
270 HideTiles ();
271 tiles.Sort = value;
272 ShowTiles ();
276 public void Select (bool focus, bool expanded)
278 if (focus && !Empty)
279 ((Gtk.Widget)VisibleTiles[0]).GrabFocus ();
280 this.expanded = expanded;