Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/xwt.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Xwt.Gtk')
-rw-r--r--Xwt.Gtk/Xwt.Gtk.csproj2
-rw-r--r--Xwt.Gtk/Xwt.Gtk3.csproj2
-rw-r--r--Xwt.Gtk/Xwt.GtkBackend.CellViews/CellUtil.cs1
-rw-r--r--Xwt.Gtk/Xwt.GtkBackend.CellViews/CellViewBackend.cs18
-rw-r--r--Xwt.Gtk/Xwt.GtkBackend.CellViews/CustomCellRenderer.cs48
-rw-r--r--Xwt.Gtk/Xwt.GtkBackend/AccessibleBackend.cs1
-rw-r--r--Xwt.Gtk/Xwt.GtkBackend/BoxBackendGtk2.cs8
-rwxr-xr-xXwt.Gtk/Xwt.GtkBackend/ButtonBackend.cs11
-rw-r--r--Xwt.Gtk/Xwt.GtkBackend/ComboBoxBackend.cs4
-rw-r--r--Xwt.Gtk/Xwt.GtkBackend/CustomTreeModel.cs219
-rw-r--r--Xwt.Gtk/Xwt.GtkBackend/GtkInterop.cs37
-rw-r--r--Xwt.Gtk/Xwt.GtkBackend/GtkWorkarounds.cs4
-rw-r--r--Xwt.Gtk/Xwt.GtkBackend/MenuItemBackend.cs9
-rwxr-xr-xXwt.Gtk/Xwt.GtkBackend/RichTextViewBackend.cs5
-rw-r--r--Xwt.Gtk/Xwt.GtkBackend/TableViewBackend.cs82
-rw-r--r--Xwt.Gtk/Xwt.GtkBackend/TextLayoutBackendHandler.cs2
-rw-r--r--Xwt.Gtk/Xwt.GtkBackend/TreeStoreBackend.cs5
-rw-r--r--Xwt.Gtk/Xwt.GtkBackend/TreeViewBackend.cs97
-rw-r--r--Xwt.Gtk/Xwt.GtkBackend/WidgetBackend.cs12
19 files changed, 442 insertions, 125 deletions
diff --git a/Xwt.Gtk/Xwt.Gtk.csproj b/Xwt.Gtk/Xwt.Gtk.csproj
index a4c35f3a..e090656d 100644
--- a/Xwt.Gtk/Xwt.Gtk.csproj
+++ b/Xwt.Gtk/Xwt.Gtk.csproj
@@ -23,6 +23,7 @@
<ConsolePause>False</ConsolePause>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -34,6 +35,7 @@
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<DebugSymbols>true</DebugSymbols>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
diff --git a/Xwt.Gtk/Xwt.Gtk3.csproj b/Xwt.Gtk/Xwt.Gtk3.csproj
index 40fbee79..6801595c 100644
--- a/Xwt.Gtk/Xwt.Gtk3.csproj
+++ b/Xwt.Gtk/Xwt.Gtk3.csproj
@@ -21,6 +21,7 @@
<WarningLevel>4</WarningLevel>
<ConsolePause>False</ConsolePause>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
+ <LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -32,6 +33,7 @@
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<DefineConstants>XWT_GTK3</DefineConstants>
<DebugSymbols>true</DebugSymbols>
+ <LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
diff --git a/Xwt.Gtk/Xwt.GtkBackend.CellViews/CellUtil.cs b/Xwt.Gtk/Xwt.GtkBackend.CellViews/CellUtil.cs
index 2b6067cd..1bcf6911 100644
--- a/Xwt.Gtk/Xwt.GtkBackend.CellViews/CellUtil.cs
+++ b/Xwt.Gtk/Xwt.GtkBackend.CellViews/CellUtil.cs
@@ -158,6 +158,7 @@ namespace Xwt.GtkBackend
Gtk.Widget EventRootWidget { get; }
bool GetCellPosition (Gtk.CellRenderer r, int ex, int ey, out int cx, out int cy, out Gtk.TreeIter iter);
void QueueDraw (object target, Gtk.TreeIter iter);
+ void QueueResize (object target, Gtk.TreeIter iter);
TreeModel Model { get; }
Gtk.TreeIter PressedIter { get; set; }
CellViewBackend PressedCell { get; set; }
diff --git a/Xwt.Gtk/Xwt.GtkBackend.CellViews/CellViewBackend.cs b/Xwt.Gtk/Xwt.GtkBackend.CellViews/CellViewBackend.cs
index 62808a41..87fe116b 100644
--- a/Xwt.Gtk/Xwt.GtkBackend.CellViews/CellViewBackend.cs
+++ b/Xwt.Gtk/Xwt.GtkBackend.CellViews/CellViewBackend.cs
@@ -190,10 +190,11 @@ namespace Xwt.GtkBackend
if (!buttonReleaseSubscribed)
rendererTarget.EventRootWidget.ButtonReleaseEvent -= HandleButtonReleaseEvent;
- var rect = rendererTarget.GetCellBounds (target, CellRenderer, iter);
+ var rect = rendererTarget.GetCellBackgroundBounds (target, CellRenderer, iter);
if (captured || rect.Contains (cx, cy)) {
ApplicationContext.InvokeUserCode (delegate {
LoadData (rendererTarget.Model, iter);
+ SetCurrentEventRow ();
var a = new ButtonEventArgs {
X = args.Event.X,
Y = args.Event.Y,
@@ -212,7 +213,7 @@ namespace Xwt.GtkBackend
int cx, cy;
Gtk.TreeIter iter;
if (rendererTarget.GetCellPosition (CellRenderer, (int)args.Event.X, (int)args.Event.Y, out cx, out cy, out iter)) {
- var rect = rendererTarget.GetCellBounds (target, CellRenderer, iter);
+ var rect = rendererTarget.GetCellBackgroundBounds (target, CellRenderer, iter);
if (rect.Contains (cx, cy)) {
rendererTarget.PressedIter = iter;
rendererTarget.PressedCell = this;
@@ -226,6 +227,7 @@ namespace Xwt.GtkBackend
}
ApplicationContext.InvokeUserCode (delegate {
LoadData (rendererTarget.Model, iter);
+ SetCurrentEventRow ();
var a = new ButtonEventArgs {
X = args.Event.X,
Y = args.Event.Y,
@@ -246,13 +248,14 @@ namespace Xwt.GtkBackend
int cx, cy;
Gtk.TreeIter iter;
if (rendererTarget.GetCellPosition (CellRenderer, (int)args.Event.X, (int)args.Event.Y, out cx, out cy, out iter)) {
- var rect = rendererTarget.GetCellBounds (target, CellRenderer, iter);
+ var rect = rendererTarget.GetCellBackgroundBounds (target, CellRenderer, iter);
if (rect.Contains (cx, cy)) {
if (enabledEvents.HasFlag (WidgetEvent.MouseMoved))
ApplicationContext.InvokeUserCode (delegate {
LoadData (rendererTarget.Model, iter);
- EventSink.OnMouseMoved (new MouseMovedEventArgs (args.Event.Time, cx, cy));
+ SetCurrentEventRow ();
+ EventSink.OnMouseMoved (new MouseMovedEventArgs (args.Event.Time, cx, cy));
});
if (!mouseInsideCell) {
@@ -260,6 +263,7 @@ namespace Xwt.GtkBackend
if (enabledEvents.HasFlag (WidgetEvent.MouseEntered))
ApplicationContext.InvokeUserCode (delegate {
LoadData (rendererTarget.Model, iter);
+ SetCurrentEventRow ();
EventSink.OnMouseEntered ();
});
}
@@ -268,6 +272,7 @@ namespace Xwt.GtkBackend
if (enabledEvents.HasFlag (WidgetEvent.MouseExited))
ApplicationContext.InvokeUserCode (delegate {
LoadData (rendererTarget.Model, iter);
+ SetCurrentEventRow ();
EventSink.OnMouseExited ();
});
}
@@ -361,6 +366,11 @@ namespace Xwt.GtkBackend
{
rendererTarget.QueueDraw (target, CurrentIter);
}
+
+ public void QueueResize ()
+ {
+ rendererTarget.QueueResize (target, CurrentIter);
+ }
}
}
diff --git a/Xwt.Gtk/Xwt.GtkBackend.CellViews/CustomCellRenderer.cs b/Xwt.Gtk/Xwt.GtkBackend.CellViews/CustomCellRenderer.cs
index 2304625c..22670f38 100644
--- a/Xwt.Gtk/Xwt.GtkBackend.CellViews/CustomCellRenderer.cs
+++ b/Xwt.Gtk/Xwt.GtkBackend.CellViews/CustomCellRenderer.cs
@@ -38,7 +38,8 @@ namespace Xwt.GtkBackend
bool isSelected;
bool hasFocus;
bool isPrelit;
- bool isDrawing;
+ TreeIter lastIter;
+ bool shown;
public override void Initialize (ICellViewFrontend cellView, ICellRendererTarget rendererTarget, object target)
{
@@ -57,17 +58,30 @@ namespace Xwt.GtkBackend
hasFocus = (flags & CellRendererState.Focused) != 0;
isPrelit = (flags & CellRendererState.Prelit) != 0;
- isDrawing = true;
+ // Gtk will rerender the cell on every status change, hence we can expect the values
+ // set here to be valid until the geometry or any other status of the cell and tree changes.
+ // Setting shown=true ensures that those values are always reused instead if queried
+ // from the parent tree after the cell has been rendered.
+ shown = true;
+ }
+
+ protected override void OnLoadData ()
+ {
+ if (!CurrentIter.Equals (lastIter)) {
+ // if the current iter has changed all cached values from the last draw are invalid
+ shown = false;
+ lastIter = CurrentIter;
+ }
+ base.OnLoadData ();
}
internal void EndDrawing ()
{
- isDrawing = false;
}
public override Rectangle CellBounds {
get {
- if (isDrawing)
+ if (shown)
return cellArea;
return base.CellBounds;
}
@@ -75,7 +89,7 @@ namespace Xwt.GtkBackend
public override Rectangle BackgroundBounds {
get {
- if (isDrawing)
+ if (shown)
return backgroundArea;
return base.BackgroundBounds;
}
@@ -83,7 +97,7 @@ namespace Xwt.GtkBackend
public override bool Selected {
get {
- if (isDrawing)
+ if (shown)
return isSelected;
return base.Selected;
}
@@ -91,7 +105,7 @@ namespace Xwt.GtkBackend
public override bool HasFocus {
get {
- if (isDrawing)
+ if (shown)
return hasFocus;
return base.HasFocus;
}
@@ -99,7 +113,7 @@ namespace Xwt.GtkBackend
public bool IsHighlighted {
get {
- if (isDrawing)
+ if (shown)
return isPrelit;
return false;
}
@@ -113,10 +127,25 @@ namespace Xwt.GtkBackend
protected override void OnRender (Cairo.Context cr, Gtk.Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, CellRendererState flags)
{
+ int wx, wy, dx = 0, dy = 0;
+ var tree = widget as Gtk.TreeView;
+ // Tree coordinates must be converted to widget coordinates,
+ // otherwise custom cell bounds will have an offset to the parent widget
+ if (tree != null) {
+ tree.ConvertBinWindowToWidgetCoords (cell_area.X, cell_area.Y, out wx, out wy);
+ dx = wx - cell_area.X;
+ dy = wy - cell_area.Y;
+ cell_area.X += dx;
+ background_area.X += dx;
+ cell_area.Y += dy;
+ background_area.Y += dy;
+ }
+
Parent.StartDrawing (new Rectangle (background_area.X, background_area.Y, background_area.Width, background_area.Height), new Rectangle (cell_area.X, cell_area.Y, cell_area.Width, cell_area.Height), flags);
CellView.ApplicationContext.InvokeUserCode (delegate {
CairoContextBackend ctx = new CairoContextBackend (Util.GetScaleFactor (widget));
ctx.Context = cr;
+ ctx.Context.Translate(-dx, -dy);
using (ctx) {
CellView.Draw (ctx, new Rectangle (cell_area.X, cell_area.Y, cell_area.Width, cell_area.Height));
}
@@ -127,8 +156,9 @@ namespace Xwt.GtkBackend
protected override void OnGetSize (Gtk.Widget widget, ref Gdk.Rectangle cell_area, out int x_offset, out int y_offset, out int width, out int height)
{
Size size = new Size ();
+ var widthConstraint = cell_area.Width > 0 ? SizeConstraint.WithSize(cell_area.Width) : SizeConstraint.Unconstrained;
CellView.ApplicationContext.InvokeUserCode (delegate {
- size = CellView.GetRequiredSize ();
+ size = CellView.GetRequiredSize (widthConstraint);
});
width = (int) size.Width;
height = (int) size.Height;
diff --git a/Xwt.Gtk/Xwt.GtkBackend/AccessibleBackend.cs b/Xwt.Gtk/Xwt.GtkBackend/AccessibleBackend.cs
index 711cea70..6c68fbd6 100644
--- a/Xwt.Gtk/Xwt.GtkBackend/AccessibleBackend.cs
+++ b/Xwt.Gtk/Xwt.GtkBackend/AccessibleBackend.cs
@@ -135,7 +135,6 @@ namespace Xwt.GtkBackend
}
set {
if (widget.Accessible is AtkValue) {
- GLib.Value val = GLib.Value.Empty;
(widget.Accessible as AtkValue)?.SetCurrentValue (new GLib.Value (value));
} else if (widget.Accessible is AtkEditableText) {
var atkText = (widget.Accessible as AtkEditableText);
diff --git a/Xwt.Gtk/Xwt.GtkBackend/BoxBackendGtk2.cs b/Xwt.Gtk/Xwt.GtkBackend/BoxBackendGtk2.cs
index 9f12f4c1..fd4ccb84 100644
--- a/Xwt.Gtk/Xwt.GtkBackend/BoxBackendGtk2.cs
+++ b/Xwt.Gtk/Xwt.GtkBackend/BoxBackendGtk2.cs
@@ -24,6 +24,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
+using System.Linq;
namespace Xwt.GtkBackend
{
@@ -34,6 +35,13 @@ namespace Xwt.GtkBackend
if (!IsReallocating)
QueueResize ();
}
+
+ protected override void OnSizeRequested (ref Gtk.Requisition requisition)
+ {
+ base.OnSizeRequested (ref requisition);
+ foreach (var c in children.Keys.ToArray ())
+ c.SizeRequest ();
+ }
}
}
diff --git a/Xwt.Gtk/Xwt.GtkBackend/ButtonBackend.cs b/Xwt.Gtk/Xwt.GtkBackend/ButtonBackend.cs
index 2c055645..8bb0514b 100755
--- a/Xwt.Gtk/Xwt.GtkBackend/ButtonBackend.cs
+++ b/Xwt.Gtk/Xwt.GtkBackend/ButtonBackend.cs
@@ -47,8 +47,12 @@ namespace Xwt.GtkBackend
{
NeedsEventBox = false;
Widget = new Gtk.Button ();
+ Widget.Realized += (o, arg) =>
+ {
+ if (Widget.IsRealized && Widget.CanDefault)
+ Widget.GrabDefault();
+ };
base.Widget.Show ();
-
}
protected new Gtk.Button Widget {
@@ -83,6 +87,11 @@ namespace Xwt.GtkBackend
}
}
+ public virtual bool IsDefault {
+ get { return Widget.CanDefault; }
+ set { Widget.CanDefault = value; }
+ }
+
public override object Font {
get {
return base.Font;
diff --git a/Xwt.Gtk/Xwt.GtkBackend/ComboBoxBackend.cs b/Xwt.Gtk/Xwt.GtkBackend/ComboBoxBackend.cs
index dfed802e..1f00511a 100644
--- a/Xwt.Gtk/Xwt.GtkBackend/ComboBoxBackend.cs
+++ b/Xwt.Gtk/Xwt.GtkBackend/ComboBoxBackend.cs
@@ -184,6 +184,10 @@ namespace Xwt.GtkBackend
{
}
+ public void QueueResize (object target, Gtk.TreeIter iter)
+ {
+ }
+
#endregion
}
}
diff --git a/Xwt.Gtk/Xwt.GtkBackend/CustomTreeModel.cs b/Xwt.Gtk/Xwt.GtkBackend/CustomTreeModel.cs
index b7e5fdb4..8753ec62 100644
--- a/Xwt.Gtk/Xwt.GtkBackend/CustomTreeModel.cs
+++ b/Xwt.Gtk/Xwt.GtkBackend/CustomTreeModel.cs
@@ -33,15 +33,25 @@ using TreeModelImplementor = Gtk.ITreeModelImplementor;
namespace Xwt.GtkBackend
{
- public class CustomTreeModel: TreeModelImplementor
+ public class CustomTreeModel: GLib.Object, TreeModelImplementor
{
ITreeDataSource source;
- Dictionary<GCHandle,TreePosition> nodeHash = new Dictionary<GCHandle,TreePosition> ();
- Dictionary<TreePosition,GCHandle> handleHash = new Dictionary<TreePosition,GCHandle> ();
+ Dictionary<TreePosition,NodeData> handleHash = new Dictionary<TreePosition,NodeData> ();
Type[] colTypes;
Gtk.TreeModelAdapter adapter;
-
+ int stamp;
+
+ /// <summary>
+ /// Stores information about the index of a noda and the GCHandle
+ /// used by the native reference
+ /// </summary>
+ class NodeData
+ {
+ public GCHandle Handle;
+ public int Index;
+ }
+
public CustomTreeModel (ITreeDataSource source)
{
this.source = source;
@@ -57,55 +67,125 @@ namespace Xwt.GtkBackend
public Gtk.TreeModelAdapter Store {
get { return adapter; }
}
-
- public IntPtr Handle {
- get {
- return IntPtr.Zero;
- }
- }
-
- Gtk.TreeIter IterFromNode (TreePosition node)
+
+ public Gtk.TreeIter IterFromNode (TreePosition node, int index = -1)
{
- GCHandle gch;
- if (!handleHash.TryGetValue (node, out gch)) {
- gch = GCHandle.Alloc (node);
- handleHash [node] = gch;
- nodeHash [gch] = node;
+ // The returned iter will have a reference to the TreePosition
+ // through a GCHandle. At the same time we store a NodeData
+ // object to a hashtable, which contains the GCHandle and
+ // the index of the node
+
+ NodeData data;
+ if (!handleHash.TryGetValue (node, out data)) {
+ // It is the first time the node is referenced.
+ // Store it in handleHash.
+ handleHash [node] = data = new NodeData {
+ Handle = GCHandle.Alloc (node),
+ Index = index
+ };
}
+
+ // If the index of the node changed, update it in its NodeData
+ if (index != -1 && index != data.Index)
+ data.Index = index;
+
Gtk.TreeIter result = Gtk.TreeIter.Zero;
- result.UserData = (IntPtr)gch;
+ result.UserData = (IntPtr)data.Handle;
+ result.Stamp = stamp;
return result;
}
+
+ int GetCachedIndex (TreePosition node)
+ {
+ // Gets the index of a node, or -1 if that information is not available
+ NodeData data;
+ if (handleHash.TryGetValue (node, out data))
+ return data.Index;
+ return -1;
+ }
- TreePosition NodeFromIter (Gtk.TreeIter iter)
+ void CacheIndex (TreePosition node, int index)
{
- TreePosition node;
- GCHandle gch = (GCHandle)iter.UserData;
- nodeHash.TryGetValue (gch, out node);
- return node;
+ // Stores the index of a node
+ NodeData data;
+ if (handleHash.TryGetValue (node, out data))
+ data.Index = index;
}
+ public bool NodeFromIter (Gtk.TreeIter iter, out TreePosition pos)
+ {
+ if (iter.UserData == IntPtr.Zero) {
+ pos = null;
+ return true;
+ }
+ if (iter.Stamp != stamp) {
+ // The iter has been invalidated
+ pos = null;
+ return false;
+ }
+ GCHandle gch = GCHandle.FromIntPtr (iter.UserData);
+ pos = (TreePosition) gch.Target;
+ return true;
+ }
+
#region TreeModelImplementor implementation
void HandleNodesReordered (object sender, TreeNodeOrderEventArgs e)
{
- Gtk.TreeIter it = IterFromNode (e.Node);
- adapter.EmitRowsReordered (GetPath (it), it, e.ChildrenOrder);
+ // Don't increase the stamp because no nodes have been removed, so all iters are still valid
+ // Update the cached indexes for all the children that have chanfed
+ for (int n = 0; n < e.ChildrenOrder.Length; n++) {
+ if (e.ChildrenOrder [n] != n) {
+ var child = source.GetChild (e.Node, n);
+ if (child != null)
+ CacheIndex (child, n);
+ }
+ }
+ adapter.EmitRowsReordered (GetPath (e.Node), IterFromNode (e.Node), e.ChildrenOrder);
}
void HandleNodeInserted (object sender, TreeNodeEventArgs e)
{
- Gtk.TreeIter it = IterFromNode (e.Node);
- adapter.EmitRowInserted (GetPath (it), it);
+ // Don't increase the stamp because no nodes have been removed, so all iters are still valid
+ // Update the cached indexes
+ var parent = source.GetParent (e.Node);
+ var count = source.GetChildrenCount (parent);
+ for (int n = e.ChildIndex + 1; n < count; n++) {
+ var child = source.GetChild (parent, n);
+ if (child != null)
+ CacheIndex (child, n);
+ }
+ var iter = IterFromNode (e.Node, e.ChildIndex);
+ adapter.EmitRowInserted (GetPath (e.Node), iter);
}
void HandleNodeDeleted (object sender, TreeNodeChildEventArgs e)
{
+ if (e.Node != null && !handleHash.ContainsKey (e.Node))
+ return;
+
+ NodeData data;
+ if (e.Child != null && handleHash.TryGetValue (e.Child, out data)) {
+ // Increase the model stamp since the node is gone and there may
+ // be iters referencing that node. Increasing the stamp will
+ // invalidate all those nodes
+ stamp++;
+ data.Handle.Free ();
+ handleHash.Remove (e.Child);
+
+ // Update the indexes of the node following the deleted one
+ var count = source.GetChildrenCount (e.Node);
+ for (int n = e.ChildIndex; n < count; n++) {
+ var child = source.GetChild (e.Node, n);
+ if (child != null)
+ CacheIndex (child, n);
+ }
+ }
+
if (e.Node == null) {
adapter.EmitRowDeleted (new Gtk.TreePath (new int[] { e.ChildIndex }));
} else {
- Gtk.TreeIter it = IterFromNode (e.Node);
- var p = GetPath (it);
+ var p = GetPath (e.Node);
int[] idx = new int [p.Indices.Length + 1];
p.Indices.CopyTo (idx, 0);
idx [idx.Length - 1] = e.ChildIndex;
@@ -115,8 +195,8 @@ namespace Xwt.GtkBackend
void HandleNodeChanged (object sender, TreeNodeEventArgs e)
{
- Gtk.TreeIter it = IterFromNode (e.Node);
- adapter.EmitRowChanged (GetPath (it), it);
+ if (handleHash.ContainsKey (e.Node))
+ adapter.EmitRowChanged (GetPath (e.Node), IterFromNode (e.Node));
}
public GLib.GType GetColumnType (int index)
@@ -136,13 +216,20 @@ namespace Xwt.GtkBackend
if (pos == null)
return false;
}
- iter = IterFromNode (pos);
+ iter = IterFromNode (pos, indices[indices.Length - 1]);
return true;
}
public Gtk.TreePath GetPath (Gtk.TreeIter iter)
{
- TreePosition pos = NodeFromIter (iter);
+ TreePosition pos;
+ if (NodeFromIter (iter, out pos))
+ return GetPath (pos);
+ return Gtk.TreePath.NewFirst ();
+ }
+
+ public Gtk.TreePath GetPath (TreePosition pos)
+ {
List<int> idx = new List<int> ();
while (pos != null) {
var parent = source.GetParent (pos);
@@ -155,34 +242,49 @@ namespace Xwt.GtkBackend
int GetIndex (TreePosition parent, TreePosition pos)
{
+ var res = GetCachedIndex (pos);
+ if (res != -1)
+ return res;
+
int n = 0;
do {
var c = source.GetChild (parent, n);
if (c == null)
return -1;
- if (c == pos || c.Equals(pos))
+ if (c == pos || c.Equals (pos)) {
+ CacheIndex (pos, n);
return n;
+ }
n++;
} while (true);
}
public void GetValue (Gtk.TreeIter iter, int column, ref GLib.Value value)
{
- TreePosition pos = NodeFromIter (iter);
+ TreePosition pos;
+ if (!NodeFromIter (iter, out pos)) {
+ value = GLib.Value.Empty;
+ return;
+ }
var v = source.GetValue (pos, column);
- value = new GLib.Value (v);
+ if (v == null)
+ value = GLib.Value.Empty;
+ else
+ value = new GLib.Value (v);
}
public bool IterNext (ref Gtk.TreeIter iter)
{
- TreePosition pos = NodeFromIter (iter);
+ TreePosition pos;
+ if (!NodeFromIter (iter, out pos))
+ return false;
TreePosition parent = source.GetParent (pos);
int i = GetIndex (parent, pos);
- if (source.GetChildrenCount (parent) >= i)
+ if (i == -1)
return false;
pos = source.GetChild (parent, i + 1);
if (pos != null) {
- iter = IterFromNode (pos);
+ iter = IterFromNode (pos, i + 1);
return true;
} else
return false;
@@ -191,12 +293,14 @@ namespace Xwt.GtkBackend
#if XWT_GTK3
public bool IterPrevious (ref Gtk.TreeIter iter)
{
- TreePosition pos = NodeFromIter (iter);
+ TreePosition pos;
+ if (!NodeFromIter (iter, out pos))
+ return false;
TreePosition parent = source.GetParent (pos);
int i = GetIndex (parent, pos);
pos = source.GetChild (parent, i - 1);
if (pos != null) {
- iter = IterFromNode (pos);
+ iter = IterFromNode (pos, i - 1);
return true;
} else
return false;
@@ -205,11 +309,13 @@ namespace Xwt.GtkBackend
public bool IterChildren (out Gtk.TreeIter iter, Gtk.TreeIter parent)
{
- iter = Gtk.TreeIter.Zero;
- TreePosition pos = NodeFromIter (parent);
+ iter = parent;
+ TreePosition pos;
+ if (!NodeFromIter (parent, out pos))
+ return false;
pos = source.GetChild (pos, 0);
if (pos != null) {
- iter = IterFromNode (pos);
+ iter = IterFromNode (pos, 0);
return true;
} else
return false;
@@ -217,23 +323,29 @@ namespace Xwt.GtkBackend
public bool IterHasChild (Gtk.TreeIter iter)
{
- TreePosition pos = NodeFromIter (iter);
+ TreePosition pos;
+ if (!NodeFromIter (iter, out pos))
+ return false;
return source.GetChildrenCount (pos) != 0;
}
public int IterNChildren (Gtk.TreeIter iter)
{
- TreePosition pos = NodeFromIter (iter);
+ TreePosition pos;
+ if (!NodeFromIter (iter, out pos))
+ return 0;
return source.GetChildrenCount (pos);
}
public bool IterNthChild (out Gtk.TreeIter iter, Gtk.TreeIter parent, int n)
{
- iter = Gtk.TreeIter.Zero;
- TreePosition pos = NodeFromIter (parent);
+ iter = parent;
+ TreePosition pos;
+ if (!NodeFromIter (parent, out pos))
+ return false;
pos = source.GetChild (pos, n);
if (pos != null) {
- iter = IterFromNode (pos);
+ iter = IterFromNode (pos, n);
return true;
} else
return false;
@@ -241,9 +353,12 @@ namespace Xwt.GtkBackend
public bool IterParent (out Gtk.TreeIter iter, Gtk.TreeIter child)
{
- iter = Gtk.TreeIter.Zero;
- TreePosition pos = NodeFromIter (iter);
- pos = source.GetParent (pos);
+ iter = child;
+ TreePosition pos;
+ if (!NodeFromIter (iter, out pos))
+ return false;
+ if (pos != null)
+ pos = source.GetParent (pos);
if (pos != null) {
iter = IterFromNode (pos);
return true;
diff --git a/Xwt.Gtk/Xwt.GtkBackend/GtkInterop.cs b/Xwt.Gtk/Xwt.GtkBackend/GtkInterop.cs
index 7aceea0d..edcf3030 100644
--- a/Xwt.Gtk/Xwt.GtkBackend/GtkInterop.cs
+++ b/Xwt.Gtk/Xwt.GtkBackend/GtkInterop.cs
@@ -228,10 +228,12 @@ namespace Xwt.GtkBackend
}
}
- internal class TextIndexer
+ public class TextIndexer
{
- int[] indexToByteIndex;
- int[] byteIndexToIndex;
+ static readonly List<int> emptyList = new List<int> ();
+ static readonly int [] emptyArray = new int [0];
+ int [] indexToByteIndex;
+ List<int> byteIndexToIndex;
public TextIndexer (string text)
{
@@ -244,7 +246,7 @@ namespace Xwt.GtkBackend
// if the index exceeds the byte index range, return the last byte index + 1
// telling pango to span the attribute to the end of the string
// this happens if the string contains multibyte characters
- return indexToByteIndex[i-1] + 1;
+ return indexToByteIndex[indexToByteIndex.Length-1] + 1;
return indexToByteIndex[i];
}
@@ -255,24 +257,27 @@ namespace Xwt.GtkBackend
public void SetupTables (string text)
{
- if (text == null) {
- this.indexToByteIndex = new int[0];
- this.byteIndexToIndex = new int[0];
+ if (string.IsNullOrEmpty (text)) {
+ this.indexToByteIndex = emptyArray;
+ this.byteIndexToIndex = emptyList;
return;
}
- var arr = text.ToCharArray ();
int byteIndex = 0;
- int[] indexToByteIndex = new int[arr.Length];
- var byteIndexToIndex = new List<int> ();
- for (int i = 0; i < arr.Length; i++) {
- indexToByteIndex[i] = byteIndex;
- byteIndex += System.Text.Encoding.UTF8.GetByteCount (arr, i, 1);
- while (byteIndexToIndex.Count < byteIndex)
- byteIndexToIndex.Add (i);
+ int [] indexToByteIndex = new int [text.Length];
+ var byteIndexToIndex = new System.Collections.Generic.List<int> (text.Length);
+ unsafe {
+ fixed (char* p = text) {
+ for (int i = 0; i < text.Length; i++) {
+ indexToByteIndex[i] = byteIndex;
+ byteIndex += System.Text.Encoding.UTF8.GetByteCount (p + i, 1);
+ while (byteIndexToIndex.Count < byteIndex)
+ byteIndexToIndex.Add (i);
+ }
+ }
}
this.indexToByteIndex = indexToByteIndex;
- this.byteIndexToIndex = byteIndexToIndex.ToArray ();
+ this.byteIndexToIndex = byteIndexToIndex;
}
}
}
diff --git a/Xwt.Gtk/Xwt.GtkBackend/GtkWorkarounds.cs b/Xwt.Gtk/Xwt.GtkBackend/GtkWorkarounds.cs
index 3808b2fa..9247d858 100644
--- a/Xwt.Gtk/Xwt.GtkBackend/GtkWorkarounds.cs
+++ b/Xwt.Gtk/Xwt.GtkBackend/GtkWorkarounds.cs
@@ -554,11 +554,11 @@ namespace Xwt.GtkBackend
//introduced in GTK 2.20
[DllImport (GtkInterop.LIBGDK, CallingConvention = CallingConvention.Cdecl)]
- extern static bool gdk_keymap_add_virtual_modifiers (IntPtr keymap, ref Gdk.ModifierType state);
+ extern static void gdk_keymap_add_virtual_modifiers (IntPtr keymap, ref Gdk.ModifierType state);
//Custom patch in Mono Mac w/GTK+ 2.24.8+
[DllImport (GtkInterop.LIBGDK, CallingConvention = CallingConvention.Cdecl)]
- extern static bool gdk_quartz_set_fix_modifiers (bool fix);
+ extern static void gdk_quartz_set_fix_modifiers (bool fix);
static Gdk.Keymap keymap = Gdk.Keymap.Default;
static Dictionary<ulong,MappedKeys> mappedKeys = new Dictionary<ulong,MappedKeys> ();
diff --git a/Xwt.Gtk/Xwt.GtkBackend/MenuItemBackend.cs b/Xwt.Gtk/Xwt.GtkBackend/MenuItemBackend.cs
index 960e114e..c7f6ee05 100644
--- a/Xwt.Gtk/Xwt.GtkBackend/MenuItemBackend.cs
+++ b/Xwt.Gtk/Xwt.GtkBackend/MenuItemBackend.cs
@@ -126,6 +126,15 @@ namespace Xwt.GtkBackend
}
}
+ public string TooltipText {
+ get {
+ return item.TooltipText;
+ }
+ set {
+ item.TooltipText = value;
+ }
+ }
+
public bool UseMnemonic {
get { return label.UseUnderline; }
set { label.UseUnderline = value; }
diff --git a/Xwt.Gtk/Xwt.GtkBackend/RichTextViewBackend.cs b/Xwt.Gtk/Xwt.GtkBackend/RichTextViewBackend.cs
index f85d6b79..88977cbd 100755
--- a/Xwt.Gtk/Xwt.GtkBackend/RichTextViewBackend.cs
+++ b/Xwt.Gtk/Xwt.GtkBackend/RichTextViewBackend.cs
@@ -584,7 +584,10 @@ namespace Xwt.GtkBackend
{
if (!IsRealized)
return;
- var color = (Gdk.Color) StyleGetProperty ("link-color");
+ var objColor = StyleGetProperty ("link-color");
+ var color = Gdk.Color.Zero;
+ if (objColor != null)
+ color = (Gdk.Color) objColor;
if (color.Equals (Gdk.Color.Zero))
color = Toolkit.CurrentEngine.Defaults.FallbackLinkColor.ToGtkValue ();
if (Buffer != null)
diff --git a/Xwt.Gtk/Xwt.GtkBackend/TableViewBackend.cs b/Xwt.Gtk/Xwt.GtkBackend/TableViewBackend.cs
index 72de4f73..3e16979e 100644
--- a/Xwt.Gtk/Xwt.GtkBackend/TableViewBackend.cs
+++ b/Xwt.Gtk/Xwt.GtkBackend/TableViewBackend.cs
@@ -29,6 +29,7 @@ using Xwt.Backends;
using Gtk;
using System.Collections.Generic;
using System.Linq;
+using Gdk;
#if XWT_GTK3
using TreeModel = Gtk.ITreeModel;
#endif
@@ -238,6 +239,7 @@ namespace Xwt.GtkBackend
public void SetSelectionMode (SelectionMode mode)
{
switch (mode) {
+ case SelectionMode.None: Widget.Selection.Mode = Gtk.SelectionMode.None; break;
case SelectionMode.Single: Widget.Selection.Mode = Gtk.SelectionMode.Single; break;
case SelectionMode.Multiple: Widget.Selection.Mode = Gtk.SelectionMode.Multiple; break;
}
@@ -463,19 +465,36 @@ namespace Xwt.GtkBackend
{
Gtk.TreeViewColumn col;
Gtk.TreePath path;
- int cellx, celly;
+ int _cellx, _celly;
cx = cy = 0;
it = Gtk.TreeIter.Zero;
- if (!Widget.GetPathAtPos (ex, ey, out path, out col, out cellx, out celly))
+ if (!Widget.GetPathAtPos (ex, ey, out path, out col, out _cellx, out _celly))
return false;
- if (!Widget.Model.GetIterFromString (out it, path.ToString ()))
+ if (!Widget.Model.GetIter (out it, path))
return false;
- int sp, w;
- if (col.CellGetPosition (r, out sp, out w)) {
- if (cellx >= sp && cellx < sp + w) {
+ var cellArea = Widget.GetCellArea (path, col);
+ var cellx = ex - cellArea.X;
+
+ var renderers = col.GetCellRenderers ();
+ int i = Array.IndexOf (renderers, r);
+
+ int rendererX, rendererWidth;
+ if (col.CellGetPosition (r, out rendererX, out rendererWidth)) {
+ if (i < renderers.Length - 1) {
+ int nextX, _w;
+ // The width returned by CellGetPosition is not reliable. Calculate the width
+ // by getting the position of the next renderer.
+ if (col.CellGetPosition (renderers [i + 1], out nextX, out _w))
+ rendererWidth = nextX - rendererX;
+ } else {
+ // Last renderer of the column. Its width is what's left in the cell area.
+ rendererWidth = cellArea.Width - rendererX;
+ }
+
+ if (cellx >= rendererX && cellx < rendererX + rendererWidth) {
Widget.ConvertBinWindowToWidgetCoords (ex, ey, out cx, out cy);
return true;
}
@@ -492,16 +511,26 @@ namespace Xwt.GtkBackend
Widget.QueueDrawArea (x, y, r.Width, r.Height);
}
+ public void QueueResize (object target, Gtk.TreeIter iter)
+ {
+ var path = Widget.Model.GetPath (iter);
+ Widget.Model.EmitRowChanged (path, iter);
+ }
+
#endregion
}
class CustomTreeView: Gtk.TreeView
{
WidgetBackend backend;
-
+ TreePath delayedSelection;
+ TreeViewColumn delayedSelectionColumn;
+
public CustomTreeView (WidgetBackend b)
{
backend = b;
+ base.DragBegin += (_, __) =>
+ delayedSelection = null;
}
static CustomTreeView ()
@@ -514,6 +543,44 @@ namespace Xwt.GtkBackend
GtkWorkarounds.RemoveKeyBindingFromClass (Gtk.TreeView.GType, Gdk.Key.BackSpace, Gdk.ModifierType.None);
}
+ protected override bool OnButtonPressEvent (EventButton evnt)
+ {
+ if (Selection.Mode == Gtk.SelectionMode.Multiple) {
+ // If we are clicking on already selected row, delay the selection until we are certain that
+ // the user is not starting a DragDrop operation.
+ // This is needed to allow user to drag multiple selected rows.
+ TreePath treePath;
+ TreeViewColumn column;
+ GetPathAtPos ((int)evnt.X, (int)evnt.Y, out treePath, out column);
+
+ var ctrlShiftMask = (evnt.State & (Gdk.ModifierType.ShiftMask | Gdk.ModifierType.ControlMask | Gdk.ModifierType.Mod2Mask));
+ if (treePath != null && evnt.Button == 1 && this.Selection.PathIsSelected (treePath) && this.Selection.CountSelectedRows() > 1 && ctrlShiftMask == 0) {
+ delayedSelection = treePath;
+ delayedSelectionColumn = column;
+ Selection.SelectFunction = (_, __, ___, ____) => false;
+ var result = false;
+ try {
+ result = base.OnButtonPressEvent (evnt);
+ } finally {
+ Selection.SelectFunction = (_, __, ___, ____) => true;
+ }
+ return result;
+ }
+ }
+ return base.OnButtonPressEvent (evnt);
+ }
+
+ protected override bool OnButtonReleaseEvent (EventButton evnt)
+ {
+ // Now, if mouse hadn't moved, we are certain that this was just a click. Proceed as usual.
+ if (delayedSelection != null) {
+ SetCursor (delayedSelection, delayedSelectionColumn, false);
+ delayedSelection = null;
+ delayedSelectionColumn = null;
+ }
+ return base.OnButtonReleaseEvent (evnt);
+ }
+
protected override void OnDragDataDelete (Gdk.DragContext context)
{
// This method is override to avoid the default implementation
@@ -523,4 +590,3 @@ namespace Xwt.GtkBackend
}
}
}
-
diff --git a/Xwt.Gtk/Xwt.GtkBackend/TextLayoutBackendHandler.cs b/Xwt.Gtk/Xwt.GtkBackend/TextLayoutBackendHandler.cs
index 842e94c8..eedfa976 100644
--- a/Xwt.Gtk/Xwt.GtkBackend/TextLayoutBackendHandler.cs
+++ b/Xwt.Gtk/Xwt.GtkBackend/TextLayoutBackendHandler.cs
@@ -198,7 +198,7 @@ namespace Xwt.GtkBackend
{
var tl = (PangoBackend) backend;
int index, trailing;
- tl.Layout.XyToIndex ((int)x, (int)y, out index, out trailing);
+ tl.Layout.XyToIndex (Pango.Units.FromPixels ((int)x), Pango.Units.FromPixels ((int)y), out index, out trailing);
return tl.TextIndexer.ByteIndexToIndex (index);
}
diff --git a/Xwt.Gtk/Xwt.GtkBackend/TreeStoreBackend.cs b/Xwt.Gtk/Xwt.GtkBackend/TreeStoreBackend.cs
index fba2ba64..efdbe50e 100644
--- a/Xwt.Gtk/Xwt.GtkBackend/TreeStoreBackend.cs
+++ b/Xwt.Gtk/Xwt.GtkBackend/TreeStoreBackend.cs
@@ -71,6 +71,7 @@ namespace Xwt.GtkBackend
public event EventHandler<TreeNodeChildEventArgs> NodeDeleted;
public event EventHandler<TreeNodeEventArgs> NodeChanged;
public event EventHandler<TreeNodeOrderEventArgs> NodesReordered;
+ public event EventHandler Cleared;
IterPos GetIterPos (TreePosition pos)
{
@@ -86,6 +87,8 @@ namespace Xwt.GtkBackend
{
version++;
Tree.Clear ();
+ if (Cleared != null)
+ Cleared (this, EventArgs.Empty);
}
public TreePosition GetChild (TreePosition pos, int index)
@@ -212,7 +215,7 @@ namespace Xwt.GtkBackend
IterPos tpos = GetIterPos (pos);
Gtk.TreeIter it = tpos.Iter;
var delPath = Tree.GetPath (it);
- var eventArgs = new TreeNodeChildEventArgs (GetParent (tpos), delPath.Indices[delPath.Indices.Length - 1]);
+ var eventArgs = new TreeNodeChildEventArgs (GetParent (tpos), delPath.Indices[delPath.Indices.Length - 1], pos);
Tree.Remove (ref it);
if (NodeDeleted != null)
NodeDeleted (this, eventArgs);
diff --git a/Xwt.Gtk/Xwt.GtkBackend/TreeViewBackend.cs b/Xwt.Gtk/Xwt.GtkBackend/TreeViewBackend.cs
index 6783094c..b43324e3 100644
--- a/Xwt.Gtk/Xwt.GtkBackend/TreeViewBackend.cs
+++ b/Xwt.Gtk/Xwt.GtkBackend/TreeViewBackend.cs
@@ -34,6 +34,7 @@ namespace Xwt.GtkBackend
{
Gtk.TreePath autoExpandPath;
uint expandTimer;
+ CustomTreeModel customModel;
protected new ITreeViewEventSink EventSink {
get { return (ITreeViewEventSink)base.EventSink; }
@@ -91,9 +92,9 @@ namespace Xwt.GtkBackend
{
Gtk.TreeIter it;
if (Widget.Model.GetIter (out it, args.Path)) {
- CurrentEventRow = new IterPos (-1, it);
+ CurrentEventRow = GetPositionFromIter (-1, it);
ApplicationContext.InvokeUserCode (delegate {
- EventSink.OnRowExpanded (new IterPos (-1, it));
+ EventSink.OnRowExpanded (GetPositionFromIter (-1, it));
});
}
}
@@ -102,9 +103,9 @@ namespace Xwt.GtkBackend
{
Gtk.TreeIter it;
if (Widget.Model.GetIter (out it, args.Path)) {
- CurrentEventRow = new IterPos (-1, it);
+ CurrentEventRow = GetPositionFromIter (-1, it);
ApplicationContext.InvokeUserCode (delegate {
- EventSink.OnRowExpanding (new IterPos (-1, it));
+ EventSink.OnRowExpanding (GetPositionFromIter (-1, it));
});
}
}
@@ -113,9 +114,9 @@ namespace Xwt.GtkBackend
{
Gtk.TreeIter it;
if (Widget.Model.GetIter (out it, args.Path)) {
- CurrentEventRow = new IterPos (-1, it);
+ CurrentEventRow = GetPositionFromIter (-1, it);
ApplicationContext.InvokeUserCode (delegate {
- EventSink.OnRowCollapsed (new IterPos (-1, it));
+ EventSink.OnRowCollapsed (GetPositionFromIter (-1, it));
});
}
}
@@ -124,9 +125,9 @@ namespace Xwt.GtkBackend
{
Gtk.TreeIter it;
if (Widget.Model.GetIter (out it, args.Path)) {
- CurrentEventRow = new IterPos (-1, it);
+ CurrentEventRow = GetPositionFromIter (-1, it);
ApplicationContext.InvokeUserCode (delegate {
- EventSink.OnRowCollapsing (new IterPos (-1, it));
+ EventSink.OnRowCollapsing (GetPositionFromIter (-1, it));
});
}
}
@@ -135,9 +136,9 @@ namespace Xwt.GtkBackend
{
Gtk.TreeIter it;
if (Widget.Model.GetIter (out it, args.Path)) {
- CurrentEventRow = new IterPos (-1, it);
+ CurrentEventRow = GetPositionFromIter (-1, it);
ApplicationContext.InvokeUserCode (delegate {
- EventSink.OnRowActivated (new IterPos (-1, it));
+ EventSink.OnRowActivated (GetPositionFromIter (-1, it));
});
}
}
@@ -195,21 +196,24 @@ namespace Xwt.GtkBackend
public void SetSource (ITreeDataSource source, IBackend sourceBackend)
{
TreeStoreBackend b = sourceBackend as TreeStoreBackend;
+ customModel = null;
if (b == null) {
- CustomTreeModel model = new CustomTreeModel (source);
- Widget.Model = model.Store;
+ customModel = new CustomTreeModel (source);
+ Widget.Model = customModel.Store;
} else
Widget.Model = b.Store;
}
+ public bool AnimationsEnabled { get; set; }
+
public TreePosition[] SelectedRows {
get {
var rows = Widget.Selection.GetSelectedRows ();
- IterPos[] sel = new IterPos [rows.Length];
+ TreePosition[] sel = new TreePosition [rows.Length];
for (int i = 0; i < rows.Length; i++) {
Gtk.TreeIter it;
Widget.Model.GetIter (out it, rows[i]);
- sel[i] = new IterPos (-1, it);
+ sel[i] = GetPositionFromIter (-1, it);
}
return sel;
}
@@ -223,13 +227,13 @@ namespace Xwt.GtkBackend
Gtk.TreeIter it;
if (path != null && Widget.Model.GetIter (out it, path))
- return new IterPos (-1, it);
+ return GetPositionFromIter (-1, it);
return null;
}
set {
Gtk.TreePath path = new Gtk.TreePath(new [] { int.MaxValue }); // set invalid path to unfocus
if (value != null)
- path = Widget.Model.GetPath (((IterPos)value).Iter);
+ path = Widget.Model.GetPath (GetIterFromPosition (value));
Widget.SetCursor (path, null, false);
}
}
@@ -241,44 +245,53 @@ namespace Xwt.GtkBackend
public void SelectRow (TreePosition pos)
{
- Widget.Selection.SelectIter (((IterPos)pos).Iter);
+ Widget.Selection.SelectIter (GetIterFromPosition (pos));
}
public void UnselectRow (TreePosition pos)
{
- Widget.Selection.UnselectIter (((IterPos)pos).Iter);
+ Widget.Selection.UnselectIter (GetIterFromPosition (pos));
}
public bool IsRowSelected (TreePosition pos)
{
- return Widget.Selection.IterIsSelected (((IterPos)pos).Iter);
+ return Widget.Selection.IterIsSelected (GetIterFromPosition (pos));
}
public bool IsRowExpanded (TreePosition pos)
{
- return Widget.GetRowExpanded (Widget.Model.GetPath (((IterPos)pos).Iter));
+ return Widget.GetRowExpanded (Widget.Model.GetPath (GetIterFromPosition (pos)));
}
public void ExpandRow (TreePosition pos, bool expandedChildren)
{
- Widget.ExpandRow (Widget.Model.GetPath (((IterPos)pos).Iter), expandedChildren);
+ Widget.ExpandRow (Widget.Model.GetPath (GetIterFromPosition (pos)), expandedChildren);
}
public void CollapseRow (TreePosition pos)
{
- Widget.CollapseRow (Widget.Model.GetPath (((IterPos)pos).Iter));
+ Widget.CollapseRow (Widget.Model.GetPath (GetIterFromPosition (pos)));
}
public void ScrollToRow (TreePosition pos)
{
- ScrollToRow (((IterPos)pos).Iter);
+ ScrollToRow (GetIterFromPosition (pos));
}
public void ExpandToRow (TreePosition pos)
{
- Widget.ExpandToPath (Widget.Model.GetPath (((IterPos)pos).Iter));
+ Widget.ExpandToPath (Widget.Model.GetPath (GetIterFromPosition (pos)));
}
-
+
+ public bool BorderVisible {
+ get {
+ return ScrolledWindow.ShadowType != Gtk.ShadowType.None;
+ }
+ set {
+ ScrolledWindow.ShadowType = value ? Gtk.ShadowType.In : Gtk.ShadowType.None;
+ }
+ }
+
public bool HeadersVisible {
get {
return Widget.HeadersVisible;
@@ -287,6 +300,15 @@ namespace Xwt.GtkBackend
Widget.HeadersVisible = value;
}
}
+
+ public bool UseAlternatingRowColors {
+ get {
+ return Widget.RulesHint;
+ }
+ set {
+ Widget.RulesHint = value;
+ }
+ }
public bool GetDropTargetRow (double x, double y, out RowDropPosition pos, out TreePosition nodePosition)
{
@@ -300,7 +322,7 @@ namespace Xwt.GtkBackend
Gtk.TreeIter it;
Widget.Model.GetIter (out it, path);
- nodePosition = new IterPos (-1, it);
+ nodePosition = GetPositionFromIter (-1, it);
switch (tpos) {
case Gtk.TreeViewDropPosition.After: pos = RowDropPosition.After; break;
case Gtk.TreeViewDropPosition.Before: pos = RowDropPosition.Before; break;
@@ -315,7 +337,7 @@ namespace Xwt.GtkBackend
if (path != null) {
Gtk.TreeIter iter;
Widget.Model.GetIter (out iter, path);
- return new IterPos (-1, iter);
+ return GetPositionFromIter (-1, iter);
}
return null;
}
@@ -324,7 +346,7 @@ namespace Xwt.GtkBackend
{
var col = GetCellColumn (cell);
var cr = GetCellRenderer (cell);
- Gtk.TreeIter iter = ((IterPos)pos).Iter;
+ Gtk.TreeIter iter = GetIterFromPosition (pos);
var rect = includeMargin ? ((ICellRendererTarget)this).GetCellBackgroundBounds (col, cr, iter) : ((ICellRendererTarget)this).GetCellBounds (col, cr, iter);
return rect;
@@ -332,7 +354,7 @@ namespace Xwt.GtkBackend
public Rectangle GetRowBounds (TreePosition pos, bool includeMargin)
{
- Gtk.TreeIter iter = ((IterPos)pos).Iter;
+ Gtk.TreeIter iter = GetIterFromPosition (pos);
Rectangle rect = includeMargin ? GetRowBackgroundBounds (iter) : GetRowBounds (iter);
return rect;
}
@@ -351,6 +373,23 @@ namespace Xwt.GtkBackend
CurrentEventRow = toggledItem;
}
+
+ TreePosition GetPositionFromIter (int treeVersion, Gtk.TreeIter iter)
+ {
+ if (customModel != null) {
+ TreePosition pos;
+ customModel.NodeFromIter (iter, out pos);
+ return pos;
+ }
+ return new IterPos (treeVersion, iter);
+ }
+
+ Gtk.TreeIter GetIterFromPosition (TreePosition position)
+ {
+ if (customModel != null)
+ return customModel.IterFromNode (position);
+ return ((IterPos)position).Iter;
+ }
}
}
diff --git a/Xwt.Gtk/Xwt.GtkBackend/WidgetBackend.cs b/Xwt.Gtk/Xwt.GtkBackend/WidgetBackend.cs
index c78649ed..97a8f983 100644
--- a/Xwt.Gtk/Xwt.GtkBackend/WidgetBackend.cs
+++ b/Xwt.Gtk/Xwt.GtkBackend/WidgetBackend.cs
@@ -192,6 +192,8 @@ namespace Xwt.GtkBackend
ctype = Gdk.CursorType.Crosshair;
else if (cursor == CursorType.Hand)
ctype = Gdk.CursorType.Hand1;
+ else if (cursor == CursorType.Hand2 || cursor == CursorType.DragCopy)
+ ctype = Gdk.CursorType.Hand2;
else if (cursor == CursorType.IBeam)
ctype = Gdk.CursorType.Xterm;
else if (cursor == CursorType.ResizeDown)
@@ -206,6 +208,16 @@ namespace Xwt.GtkBackend
ctype = Gdk.CursorType.SbHDoubleArrow;
else if (cursor == CursorType.ResizeUpDown)
ctype = Gdk.CursorType.SbVDoubleArrow;
+ else if (cursor == CursorType.ResizeNE)
+ ctype = Gdk.CursorType.TopRightCorner;
+ else if (cursor == CursorType.ResizeNW)
+ ctype = Gdk.CursorType.TopLeftCorner;
+ else if (cursor == CursorType.ResizeSE)
+ ctype = Gdk.CursorType.BottomRightCorner;
+ else if (cursor == CursorType.ResizeSW)
+ ctype = Gdk.CursorType.BottomLeftCorner;
+ else if (cursor == CursorType.NotAllowed)
+ ctype = Gdk.CursorType.XCursor;
else if (cursor == CursorType.Move)
ctype = Gdk.CursorType.Fleur;
else if (cursor == CursorType.Wait)