4 using System
.Collections
;
9 public abstract class Category
: Container
{
14 protected Gtk
.HBox header
;
15 Gtk
.Label headerLabel
, position
;
16 Gtk
.Button prev
, next
;
17 int fewRows
, manyRows
, columns
;
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
);
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);
38 prev
= MakeButton (header
, Gtk
.Stock
.GoBack
, OnPrev
);
39 next
= MakeButton (header
, Gtk
.Stock
.GoForward
, OnNext
);
43 header
.SizeRequested
+= HeaderSizeRequested
;
45 tiles
= new SortedTileList (SortType
.Relevance
);
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
);
60 button
.Relief
= Gtk
.ReliefStyle
.None
;
61 button
.Clicked
+= handler
;
63 header
.PackStart (button
, false, false, 0);
69 protected int Columns
{
76 few
= fewRows
* columns
;
77 many
= manyRows
* columns
;
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
;
99 if (tiles
.Count
<= FirstVisible
&& page
> 0) {
100 // The page we were viewing disappeared
104 prev
.Sensitive
= (page
!= 0);
105 next
.Sensitive
= (tiles
.Count
> LastVisible
+ 1);
107 if (tiles
.Count
> 0) {
108 if (FirstVisible
== 0 && LastVisible
+ 1 == tiles
.Count
)
109 position
.LabelProp
= String
.Format (Catalog
.GetPluralString ("{0} result", "{0} results", tiles
.Count
), tiles
.Count
);
111 position
.LabelProp
= String
.Format (Catalog
.GetString ("{0}-{1} of {2}"), FirstVisible
+ 1, LastVisible
+ 1, tiles
.Count
);
113 position
.LabelProp
= "";
116 protected override void OnAdded (Gtk
.Widget widget
)
119 widget
.ChildVisible
= false;
120 tiles
.Add ((Tiles
.Tile
)widget
);
121 widget
.Parent
= this;
125 protected override void OnRemoved (Gtk
.Widget widget
)
128 tiles
.Remove ((Tiles
.Tile
)widget
);
133 private Tiles
.Tile lastTarget
;
134 private bool hadFocus
;
139 foreach (Tiles
.Tile tile
in VisibleTiles
) {
140 if (tile
.HasFocus
|| lastTarget
== null) {
142 hadFocus
= tile
.HasFocus
;
144 tile
.ChildVisible
= false;
149 void ShowTiles (bool recenter
)
151 if (recenter
&& lastTarget
!= null) {
152 int index
= tiles
.IndexOf (lastTarget
);
153 if (hadFocus
|| page
> 0) {
157 page
= index
/ (manyRows
* columns
);
159 page
= ((index
- few
) / (manyRows
* columns
)) + 1;
163 foreach (Tiles
.Tile tile
in VisibleTiles
) {
164 tile
.ChildVisible
= true;
165 if (tile
== lastTarget
&& hadFocus
&& !tile
.HasFocus
)
173 private bool showingMany
{
175 // Show extra tiles on every page after the first, unless
176 // there are only two pages and the second one only has
177 // enough tiles to fit the "fewer" size.
178 return (page
> 0 && tiles
.Count
> 2 * few
) || expanded
;
182 void OnPrev (object obj
, EventArgs args
)
189 void OnNext (object obj
, EventArgs args
)
196 protected int PageSize
{
198 return Math
.Min (showingMany
? many
: few
, tiles
.Count
);
202 protected int FirstVisible
{
209 return few
+ (page
- 1) * many
;
213 protected int LastVisible
{
215 return Math
.Min (FirstVisible
+ PageSize
, tiles
.Count
) - 1;
219 protected IList VisibleTiles
{
221 return tiles
.GetRange (FirstVisible
, LastVisible
- FirstVisible
+ 1);
225 public IEnumerable AllTiles
{
231 protected override void ForAll (bool include_internals
, Callback callback
)
233 foreach (Widget w
in (SortedTileList
)tiles
.Clone ())
235 if (include_internals
)
239 protected override bool OnExposeEvent (Gdk
.EventExpose evt
)
241 Rectangle headerRect
, bgRect
;
242 int headerHeight
= header
.Allocation
.Height
;
243 Gdk
.Color white
, bg
, mid
;
245 headerRect
= bgRect
= Allocation
;
246 headerRect
.Height
= headerHeight
;
247 bgRect
.Y
+= headerHeight
;
248 bgRect
.Height
-= headerHeight
;
250 GdkWindow
.DrawRectangle (Style
.BaseGC (State
), true, bgRect
);
252 white
= Style
.Base (State
);
253 bg
= Style
.Background (State
);
255 mid
= new Gdk
.Color ();
256 mid
.Red
= (ushort)((white
.Red
+ bg
.Red
) / 2);
257 mid
.Green
= (ushort)((white
.Green
+ bg
.Green
) / 2);
258 mid
.Blue
= (ushort)((white
.Blue
+ bg
.Blue
) / 2);
259 Style
.BaseGC (State
).RgbFgColor
= mid
;
260 GdkWindow
.DrawRectangle (Style
.BaseGC (State
), true, headerRect
);
261 Style
.BaseGC (State
).Foreground
= white
;
263 return base.OnExposeEvent (evt
);
268 while (tiles
.Count
> 0)
269 Remove (tiles
[tiles
.Count
- 1]);
274 return tiles
.Count
== 0;
284 public Search
.SortType Sort
{
292 public void Select (bool focus
, bool expanded
)
296 this.expanded
= expanded
;
300 ((Gtk
.Widget
)VisibleTiles
[0]).GrabFocus ();