* Filters/FilterPackage.cs, Filters/FilterRPM.cs,
[beagle.git] / search / Category.cs
blob1bfe6a39669aaa8d1c5bdb6c0f5cd9dbab0a70ff
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 ();
75 columns = value;
76 few = fewRows * columns;
77 many = manyRows * columns;
78 ShowTiles (true);
82 void HeaderSizeRequested (object obj, Gtk.SizeRequestedArgs args)
84 Gtk.Requisition req = args.Requisition;
85 Gtk.Requisition labelReq = headerLabel.ChildRequisition;
87 req.Height = (int) (labelReq.Height * 1.5);
89 int icon_height, icon_width;
91 if (Gtk.Icon.SizeLookup (Gtk.IconSize.Button, out icon_height, out icon_width) && req.Height < icon_height * 1.5)
92 req.Height = (int) (icon_height * 1.5);
94 args.Requisition = req;
97 void UpdateButtons ()
99 if (tiles.Count <= FirstVisible && page > 0) {
100 // The page we were viewing disappeared
101 page--;
104 prev.Sensitive = (page != 0);
105 next.Sensitive = (tiles.Count > LastVisible + 1);
107 if (tiles.Count > 0)
108 position.LabelProp = String.Format (Catalog.GetString ("{0}-{1} of {2}"), FirstVisible + 1, LastVisible + 1, tiles.Count);
109 else
110 position.LabelProp = "";
113 protected override void OnAdded (Gtk.Widget widget)
115 HideTiles ();
116 widget.ChildVisible = false;
117 tiles.Add ((Tiles.Tile)widget);
118 widget.Parent = this;
119 ShowTiles (true);
122 protected override void OnRemoved (Gtk.Widget widget)
124 HideTiles ();
125 tiles.Remove ((Tiles.Tile)widget);
126 widget.Unparent ();
127 ShowTiles (true);
130 private Tiles.Tile lastTarget;
131 private bool hadFocus;
133 void HideTiles ()
135 lastTarget = null;
136 foreach (Tiles.Tile tile in VisibleTiles) {
137 if (tile.HasFocus || lastTarget == null) {
138 lastTarget = tile;
139 hadFocus = tile.HasFocus;
141 tile.ChildVisible = false;
143 QueueResize ();
146 void ShowTiles (bool recenter)
148 if (recenter && lastTarget != null) {
149 int index = tiles.IndexOf (lastTarget);
150 if (hadFocus || page > 0) {
151 if (index < few)
152 page = 0;
153 else if (expanded)
154 page = index / (manyRows * columns);
155 else
156 page = ((index - few) / (manyRows * columns)) + 1;
160 foreach (Tiles.Tile tile in VisibleTiles) {
161 tile.ChildVisible = true;
162 if (tile == lastTarget && hadFocus && !tile.HasFocus)
163 tile.GrabFocus ();
166 UpdateButtons ();
167 QueueResize ();
170 private bool showingMany {
171 get {
172 // Show extra tiles on every page after the first, unless
173 // there are only two pages and the second one only has
174 // enough tiles to fit the "fewer" size.
175 return (page > 0 && tiles.Count > 2 * few) || expanded;
179 void OnPrev (object obj, EventArgs args)
181 HideTiles ();
182 page--;
183 ShowTiles (false);
186 void OnNext (object obj, EventArgs args)
188 HideTiles ();
189 page++;
190 ShowTiles (false);
193 protected int PageSize {
194 get {
195 return Math.Min (showingMany ? many : few, tiles.Count);
199 protected int FirstVisible {
200 get {
201 if (page == 0)
202 return 0;
203 else if (expanded)
204 return page * many;
205 else
206 return few + (page - 1) * many;
210 protected int LastVisible {
211 get {
212 return Math.Min (FirstVisible + PageSize, tiles.Count) - 1;
216 protected IList VisibleTiles {
217 get {
218 return tiles.GetRange (FirstVisible, LastVisible - FirstVisible + 1);
222 public IEnumerable AllTiles {
223 get {
224 return tiles;
228 protected override void ForAll (bool include_internals, Callback callback)
230 foreach (Widget w in (SortedTileList)tiles.Clone ())
231 callback (w);
232 if (include_internals)
233 callback (header);
236 protected override bool OnExposeEvent (Gdk.EventExpose evt)
238 Rectangle headerRect, bgRect;
239 int headerHeight = header.Allocation.Height;
240 Gdk.Color white, bg, mid;
242 headerRect = bgRect = Allocation;
243 headerRect.Height = headerHeight;
244 bgRect.Y += headerHeight;
245 bgRect.Height -= headerHeight;
247 GdkWindow.DrawRectangle (Style.BaseGC (State), true, bgRect);
249 white = Style.Base (State);
250 bg = Style.Background (State);
252 mid = new Gdk.Color ();
253 mid.Red = (ushort)((white.Red + bg.Red) / 2);
254 mid.Green = (ushort)((white.Green + bg.Green) / 2);
255 mid.Blue = (ushort)((white.Blue + bg.Blue) / 2);
256 Style.BaseGC (State).RgbFgColor = mid;
257 GdkWindow.DrawRectangle (Style.BaseGC (State), true, headerRect);
258 Style.BaseGC (State).Foreground = white;
260 return base.OnExposeEvent (evt);
263 public void Clear ()
265 while (tiles.Count > 0)
266 Remove (tiles[tiles.Count - 1]);
269 public bool Empty {
270 get {
271 return tiles.Count == 0;
275 public int Count {
276 get {
277 return tiles.Count;
281 public Search.SortType Sort {
282 set {
283 HideTiles ();
284 tiles.Sort = value;
285 ShowTiles (true);
289 public void Select (bool focus, bool expanded)
291 if (expanded) {
292 HideTiles ();
293 this.expanded = expanded;
294 ShowTiles (false);
296 if (focus && !Empty)
297 ((Gtk.Widget)VisibleTiles[0]).GrabFocus ();