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);
108 position
.LabelProp
= String
.Format (Catalog
.GetString ("{0}-{1} of {2}"), FirstVisible
+ 1, LastVisible
+ 1, tiles
.Count
);
110 position
.LabelProp
= "";
113 protected override void OnAdded (Gtk
.Widget widget
)
116 widget
.ChildVisible
= false;
117 tiles
.Add ((Tiles
.Tile
)widget
);
118 widget
.Parent
= this;
122 protected override void OnRemoved (Gtk
.Widget widget
)
125 tiles
.Remove ((Tiles
.Tile
)widget
);
130 private Tiles
.Tile lastTarget
;
131 private bool hadFocus
;
136 foreach (Tiles
.Tile tile
in VisibleTiles
) {
137 if (tile
.HasFocus
|| lastTarget
== null) {
139 hadFocus
= tile
.HasFocus
;
141 tile
.ChildVisible
= false;
146 void ShowTiles (bool recenter
)
148 if (recenter
&& lastTarget
!= null) {
149 int index
= tiles
.IndexOf (lastTarget
);
150 if (hadFocus
|| page
> 0) {
154 page
= index
/ (manyRows
* columns
);
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
)
170 private bool showingMany
{
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
)
186 void OnNext (object obj
, EventArgs args
)
193 protected int PageSize
{
195 return Math
.Min (showingMany
? many
: few
, tiles
.Count
);
199 protected int FirstVisible
{
206 return few
+ (page
- 1) * many
;
210 protected int LastVisible
{
212 return Math
.Min (FirstVisible
+ PageSize
, tiles
.Count
) - 1;
216 protected IList VisibleTiles
{
218 return tiles
.GetRange (FirstVisible
, LastVisible
- FirstVisible
+ 1);
222 public IEnumerable AllTiles
{
228 protected override void ForAll (bool include_internals
, Callback callback
)
230 foreach (Widget w
in (SortedTileList
)tiles
.Clone ())
232 if (include_internals
)
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
);
265 while (tiles
.Count
> 0)
266 Remove (tiles
[tiles
.Count
- 1]);
271 return tiles
.Count
== 0;
281 public Search
.SortType Sort
{
289 public void Select (bool focus
, bool expanded
)
293 this.expanded
= expanded
;
297 ((Gtk
.Widget
)VisibleTiles
[0]).GrabFocus ();