[hyena] Sync Hyena.Gui with Banshee
- From: Gabriel Burt <gburt src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [hyena] Sync Hyena.Gui with Banshee
- Date: Tue, 12 Jan 2010 20:24:08 +0000 (UTC)
commit c92fb23f08b9bcc5ed58af0f4f55d0637ff649e8
Author: Gabriel Burt <gabriel burt gmail com>
Date: Tue Jan 12 12:15:19 2010 -0800
Sync Hyena.Gui with Banshee
.../Accessibility/ColumnCellAccessible.cs | 151 +++++++++++
.../Accessibility/ColumnCellTextAccessible.cs | 40 +++
.../ColumnHeaderCellTextAccessible.cs | 114 +++++++++
.../Accessibility/ICellAccessibleParent.cs | 45 ++++
.../Accessibility/ListViewAccessible.cs | 245 ++++++++++++++++++
.../Accessibility/ListViewAccessible_Selection.cs | 92 +++++++
.../Accessibility/ListViewAccessible_Table.cs | 192 ++++++++++++++
src/Hyena.Gui/Hyena.Data.Gui/CellContext.cs | 8 +-
src/Hyena.Gui/Hyena.Data.Gui/ColumnCell.cs | 12 +
src/Hyena.Gui/Hyena.Data.Gui/ColumnCellRating.cs | 10 +
src/Hyena.Gui/Hyena.Data.Gui/ColumnCellText.cs | 27 ++-
.../Hyena.Data.Gui/ColumnHeaderCellText.cs | 7 +
.../Hyena.Data.Gui/ListView/ListView_Accessible.cs | 177 +++++++++++++
.../Hyena.Data.Gui/ListView/ListView_Header.cs | 57 +++++-
.../ListView/ListView_Interaction.cs | 156 +++++++++----
.../Hyena.Data.Gui/ListView/ListView_Model.cs | 53 ++--
.../Hyena.Data.Gui/ListView/ListView_Rendering.cs | 53 +++--
.../Hyena.Data.Gui/ListView/ListView_Windowing.cs | 4 +
src/Hyena.Gui/Hyena.Gui.Dialogs/ExceptionDialog.cs | 1 +
src/Hyena.Gui/Hyena.Gui.Theming/GtkTheme.cs | 63 +++++-
src/Hyena.Gui/Hyena.Gui.Theming/Theme.cs | 20 ++-
src/Hyena.Gui/Hyena.Gui/BaseWidgetAccessible.cs | 262 ++++++++++++++++++++
src/Hyena.Gui/Hyena.Widgets/AnimatedWidget.cs | 7 +-
src/Hyena.Gui/Hyena.Widgets/EntryPopup.cs | 226 +++++++++++++++++
src/Hyena.Gui/Hyena.Widgets/HigMessageDialog.cs | 11 +-
src/Hyena.Gui/Hyena.Widgets/ImageButton.cs | 18 ++-
src/Hyena.Gui/Hyena.Widgets/MenuButton.cs | 1 +
src/Hyena.Gui/Hyena.Widgets/MessageBar.cs | 5 +-
src/Hyena.Gui/Hyena.Widgets/RatingEntry.cs | 79 ++++++
src/Hyena.Gui/Hyena.Widgets/SimpleTable.cs | 103 ++++++++
src/Hyena.Gui/Hyena.Widgets/WrapLabel.cs | 7 +-
src/Hyena.Gui/Makefile.am | 11 +
32 files changed, 2131 insertions(+), 126 deletions(-)
---
diff --git a/src/Hyena.Gui/Hyena.Data.Gui/Accessibility/ColumnCellAccessible.cs b/src/Hyena.Gui/Hyena.Data.Gui/Accessibility/ColumnCellAccessible.cs
new file mode 100644
index 0000000..f0e797a
--- /dev/null
+++ b/src/Hyena.Gui/Hyena.Data.Gui/Accessibility/ColumnCellAccessible.cs
@@ -0,0 +1,151 @@
+//
+// ColumnCellAccessible.cs
+//
+// Author:
+// Eitan Isaacson <eitan ascender com>
+//
+// Copyright (C) 2009 Eitan Isaacson.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+
+namespace Hyena.Data.Gui.Accessibility
+{
+ public class ColumnCellAccessible: Atk.Object, Atk.ComponentImplementor
+ {
+ protected ColumnCell cell;
+ protected object bound_object;
+ private ICellAccessibleParent cell_parent;
+
+ public ColumnCellAccessible (object bound_object, ColumnCell cell, ICellAccessibleParent parent)
+ {
+ Role = Atk.Role.TableCell;
+ this.bound_object = bound_object;
+ this.cell = cell;
+ cell_parent = parent;
+ Parent = (Atk.Object) parent;
+ }
+
+#if ENABLE_ATK
+ protected override Atk.StateSet OnRefStateSet ()
+ {
+ Atk.StateSet states = base.OnRefStateSet ();
+ states.AddState (Atk.StateType.Transient);
+ states.AddState (Atk.StateType.Focusable);
+ states.AddState (Atk.StateType.Enabled);
+ states.AddState (Atk.StateType.Sensitive);
+ states.AddState (Atk.StateType.Visible);
+
+ if (cell_parent.IsCellShowing (this))
+ states.AddState (Atk.StateType.Showing);
+
+ if (cell_parent.IsCellFocused (this))
+ states.AddState (Atk.StateType.Focused);
+
+ if (cell_parent.IsCellSelected (this))
+ states.AddState (Atk.StateType.Selected);
+
+ if (cell_parent.IsCellActive (this))
+ states.AddState (Atk.StateType.Active);
+
+ return states;
+ }
+
+ protected override int OnGetIndexInParent ()
+ {
+ return cell_parent.GetCellIndex (this);
+ }
+#endif
+
+ public double Alpha {
+ get { return 1.0; }
+ }
+
+ public bool SetSize (int w, int h)
+ {
+ return false;
+ }
+
+ public bool SetPosition (int x, int y, Atk.CoordType coordType)
+ {
+ return false;
+ }
+
+ public bool SetExtents (int x, int y, int w, int h, Atk.CoordType coordType)
+ {
+ return false;
+ }
+
+ public void RemoveFocusHandler (uint handlerId)
+ {
+ }
+
+ public bool GrabFocus ()
+ {
+ return false;
+ }
+
+ public void GetSize (out int w, out int h)
+ {
+ Gdk.Rectangle rectangle = cell_parent.GetCellExtents(this, Atk.CoordType.Screen);
+ w = rectangle.Width;
+ h = rectangle.Height;
+ }
+
+ public void GetPosition (out int x, out int y, Atk.CoordType coordType)
+ {
+ Gdk.Rectangle rectangle = cell_parent.GetCellExtents(this, coordType);
+
+ x = rectangle.X;
+ y = rectangle.Y;
+ }
+
+ public void GetExtents (out int x, out int y, out int w, out int h, Atk.CoordType coordType)
+ {
+ Gdk.Rectangle rectangle = cell_parent.GetCellExtents(this, coordType);
+
+ x = rectangle.X;
+ y = rectangle.Y;
+ w = rectangle.Width;
+ h = rectangle.Height;
+ }
+
+ public virtual Atk.Object RefAccessibleAtPoint (int x, int y, Atk.CoordType coordType)
+ {
+ return null;
+ }
+
+ public bool Contains (int x, int y, Atk.CoordType coordType)
+ {
+ return false;
+ }
+
+ public uint AddFocusHandler (Atk.FocusHandler handler)
+ {
+ return 0;
+ }
+
+ public virtual void Redrawn ()
+ {
+ }
+ }
+}
diff --git a/src/Hyena.Gui/Hyena.Data.Gui/Accessibility/ColumnCellTextAccessible.cs b/src/Hyena.Gui/Hyena.Data.Gui/Accessibility/ColumnCellTextAccessible.cs
new file mode 100644
index 0000000..76eb0c3
--- /dev/null
+++ b/src/Hyena.Gui/Hyena.Data.Gui/Accessibility/ColumnCellTextAccessible.cs
@@ -0,0 +1,40 @@
+//
+// ColumnCellTextAccessible.cs
+//
+// Author:
+// Eitan Isaacson <eitan ascender com>
+//
+// Copyright (C) 2009 Eitan Isaacson.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+
+namespace Hyena.Data.Gui.Accessibility
+{
+ class ColumnCellTextAccessible : ColumnCellAccessible
+ {
+ public ColumnCellTextAccessible (object bound_object, ColumnCellText cell, ICellAccessibleParent parent): base (bound_object, cell as ColumnCell, parent)
+ {
+ Name = cell.GetTextAlternative (bound_object);
+ }
+ }
+}
diff --git a/src/Hyena.Gui/Hyena.Data.Gui/Accessibility/ColumnHeaderCellTextAccessible.cs b/src/Hyena.Gui/Hyena.Data.Gui/Accessibility/ColumnHeaderCellTextAccessible.cs
new file mode 100644
index 0000000..2b6704f
--- /dev/null
+++ b/src/Hyena.Gui/Hyena.Data.Gui/Accessibility/ColumnHeaderCellTextAccessible.cs
@@ -0,0 +1,114 @@
+//
+// ColumnHeaderCellTextAccessible.cs
+//
+// Author:
+// Eitan Isaacson <eitan ascender com>
+//
+// Copyright (C) 2009 Eitan Isaacson.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using Mono.Unix;
+
+namespace Hyena.Data.Gui.Accessibility
+{
+ class ColumnHeaderCellTextAccessible: ColumnCellTextAccessible, Atk.ActionImplementor
+ {
+ private static string [] action_descriptions = new string[] {"", Catalog.GetString ("open context menu")};
+ private static string [] action_names_localized = new string[] {Catalog.GetString ("click"), Catalog.GetString ("menu")};
+
+ private enum Actions {
+ Click,
+ Menu,
+ Last
+ };
+
+ public ColumnHeaderCellTextAccessible (object bound_object, ColumnHeaderCellText cell, ICellAccessibleParent parent)
+ : base (bound_object, cell as ColumnCellText, parent)
+ {
+ Role = Atk.Role.TableColumnHeader;
+ }
+
+#if ENABLE_ATK
+ protected override Atk.StateSet OnRefStateSet ()
+ {
+ Atk.StateSet states = base.OnRefStateSet ();
+ states.RemoveState (Atk.StateType.Selectable);
+ states.RemoveState (Atk.StateType.Transient);
+ return states;
+ }
+#endif
+
+ public string GetLocalizedName (int action)
+ {
+ if (action >= action_names_localized.Length)
+ return "";
+
+ return action_names_localized[action];
+ }
+
+ public string GetName (int action)
+ {
+ if (action >= (int)Actions.Last)
+ return "";
+
+ return ((Actions)action).ToString ().ToLower ();
+ }
+
+ public string GetDescription (int action)
+ {
+ if (action >= action_descriptions.Length)
+ return "";
+
+ return action_descriptions[action];
+ }
+
+ public string GetKeybinding (int action)
+ {
+ return "";
+ }
+
+ public int NActions {
+ get { return (int)Actions.Last; }
+ }
+
+ public bool DoAction (int action)
+ {
+ ICellAccessibleParent parent = (ICellAccessibleParent)Parent;
+ switch ((Actions)action) {
+ case Actions.Menu: parent.InvokeColumnHeaderMenu (this); break;
+ case Actions.Click: parent.ClickColumnHeader (this); break;
+ }
+
+ if (action == (int)Actions.Menu) {
+ ((ICellAccessibleParent)Parent).InvokeColumnHeaderMenu (this);
+ }
+
+ return true;
+ }
+
+ public bool SetDescription (int action, string description)
+ {
+ return false;
+ }
+ }
+}
diff --git a/src/Hyena.Gui/Hyena.Data.Gui/Accessibility/ICellAccessibleParent.cs b/src/Hyena.Gui/Hyena.Data.Gui/Accessibility/ICellAccessibleParent.cs
new file mode 100644
index 0000000..499a2ab
--- /dev/null
+++ b/src/Hyena.Gui/Hyena.Data.Gui/Accessibility/ICellAccessibleParent.cs
@@ -0,0 +1,45 @@
+//
+// ICellAccessibleParent.cs
+//
+// Author:
+// Eitan Isaacson <eitan ascender com>
+//
+// Copyright (C) 2009 Eitan Isaacson.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+
+namespace Hyena.Data.Gui.Accessibility
+{
+ public interface ICellAccessibleParent
+ {
+ Gdk.Rectangle GetCellExtents (ColumnCellAccessible cell, Atk.CoordType coord_type);
+ int GetCellIndex (ColumnCellAccessible cell);
+ bool IsCellShowing (ColumnCellAccessible cell);
+ bool IsCellFocused (ColumnCellAccessible cell);
+ bool IsCellSelected (ColumnCellAccessible cell);
+ bool IsCellActive (ColumnCellAccessible cell);
+ void InvokeColumnHeaderMenu (ColumnCellAccessible column);
+ void ClickColumnHeader (ColumnCellAccessible column);
+ void CellRedrawn (int column, int row);
+ }
+}
diff --git a/src/Hyena.Gui/Hyena.Data.Gui/Accessibility/ListViewAccessible.cs b/src/Hyena.Gui/Hyena.Data.Gui/Accessibility/ListViewAccessible.cs
new file mode 100644
index 0000000..dc2f8c9
--- /dev/null
+++ b/src/Hyena.Gui/Hyena.Data.Gui/Accessibility/ListViewAccessible.cs
@@ -0,0 +1,245 @@
+//
+// ListViewAccessible.cs
+//
+// Authors:
+// Eitan Isaacson <eitan ascender com>
+// Gabriel Burt <gburt novell com>
+//
+// Copyright (C) 2009 Novell, Inc.
+// Copyright (C) 2009 Eitan Isaacson
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Linq;
+using System.Collections.Generic;
+
+using Hyena.Data.Gui;
+
+namespace Hyena.Data.Gui.Accessibility
+{
+#if ENABLE_ATK
+ public partial class ListViewAccessible<T> : Hyena.Gui.BaseWidgetAccessible, ICellAccessibleParent
+ {
+ private ListView<T> list_view;
+ private Dictionary<int, ColumnCellAccessible> cell_cache;
+
+ public ListViewAccessible (GLib.Object widget) : base (widget as Gtk.Widget)
+ {
+ list_view = widget as ListView<T>;
+ // TODO replace with list_view.Name?
+ Name = "ListView";
+ Description = "ListView";
+ Role = Atk.Role.Table;
+ Parent = list_view.Parent.RefAccessible ();
+
+ cell_cache = new Dictionary<int, ColumnCellAccessible> ();
+
+ list_view.ModelChanged += (o, a) => OnModelChanged ();
+ list_view.Model.Reloaded += (o, a) => OnModelChanged ();
+ OnModelChanged ();
+
+ list_view.Selection.FocusChanged += OnSelectionFocusChanged;
+ list_view.ActiveColumnChanged += OnSelectionFocusChanged;
+
+ ListViewAccessible_Selection ();
+ ListViewAccessible_Table ();
+ }
+
+ protected override Atk.StateSet OnRefStateSet ()
+ {
+ Atk.StateSet states = base.OnRefStateSet ();
+ states.AddState (Atk.StateType.ManagesDescendants);
+
+ return states;
+ }
+
+ protected override int OnGetIndexInParent ()
+ {
+ for (int i=0; i < Parent.NAccessibleChildren; i++) {
+ if (Parent.RefAccessibleChild (i) == this) {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ protected override int OnGetNChildren ()
+ {
+ return n_columns * n_rows + n_columns;
+ }
+
+ protected override Atk.Object OnRefChild (int index)
+ {
+ ColumnCellAccessible child;
+
+ if (cell_cache.ContainsKey (index)) {
+ return cell_cache[index];
+ }
+
+ var columns = list_view.ColumnController.Where (c => c.Visible);
+
+ if (index - n_columns < 0) {
+ child = columns.ElementAtOrDefault (index)
+ .HeaderCell
+ .GetAccessible (this) as ColumnCellAccessible;
+ } else {
+ int column = (index - n_columns) % n_columns;
+ int row = (index - n_columns) / n_columns;
+ var cell = columns.ElementAtOrDefault (column).GetCell (0);
+ cell.BindListItem (list_view.Model[row]);
+ child = (ColumnCellAccessible) cell.GetAccessible (this);
+ }
+
+ cell_cache.Add (index, child);
+
+ return child;
+ }
+
+ public override Atk.Object RefAccessibleAtPoint (int x, int y, Atk.CoordType coordType)
+ {
+ int row, col;
+ list_view.GetCellAtPoint (x, y, coordType, out row, out col);
+ return RefAt (row, col);
+ }
+
+ private void OnModelChanged ()
+ {
+ GLib.Signal.Emit (this, "model_changed");
+ cell_cache.Clear ();
+ /*var handler = ModelChanged;
+ if (handler != null) {
+ handler (this, EventArgs.Empty);
+ }*/
+ }
+
+ private void OnSelectionFocusChanged (object o, EventArgs a)
+ {
+ GLib.Signal.Emit (this, "active-descendant-changed", ActiveCell.Handle);
+ }
+
+ private Atk.Object ActiveCell {
+ get {
+ if (list_view.HeaderFocused)
+ return OnRefChild (list_view.ActiveColumn);
+ else
+ return RefAt (list_view.Selection.FocusedIndex, list_view.ActiveColumn);
+ }
+ }
+
+ private int n_columns {
+ get { return list_view.ColumnController.Count (c => c.Visible); }
+ }
+
+ private int n_rows {
+ get { return list_view.Model.Count; }
+ }
+
+ #region ICellAccessibleParent
+
+ public int GetCellIndex (ColumnCellAccessible cell)
+ {
+ foreach (KeyValuePair<int, ColumnCellAccessible> kv in cell_cache)
+ {
+ if ((ColumnCellAccessible)kv.Value == cell)
+ return (int)kv.Key;
+ }
+
+ return -1;
+ }
+
+ public Gdk.Rectangle GetCellExtents (ColumnCellAccessible cell, Atk.CoordType coord_type)
+ {
+ int cache_index = GetCellIndex (cell);
+ int minval = Int32.MinValue;
+ if (cache_index == -1)
+ return new Gdk.Rectangle (minval, minval, minval, minval);
+
+ if (cache_index - n_columns >= 0)
+ {
+ int column = (cache_index - NColumns)%NColumns;
+ int row = (cache_index - NColumns)/NColumns;
+ return list_view.GetColumnCellExtents (row, column, true, coord_type);
+ } else
+ {
+ return list_view.GetColumnHeaderCellExtents (cache_index, true, coord_type);
+ }
+ }
+
+ public bool IsCellShowing (ColumnCellAccessible cell)
+ {
+ Gdk.Rectangle cell_extents = GetCellExtents (cell, Atk.CoordType.Window);
+
+ if (cell_extents.X == Int32.MinValue && cell_extents.Y == Int32.MinValue)
+ return false;
+
+ return true;
+ }
+
+ public bool IsCellFocused (ColumnCellAccessible cell)
+ {
+ int cell_index = GetCellIndex (cell);
+ if (cell_index % NColumns != 0)
+ return false; // Only 0 column cells get focus now.
+
+ int row = cell_index / NColumns;
+
+ return row == list_view.Selection.FocusedIndex;
+ }
+
+ public bool IsCellSelected (ColumnCellAccessible cell)
+ {
+ return IsChildSelected (GetCellIndex (cell));
+ }
+
+ public bool IsCellActive (ColumnCellAccessible cell)
+ {
+ return (ActiveCell == (Atk.Object)cell);
+ }
+
+ public void InvokeColumnHeaderMenu (ColumnCellAccessible cell)
+ {
+ list_view.InvokeColumnHeaderMenu (GetCellIndex (cell));
+ }
+
+ public void ClickColumnHeader (ColumnCellAccessible cell)
+ {
+ list_view.ClickColumnHeader (GetCellIndex (cell));
+ }
+
+ public void CellRedrawn (int column, int row)
+ {
+ int index;
+ if (row >= 0)
+ index = row * n_columns + column + n_columns;
+ else
+ index = column;
+
+ if (cell_cache.ContainsKey (index)) {
+ cell_cache[index].Redrawn ();
+ }
+ }
+
+ #endregion
+ }
+#endif
+}
diff --git a/src/Hyena.Gui/Hyena.Data.Gui/Accessibility/ListViewAccessible_Selection.cs b/src/Hyena.Gui/Hyena.Data.Gui/Accessibility/ListViewAccessible_Selection.cs
new file mode 100644
index 0000000..caa6728
--- /dev/null
+++ b/src/Hyena.Gui/Hyena.Data.Gui/Accessibility/ListViewAccessible_Selection.cs
@@ -0,0 +1,92 @@
+//
+// ListViewAccessible_Selection.cs
+//
+// Authors:
+// Eitan Isaacson <eitan ascender com>
+// Gabriel Burt <gburt novell com>
+//
+// Copyright (C) 2009 Novell, Inc.
+// Copyright (C) 2009 Eitan Isaacson
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Linq;
+using System.Collections.Generic;
+
+using Hyena.Data.Gui;
+
+namespace Hyena.Data.Gui.Accessibility
+{
+#if ENABLE_ATK
+ public partial class ListViewAccessible<T> : Atk.SelectionImplementor
+ {
+ public void ListViewAccessible_Selection ()
+ {
+ list_view.SelectionProxy.Changed += OnSelectionChanged;
+ }
+
+ public bool AddSelection (int index)
+ {
+ return AddRowSelection (GetRowAtIndex (index));
+ }
+
+ public bool ClearSelection ()
+ {
+ list_view.Selection.Clear ();
+ return true;
+ }
+
+ public bool IsChildSelected (int index)
+ {
+ return IsRowSelected (GetRowAtIndex (index));
+ }
+
+ public bool RemoveSelection (int index)
+ {
+ int row = list_view.Selection.RangeCollection [index / n_columns];
+ return RemoveRowSelection (row);
+ }
+
+ public Atk.Object RefSelection (int index)
+ {
+ int row = list_view.Selection.RangeCollection [index / n_columns];
+ int column = index % n_columns;
+ return RefAt (row, column);
+ }
+
+ public int SelectionCount {
+ get { return list_view.Selection.Count * n_columns; }
+ }
+
+ public bool SelectAllSelection ()
+ {
+ list_view.Selection.SelectAll ();
+ return true;
+ }
+
+ private void OnSelectionChanged (object o, EventArgs a)
+ {
+ GLib.Signal.Emit (this, "selection_changed");
+ }
+ }
+#endif
+}
diff --git a/src/Hyena.Gui/Hyena.Data.Gui/Accessibility/ListViewAccessible_Table.cs b/src/Hyena.Gui/Hyena.Data.Gui/Accessibility/ListViewAccessible_Table.cs
new file mode 100644
index 0000000..ed43a8c
--- /dev/null
+++ b/src/Hyena.Gui/Hyena.Data.Gui/Accessibility/ListViewAccessible_Table.cs
@@ -0,0 +1,192 @@
+//
+// ListViewAccessible_Table.cs
+//
+// Authors:
+// Eitan Isaacson <eitan ascender com>
+// Gabriel Burt <gburt novell com>
+//
+// Copyright (C) 2009 Novell, Inc.
+// Copyright (C) 2009 Eitan Isaacson
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Linq;
+using System.Collections.Generic;
+
+using Hyena.Data.Gui;
+
+namespace Hyena.Data.Gui.Accessibility
+{
+#if ENABLE_ATK
+ public partial class ListViewAccessible<T> : Atk.TableImplementor
+ {
+ public void ListViewAccessible_Table ()
+ {
+ }
+
+ public Atk.Object Caption {
+ get { return new Atk.NoOpObject (list_view); }
+ set {}
+ }
+
+ public int NColumns {
+ get { return n_columns; }
+ set {}
+ }
+
+ public int NRows {
+ get { return n_rows; }
+ set {}
+ }
+
+ public Atk.Object Summary {
+ get { return new Atk.NoOpObject (list_view); }
+ set {}
+ }
+
+ public bool AddColumnSelection (int column)
+ {
+ return false;
+ }
+
+ public bool AddRowSelection (int row)
+ {
+ list_view.Selection.Select (row);
+ return true;
+ }
+
+ public int GetColumnAtIndex (int index)
+ {
+ return NColumns == 0 ? -1 : (index - NColumns) % NColumns;
+ }
+
+ public string GetColumnDescription (int column)
+ {
+ var col = list_view.ColumnController.Where (c => c.Visible).ElementAtOrDefault (column);
+ return col == null ? null : col.LongTitle;
+ }
+
+ public int GetColumnExtentAt (int row, int column)
+ {
+ return 1;
+ }
+
+ public Atk.Object GetColumnHeader (int column)
+ {
+ if (column >= NColumns)
+ return new Atk.NoOpObject (list_view);
+ else
+ return OnRefChild (column);
+ }
+
+ public int GetIndexAt (int row, int column)
+ {
+ return row * NColumns + column + NColumns;
+ }
+
+ public int GetRowAtIndex (int index)
+ {
+ if (NColumns == 0)
+ return -1;
+ return (index - NColumns) / NColumns;
+ }
+
+ public string GetRowDescription (int row)
+ {
+ return "";
+ }
+
+ public int GetRowExtentAt (int row, int column)
+ {
+ return 1;
+ }
+
+ public Atk.Object GetRowHeader (int row)
+ {
+ return new Atk.NoOpObject (list_view);
+ }
+
+// Ensure https://bugzilla.novell.com/show_bug.cgi?id=512477 is fixed
+#if ENABLE_ATK
+ private static readonly int [] empty_int_array = new int[0];
+ public int [] SelectedColumns {
+ get { return empty_int_array; }
+ }
+
+ public int [] SelectedRows {
+ get { return list_view.Selection.ToArray (); }
+ }
+#else
+ public int GetSelectedRows (out int row) { row = 0; return 0; }
+ public int GetSelectedColumns (out int cols) { cols = 0; return 0; }
+#endif
+
+ public bool IsColumnSelected (int column)
+ {
+ return false;
+ }
+
+ public bool IsRowSelected (int row)
+ {
+ return list_view.Selection.Contains (row);
+ }
+
+ public bool IsSelected (int row, int column)
+ {
+ return list_view.Selection.Contains (row);
+ }
+
+ public Atk.Object RefAt (int row, int column)
+ {
+ int index = NColumns * row + column + NColumns;
+ return OnRefChild (index);
+ }
+
+ public bool RemoveColumnSelection (int column)
+ {
+ return false;
+ }
+
+ public bool RemoveRowSelection (int row)
+ {
+ list_view.Selection.Unselect (row);
+ return true;
+ }
+
+ public void SetColumnDescription (int column, string description)
+ {
+ }
+
+ public void SetColumnHeader (int column, Atk.Object header)
+ {
+ }
+
+ public void SetRowDescription (int row, string description)
+ {
+ }
+
+ public void SetRowHeader (int row, Atk.Object header)
+ {
+ }
+ }
+#endif
+}
diff --git a/src/Hyena.Gui/Hyena.Data.Gui/CellContext.cs b/src/Hyena.Gui/Hyena.Data.Gui/CellContext.cs
index 97f54ff..f25ec0d 100644
--- a/src/Hyena.Gui/Hyena.Data.Gui/CellContext.cs
+++ b/src/Hyena.Gui/Hyena.Data.Gui/CellContext.cs
@@ -42,7 +42,7 @@ namespace Hyena.Data.Gui
private Gdk.Rectangle area;
private Gdk.Rectangle clip;
private bool text_as_foreground = false;
- private bool sensitive = true;
+ private bool opaque = true;
public Cairo.Context Context {
get { return context; }
@@ -84,9 +84,9 @@ namespace Hyena.Data.Gui
set { text_as_foreground = value; }
}
- public bool Sensitive {
- get { return sensitive; }
- set { sensitive = value; }
+ public bool Opaque {
+ get { return opaque; }
+ set { opaque = value; }
}
}
}
diff --git a/src/Hyena.Gui/Hyena.Data.Gui/ColumnCell.cs b/src/Hyena.Gui/Hyena.Data.Gui/ColumnCell.cs
index eb6043b..65b3904 100644
--- a/src/Hyena.Gui/Hyena.Data.Gui/ColumnCell.cs
+++ b/src/Hyena.Gui/Hyena.Data.Gui/ColumnCell.cs
@@ -31,6 +31,8 @@ using System.Reflection;
using Gtk;
using Cairo;
+using Hyena.Data.Gui.Accessibility;
+
namespace Hyena.Data.Gui
{
public abstract class ColumnCell
@@ -41,6 +43,16 @@ namespace Hyena.Data.Gui
private object bound_object;
private object bound_object_parent;
+ public virtual Atk.Object GetAccessible (ICellAccessibleParent parent)
+ {
+ return new ColumnCellAccessible (BoundObject, this, parent);
+ }
+
+ public virtual string GetTextAlternative (object obj)
+ {
+ return "";
+ }
+
public ColumnCell (string property, bool expand)
{
Property = property;
diff --git a/src/Hyena.Gui/Hyena.Data.Gui/ColumnCellRating.cs b/src/Hyena.Gui/Hyena.Data.Gui/ColumnCellRating.cs
index 420ccb4..e1efeb2 100644
--- a/src/Hyena.Gui/Hyena.Data.Gui/ColumnCellRating.cs
+++ b/src/Hyena.Gui/Hyena.Data.Gui/ColumnCellRating.cs
@@ -67,6 +67,10 @@ namespace Hyena.Data.Gui
public bool ButtonEvent (int x, int y, bool pressed, Gdk.EventButton evnt)
{
+ if (ReadOnly) {
+ return false;
+ }
+
if (pressed) {
last_pressed_bound = BoundObjectParent;
return false;
@@ -82,6 +86,10 @@ namespace Hyena.Data.Gui
public bool MotionEvent (int x, int y, Gdk.EventMotion evnt)
{
+ if (ReadOnly) {
+ return false;
+ }
+
int value = RatingFromPosition (x);
if (hover_bound == BoundObjectParent && value == hover_value) {
@@ -144,5 +152,7 @@ namespace Hyena.Data.Gui
get { return renderer.Ypad; }
set { renderer.Ypad = value; }
}
+
+ public bool ReadOnly { get; set; }
}
}
diff --git a/src/Hyena.Gui/Hyena.Data.Gui/ColumnCellText.cs b/src/Hyena.Gui/Hyena.Data.Gui/ColumnCellText.cs
index c331369..0a2c126 100644
--- a/src/Hyena.Gui/Hyena.Data.Gui/ColumnCellText.cs
+++ b/src/Hyena.Gui/Hyena.Data.Gui/ColumnCellText.cs
@@ -32,6 +32,7 @@ using Cairo;
using Hyena.Gui;
using Hyena.Gui.Theming;
+using Hyena.Data.Gui.Accessibility;
namespace Hyena.Data.Gui
{
@@ -44,7 +45,6 @@ namespace Hyena.Data.Gui
private Pango.Weight font_weight = Pango.Weight.Normal;
private Pango.EllipsizeMode ellipsize_mode = Pango.EllipsizeMode.End;
private Pango.Alignment alignment = Pango.Alignment.Left;
- private double opacity = 1.0;
private int text_width;
private int text_height;
private string text_format = null;
@@ -56,12 +56,22 @@ namespace Hyena.Data.Gui
{
}
- protected void SetMinMaxStrings (object min_max)
+ public override Atk.Object GetAccessible (ICellAccessibleParent parent)
+ {
+ return new ColumnCellTextAccessible (BoundObject, this, parent);
+ }
+
+ public override string GetTextAlternative (object obj)
+ {
+ return GetText (obj);
+ }
+
+ public void SetMinMaxStrings (object min_max)
{
SetMinMaxStrings (min_max, min_max);
}
- protected void SetMinMaxStrings (object min, object max)
+ public void SetMinMaxStrings (object min, object max)
{
// Set the min/max strings from the min/max objects
MinString = GetText (min);
@@ -81,7 +91,7 @@ namespace Hyena.Data.Gui
context.Context.MoveTo (Spacing, ((int)cellHeight - text_height) / 2);
Cairo.Color color = context.Theme.Colors.GetWidgetColor (
context.TextAsForeground ? GtkColorClass.Foreground : GtkColorClass.Text, state);
- color.A = (!context.Sensitive) ? 0.3 : opacity;
+ color.A = context.Opaque ? 1.0 : 0.5;
context.Context.Color = color;
PangoCairoHelper.ShowLayout (context.Context, context.Layout);
@@ -106,9 +116,13 @@ namespace Hyena.Data.Gui
is_ellipsized = context.Layout.IsEllipsized;
}
+ private static char[] lfcr = new char[] {'\n', '\r'};
private void UpdateLayout (Pango.Layout layout, string text)
{
string final_text = GetFormattedText (text);
+ if (final_text.IndexOfAny (lfcr) >= 0) {
+ final_text = final_text.Replace ("\r\n", "\x20").Replace ('\n', '\x20').Replace ('\r', '\x20');
+ }
if (use_markup) {
layout.SetMarkup (final_text);
} else {
@@ -172,11 +186,6 @@ namespace Hyena.Data.Gui
set { ellipsize_mode = value; }
}
- public virtual double Opacity {
- get { return opacity; }
- set { opacity = value; }
- }
-
internal static int ComputeRowHeight (Widget widget)
{
int w_width, row_height;
diff --git a/src/Hyena.Gui/Hyena.Data.Gui/ColumnHeaderCellText.cs b/src/Hyena.Gui/Hyena.Data.Gui/ColumnHeaderCellText.cs
index a63753e..a5d17b6 100644
--- a/src/Hyena.Gui/Hyena.Data.Gui/ColumnHeaderCellText.cs
+++ b/src/Hyena.Gui/Hyena.Data.Gui/ColumnHeaderCellText.cs
@@ -30,6 +30,8 @@ using System;
using Gtk;
using Cairo;
+using Hyena.Data.Gui.Accessibility;
+
namespace Hyena.Data.Gui
{
public class ColumnHeaderCellText : ColumnCellText, IHeaderCell
@@ -44,6 +46,11 @@ namespace Hyena.Data.Gui
this.data_handler = data_handler;
}
+ public override Atk.Object GetAccessible (ICellAccessibleParent parent)
+ {
+ return new ColumnHeaderCellTextAccessible (BoundObject, this, parent);
+ }
+
public override void Render (CellContext context, StateType state, double cellWidth, double cellHeight)
{
if (data_handler == null) {
diff --git a/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Accessible.cs b/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Accessible.cs
new file mode 100644
index 0000000..1c8abc7
--- /dev/null
+++ b/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Accessible.cs
@@ -0,0 +1,177 @@
+//
+// ListView_Accessible.cs
+//
+// Authors:
+// Gabriel Burt <gburt novell com>
+// Eitan Isaacson <eitan ascender com>
+//
+// Copyright (C) 2009 Novell, Inc.
+// Copyright (C) 2009 Eitan Isaacson
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Linq;
+using System.Collections.Generic;
+
+using Gtk;
+
+using Hyena.Data.Gui.Accessibility;
+
+namespace Hyena.Data.Gui
+{
+ public partial class ListView<T> : ListViewBase
+ {
+ static ListView ()
+ {
+#if ENABLE_ATK
+ ListViewAccessibleFactory<T>.Init ();
+#endif
+ }
+
+ public Gdk.Rectangle GetColumnCellExtents (int row, int column)
+ {
+ return GetColumnCellExtents (row, column, true);
+ }
+
+ public Gdk.Rectangle GetColumnCellExtents (int row, int column, bool clip) {
+ return GetColumnCellExtents (row, column, clip, Atk.CoordType.Window);
+ }
+
+ public Gdk.Rectangle GetColumnCellExtents (int row, int column, bool clip, Atk.CoordType coord_type)
+ {
+ int width = GetColumnWidth (column);
+ int height = RowHeight;
+
+ int y = (int)GetYAtRow (row) - VadjustmentValue + ListAllocation.Y;
+
+ int x = ListAllocation.X - HadjustmentValue;
+ for (int index=0;index<column;index++)
+ x += GetColumnWidth (index);
+
+ Gdk.Rectangle rectangle = new Gdk.Rectangle (x, y, width, height);
+
+ if (clip && !ListAllocation.Contains (rectangle))
+ return new Gdk.Rectangle (Int32.MinValue, Int32.MinValue, Int32.MinValue, Int32.MinValue);
+
+ if (coord_type == Atk.CoordType.Window)
+ return rectangle;
+
+ int origin_x, origin_y;
+ GdkWindow.GetPosition (out origin_x, out origin_y);
+
+ rectangle.X += origin_x;
+ rectangle.Y += origin_y;
+
+ return rectangle;
+ }
+
+ public Gdk.Rectangle GetColumnHeaderCellExtents (int column, bool clip, Atk.CoordType coord_type)
+ {
+ if (!HeaderVisible)
+ return new Gdk.Rectangle (Int32.MinValue, Int32.MinValue, Int32.MinValue, Int32.MinValue);
+ int width = GetColumnWidth (column);
+ int height = HeaderHeight;
+
+ int x = header_rendering_alloc.X - HadjustmentValue + Theme.BorderWidth;
+ if (column != 0)
+ x += Theme.InnerBorderWidth;
+ for (int index=0;index<column;index++)
+ x += GetColumnWidth (index);
+
+ int y = Theme.BorderWidth + header_rendering_alloc.Y;
+
+ Gdk.Rectangle rectangle = new Gdk.Rectangle (x, y, width, height);
+
+ if (coord_type == Atk.CoordType.Window)
+ return rectangle;
+
+ int origin_x, origin_y;
+ GdkWindow.GetPosition (out origin_x, out origin_y);
+
+ rectangle.X += origin_x;
+ rectangle.Y += origin_y;
+
+ return rectangle;
+ }
+
+ public void GetCellAtPoint (int x, int y, Atk.CoordType coord_type, out int row, out int col)
+ {
+ int origin_x = 0;
+ int origin_y = 0;
+ if (coord_type == Atk.CoordType.Screen)
+ GdkWindow.GetPosition (out origin_x, out origin_y);
+
+ x = x - ListAllocation.X - origin_x;
+ y = y - ListAllocation.Y - origin_y;
+
+ Column column = GetColumnAt (x);
+
+ CachedColumn cached_column = GetCachedColumnForColumn (column);
+
+ row = GetRowAtY (y);
+ col = cached_column.Index;
+ }
+
+ public void InvokeColumnHeaderMenu (int column)
+ {
+ Gdk.Rectangle rectangle = GetColumnHeaderCellExtents (column, true, Atk.CoordType.Window);
+ Column col = ColumnController.Where (c => c.Visible).ElementAtOrDefault (column);
+ OnColumnRightClicked (col, rectangle.X + rectangle.Width/2, rectangle.Y + rectangle.Height/2);
+ }
+
+ public void ClickColumnHeader (int column)
+ {
+ Column col = ColumnController.Where (c => c.Visible).ElementAtOrDefault (column);
+ OnColumnLeftClicked (col);
+ }
+
+ private void AccessibleCellRedrawn (int column, int row)
+ {
+ var accessible = Accessible as ICellAccessibleParent;
+ if (accessible != null) {
+ accessible.CellRedrawn (column, row);
+ }
+ }
+
+ }
+
+#if ENABLE_ATK
+ internal class ListViewAccessibleFactory<T> : Atk.ObjectFactory
+ {
+ public static void Init ()
+ {
+ new ListViewAccessibleFactory<T> ();
+ Atk.Global.DefaultRegistry.SetFactoryType ((GLib.GType)typeof (ListView<T>), (GLib.GType)typeof (ListViewAccessibleFactory<T>));
+ }
+
+ protected override Atk.Object OnCreateAccessible (GLib.Object obj)
+ {
+ return new ListViewAccessible<T> (obj);
+ }
+
+ protected override GLib.GType OnGetAccessibleType ()
+ {
+ return ListViewAccessible<T>.GType;
+ }
+ }
+#endif
+}
diff --git a/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Header.cs b/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Header.cs
index 9173e83..f9aae51 100644
--- a/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Header.cs
+++ b/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Header.cs
@@ -57,6 +57,7 @@ namespace Hyena.Data.Gui
private bool resizable;
private int header_width;
+ private double list_width, max_width;
private int sort_column_index = -1;
private int resizing_column_index = -1;
private int pressed_column_index = -1;
@@ -73,6 +74,14 @@ namespace Hyena.Data.Gui
private CachedColumn [] column_cache;
private List<int> elastic_columns;
+ public int Width {
+ get { return (int)list_width; }
+ }
+
+ public int MaxWidth {
+ get { return (int)max_width + Theme.TotalBorderWidth*2; }
+ }
+
#region Columns
private void InvalidateColumnCache ()
@@ -191,7 +200,7 @@ namespace Hyena.Data.Gui
double remaining_width = RecalculateColumnSizes (header_width, header_width);
- while (remaining_width != 0 && elastic_columns.Count > 0) {
+ while (Math.Round (remaining_width) != 0.0 && elastic_columns.Count > 0) {
double total_elastic_width = 0.0;
foreach (int i in elastic_columns) {
total_elastic_width += column_cache[i].ElasticWidth;
@@ -203,6 +212,15 @@ namespace Hyena.Data.Gui
column_cache[i].Column.Width = column_cache[i].ElasticWidth / (double)header_width;
}
}
+
+ double tmp_width = 0.0;
+ double tmp_max = 0.0;
+ foreach (var col in column_cache) {
+ tmp_width += col.ElasticWidth;
+ tmp_max += col.MaxWidth == Int32.MaxValue ? col.MinWidth : col.MaxWidth;
+ }
+ list_width = tmp_width;
+ max_width = tmp_max;
}
private double RecalculateColumnSizes (double total_width, double total_elastic_width)
@@ -246,6 +264,37 @@ namespace Hyena.Data.Gui
QueueDraw ();
}
+ protected virtual void OnColumnLeftClicked (Column clickedColumn)
+ {
+ if (Model is ISortable && clickedColumn is ISortableColumn) {
+ ISortableColumn sort_column = clickedColumn as ISortableColumn;
+ ISortable sortable = Model as ISortable;
+
+ // Change the sort-type with every click
+ if (sort_column == ColumnController.SortColumn) {
+ switch (sort_column.SortType) {
+ case SortType.Ascending: sort_column.SortType = SortType.Descending; break;
+ case SortType.Descending: sort_column.SortType = SortType.None; break;
+ case SortType.None: sort_column.SortType = SortType.Ascending; break;
+ }
+ }
+
+ // If we're switching from a different column, or we aren't reorderable, make sure sort type isn't None
+ if ((sort_column != ColumnController.SortColumn || !IsEverReorderable) && sort_column.SortType == SortType.None) {
+ sort_column.SortType = SortType.Ascending;
+ }
+
+ sortable.Sort (sort_column);
+ ColumnController.SortColumn = sort_column;
+ IsReorderable = sortable.SortColumn == null || sortable.SortColumn.SortType == SortType.None;
+
+ Model.Reload ();
+ RecalculateColumnSizes ();
+ RegenerateColumnCache ();
+ InvalidateHeader ();
+ }
+ }
+
protected virtual void OnColumnRightClicked (Column clickedColumn, int x, int y)
{
Column [] columns = ColumnController.ToArray ();
@@ -386,6 +435,12 @@ namespace Hyena.Data.Gui
return null;
}
+ protected int GetColumnWidth (int column_index)
+ {
+ CachedColumn cached_column = column_cache[column_index];
+ return cached_column.Width;
+ }
+
private bool CanResizeColumn (int column_index)
{
// At least one column to the left (including the one being resized) should be resizable.
diff --git a/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Interaction.cs b/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Interaction.cs
index 0465c5e..02a05de 100644
--- a/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Interaction.cs
+++ b/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Interaction.cs
@@ -1,11 +1,13 @@
//
// ListView_Interaction.cs
//
-// Author:
+// Authors:
// Aaron Bockover <abockover novell com>
// Gabriel Burt <gburt novell com>
+// Eitan Isaacson <eitan ascender com>
//
-// Copyright (C) 2007-2008 Novell, Inc.
+// Copyright (C) 2007-2009 Novell, Inc.
+// Copyright (C) 2009 Eitan Isaacson
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
@@ -37,6 +39,32 @@ namespace Hyena.Data.Gui
{
public partial class ListView<T> : ListViewBase
{
+ private bool header_focused = false;
+ public bool HeaderFocused {
+ get { return header_focused; }
+ set {
+ header_focused = value;
+ InvalidateHeader ();
+ InvalidateList ();
+ }
+ }
+
+ #pragma warning disable 0067
+ public event EventHandler ActiveColumnChanged;
+ #pragma warning restore 0067
+
+ private int active_column = 0;
+ public int ActiveColumn {
+ get { return active_column; }
+ set {
+ active_column = value;
+ var handler = ActiveColumnChanged;
+ if (handler != null) {
+ handler (this, EventArgs.Empty);
+ }
+ }
+ }
+
private Adjustment vadjustment;
public Adjustment Vadjustment {
get { return vadjustment; }
@@ -152,41 +180,72 @@ namespace Hyena.Data.Gui
case Gdk.Key.K:
case Gdk.Key.Up:
case Gdk.Key.KP_Up:
- handled = KeyboardScroll (press.State, -1, true);
+ if (!HeaderFocused)
+ handled = KeyboardScroll (press.State, -1, true);
break;
case Gdk.Key.j:
case Gdk.Key.J:
case Gdk.Key.Down:
case Gdk.Key.KP_Down:
- handled = KeyboardScroll (press.State, 1, true);
+ if (!HeaderFocused) {
+ handled = KeyboardScroll (press.State, 1, true);
+ } else if (HeaderFocused) {
+ handled = true;
+ HeaderFocused = false;
+ }
+ break;
+ case Gdk.Key.Right:
+ case Gdk.Key.KP_Right:
+ if (ActiveColumn + 1 < column_cache.Length) {
+ ActiveColumn++;
+ InvalidateHeader ();
+ }
+ handled = true;
+ break;
+ case Gdk.Key.Left:
+ case Gdk.Key.KP_Left:
+ if (ActiveColumn - 1 >= 0) {
+ ActiveColumn--;
+ InvalidateHeader ();
+ }
+ handled = true;
break;
-
case Gdk.Key.Page_Up:
case Gdk.Key.KP_Page_Up:
- handled = vadjustment != null && KeyboardScroll (press.State,
- (int)(-vadjustment.PageIncrement / (double)RowHeight), false);
+ if (!HeaderFocused)
+ handled = vadjustment != null && KeyboardScroll (press.State,
+ (int)(-vadjustment.PageIncrement / (double)RowHeight), false);
break;
case Gdk.Key.Page_Down:
case Gdk.Key.KP_Page_Down:
- handled = vadjustment != null && KeyboardScroll (press.State,
- (int)(vadjustment.PageIncrement / (double)RowHeight), false);
+ if (!HeaderFocused)
+ handled = vadjustment != null && KeyboardScroll (press.State,
+ (int)(vadjustment.PageIncrement / (double)RowHeight), false);
break;
case Gdk.Key.Home:
case Gdk.Key.KP_Home:
- handled = KeyboardScroll (press.State, -10000000, false);
+ if (!HeaderFocused)
+ handled = KeyboardScroll (press.State, -10000000, false);
break;
case Gdk.Key.End:
case Gdk.Key.KP_End:
- handled = KeyboardScroll (press.State, 10000000, false);
+ if (!HeaderFocused)
+ handled = KeyboardScroll (press.State, 10000000, false);
break;
case Gdk.Key.Return:
case Gdk.Key.KP_Enter:
- handled = ActivateSelection ();
+ if (!HeaderFocused) {
+ handled = ActivateSelection ();
+ } else if (HeaderFocused && ActiveColumn >= 0) {
+ OnColumnLeftClicked (
+ column_cache[ActiveColumn].Column);
+ handled = true;
+ }
break;
case Gdk.Key.Escape:
@@ -194,11 +253,25 @@ namespace Hyena.Data.Gui
break;
case Gdk.Key.space:
- if (Selection != null && Selection.FocusedIndex != 1) {
+ if (Selection != null && Selection.FocusedIndex != 1 &&
+ !HeaderFocused) {
Selection.ToggleSelect (Selection.FocusedIndex);
handled = true;
}
break;
+
+ case Gdk.Key.F10:
+ if ((press.State & Gdk.ModifierType.ShiftMask) != 0)
+ goto case Gdk.Key.Menu;
+ break;
+
+ case Gdk.Key.Menu:
+ // OnPopupMenu() is reserved for list items in derived classes.
+ if (HeaderFocused) {
+ InvokeColumnHeaderMenu (ActiveColumn);
+ handled = true;
+ }
+ break;
}
if (handled) {
@@ -345,8 +418,10 @@ namespace Hyena.Data.Gui
{
HasFocus = true;
if (header_visible && header_interaction_alloc.Contains ((int)evnt.X, (int)evnt.Y)) {
+ HeaderFocused = true;
return OnHeaderButtonPressEvent (evnt);
} else if (list_interaction_alloc.Contains ((int)evnt.X, (int)evnt.Y) && model != null) {
+ HeaderFocused = false;
return OnListButtonPressEvent (evnt);
}
return true;
@@ -399,6 +474,7 @@ namespace Hyena.Data.Gui
int row_index = GetRowAtY (y);
if (row_index < 0 || row_index >= Model.Count) {
+ Gtk.Drag.SourceUnset (this);
return true;
}
@@ -493,31 +569,9 @@ namespace Hyena.Data.Gui
{
if (pressed_column_index >= 0 && pressed_column_index < column_cache.Length) {
Column column = column_cache[pressed_column_index].Column;
- if (column != null && Model is ISortable && column is ISortableColumn) {
- ISortableColumn sort_column = column as ISortableColumn;
- ISortable sortable = Model as ISortable;
-
- // Change the sort-type with every click
- switch (sort_column.SortType) {
- case SortType.Ascending: sort_column.SortType = SortType.Descending; break;
- case SortType.Descending: sort_column.SortType = SortType.None; break;
- case SortType.None: sort_column.SortType = SortType.Ascending; break;
- }
-
- // If we're switching to a different column or we aren't reorderable and the type is None, sort Ascending
- if (sort_column != ColumnController.SortColumn || (!IsEverReorderable && sort_column.SortType == SortType.None)) {
- sort_column.SortType = SortType.Ascending;
- }
-
- sortable.Sort (sort_column);
- ColumnController.SortColumn = sort_column;
- IsReorderable = sortable.SortColumn == null || sortable.SortColumn.SortType == SortType.None;
-
- Model.Reload ();
- RecalculateColumnSizes ();
- RegenerateColumnCache ();
- InvalidateHeader ();
- }
+ ActiveColumn = pressed_column_index;
+ if (column != null)
+ OnColumnLeftClicked (column);
pressed_column_index = -1;
return true;
@@ -652,14 +706,28 @@ namespace Hyena.Data.Gui
return base.OnLeaveNotifyEvent (evnt);
}
- protected override bool OnFocusInEvent (Gdk.EventFocus evnt)
+ protected override bool OnFocused (Gtk.DirectionType directionType)
{
- return base.OnFocusInEvent (evnt);
- }
+ if (!HeaderVisible)
+ return base.OnFocused (directionType);
- protected override bool OnFocusOutEvent (Gdk.EventFocus evnt)
- {
- return base.OnFocusOutEvent (evnt);
+ if (HasFocus) {
+ if (directionType == DirectionType.TabForward && HeaderFocused)
+ HeaderFocused = false;
+ else if (directionType == DirectionType.TabBackward && !HeaderFocused)
+ HeaderFocused = true;
+ else
+ return base.OnFocused (directionType);
+
+ return true;
+ } else {
+ if (directionType == DirectionType.TabForward )
+ HeaderFocused = true;
+ else if (directionType == DirectionType.TabBackward)
+ HeaderFocused = false;
+
+ return base.OnFocused (directionType);
+ }
}
protected virtual void OnRowActivated ()
diff --git a/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Model.cs b/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Model.cs
index 9c576a0..8663161 100644
--- a/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Model.cs
+++ b/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Model.cs
@@ -35,6 +35,10 @@ namespace Hyena.Data.Gui
{
public partial class ListView<T> : ListViewBase
{
+ #pragma warning disable 0067
+ public event EventHandler ModelChanged;
+ #pragma warning restore 0067
+
public void SetModel (IListModel<T> model)
{
SetModel (model, 0.0);
@@ -73,8 +77,14 @@ namespace Hyena.Data.Gui
}
RefreshViewForModel (vpos);
+
+ var handler = ModelChanged;
+ if (handler != null) {
+ handler (this, EventArgs.Empty);
+ }
}
+
private void RefreshViewForModel (double? vpos)
{
if (Model == null) {
@@ -131,41 +141,41 @@ namespace Hyena.Data.Gui
get { return model; }
}
- private string row_sensitive_property_name = "Sensitive";
- private PropertyInfo row_sensitive_property_info;
- bool row_sensitive_property_invalid = false;
+ private string row_opaque_property_name = "Sensitive";
+ private PropertyInfo row_opaque_property_info;
+ bool row_opaque_property_invalid = false;
- public string RowSensitivePropertyName {
- get { return row_sensitive_property_name; }
+ public string RowOpaquePropertyName {
+ get { return row_opaque_property_name; }
set {
- if (value == row_sensitive_property_name) {
+ if (value == row_opaque_property_name) {
return;
}
- row_sensitive_property_name = value;
- row_sensitive_property_info = null;
- row_sensitive_property_invalid = false;
+ row_opaque_property_name = value;
+ row_opaque_property_info = null;
+ row_opaque_property_invalid = false;
InvalidateList ();
}
}
- private bool IsRowSensitive (object item)
+ private bool IsRowOpaque (object item)
{
- if (item == null || row_sensitive_property_invalid) {
+ if (item == null || row_opaque_property_invalid) {
return true;
}
- if (row_sensitive_property_info == null || row_sensitive_property_info.ReflectedType != item.GetType ()) {
- row_sensitive_property_info = item.GetType ().GetProperty (row_sensitive_property_name);
- if (row_sensitive_property_info == null || row_sensitive_property_info.PropertyType != typeof (bool)) {
- row_sensitive_property_info = null;
- row_sensitive_property_invalid = true;
+ if (row_opaque_property_info == null || row_opaque_property_info.ReflectedType != item.GetType ()) {
+ row_opaque_property_info = item.GetType ().GetProperty (row_opaque_property_name);
+ if (row_opaque_property_info == null || row_opaque_property_info.PropertyType != typeof (bool)) {
+ row_opaque_property_info = null;
+ row_opaque_property_invalid = true;
return true;
}
}
- return (bool)row_sensitive_property_info.GetValue (item, null);
+ return (bool)row_opaque_property_info.GetValue (item, null);
}
private string row_bold_property_name = "IsBold";
@@ -204,14 +214,5 @@ namespace Hyena.Data.Gui
return (bool)row_bold_property_info.GetValue (item, null);
}
-
- #pragma warning disable 0169
-
- private bool IsRowSensitive (int index)
- {
- return IsRowSensitive (model[index]);
- }
-
- #pragma warning restore 0169
}
}
diff --git a/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Rendering.cs b/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Rendering.cs
index 9f396fd..0cc1c68 100644
--- a/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Rendering.cs
+++ b/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Rendering.cs
@@ -103,9 +103,13 @@ namespace Hyena.Data.Gui
PaintHeader (damage);
}
- Theme.DrawFrameBorder (cairo_context, Allocation);
+ if (HasFocus)
+ Theme.DrawFrameBorderFocused (cairo_context, Allocation);
+ else
+ Theme.DrawFrameBorder (cairo_context, Allocation);
+
if (Model != null) {
- PaintRows(damage);
+ PaintRows (damage);
}
PaintDraggingColumn (damage);
@@ -131,7 +135,7 @@ namespace Hyena.Data.Gui
cell_area.Height = header_rendering_alloc.Height;
cell_context.Clip = clip;
- cell_context.Sensitive = true;
+ cell_context.Opaque = true;
cell_context.TextAsForeground = true;
bool have_drawn_separator = false;
@@ -160,6 +164,10 @@ namespace Hyena.Data.Gui
if (ci < 0 || column_cache.Length <= ci)
return;
+ if (ci == ActiveColumn && HasFocus && HeaderFocused) {
+ Theme.DrawColumnHeaderFocus (cairo_context, area);
+ }
+
if (dragging) {
Theme.DrawColumnHighlight (cairo_context, area,
CairoExtensions.ColorShade (Theme.Colors.GetWidgetColor (GtkColorClass.Dark, StateType.Normal), 0.9));
@@ -260,13 +268,19 @@ namespace Hyena.Data.Gui
corners &= ~(CairoCorners.BottomLeft | CairoCorners.BottomRight);
}
- Theme.DrawRowSelection (cairo_context, single_list_alloc.X, single_list_alloc.Y,
- single_list_alloc.Width, single_list_alloc.Height, false, true,
- Theme.Colors.GetWidgetColor (GtkColorClass.Background, StateType.Selected), corners);
+ if (HasFocus && !HeaderFocused) // Cursor out of selection.
+ Theme.DrawRowCursor (cairo_context, single_list_alloc.X, single_list_alloc.Y,
+ single_list_alloc.Width, single_list_alloc.Height,
+ CairoExtensions.ColorShade (Theme.Colors.GetWidgetColor (GtkColorClass.Background, StateType.Selected), 0.85));
}
if (selection_height > 0) {
- Theme.DrawRowSelection (cairo_context, list_rendering_alloc.X, selection_y, list_rendering_alloc.Width, selection_height);
+ Cairo.Color selection_color = Theme.Colors.GetWidgetColor (GtkColorClass.Background, StateType.Selected);
+ if (!HasFocus || HeaderFocused)
+ selection_color = CairoExtensions.ColorShade (selection_color, 1.1);
+
+ Theme.DrawRowSelection (cairo_context, list_rendering_alloc.X, selection_y, list_rendering_alloc.Width, selection_height,
+ true, true, selection_color, CairoCorners.All);
selection_height = 0;
}
@@ -285,10 +299,11 @@ namespace Hyena.Data.Gui
}
if (Selection != null && Selection.Count > 1 &&
- !selected_focus_alloc.Equals (Rectangle.Zero) && HasFocus) {
- Theme.DrawRowSelection (cairo_context, selected_focus_alloc.X, selected_focus_alloc.Y,
- selected_focus_alloc.Width, selected_focus_alloc.Height, false, true,
- Theme.Colors.GetWidgetColor (GtkColorClass.Dark, StateType.Selected));
+ !selected_focus_alloc.Equals (Rectangle.Zero) &&
+ HasFocus && !HeaderFocused) { // Cursor inside selection.
+ Theme.DrawRowCursor (cairo_context, selected_focus_alloc.X, selected_focus_alloc.Y,
+ selected_focus_alloc.Width, selected_focus_alloc.Height,
+ Theme.Colors.GetWidgetColor (GtkColorClass.Text, StateType.Selected));
}
foreach (int ri in selected_rows) {
@@ -320,7 +335,7 @@ namespace Hyena.Data.Gui
}
object item = model[row_index];
- bool sensitive = IsRowSensitive (item);
+ bool opaque = IsRowOpaque (item);
bool bold = IsRowBold (item);
Rectangle cell_area = new Rectangle ();
@@ -334,18 +349,18 @@ namespace Hyena.Data.Gui
cell_area.Width = column_cache[ci].Width;
cell_area.X = column_cache[ci].X1 + area.X;
- PaintCell (item, ci, row_index, cell_area, sensitive, bold, state, false);
+ PaintCell (item, ci, row_index, cell_area, opaque, bold, state, false);
}
if (pressed_column_is_dragging && pressed_column_index >= 0) {
cell_area.Width = column_cache[pressed_column_index].Width;
cell_area.X = pressed_column_x_drag + list_rendering_alloc.X -
list_interaction_alloc.X - HadjustmentValue;
- PaintCell (item, pressed_column_index, row_index, cell_area, sensitive, bold, state, true);
+ PaintCell (item, pressed_column_index, row_index, cell_area, opaque, bold, state, true);
}
}
- private void PaintCell (object item, int column_index, int row_index, Rectangle area, bool sensitive, bool bold,
+ private void PaintCell (object item, int column_index, int row_index, Rectangle area, bool opaque, bool bold,
StateType state, bool dragging)
{
ColumnCell cell = column_cache[column_index].Column.GetCell (0);
@@ -368,9 +383,11 @@ namespace Hyena.Data.Gui
cairo_context.Save ();
cairo_context.Translate (area.X, area.Y);
cell_context.Area = area;
- cell_context.Sensitive = sensitive;
+ cell_context.Opaque = opaque;
cell.Render (cell_context, dragging ? StateType.Normal : state, area.Width, area.Height);
cairo_context.Restore ();
+
+ AccessibleCellRedrawn (column_index, row_index);
}
private void PaintDraggingColumn (Rectangle clip)
@@ -405,7 +422,7 @@ namespace Hyena.Data.Gui
cairo_context.Stroke ();
}
- private void InvalidateList ()
+ protected void InvalidateList ()
{
if (IsRealized) {
QueueDrawArea (list_rendering_alloc.X, list_rendering_alloc.Y, list_rendering_alloc.Width, list_rendering_alloc.Height);
@@ -455,7 +472,7 @@ namespace Hyena.Data.Gui
}
private int row_height = 32;
- protected int RowHeight {
+ public int RowHeight {
get {
if (RecomputeRowHeight) {
row_height = RowHeightProvider != null
diff --git a/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Windowing.cs b/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Windowing.cs
index 99ca456..c97f3a0 100644
--- a/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Windowing.cs
+++ b/src/Hyena.Gui/Hyena.Data.Gui/ListView/ListView_Windowing.cs
@@ -47,6 +47,10 @@ namespace Hyena.Data.Gui
get { return list_rendering_alloc; }
}
+ protected Gdk.Window EventWindow {
+ get { return event_window; }
+ }
+
protected override void OnRealized ()
{
WidgetFlags |= WidgetFlags.Realized | WidgetFlags.NoWindow;
diff --git a/src/Hyena.Gui/Hyena.Gui.Dialogs/ExceptionDialog.cs b/src/Hyena.Gui/Hyena.Gui.Dialogs/ExceptionDialog.cs
index b9271c8..b185cea 100644
--- a/src/Hyena.Gui/Hyena.Gui.Dialogs/ExceptionDialog.cs
+++ b/src/Hyena.Gui/Hyena.Gui.Dialogs/ExceptionDialog.cs
@@ -82,6 +82,7 @@ namespace Hyena.Gui.Dialogs
label.UseUnderline = false;
label.Justify = Gtk.Justification.Left;
label.LineWrap = true;
+ label.Selectable = true;
label.SetAlignment(0.0f, 0.5f);
label_vbox.PackStart(label, false, false, 0);
diff --git a/src/Hyena.Gui/Hyena.Gui.Theming/GtkTheme.cs b/src/Hyena.Gui/Hyena.Gui.Theming/GtkTheme.cs
index 3a40506..e67768a 100644
--- a/src/Hyena.Gui/Hyena.Gui.Theming/GtkTheme.cs
+++ b/src/Hyena.Gui/Hyena.Gui.Theming/GtkTheme.cs
@@ -143,10 +143,20 @@ namespace Hyena.Gui.Theming
{
cr.LineWidth = BorderWidth;
cr.Color = border_color;
- double offset = (double)BorderWidth / 2.0;
+ double offset = (double)cr.LineWidth / 2.0;
CairoExtensions.RoundedRectangle (cr, alloc.X + offset, alloc.Y + offset,
- alloc.Width - BorderWidth, alloc.Height - BorderWidth, Context.Radius, CairoCorners.All);
- cr.Stroke();
+ alloc.Width - cr.LineWidth, alloc.Height - cr.LineWidth, Context.Radius, CairoCorners.All);
+ cr.Stroke ();
+ }
+
+ public override void DrawFrameBorderFocused (Cairo.Context cr, Gdk.Rectangle alloc)
+ {
+ cr.LineWidth = BorderWidth * 1.5;
+ cr.Color = CairoExtensions.ColorShade (border_color, 0.8);
+ double offset = (double)cr.LineWidth / 2.0;
+ CairoExtensions.RoundedRectangle (cr, alloc.X + offset, alloc.Y + offset,
+ alloc.Width - cr.LineWidth, alloc.Height - cr.LineWidth, Context.Radius, CairoCorners.All);
+ cr.Stroke ();
}
public override void DrawColumnHighlight (Cairo.Context cr, Gdk.Rectangle alloc, Cairo.Color color)
@@ -187,6 +197,41 @@ namespace Hyena.Gui.Theming
grad.Destroy ();
}
+ public override void DrawColumnHeaderFocus (Cairo.Context cr, Gdk.Rectangle alloc)
+ {
+ double top_offset = 2.0;
+ double right_offset = 2.0;
+
+ double margin = 0.5;
+ double line_width = 0.7;
+
+ Cairo.Color stroke_color = CairoExtensions.ColorShade (
+ Colors.GetWidgetColor (GtkColorClass.Background, StateType.Selected), 0.8);
+
+ stroke_color.A = 0.1;
+ cr.Color = stroke_color;
+
+ CairoExtensions.RoundedRectangle (cr,
+ alloc.X + margin + line_width + right_offset,
+ alloc.Y + margin + line_width + top_offset,
+ alloc.Width - (margin + line_width)*2.0 - right_offset,
+ alloc.Height - (margin + line_width)*2.0 - top_offset,
+ Context.Radius/2.0, CairoCorners.None);
+
+ cr.Fill ();
+
+ stroke_color.A = 1.0;
+ cr.LineWidth = line_width;
+ cr.Color = stroke_color;
+ CairoExtensions.RoundedRectangle (cr,
+ alloc.X + margin + line_width + right_offset,
+ alloc.Y + margin + line_width + top_offset,
+ alloc.Width - (line_width + margin)*2.0 - right_offset,
+ alloc.Height - (line_width + margin)*2.0 - right_offset,
+ Context.Radius/2.0, CairoCorners.All);
+ cr.Stroke ();
+ }
+
public override void DrawHeaderSeparator (Cairo.Context cr, Gdk.Rectangle alloc, int x)
{
Cairo.Color gtk_background_color = Colors.GetWidgetColor (GtkColorClass.Background, StateType.Normal);
@@ -220,6 +265,16 @@ namespace Hyena.Gui.Theming
cr.Fill ();
}
+ public override void DrawRowCursor (Cairo.Context cr, int x, int y, int width, int height,
+ Cairo.Color color, CairoCorners corners)
+ {
+ cr.LineWidth = 1.25;
+ cr.Color = color;
+ CairoExtensions.RoundedRectangle (cr, x + cr.LineWidth/2.0, y + cr.LineWidth/2.0,
+ width - cr.LineWidth, height - cr.LineWidth, Context.Radius, corners, true);
+ cr.Stroke ();
+ }
+
public override void DrawRowSelection (Cairo.Context cr, int x, int y, int width, int height,
bool filled, bool stroked, Cairo.Color color, CairoCorners corners)
{
@@ -264,7 +319,7 @@ namespace Hyena.Gui.Theming
}
}
- public override void DrawRowRule(Cairo.Context cr, int x, int y, int width, int height)
+ public override void DrawRowRule (Cairo.Context cr, int x, int y, int width, int height)
{
cr.Color = new Cairo.Color (rule_color.R, rule_color.G, rule_color.B, Context.FillAlpha);
cr.Rectangle (x, y, width, height);
diff --git a/src/Hyena.Gui/Hyena.Gui.Theming/Theme.cs b/src/Hyena.Gui/Hyena.Gui.Theming/Theme.cs
index db835fe..5d093c1 100644
--- a/src/Hyena.Gui/Hyena.Gui.Theming/Theme.cs
+++ b/src/Hyena.Gui/Hyena.Gui.Theming/Theme.cs
@@ -114,9 +114,13 @@ namespace Hyena.Gui.Theming
public abstract void DrawFrameBorder (Cairo.Context cr, Gdk.Rectangle alloc);
+ public abstract void DrawFrameBorderFocused (Cairo.Context cr, Gdk.Rectangle alloc);
+
public abstract void DrawHeaderBackground (Cairo.Context cr, Gdk.Rectangle alloc);
- public abstract void DrawHeaderSeparator(Cairo.Context cr, Gdk.Rectangle alloc, int x);
+ public abstract void DrawColumnHeaderFocus (Cairo.Context cr, Gdk.Rectangle alloc);
+
+ public abstract void DrawHeaderSeparator (Cairo.Context cr, Gdk.Rectangle alloc, int x);
public void DrawListBackground (Cairo.Context cr, Gdk.Rectangle alloc, bool baseColor)
{
@@ -137,7 +141,7 @@ namespace Hyena.Gui.Theming
public void DrawColumnHighlight (Cairo.Context cr, Gdk.Rectangle alloc)
{
- DrawColumnHighlight (cr, alloc, colors.GetWidgetColor(GtkColorClass.Background, StateType.Selected));
+ DrawColumnHighlight (cr, alloc, colors.GetWidgetColor (GtkColorClass.Background, StateType.Selected));
}
public abstract void DrawColumnHighlight (Cairo.Context cr, Gdk.Rectangle alloc, Cairo.Color color);
@@ -159,6 +163,18 @@ namespace Hyena.Gui.Theming
DrawRowSelection (cr, x, y, width, height, filled, stroked, color, CairoCorners.All);
}
+ public void DrawRowCursor (Cairo.Context cr, int x, int y, int width, int height)
+ {
+ DrawRowCursor (cr, x, y, width, height, colors.GetWidgetColor (GtkColorClass.Background, StateType.Selected));
+ }
+
+ public void DrawRowCursor (Cairo.Context cr, int x, int y, int width, int height, Cairo.Color color)
+ {
+ DrawRowCursor (cr, x, y, width, height, color, CairoCorners.All);
+ }
+
+ public abstract void DrawRowCursor (Cairo.Context cr, int x, int y, int width, int height, Cairo.Color color, CairoCorners corners);
+
public abstract void DrawRowSelection (Cairo.Context cr, int x, int y, int width, int height,
bool filled, bool stroked, Cairo.Color color, CairoCorners corners);
diff --git a/src/Hyena.Gui/Hyena.Gui/BaseWidgetAccessible.cs b/src/Hyena.Gui/Hyena.Gui/BaseWidgetAccessible.cs
new file mode 100644
index 0000000..dea5da0
--- /dev/null
+++ b/src/Hyena.Gui/Hyena.Gui/BaseWidgetAccessible.cs
@@ -0,0 +1,262 @@
+//
+// BaseWidgetAccessible.cs
+//
+// Author:
+// Gabriel Burt <gburt novell com>
+//
+// Copyright (C) 2009 Novell, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Linq;
+using System.Collections.Generic;
+
+using Atk;
+
+namespace Hyena.Gui
+{
+#if ENABLE_ATK
+ public class BaseWidgetAccessible : Gtk.Accessible, Atk.ComponentImplementor
+ {
+ private Gtk.Widget widget;
+ private uint focus_id = 0;
+ private Dictionary<uint, Atk.FocusHandler> focus_handlers = new Dictionary<uint, Atk.FocusHandler> ();
+
+ public BaseWidgetAccessible (Gtk.Widget widget)
+ {
+ this.widget = widget;
+ widget.SizeAllocated += OnAllocated;
+ widget.Mapped += OnMap;
+ widget.Unmapped += OnMap;
+ widget.FocusInEvent += OnFocus;
+ widget.FocusOutEvent += OnFocus;
+ widget.AddNotification ("sensitive", (o, a) => NotifyStateChange (StateType.Sensitive, widget.Sensitive));
+ widget.AddNotification ("visible", (o, a) => NotifyStateChange (StateType.Visible, widget.Visible));
+ }
+
+ public virtual new Atk.Layer Layer {
+ get { return Layer.Widget; }
+ }
+
+ protected override Atk.StateSet OnRefStateSet ()
+ {
+ var s = base.OnRefStateSet ();
+
+ AddStateIf (s, widget.CanFocus, StateType.Focusable);
+ AddStateIf (s, widget.HasFocus, StateType.Focused);
+ AddStateIf (s, widget.Sensitive, StateType.Sensitive);
+ AddStateIf (s, widget.Sensitive, StateType.Enabled);
+ AddStateIf (s, widget.HasDefault, StateType.Default);
+ AddStateIf (s, widget.Visible, StateType.Visible);
+ AddStateIf (s, widget.Visible && widget.IsMapped, StateType.Showing);
+
+ return s;
+ }
+
+ private static void AddStateIf (StateSet s, bool condition, StateType t)
+ {
+ if (condition) {
+ s.AddState (t);
+ }
+ }
+
+ private void OnFocus (object o, EventArgs args)
+ {
+ NotifyStateChange (StateType.Focused, widget.HasFocus);
+ var handler = FocusChanged;
+ if (handler != null) {
+ handler (this, widget.HasFocus);
+ }
+ }
+
+ private void OnMap (object o, EventArgs args)
+ {
+ NotifyStateChange (StateType.Showing, widget.Visible && widget.IsMapped);
+ }
+
+ private void OnAllocated (object o, EventArgs args)
+ {
+ var a = widget.Allocation;
+ var bounds = new Atk.Rectangle () { X = a.X, Y = a.Y, Width = a.Width, Height = a.Height };
+ GLib.Signal.Emit (this, "bounds_changed", bounds);
+ /*var handler = BoundsChanged;
+ if (handler != null) {
+ handler (this, new BoundsChangedArgs () { Args = new object [] { bounds } });
+ }*/
+ }
+
+ private event FocusHandler FocusChanged;
+
+ #region Atk.Component
+
+ public uint AddFocusHandler (Atk.FocusHandler handler)
+ {
+ if (!focus_handlers.ContainsValue (handler)) {
+ FocusChanged += handler;
+ focus_handlers[++focus_id] = handler;
+ return focus_id;
+ }
+ return 0;
+ }
+
+ public bool Contains (int x, int y, Atk.CoordType coordType)
+ {
+ int x_extents, y_extents, w, h;
+ GetExtents (out x_extents, out y_extents, out w, out h, coordType);
+ Gdk.Rectangle extents = new Gdk.Rectangle (x_extents, y_extents, w, h);
+ return extents.Contains (x, y);
+ }
+
+ public virtual Atk.Object RefAccessibleAtPoint (int x, int y, Atk.CoordType coordType)
+ {
+ return new NoOpObject (widget);
+ }
+
+ public void GetExtents (out int x, out int y, out int w, out int h, Atk.CoordType coordType)
+ {
+ w = widget.Allocation.Width;
+ h = widget.Allocation.Height;
+
+ GetPosition (out x, out y, coordType);
+ }
+
+ public void GetPosition (out int x, out int y, Atk.CoordType coordType)
+ {
+ Gdk.Window window = null;
+
+ if (!widget.IsDrawable) {
+ x = y = Int32.MinValue;
+ return;
+ }
+
+ if (widget.Parent != null) {
+ x = widget.Allocation.X;
+ y = widget.Allocation.Y;
+ window = widget.ParentWindow;
+ } else {
+ x = 0;
+ y = 0;
+ window = widget.GdkWindow;
+ }
+
+ int x_window, y_window;
+ window.GetOrigin (out x_window, out y_window);
+ x += x_window;
+ y += y_window;
+
+ if (coordType == Atk.CoordType.Window) {
+ window = widget.GdkWindow.Toplevel;
+ int x_toplevel, y_toplevel;
+ window.GetOrigin (out x_toplevel, out y_toplevel);
+
+ x -= x_toplevel;
+ y -= y_toplevel;
+ }
+ }
+
+ public void GetSize (out int w, out int h)
+ {
+ w = widget.Allocation.Width;
+ h = widget.Allocation.Height;
+ }
+
+ public bool GrabFocus ()
+ {
+ if (!widget.CanFocus) {
+ return false;
+ }
+
+ widget.GrabFocus ();
+
+ var toplevel_window = widget.Toplevel as Gtk.Window;
+ if (toplevel_window != null) {
+ toplevel_window.Present ();
+ }
+
+ return true;
+ }
+
+ public void RemoveFocusHandler (uint handlerId)
+ {
+ if (focus_handlers.ContainsKey (handlerId)) {
+ FocusChanged -= focus_handlers[handlerId];
+ focus_handlers.Remove (handlerId);
+ }
+ }
+
+ public bool SetExtents (int x, int y, int w, int h, Atk.CoordType coordType)
+ {
+ return SetSizeAndPosition (x, y, w, h, coordType, true);
+ }
+
+ public bool SetPosition (int x, int y, Atk.CoordType coordType)
+ {
+ return SetSizeAndPosition (x, y, 0, 0, coordType, false);
+ }
+
+ private bool SetSizeAndPosition (int x, int y, int w, int h, Atk.CoordType coordType, bool setSize)
+ {
+ if (!widget.IsTopLevel) {
+ return false;
+ }
+
+ if (coordType == CoordType.Window) {
+ int x_off, y_off;
+ widget.GdkWindow.GetOrigin (out x_off, out y_off);
+ x += x_off;
+ y += y_off;
+
+ if (x < 0 || y < 0) {
+ return false;
+ }
+ }
+
+ #pragma warning disable 0612
+ widget.SetUposition (x, y);
+ #pragma warning restore 0612
+
+ if (setSize) {
+ widget.SetSizeRequest (w, h);
+ }
+
+ return true;
+ }
+
+ public bool SetSize (int w, int h)
+ {
+ if (widget.IsTopLevel) {
+ widget.SetSizeRequest (w, h);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public double Alpha {
+ get { return 1.0; }
+ }
+
+ #endregion Atk.Component
+
+ }
+#endif
+}
diff --git a/src/Hyena.Gui/Hyena.Widgets/AnimatedWidget.cs b/src/Hyena.Gui/Hyena.Widgets/AnimatedWidget.cs
index e5e7165..a77eadf 100644
--- a/src/Hyena.Gui/Hyena.Widgets/AnimatedWidget.cs
+++ b/src/Hyena.Gui/Hyena.Widgets/AnimatedWidget.cs
@@ -167,7 +167,10 @@ namespace Hyena.Widgets
widget_alloc.Y = allocation.Height - widget_alloc.Height;
}
}
- Widget.SizeAllocate (widget_alloc);
+
+ if (widget_alloc.Height > 0 && widget_alloc.Width > 0) {
+ Widget.SizeAllocate (widget_alloc);
+ }
}
}
@@ -192,4 +195,4 @@ namespace Hyena.Widgets
#endregion
}
-}
\ No newline at end of file
+}
diff --git a/src/Hyena.Gui/Hyena.Widgets/EntryPopup.cs b/src/Hyena.Gui/Hyena.Widgets/EntryPopup.cs
new file mode 100644
index 0000000..f11d586
--- /dev/null
+++ b/src/Hyena.Gui/Hyena.Widgets/EntryPopup.cs
@@ -0,0 +1,226 @@
+//
+// EntryPopup.cs
+//
+// Author:
+// Neil Loknath <neil loknath gmail com>
+//
+// Copyright (C) 2009 Neil Loknath
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Timers;
+using Gdk;
+using Gtk;
+
+namespace Hyena.Widgets
+{
+ public class EntryPopup : Gtk.Window
+ {
+ private Entry text_entry;
+ private uint timeout_id = 0;
+
+ public event EventHandler<EventArgs> Changed;
+ public event EventHandler<KeyPressEventArgs> KeyPressed;
+
+ public EntryPopup (string text) : this ()
+ {
+ Text = text;
+ }
+
+ public EntryPopup () : base (Gtk.WindowType.Popup)
+ {
+ CanFocus = true;
+ Resizable = false;
+ TypeHint = Gdk.WindowTypeHint.Utility;
+ Modal = true;
+
+ Frame frame = new Frame ();
+ frame.Shadow = ShadowType.EtchedIn;
+ Add (frame);
+
+ HBox box = new HBox ();
+ text_entry = new Entry();
+ box.PackStart (text_entry, true, true, 0);
+ box.BorderWidth = 3;
+
+ frame.Add (box);
+ frame.ShowAll ();
+
+ text_entry.Text = String.Empty;
+ text_entry.CanFocus = true;
+
+ //TODO figure out why this event does not get raised
+ text_entry.FocusOutEvent += (o, a) => {
+ if (hide_when_focus_lost) {
+ HidePopup ();
+ }
+ };
+
+ text_entry.KeyReleaseEvent += delegate (object o, KeyReleaseEventArgs args) {
+ if (args.Event.Key == Gdk.Key.Escape ||
+ args.Event.Key == Gdk.Key.Return ||
+ args.Event.Key == Gdk.Key.Tab) {
+
+ HidePopup ();
+ }
+
+ InitializeDelayedHide ();
+ };
+
+ text_entry.KeyPressEvent += (o, a) => OnKeyPressed (a);
+
+ text_entry.Changed += (o, a) => {
+ if (GdkWindow.IsVisible) {
+ OnChanged (a);
+ }
+ };
+ }
+
+ public new bool HasFocus {
+ get { return text_entry.HasFocus; }
+ set { text_entry.HasFocus = value; }
+ }
+
+ public string Text {
+ get { return text_entry.Text; }
+ set { text_entry.Text = value; }
+ }
+
+ public Entry Entry {
+ get { return text_entry; }
+ }
+
+ private bool hide_after_timeout = true;
+ public bool HideAfterTimeout {
+ get { return hide_after_timeout; }
+ set { hide_after_timeout = value; }
+ }
+
+ private uint timeout = 5000;
+ public uint Timeout {
+ get { return timeout; }
+ set { timeout = value; }
+ }
+
+ private bool hide_when_focus_lost = true;
+ public bool HideOnFocusOut {
+ get { return hide_when_focus_lost; }
+ set { hide_when_focus_lost = value; }
+ }
+
+ private bool reset_when_hiding = true;
+ public bool ResetOnHide {
+ get { return reset_when_hiding; }
+ set { reset_when_hiding = value; }
+ }
+
+ public override void Dispose ()
+ {
+ text_entry.Dispose ();
+ base.Dispose ();
+ }
+
+ public new void GrabFocus ()
+ {
+ text_entry.GrabFocus ();
+ }
+
+ private void ResetDelayedHide ()
+ {
+ if (timeout_id > 0) {
+ GLib.Source.Remove (timeout_id);
+ timeout_id = 0;
+ }
+ }
+
+ private void InitializeDelayedHide ()
+ {
+ ResetDelayedHide ();
+ timeout_id = GLib.Timeout.Add (timeout, delegate {
+ HidePopup ();
+ return false;
+ });
+ }
+
+ private void HidePopup ()
+ {
+ ResetDelayedHide ();
+ Hide ();
+
+ if (reset_when_hiding) {
+ text_entry.Text = String.Empty;
+ }
+ }
+
+ protected virtual void OnChanged (EventArgs args)
+ {
+ var handler = Changed;
+ if (handler != null) {
+ handler (this, EventArgs.Empty);
+ }
+ }
+
+ protected virtual void OnKeyPressed (KeyPressEventArgs args)
+ {
+ var handler = KeyPressed;
+ if (handler != null) {
+ handler (this, args);
+ }
+ }
+
+ //TODO figure out why this event does not get raised
+ protected override bool OnFocusOutEvent (Gdk.EventFocus evnt)
+ {
+ if (hide_when_focus_lost) {
+ HidePopup ();
+ return true;
+ }
+
+ return base.OnFocusOutEvent (evnt);
+ }
+
+ protected override bool OnExposeEvent (Gdk.EventExpose evnt)
+ {
+ InitializeDelayedHide ();
+ return base.OnExposeEvent (evnt);
+ }
+
+ protected override bool OnButtonReleaseEvent (Gdk.EventButton evnt)
+ {
+ if (!text_entry.HasFocus && hide_when_focus_lost) {
+ HidePopup ();
+ return true;
+ }
+
+ return base.OnButtonReleaseEvent (evnt);
+ }
+
+ protected override bool OnButtonPressEvent (Gdk.EventButton evnt)
+ {
+ if (!text_entry.HasFocus && hide_when_focus_lost) {
+ HidePopup ();
+ return true;
+ }
+
+ return base.OnButtonPressEvent (evnt);
+ }
+ }
+}
diff --git a/src/Hyena.Gui/Hyena.Widgets/HigMessageDialog.cs b/src/Hyena.Gui/Hyena.Widgets/HigMessageDialog.cs
index d23d108..338dc8e 100644
--- a/src/Hyena.Gui/Hyena.Widgets/HigMessageDialog.cs
+++ b/src/Hyena.Gui/Hyena.Widgets/HigMessageDialog.cs
@@ -32,7 +32,6 @@ namespace Hyena.Widgets
{
public class HigMessageDialog : Gtk.Dialog
{
- private Gtk.AccelGroup accel_group;
private Gtk.Image image;
private Gtk.VBox label_vbox;
private Gtk.Label message_label;
@@ -54,9 +53,6 @@ namespace Hyena.Widgets
VBox.Spacing = 12;
ActionArea.Layout = Gtk.ButtonBoxStyle.End;
- accel_group = new Gtk.AccelGroup ();
- AddAccelGroup (accel_group);
-
Gtk.HBox hbox = new Gtk.HBox (false, 12);
hbox.BorderWidth = 5;
hbox.Show ();
@@ -177,12 +173,9 @@ namespace Hyena.Widgets
AddActionWidget (button, response);
if (isDefault) {
+ Default = button;
DefaultResponse = response;
- button.AddAccelerator ("activate",
- accel_group,
- (uint) Gdk.Key.Return,
- 0,
- Gtk.AccelFlags.Visible);
+ button.GrabDefault ();
}
}
diff --git a/src/Hyena.Gui/Hyena.Widgets/ImageButton.cs b/src/Hyena.Gui/Hyena.Widgets/ImageButton.cs
index 33f67e1..9431b0a 100644
--- a/src/Hyena.Gui/Hyena.Widgets/ImageButton.cs
+++ b/src/Hyena.Gui/Hyena.Widgets/ImageButton.cs
@@ -33,20 +33,32 @@ namespace Hyena.Widgets
{
public class ImageButton : Button
{
+ private Image image;
+ private Label label;
+ private HBox hbox;
+
+ public Image ImageWidget { get { return image; } }
+ public Label LabelWidget { get { return label; } }
+
+ public uint InnerPadding {
+ get { return hbox.BorderWidth; }
+ set { hbox.BorderWidth = value; }
+ }
+
public ImageButton (string text, string iconName) : this (text, iconName, Gtk.IconSize.Button)
{
}
public ImageButton (string text, string iconName, Gtk.IconSize iconSize) : base ()
{
- Image image = new Image ();
+ image = new Image ();
image.IconName = iconName;
image.IconSize = (int) iconSize;
- Label label = new Label ();
+ label = new Label ();
label.MarkupWithMnemonic = text;
- HBox hbox = new HBox ();
+ hbox = new HBox ();
hbox.Spacing = 2;
hbox.PackStart (image, false, false, 0);
hbox.PackStart (label, true, true, 0);
diff --git a/src/Hyena.Gui/Hyena.Widgets/MenuButton.cs b/src/Hyena.Gui/Hyena.Widgets/MenuButton.cs
index f40dbbd..138bb86 100644
--- a/src/Hyena.Gui/Hyena.Widgets/MenuButton.cs
+++ b/src/Hyena.Gui/Hyena.Widgets/MenuButton.cs
@@ -73,6 +73,7 @@ namespace Hyena.Widgets
alignment.Add (arrow);
box.PackStart (alignment, false, false, 5);
size_widget = box;
+ FocusChain = new Widget[] {toggle_button, box};
} else {
toggle_button.Add (button_widget);
size_widget = toggle_button;
diff --git a/src/Hyena.Gui/Hyena.Widgets/MessageBar.cs b/src/Hyena.Gui/Hyena.Widgets/MessageBar.cs
index c1e901e..1934697 100644
--- a/src/Hyena.Gui/Hyena.Widgets/MessageBar.cs
+++ b/src/Hyena.Gui/Hyena.Widgets/MessageBar.cs
@@ -39,7 +39,7 @@ namespace Hyena.Widgets
private HBox box;
private HBox button_box;
private AnimatedImage image;
- private Label label;
+ private WrapLabel label;
private Button close_button;
private Window win;
@@ -76,8 +76,7 @@ namespace Hyena.Widgets
} catch {
}
- label = new Label ();
- label.Xalign = 0.0f;
+ label = new WrapLabel ();
label.Show ();
box.PackStart (image, false, false, 0);
diff --git a/src/Hyena.Gui/Hyena.Widgets/RatingEntry.cs b/src/Hyena.Gui/Hyena.Widgets/RatingEntry.cs
index 4fcf73a..ddaf603 100644
--- a/src/Hyena.Gui/Hyena.Widgets/RatingEntry.cs
+++ b/src/Hyena.Gui/Hyena.Widgets/RatingEntry.cs
@@ -47,6 +47,13 @@ namespace Hyena.Widgets
public event EventHandler Changing;
public event EventHandler Changed;
+ static RatingEntry ()
+ {
+#if ENABLE_ATK
+ RatingAccessibleFactory.Init ();
+#endif
+ }
+
public RatingEntry () : this (0)
{
WidgetFlags |= Gtk.WidgetFlags.NoWindow;
@@ -381,6 +388,78 @@ namespace Hyena.Widgets
#region Test Module
+#if ENABLE_ATK
+ public class RatingAccessible : Atk.Object, Atk.Value, Atk.ValueImplementor
+ {
+ private RatingEntry rating;
+
+ public RatingAccessible (IntPtr raw) : base (raw)
+ {
+ Hyena.Log.Information ("RatingAccessible raw ctor..");
+ }
+
+ public RatingAccessible (GLib.Object widget): base ()
+ {
+ rating = widget as RatingEntry;
+ Name = "Rating entry";
+ Description = "Rating entry, from 0 to 5 stars";
+ Role = Atk.Role.Slider;
+ }
+
+ public void GetMaximumValue (ref GLib.Value val)
+ {
+ val = new GLib.Value (5);
+ }
+
+ public void GetMinimumIncrement (ref GLib.Value val)
+ {
+ val = new GLib.Value (1);
+ }
+
+ public void GetMinimumValue (ref GLib.Value val)
+ {
+ val = new GLib.Value (0);
+ }
+
+ public void GetCurrentValue (ref GLib.Value val)
+ {
+ val = new GLib.Value (rating.Value);
+ }
+
+ public bool SetCurrentValue (GLib.Value val)
+ {
+ int r = (int) val.Val;
+ if (r <= 0 || r > 5) {
+ return false;
+ }
+
+ rating.Value = (int) val.Val;
+ return true;
+ }
+ }
+#endif
+
+#if ENABLE_ATK
+ internal class RatingAccessibleFactory : Atk.ObjectFactory
+ {
+ public static void Init ()
+ {
+ new RatingAccessibleFactory ();
+ Atk.Global.DefaultRegistry.SetFactoryType ((GLib.GType)typeof (RatingEntry), (GLib.GType)typeof (RatingAccessibleFactory));
+ }
+
+ protected override Atk.Object OnCreateAccessible (GLib.Object obj)
+ {
+ return new RatingAccessible (obj);
+ }
+
+ protected override GLib.GType OnGetAccessibleType ()
+ {
+ return RatingAccessible.GType;
+ }
+ }
+#endif
+
[Hyena.Gui.TestModule ("Rating Entry")]
internal class RatingEntryTestModule : Gtk.Window
{
diff --git a/src/Hyena.Gui/Hyena.Widgets/SimpleTable.cs b/src/Hyena.Gui/Hyena.Widgets/SimpleTable.cs
new file mode 100644
index 0000000..15417c7
--- /dev/null
+++ b/src/Hyena.Gui/Hyena.Widgets/SimpleTable.cs
@@ -0,0 +1,103 @@
+//
+// SimpleTable.cs
+//
+// Author:
+// Gabriel Burt <gburt novell com>
+//
+// Copyright (C) 2009 Novell, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections.Generic;
+using Gtk;
+
+namespace Hyena.Widgets
+{
+ public class SimpleTable<T> : Table
+ {
+ private bool added_any;
+
+ private List<T> items = new List<T> ();
+ private Dictionary<T, Widget []> item_widgets = new Dictionary<T, Widget []> ();
+
+ public SimpleTable () : base (1, 2, false)
+ {
+ ColumnSpacing = 5;
+ RowSpacing = 5;
+ }
+
+ public void AddRow (T item, params Widget [] cols)
+ {
+ InsertRow (item, (uint)items.Count, cols);
+ }
+
+ public void InsertRow (T item, uint row, params Widget [] cols)
+ {
+ if (!added_any) {
+ added_any = true;
+ } else if (NColumns != cols.Length) {
+ throw new ArgumentException ("cols", String.Format ("Expected {0} column widgets, same as previous calls to Add", NColumns));
+ }
+
+ Resize ((uint) items.Count + 1, (uint) cols.Length);
+
+ for (int y = items.Count - 1; y >= row; y--) {
+ for (uint x = 0; x < NColumns; x++) {
+ var widget = item_widgets[items[y]][x];
+ Remove (widget);
+ Attach (widget, x, x + 1, (uint) y + 1, (uint) y + 2);
+ }
+ }
+
+ items.Insert ((int)row, item);
+ item_widgets[item] = cols;
+
+ for (uint x = 0; x < NColumns; x++) {
+ Attach (cols[x], x, x + 1, row, row + 1);
+ }
+ }
+
+ public void RemoveRow (T item)
+ {
+ FreezeChildNotify ();
+
+ foreach (var widget in item_widgets[item]) {
+ Remove (widget);
+ }
+
+ int index = items.IndexOf (item);
+ for (int y = index + 1; y < items.Count; y++) {
+ for (uint x = 0; x < NColumns; x++) {
+ var widget = item_widgets[items[y]][x];
+ Remove (widget);
+ Attach (widget, x, x + 1, (uint) y - 1, (uint) y);
+ }
+ }
+
+ Resize ((uint) Math.Max (1, items.Count - 1), NColumns);
+
+ ThawChildNotify ();
+ items.Remove (item);
+ item_widgets.Remove (item);
+ }
+ }
+}
diff --git a/src/Hyena.Gui/Hyena.Widgets/WrapLabel.cs b/src/Hyena.Gui/Hyena.Widgets/WrapLabel.cs
index b0a04e7..c2a4923 100644
--- a/src/Hyena.Gui/Hyena.Widgets/WrapLabel.cs
+++ b/src/Hyena.Gui/Hyena.Widgets/WrapLabel.cs
@@ -102,8 +102,13 @@ namespace Hyena.Widgets
protected override bool OnExposeEvent (Gdk.EventExpose evnt)
{
if (evnt.Window == GdkWindow) {
+ // Center the text vertically
+ int lw, lh;
+ layout.GetPixelSize (out lw, out lh);
+ int y = Allocation.Y + (Allocation.Height - lh) / 2;
+
Gtk.Style.PaintLayout (Style, GdkWindow, State, false,
- evnt.Area, this, null, Allocation.X, Allocation.Y, layout);
+ evnt.Area, this, null, Allocation.X, y, layout);
}
return true;
diff --git a/src/Hyena.Gui/Makefile.am b/src/Hyena.Gui/Makefile.am
index 0178685..0cec6fe 100644
--- a/src/Hyena.Gui/Makefile.am
+++ b/src/Hyena.Gui/Makefile.am
@@ -97,6 +97,9 @@ FILES = \
Hyena.Gui.Theming/ThemeEngine.cs \
Hyena.Gui.Theming/GtkTheme.cs \
Hyena.Data.Gui/ListView/ListView_DragAndDrop.cs \
+ Hyena.Gui/BaseWidgetAccessible.cs \
+ Hyena.Widgets/EntryPopup.cs \
+ Hyena.Widgets/SimpleTable.cs \
Hyena.Gui/PangoCairoHelper.cs \
Hyena.Widgets/AnimatedBox.cs \
Hyena.Widgets/AnimatedHBox.cs \
@@ -123,6 +126,14 @@ FILES = \
Hyena.Data.Gui/ISizeRequestCell.cs \
Hyena.Data.Gui/ITooltipCell.cs \
Hyena.Data.Gui/ColumnCellRating.cs \
+ Hyena.Data.Gui/Accessibility/ColumnCellAccessible.cs \
+ Hyena.Data.Gui/Accessibility/ColumnCellTextAccessible.cs \
+ Hyena.Data.Gui/Accessibility/ColumnHeaderCellTextAccessible.cs \
+ Hyena.Data.Gui/Accessibility/ICellAccessibleParent.cs \
+ Hyena.Data.Gui/Accessibility/ListViewAccessible.cs \
+ Hyena.Data.Gui/Accessibility/ListViewAccessible_Selection.cs \
+ Hyena.Data.Gui/Accessibility/ListViewAccessible_Table.cs \
+ Hyena.Data.Gui/ListView/ListView_Accessible.cs \
Hyena.Widgets/RatingEntry.cs \
Hyena.Widgets/RatingMenuItem.cs \
Hyena.Widgets/ComplexMenuItem.cs \
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]